From: Jeremy Harris Date: Sun, 5 Sep 2021 10:32:09 +0000 (+0100) Subject: Fix validation of domain-literals in Message_ID: headers. Bug 2805 X-Git-Tag: exim-4.95~9 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/889894461aa958da4604299acc161c29e2aa603c Fix validation of domain-literals in Message_ID: headers. Bug 2805 --- diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 5fa80401f..463bf6ff6 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -332,6 +332,10 @@ JH/59 DKIM: Fix small-message verification under TLS with chunking. If a incorrrectly treated as part of the message body, causing a verification fail. +JH/60 Bug 2805: Fix logging of domain-literals in Message_ID: headers. They + require looser validation rules than those for 821-level addresses, + which only permit IP addresses. + Exim version 4.94 ----------------- diff --git a/src/src/parse.c b/src/src/parse.c index 58f894199..42f1234be 100644 --- a/src/src/parse.c +++ b/src/src/parse.c @@ -224,16 +224,20 @@ If allow_domain_literals is TRUE, a "domain" may also be an IP address enclosed in []. Make sure the output is set to the null string if there is a syntax error as well as if there is no domain at all. +Optionally, msg_id domain literals ( printable-ascii enclosed in [] ) +are permitted. + Arguments: s current character pointer t where to put the domain + msg_id_literals flag for relaxed domain-literal processing errorptr put error message here on failure (*t will be 0 on exit) Returns: new character pointer */ static const uschar * -read_domain(const uschar *s, uschar *t, uschar **errorptr) +read_domain(const uschar *s, uschar *t, BOOL msg_id_literals, uschar **errorptr) { uschar *tt = t; s = skip_comment(s); @@ -259,7 +263,11 @@ if (*s == '[') t += 5; s += 5; } - while (*s == '.' || *s == ':' || isxdigit(*s)) *t++ = *s++; + + if (msg_id_literals) + while (*s >= 33 && *s <= 90 || *s >= 94 && *s <= 126) *t++ = *s++; + else + while (*s == '.' || *s == ':' || isxdigit(*s)) *t++ = *s++; if (*s == ']') *t++ = *s++; else { @@ -267,7 +275,7 @@ if (*s == '[') *tt = 0; } - if (!allow_domain_literals) + if (!allow_domain_literals && !msg_id_literals) { *errorptr = US"domain literals not allowed"; *tt = 0; @@ -500,7 +508,7 @@ BOOL commas = FALSE; while (*s == '@') { *t++ = '@'; - s = read_domain(s+1, t, errorptr); + s = read_domain(s+1, t, FALSE, errorptr); if (*t == 0) return s; t += Ustrlen((const uschar *)t); if (*s != ',') break; @@ -559,7 +567,7 @@ if (*errorptr == NULL) t += Ustrlen((const uschar *)t); *t++ = *s++; *domainptr = t; - s = read_domain(s, t, errorptr); + s = read_domain(s, t, FALSE, errorptr); } return s; } @@ -649,7 +657,7 @@ if (*s != '@' && *s != '<') { if (*s == 0 || *s == ';') { - if (*t == 0) FAILED(US"empty address"); + if (!*t) FAILED(US"empty address"); endptr = last_comment_position; goto PARSE_SUCCEEDED; /* Bare local part */ } @@ -740,7 +748,7 @@ if (*s == '<') } endptr = s; - if (*errorptr != NULL) goto PARSE_FAILED; + if (*errorptr) goto PARSE_FAILED; while (bracket_count-- > 0) if (*s++ != '>') { *errorptr = s[-1] == 0 @@ -759,14 +767,14 @@ should be the domain. However, for flexibility we allow for a route-address not enclosed in <> as well, which is indicated by an empty first local part preceding '@'. The source routing is, however, ignored. */ -else if (*t == 0) +else if (!*t) { uschar *domainptr = yield; 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 */ s = read_addr_spec(s, t, 0, errorptr, &domainptr); - if (*errorptr != NULL) goto PARSE_FAILED; + if (*errorptr) goto PARSE_FAILED; *domain = domainptr - yield; endptr = last_comment_position; if (*domain == 0) FAILED(US"domain missing in source-routed address"); @@ -779,8 +787,8 @@ else t += Ustrlen((const uschar *)t); *t++ = *s++; *domain = t - yield; - s = read_domain(s, t, errorptr); - if (*t == 0) goto PARSE_FAILED; + s = read_domain(s, t, TRUE, errorptr); + if (!*t) goto PARSE_FAILED; endptr = last_comment_position; } @@ -789,7 +797,7 @@ through for other cases. Endptr may have been moved over whitespace, so move it back past white space if necessary. */ PARSE_SUCCEEDED: -if (*s != 0) +if (*s) { if (f.parse_found_group && *s == ';') { diff --git a/src/src/receive.c b/src/src/receive.c index c2b313c63..5471aa7cb 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1663,7 +1663,6 @@ int process_info_len = Ustrlen(process_info); int error_rc = error_handling == ERRORS_SENDER ? errors_sender_rc : EXIT_FAILURE; int header_size = 256; -int start, end, domain; int id_resolution = 0; int had_zero = 0; int prevlines_length = 0; @@ -4084,6 +4083,8 @@ if ( LOGGING(msg_id) && msgid_header uschar * old_id; BOOL save_allow_domain_literals = allow_domain_literals; allow_domain_literals = TRUE; + int start, end, domain; + old_id = parse_extract_address(Ustrchr(msgid_header->text, ':') + 1, &errmsg, &start, &end, &domain, FALSE); allow_domain_literals = save_allow_domain_literals; diff --git a/test/log/0604 b/test/log/0604 index 36354ac56..3a17c1021 100644 --- a/test/log/0604 +++ b/test/log/0604 @@ -1,10 +1,11 @@ 1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id=original1235@example.com for a@test.ex -1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for b@test.ex -1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id*=E10HmaZ-0005vi-00@myhost.test.ex for c@test.ex -1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id=original1235@example.com for d@test.ex +1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id=original1235@[foobar] for a2@test.ex +1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for b@test.ex +1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id*=E10HmbA-0005vi-00@myhost.test.ex for c@test.ex +1999-03-02 09:44:33 10HmbB-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss id=original1235@example.com for d@test.ex 1999-03-02 09:44:33 10HmaX-0005vi-00 ** a@test.ex: Unrouteable address -1999-03-02 09:44:33 10HmbB-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss for CALLER@myhost.test.ex +1999-03-02 09:44:33 10HmbC-0005vi-00 <= <> R=10HmaX-0005vi-00 U=EXIMUSER P=local S=sss for CALLER@myhost.test.ex 1999-03-02 09:44:33 10HmaX-0005vi-00 Completed -1999-03-02 09:44:33 10HmaY-0005vi-00 ** b@test.ex: Unrouteable address -1999-03-02 09:44:33 10HmbC-0005vi-00 <= <> R=10HmaY-0005vi-00 U=EXIMUSER P=local S=sss id*=E10HmbC-0005vi-00@myhost.test.ex for CALLER@myhost.test.ex +1999-03-02 09:44:33 10HmaY-0005vi-00 ** a2@test.ex: Unrouteable address +1999-03-02 09:44:33 10HmbD-0005vi-00 <= <> R=10HmaY-0005vi-00 U=EXIMUSER P=local S=sss id*=E10HmbD-0005vi-00@myhost.test.ex for CALLER@myhost.test.ex 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed diff --git a/test/scripts/0000-Basic/0604 b/test/scripts/0000-Basic/0604 index 196b9dc0c..9e2e4d16e 100644 --- a/test/scripts/0000-Basic/0604 +++ b/test/scripts/0000-Basic/0604 @@ -6,6 +6,15 @@ From: CALLER@test.ex To: a@test.ex Message-ID: original1235@example.com +body +**** +# +# check for 822-rules for domain-listeral in Message_ID: +exim -DLOG_SELECTOR=+received_recipients -t +From: CALLER@test.ex +To: a2@test.ex +Message-ID: original1235@[foobar] + body **** #