summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTodd Lyons <tlyons@exim.org>2014-05-12 16:15:07 -0700
committerTodd Lyons <tlyons@exim.org>2014-05-13 11:21:51 -0700
commit367193425cbb5a77ee8ada9c5b2a203ca293d823 (patch)
treeaeefd2bae73ce4d997baf6182263b5ef6621c554 /src
parentfabe4dd996dd1e08707c4c33c498d86deaae6edd (diff)
Bug 1394: PPv2 header modifed
The HAProxy dev team adjusted the layout of the 16 byte header to allow it to be used for SSL connections. Had to adjust PPv2 handling code and perl proxy emulation script. Added link to this HAProxy commit in the documentation.
Diffstat (limited to 'src')
-rw-r--r--src/src/smtp_in.c34
-rw-r--r--src/src/string.c2
-rw-r--r--src/util/proxy_protocol_client.pl6
3 files changed, 28 insertions, 14 deletions
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,