From: Jeremy Harris Date: Sun, 15 Feb 2015 20:38:26 +0000 (+0000) Subject: Verify callout/random: repoen connection if error after random rcpt attempt. Bug 495 X-Git-Tag: exim-4_86_RC1~111 X-Git-Url: https://git.exim.org/users/jgh/exim.git/commitdiff_plain/65f1c92a5c06bb7de867f8d72c7eef5f829daeb4 Verify callout/random: repoen connection if error after random rcpt attempt. Bug 495 --- diff --git a/src/src/verify.c b/src/src/verify.c index ec75ce5ce..c1fb17767 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -388,12 +388,9 @@ else log the fact, but carry on without randomming. */ if (callout_random && callout_random_local_part != NULL) - { - random_local_part = expand_string(callout_random_local_part); - if (random_local_part == NULL) + if (!(random_local_part = expand_string(callout_random_local_part))) log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand " "callout_random_local_part: %s", expand_string_message); - } /* Default the connect and overall callout timeouts if not set, and record the time we are starting so that we can enforce it. */ @@ -635,14 +632,14 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. outblock.cmd_count = 0; outblock.authenticating = FALSE; - /* Reset the parameters of a TLS session */ - tls_out.cipher = tls_out.peerdn = tls_out.peercert = NULL; - /* Connect to the host; on failure, just loop for the next one, but we set the error for the last one. Use the callout_connect timeout. */ tls_retry_connection: + /* Reset the parameters of a TLS session */ + tls_out.cipher = tls_out.peerdn = tls_out.peercert = NULL; + inblock.sock = outblock.sock = smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL #ifdef EXPERIMENTAL_EVENT @@ -1009,10 +1006,15 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. /* Otherwise, cache a real negative response, and get back to the right state to send RCPT. Unless there's some problem such as a dropped - connection, we expect to succeed, because the commands succeeded above. */ + connection, we expect to succeed, because the commands succeeded above. + However, some servers drop the connection after responding to an + invalid recipient, so on (any) error we drop and remake the connection. + */ else if (errno == 0) { + /* This would be ok for 1st rcpt a cutthrough, but no way to + handle a subsequent. So refuse to support any */ cancel_cutthrough_connection("random-recipient"); if (randombuffer[0] == '5') @@ -1027,6 +1029,22 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. from_address) >= 0 && smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout); + + if (!done) + { + HDEBUG(D_acl|D_v) + debug_printf("problem after random/rset/mfrom; reopen conn\n"); + random_local_part = NULL; +#ifdef SUPPORT_TLS + tls_close(FALSE, TRUE); +#endif + (void)close(inblock.sock); +#ifdef EXPERIMENTAL_EVENT + (void) event_raise(addr->transport->event_action, + US"tcp:close", NULL); +#endif + goto tls_retry_connection; + } } else done = FALSE; /* Some timeout/connection problem */ } /* Random check */ @@ -1060,8 +1078,9 @@ can do it there for the non-rcpt-verify case. For this we keep an addresscount. if (done && pm_mailfrom != NULL) { - /*XXX not suitable for cutthrough - we cannot afford to do an RSET - and lose the original mail-from */ + /* Could possibly shift before main verify, just above, and be ok + for cutthrough. But no way to handle a subsequent rcpt, so just + refuse any */ cancel_cutthrough_connection("postmaster verify"); HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of postmaster verify\n"); diff --git a/test/scripts/0000-Basic/0473 b/test/scripts/0000-Basic/0473 index 3d17e5ed0..df613c4b7 100644 --- a/test/scripts/0000-Basic/0473 +++ b/test/scripts/0000-Basic/0473 @@ -150,6 +150,34 @@ rcpt to: r11@two.test.ex quit **** dump callout +# +# callout target dumps after random-reject +server PORT_S 2 +220 Server ready +EHLO +250 OK +MAIL FROM +250 OK +RCPT TO +550 Bad receipient, dropping conn +>*eof +220 Server ready +EHLO +250 OK +MAIL FROM +250 OK +RCPT TO +250 OK +QUIT +250 OK +**** +exim -DUSE_SENDER=,random -bs +ehlo xxxx +mail from: x12@three.test.ex +rcpt to: r12@three.test.ex +quit +**** +dump callout server PORT_S 220 Server ready EHLO diff --git a/test/stdout/0473 b/test/stdout/0473 index 9fff9a601..59ed36d6a 100644 --- a/test/stdout/0473 +++ b/test/stdout/0473 @@ -107,6 +107,26 @@ 250-PIPELINING 250 HELP 250 OK +250 Accepted +221 the.local.host.name closing connection ++++++++++++++++++++++++++++ +07-Mar-2000 12:21:52 r12@three.test.ex callout=accept +07-Mar-2000 12:21:52 r1@test.ex callout=accept +07-Mar-2000 12:21:52 r1@test.ex/ callout=accept +07-Mar-2000 12:21:52 r1@test.ex/ callout=accept +07-Mar-2000 12:21:52 r1@test.ex/ callout=accept +07-Mar-2000 12:21:52 r9@test.ex/ callout=reject +07-Mar-2000 12:21:52 test.ex callout=accept postmaster=unknown random=unknown +07-Mar-2000 12:21:52 three.test.ex callout=accept postmaster=unknown random=reject (07-Mar-2000 12:21:52) +07-Mar-2000 12:21:52 two.test.ex callout=accept postmaster=unknown random=accept (07-Mar-2000 12:21:52) +07-Mar-2000 12:21:52 x9@test.ex callout=reject +220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 +250-the.local.host.name Hello CALLER at xxxx +250-SIZE 52428800 +250-8BITMIME +250-PIPELINING +250 HELP +250 OK 451 Could not complete recipient verify callout 221 the.local.host.name closing connection 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 @@ -221,6 +241,28 @@ EHLO the.local.host.name 250 OK MAIL FROM:<> 250 OK +RCPT TO: +550 Bad receipient, dropping conn +>*eof +Listening on port 1224 ... +Connection request from [127.0.0.1] +220 Server ready +EHLO the.local.host.name +250 OK +MAIL FROM:<> +250 OK +RCPT TO: +250 OK +QUIT +250 OK +End of script +Listening on port 1224 ... +Connection request from [127.0.0.1] +220 Server ready +EHLO the.local.host.name +250 OK +MAIL FROM:<> +250 OK RCPT TO: *sleep 2 End of script