From b6040544759110aa97f93e9ba0dd8232cd5e5188 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 30 Jan 2017 15:37:50 +0000 Subject: [PATCH] Restrict address-parsing to a maximum of five layers of nested angle-brackets, under main-option strip_excess_angle_brackets --- doc/doc-txt/ChangeLog | 4 ++++ src/src/parse.c | 24 ++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index a4c11e58d..bc9b19f19 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -69,6 +69,10 @@ JH/14 Bug 2000: Reject messages recieved with CHUNKING but with malformed line endings, at least on the first header line. Try to canonify any that get past that check, despite the cost. +JH/15 Angle-bracket nesting (an error inserted by broken sendmails) levels are + now limited to an arbitrary five deep, while parsing addresses with the + strip_excess_angle_brackets option enabled. + Exim version 4.88 ----------------- diff --git a/src/src/parse.c b/src/src/parse.c index 3f0823a1e..b2771b5b8 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -661,7 +661,7 @@ if (*s != '@' && *s != '<') while (*s != '<' && (!parse_allow_group || *s != ':')) { s = read_local_part(s, t, errorptr, FALSE); - if (*errorptr != NULL) + if (*errorptr) { *errorptr = string_sprintf("%s (expected word or \"<\")", *errorptr); goto PARSE_FAILED; @@ -686,8 +686,8 @@ processing it. Note that this is "if" rather than "else if" because it's also used after reading a preceding phrase. There are a lot of broken sendmails out there that put additional pairs of <> -round s. If strip_excess_angle_brackets is set, allow any number of -them, as long as they match. */ +round s. If strip_excess_angle_brackets is set, allow a limited +number of them, as long as they match. */ if (*s == '<') { @@ -696,8 +696,11 @@ if (*s == '<') int bracket_count = 1; s++; - if (strip_excess_angle_brackets) - while (*s == '<') { bracket_count++; s++; } + if (strip_excess_angle_brackets) while (*s == '<') + { + if(bracket_count++ > 5) FAILED(US"angle-brackets nested too deep"); + s++; + } t = yield; startptr = s; @@ -711,7 +714,7 @@ if (*s == '<') if (*s == '@') { s = read_route(s, t, errorptr); - if (*errorptr != NULL) goto PARSE_FAILED; + if (*errorptr) goto PARSE_FAILED; *t = 0; /* Ensure route is ignored - probably overkill */ source_routed = TRUE; } @@ -729,7 +732,7 @@ if (*s == '<') else { s = read_addr_spec(s, t, '>', errorptr, &domainptr); - if (*errorptr != NULL) goto PARSE_FAILED; + if (*errorptr) goto PARSE_FAILED; *domain = domainptr - yield; if (source_routed && *domain == 0) FAILED(US"domain missing in source-routed address"); @@ -739,9 +742,10 @@ if (*s == '<') if (*errorptr != NULL) goto PARSE_FAILED; while (bracket_count-- > 0) if (*s++ != '>') { - *errorptr = (s[-1] == 0)? US"'>' missing at end of address" : - string_sprintf("malformed address: %.32s may not follow %.*s", - s-1, s - (uschar *)mailbox - 1, mailbox); + *errorptr = s[-1] == 0 + ? US"'>' missing at end of address" + : string_sprintf("malformed address: %.32s may not follow %.*s", + s-1, s - (uschar *)mailbox - 1, mailbox); goto PARSE_FAILED; } -- 2.30.2