summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/doc-txt/experimental-spec.txt2
-rw-r--r--src/src/smtp_in.c34
-rw-r--r--src/src/string.c2
-rw-r--r--src/util/proxy_protocol_client.pl6
4 files changed, 30 insertions, 14 deletions
diff --git a/doc/doc-txt/experimental-spec.txt b/doc/doc-txt/experimental-spec.txt
index 018bfddb9..d8c26bf93 100644
--- a/doc/doc-txt/experimental-spec.txt
+++ b/doc/doc-txt/experimental-spec.txt
@@ -1025,6 +1025,8 @@ Proxy Protocol Support
Exim now has Experimental "Proxy Protocol" support. It was built on
specifications from:
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
+Above URL revised May 2014 to change version 2 spec:
+http://git.1wt.eu/web?p=haproxy.git;a=commitdiff;h=afb768340c9d7e50d8e
The purpose of this function is so that an application load balancer,
such as HAProxy, can sit in front of several Exim servers and Exim
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index aad778eef..b7e60bfab 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -623,10 +623,9 @@ union {
} v1;
struct {
uschar sig[12];
- uschar ver;
- uschar cmd;
- uschar fam;
- uschar len;
+ uint8_t ver_cmd;
+ uint8_t fam;
+ uint16_t len;
union {
struct { /* TCP/UDP over IPv4, len = 12 */
uint32_t src_addr;
@@ -657,7 +656,7 @@ struct sockaddr_in6 tmpaddr6;
int get_ok = 0;
int size, ret, fd;
-const char v2sig[13] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02";
+const char v2sig[12] = "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A";
uschar *iptype; /* To display debug info */
struct timeval tv;
socklen_t vslen = 0;
@@ -693,16 +692,32 @@ if (ret == -1)
}
if (ret >= 16 &&
- memcmp(&hdr.v2, v2sig, 13) == 0)
+ memcmp(&hdr.v2, v2sig, 12) == 0)
{
+ uint8_t ver, cmd;
+
+ /* May 2014: haproxy combined the version and command into one byte to
+ allow two full bytes for the length field in order to proxy SSL
+ connections. SSL Proxy is not supported in this version of Exim, but
+ must still seperate values here. */
+ ver = (hdr.v2.ver_cmd & 0xf0) >> 4;
+ cmd = (hdr.v2.ver_cmd & 0x0f);
+
+ if (ver != 0x02)
+ {
+ DEBUG(D_receive) debug_printf("Invalid Proxy Protocol version: %d\n", ver);
+ goto proxyfail;
+ }
DEBUG(D_receive) debug_printf("Detected PROXYv2 header\n");
+ /* The v2 header will always be 16 bytes per the spec. */
size = 16 + hdr.v2.len;
if (ret < size)
{
- DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header\n");
+ DEBUG(D_receive) debug_printf("Truncated or too large PROXYv2 header (%d/%d)\n",
+ ret, size);
goto proxyfail;
}
- switch (hdr.v2.cmd)
+ switch (cmd)
{
case 0x01: /* PROXY command */
switch (hdr.v2.fam)
@@ -772,8 +787,7 @@ if (ret >= 16 &&
break;
default:
DEBUG(D_receive)
- debug_printf("Unsupported PROXYv2 command: 0x%02x\n",
- hdr.v2.cmd);
+ debug_printf("Unsupported PROXYv2 command: 0x%x\n", cmd);
goto proxyfail;
}
}
diff --git a/src/src/string.c b/src/src/string.c
index 914390255..0f657dcca 100644
--- a/src/src/string.c
+++ b/src/src/string.c
@@ -304,7 +304,7 @@ if (nonprintcount == 0) return s;
/* Get a new block of store guaranteed big enough to hold the
expanded string. */
-ss = store_get(length + nonprintcount * 4 + 1);
+ss = store_get(length + nonprintcount * 3 + 1);
/* Copy everying, escaping non printers. */
diff --git a/src/util/proxy_protocol_client.pl b/src/util/proxy_protocol_client.pl
index 7cfc13ddc..feae3ca90 100644
--- a/src/util/proxy_protocol_client.pl
+++ b/src/util/proxy_protocol_client.pl
@@ -82,10 +82,10 @@ sub generate_preamble {
if (!$opts{version} || $opts{version} == 2) {
@preamble = (
"\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", # 12 byte v2 header
- "\x02", # declares v2
- "\x01", # connection is proxied
+ "\x21", # top 4 bits declares v2
+ # bottom 4 bits is command
$opts{6} ? "\x21" : "\x11", # inet6/4 and TCP (stream)
- $opts{6} ? "\x24" : "\x0b", # 36 bytes / 12 bytes
+ $opts{6} ? "\x00\x24" : "\x00\x0b", # 36 bytes / 12 bytes
$source_ip,
$dest_ip,
$source_port,