From c46782effbf7f5ecde21a8d29cb22b42fda0fe8e Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Thu, 2 Mar 2006 12:25:48 +0000 Subject: [PATCH] Implemented control=allow_auth_unadvertised. --- doc/doc-misc/WishList | 9 +-- doc/doc-txt/ChangeLog | 5 +- doc/doc-txt/NewStuff | 15 +++- src/src/acl.c | 114 +++++++++++++++++++------------ src/src/globals.c | 3 +- src/src/globals.h | 3 +- src/src/smtp_in.c | 21 +++--- test/confs/3400 | 6 ++ test/scripts/3400-plaintext/3400 | 18 ++++- test/stderr/3400 | 35 ++++++++++ test/stdout/3400 | 15 ++++ 11 files changed, 180 insertions(+), 64 deletions(-) diff --git a/doc/doc-misc/WishList b/doc/doc-misc/WishList index 55aa19d9d..23a597d8a 100644 --- a/doc/doc-misc/WishList +++ b/doc/doc-misc/WishList @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-misc/WishList,v 1.61 2006/03/02 11:24:25 ph10 Exp $ +$Cambridge: exim/doc/doc-misc/WishList,v 1.62 2006/03/02 12:25:48 ph10 Exp $ EXIM 4 WISH LIST ---------------- @@ -1997,13 +1997,6 @@ code, because of caching. Probably means we have to invent ewildlsearch and enwildlsearch. ------------------------------------------------------------------------------ -(348) 17-Nov-05 S Option to allow AUTH when not advertised. - -It seems that there are clients that send AUTH when it hasn't been advertised, -some even after HELO, not even EHLO. Sigh. Possibly this should be an ACL -control, to enable it to be restricted to certain hosts. ------------------------------------------------------------------------------- - (350) 28-Feb-06 S Additional errors for retry rules (i) Unexpected connection close; (ii) mail_4xx. diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 71e3e5e7e..6266ed56b 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.320 2006/03/01 16:07:16 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.321 2006/03/02 12:25:48 ph10 Exp $ Change log file for Exim from version 4.21 ------------------------------------------- @@ -272,6 +272,9 @@ PH/53 This is related to PH/52, but is more general: for any failing address, "retry timeout exceeded" was returned. Now it returns the full error as well as "retry timeout exceeded". +PH/54 Added control=allow_auth_unadvertised, as it seems there are clients that + do this, and (what is worse) MTAs that accept it. + Exim version 4.60 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index e8792c3fc..06c676050 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -1,4 +1,4 @@ -$Cambridge: exim/doc/doc-txt/NewStuff,v 1.93 2006/03/01 11:40:51 ph10 Exp $ +$Cambridge: exim/doc/doc-txt/NewStuff,v 1.94 2006/03/02 12:25:48 ph10 Exp $ New Features in Exim -------------------- @@ -105,6 +105,19 @@ PH/15 The smtp transport has a new option called authenticated_sender_force. PH/16 The expansion ${time_eval:} converts an Exim time string such as 2d4h1m into a number of seconds. +PH/17 The ACL modifier control=allow_auth_unadvertised can be used to permit a + client host to use the SMTP AUTH command even when it has not been + advertised in response to EHLO. Furthermore, because there are apparently + some really broken clients that do this, Exim will even accept AUTH after + HELO when this control is set. It should only be used if you really need + it, and you should limit its use to those broken hosts that do not work + without it. For example: + + warn hosts = 192.168.34.25 + control = allow_auth_unadvertised + + This control is permitted only in the connection and HELO ACLs. + Version 4.60 ------------ diff --git a/src/src/acl.c b/src/src/acl.c index 6efc313d1..2a7b5afe8 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.55 2006/02/13 12:02:59 ph10 Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.56 2006/03/02 12:25:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -132,19 +132,29 @@ static uschar *conditions[] = { that follows! */ enum { -#ifdef EXPERIMENTAL_BRIGHTMAIL + CONTROL_AUTH_UNADVERTISED, + #ifdef EXPERIMENTAL_BRIGHTMAIL CONTROL_BMI_RUN, -#endif -#ifdef EXPERIMENTAL_DOMAINKEYS + #endif + #ifdef EXPERIMENTAL_DOMAINKEYS CONTROL_DK_VERIFY, -#endif - CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART, - CONTROL_ENFORCE_SYNC, CONTROL_NO_ENFORCE_SYNC, CONTROL_FREEZE, - CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION, CONTROL_SUPPRESS_LOCAL_FIXUPS, -#ifdef WITH_CONTENT_SCAN + #endif + CONTROL_ERROR, + CONTROL_CASEFUL_LOCAL_PART, + CONTROL_CASELOWER_LOCAL_PART, + CONTROL_ENFORCE_SYNC, + CONTROL_NO_ENFORCE_SYNC, + CONTROL_FREEZE, + CONTROL_QUEUE_ONLY, + CONTROL_SUBMISSION, + CONTROL_SUPPRESS_LOCAL_FIXUPS, + #ifdef WITH_CONTENT_SCAN CONTROL_NO_MBOX_UNSPOOL, -#endif - CONTROL_FAKEDEFER, CONTROL_FAKEREJECT, CONTROL_NO_MULTILINE }; + #endif + CONTROL_FAKEDEFER, + CONTROL_FAKEREJECT, + CONTROL_NO_MULTILINE +}; /* ACL control names; keep in step with the table above! This list is used for turning ids into names. The actual list of recognized names is in the variable @@ -152,20 +162,27 @@ control_def controls_list[] below. The fact that there are two lists is a mess and should be tidied up. */ static uschar *controls[] = { + US"allow_auth_unadvertised", #ifdef EXPERIMENTAL_BRIGHTMAIL US"bmi_run", #endif #ifdef EXPERIMENTAL_DOMAINKEYS US"dk_verify", #endif - US"error", US"caseful_local_part", - US"caselower_local_part", US"enforce_sync", US"no_enforce_sync", US"freeze", - US"queue_only", US"submission", US"suppress_local_fixups", + US"error", + US"caseful_local_part", + US"caselower_local_part", + US"enforce_sync", + US"no_enforce_sync", + US"freeze", + US"queue_only", + US"submission", + US"suppress_local_fixups", #ifdef WITH_CONTENT_SCAN US"no_mbox_unspool", #endif - - US"no_multiline"}; + US"no_multiline" +}; /* Flags to indicate for which conditions /modifiers a string expansion is done at the outer level. In the other cases, expansion already occurs in the @@ -453,12 +470,16 @@ each control, there's a bitmap of dis-allowed times. For some, it is easier to specify the negation of a small number of allowed times. */ static unsigned int control_forbids[] = { -#ifdef EXPERIMENTAL_BRIGHTMAIL + (unsigned int) + ~((1<next) switch(control_type) { -#ifdef EXPERIMENTAL_BRIGHTMAIL + case CONTROL_AUTH_UNADVERTISED: + allow_auth_unadvertised = TRUE; + break; + + #ifdef EXPERIMENTAL_BRIGHTMAIL case CONTROL_BMI_RUN: bmi_run = 1; break; -#endif -#ifdef EXPERIMENTAL_DOMAINKEYS + #endif + + #ifdef EXPERIMENTAL_DOMAINKEYS case CONTROL_DK_VERIFY: dk_do_verify = 1; break; -#endif + #endif + case CONTROL_ERROR: return ERROR; @@ -2459,11 +2487,11 @@ for (; cb != NULL; cb = cb->next) smtp_enforce_sync = FALSE; break; -#ifdef WITH_CONTENT_SCAN + #ifdef WITH_CONTENT_SCAN case CONTROL_NO_MBOX_UNSPOOL: no_mbox_unspool = TRUE; break; -#endif + #endif case CONTROL_NO_MULTILINE: no_multiline_responses = TRUE; diff --git a/src/src/globals.c b/src/src/globals.c index 58b032145..5d898d546 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.51 2006/02/20 16:31:49 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.52 2006/03/02 12:25:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -299,6 +299,7 @@ tree_node *addresslist_anchor = NULL; int addresslist_count = 0; gid_t *admin_groups = NULL; BOOL admin_user = FALSE; +BOOL allow_auth_unadvertised= FALSE; BOOL allow_domain_literals = FALSE; BOOL allow_mx_to_ip = FALSE; BOOL allow_unqualified_recipient = TRUE; /* For local messages */ diff --git a/src/src/globals.h b/src/src/globals.h index c884dfaf2..114f859fb 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.35 2006/02/13 12:02:59 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.36 2006/03/02 12:25:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -143,6 +143,7 @@ extern tree_node *addresslist_anchor; /* Tree of defined address lists */ extern int addresslist_count; /* Number defined */ extern gid_t *admin_groups; /* List of admin groups */ extern BOOL admin_user; /* True if caller can do admin */ +extern BOOL allow_auth_unadvertised;/* As it says */ extern BOOL allow_domain_literals; /* As it says */ extern BOOL allow_mx_to_ip; /* Allow MX records to -> ip address */ extern BOOL allow_unqualified_recipient; /* As it says */ diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index 4ed335c02..9df0f592a 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.33 2006/02/14 14:55:37 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.34 2006/03/02 12:25:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -2147,10 +2147,14 @@ while (done <= 0) switch(smtp_read_command(TRUE)) { /* The AUTH command is not permitted to occur inside a transaction, and may - occur successfully only once per connection, and then only when we've - advertised it. Actually, that isn't quite true. When TLS is started, all - previous information about a connection must be discarded, so a new AUTH is - permitted at that time. + occur successfully only once per connection. Actually, that isn't quite + true. When TLS is started, all previous information about a connection must + be discarded, so a new AUTH is permitted at that time. + + AUTH may only be used when it has been advertised. However, it seems that + there are clients that send AUTH when it hasn't been advertised, some of + them even doing this after HELO. And there are MTAs that accept this. Sigh. + So there's a get-out that allows this to happen. AUTH is initially labelled as a "nonmail command" so that one occurrence doesn't get counted. We change the label here so that multiple failing @@ -2160,7 +2164,7 @@ while (done <= 0) authentication_failed = TRUE; cmd_list[CMD_LIST_AUTH].is_mail_cmd = FALSE; - if (!auth_advertised) + if (!auth_advertised && !allow_auth_unadvertised) { done = synprot_error(L_smtp_protocol_error, 503, NULL, US"AUTH command used when not advertised"); @@ -2215,12 +2219,13 @@ while (done <= 0) } /* Search for an authentication mechanism which is configured for use - as a server and which has been advertised. */ + as a server and which has been advertised (unless, sigh, allow_auth_ + unadvertised is set). */ for (au = auths; au != NULL; au = au->next) { if (strcmpic(s, au->public_name) == 0 && au->server && - au->advertised) break; + (au->advertised || allow_auth_unadvertised)) break; } if (au == NULL) diff --git a/test/confs/3400 b/test/confs/3400 index b84ee56c4..e56756543 100644 --- a/test/confs/3400 +++ b/test/confs/3400 @@ -17,6 +17,7 @@ hostlist auth_hosts = 10.0.0.1 hostlist relay_hosts = 10.0.0.4 hostlist auth_relay_hosts = 10.0.0.3 : 10.0.0.4 +acl_smtp_connect = check_connect acl_smtp_etrn = check_etrn acl_smtp_expn = check_expn acl_smtp_rcpt = check_recipient @@ -32,6 +33,11 @@ trusted_users = CALLER begin acl +check_connect: + warn hosts = 10.0.0.6 + control = allow_auth_unadvertised + accept + check_recipient: warn hosts = 10.0.0.5 message = authentication-failed: $authentication_failed diff --git a/test/scripts/3400-plaintext/3400 b/test/scripts/3400-plaintext/3400 index b547a21b9..164ace593 100644 --- a/test/scripts/3400-plaintext/3400 +++ b/test/scripts/3400-plaintext/3400 @@ -150,9 +150,11 @@ auth expandfail AHVzZXJ4AHNlY3JldA== quit **** +# 10.0.0.2 is not allowed to use AUTH when it is not advertised +# exim -bs -oMa 10.0.0.2 ehlo test.host -auth expandfail +auth explain AHVzZXJ4AHNlY3JldA== quit **** @@ -215,4 +217,18 @@ ehlo testing.testing auth mylogin dXNlcnggc2VjcmV0 quit **** +# 10.0.0.6 is allowed to use AUTH when it is not advertised +# +exim -bs -oMa 10.0.0.6 +ehlo test.host +auth explain +AHVzZXJ4AHNlY3JldA== +quit +**** +exim -bs -oMa 10.0.0.6 +helo test.host +auth explain +AHVzZXJ4AHNlY3JldA== +quit +**** no_msglog_check diff --git a/test/stderr/3400 b/test/stderr/3400 index fb3b9895b..573d3afee 100644 --- a/test/stderr/3400 +++ b/test/stderr/3400 @@ -6,6 +6,13 @@ >>> host in helo_verify_hosts? no (option unset) >>> host in helo_try_verify_hosts? no (option unset) >>> host in helo_accept_junk_hosts? no (option unset) +>>> using ACL "check_connect" +>>> processing "warn" +>>> check hosts = 10.0.0.6 +>>> host in "10.0.0.6"? no (end of list) +>>> warn: condition test failed +>>> processing "accept" +>>> accept: condition test succeeded >>> host in smtp_accept_max_nonmail_hosts? yes (matched "*") >>> using ACL "check_vrfy" >>> processing "deny" @@ -62,6 +69,13 @@ LOG: H=[10.0.0.2] Warning: accepted ETRN #abcd >>> host in helo_verify_hosts? no (option unset) >>> host in helo_try_verify_hosts? no (option unset) >>> host in helo_accept_junk_hosts? no (option unset) +>>> using ACL "check_connect" +>>> processing "warn" +>>> check hosts = 10.0.0.6 +>>> host in "10.0.0.6"? no (end of list) +>>> warn: condition test failed +>>> processing "accept" +>>> accept: condition test succeeded >>> test.host in helo_lookup_domains? no (end of list) >>> host in pipelining_advertise_hosts? yes (matched "*") >>> host in "10.0.0.1"? yes (matched "10.0.0.1") @@ -234,6 +248,13 @@ LOG: H=(test.host) [10.0.0.1] Warning: accepted ETRN #abcd >>> host in helo_verify_hosts? no (option unset) >>> host in helo_try_verify_hosts? no (option unset) >>> host in helo_accept_junk_hosts? no (option unset) +>>> using ACL "check_connect" +>>> processing "warn" +>>> check hosts = 10.0.0.6 +>>> host in "10.0.0.6"? no (end of list) +>>> warn: condition test failed +>>> processing "accept" +>>> accept: condition test succeeded >>> test.host in helo_lookup_domains? no (end of list) >>> host in pipelining_advertise_hosts? yes (matched "*") >>> host in "10.0.0.1"? no (end of list) @@ -318,6 +339,13 @@ LOG: H=(test.host) [10.0.0.3] F= rejected RCPT >> host in helo_verify_hosts? no (option unset) >>> host in helo_try_verify_hosts? no (option unset) >>> host in helo_accept_junk_hosts? no (option unset) +>>> using ACL "check_connect" +>>> processing "warn" +>>> check hosts = 10.0.0.6 +>>> host in "10.0.0.6"? no (end of list) +>>> warn: condition test failed +>>> processing "accept" +>>> accept: condition test succeeded >>> test.host in helo_lookup_domains? no (end of list) >>> host in pipelining_advertise_hosts? yes (matched "*") >>> host in "10.0.0.1"? no (end of list) @@ -348,6 +376,13 @@ host in recipient_unqualified_hosts? no (option unset) host in helo_verify_hosts? no (option unset) host in helo_try_verify_hosts? no (option unset) host in helo_accept_junk_hosts? no (option unset) +using ACL "check_connect" +processing "warn" +check hosts = 10.0.0.6 +host in "10.0.0.6"? no (end of list) +warn: condition test failed +processing "accept" +accept: condition test succeeded SMTP>> 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 smtp_setup_msg entered SMTP<< ehlo testing.testing diff --git a/test/stdout/3400 b/test/stdout/3400 index 7d8e3689a..002166e90 100644 --- a/test/stdout/3400 +++ b/test/stdout/3400 @@ -326,3 +326,18 @@ 250 HELP 235 Authentication succeeded 221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-myhost.test.ex Hello CALLER at test.host [10.0.0.6] +250-SIZE 52428800 +250-ETRN +250-EXPN +250-PIPELINING +250 HELP +334 +235 Authentication succeeded +221 myhost.test.ex closing connection +220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250 myhost.test.ex Hello CALLER at test.host [10.0.0.6] +334 +235 Authentication succeeded +221 myhost.test.ex closing connection -- 2.25.1