X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/71c158466dab1d452d450843e8c204a42200b7a8..13c7874e0a41d696ecf55774d62ea7d11778414f:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index b95913c59..aac47aa5a 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -163,13 +163,13 @@ optionlist smtp_transport_options[] = { { "serialize_hosts", opt_stringptr, (void *)offsetof(smtp_transport_options_block, serialize_hosts) }, { "size_addition", opt_int, - (void *)offsetof(smtp_transport_options_block, size_addition) } + (void *)offsetof(smtp_transport_options_block, size_addition) }, #ifdef SUPPORT_SOCKS - ,{ "socks_proxy", opt_stringptr, - (void *)offsetof(smtp_transport_options_block, socks_proxy) } + { "socks_proxy", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, socks_proxy) }, #endif #ifdef SUPPORT_TLS - ,{ "tls_certificate", opt_stringptr, + { "tls_certificate", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_certificate) }, { "tls_crl", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_crl) }, @@ -795,8 +795,9 @@ responses before returning, except after I/O errors and timeouts. */ if (sx->pending_MAIL) { + DEBUG(D_transport) debug_printf("%s expect mail\n", __FUNCTION__); count--; - if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), + if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', ob->command_timeout)) { DEBUG(D_transport) debug_printf("bad response for MAIL\n"); @@ -812,7 +813,7 @@ if (sx->pending_MAIL) } while (count-- > 0) { - if (!smtp_read_response(&sx->inblock, flushbuffer, sizeof(flushbuffer), + if (!smtp_read_response(sx, flushbuffer, sizeof(flushbuffer), '2', ob->command_timeout) && (errno != 0 || flushbuffer[0] == 0)) break; @@ -846,7 +847,8 @@ while (count-- > 0) /* The address was accepted */ addr->host_used = sx->host; - if (smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), + DEBUG(D_transport) debug_printf("%s expect rcpt\n", __FUNCTION__); + if (smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', ob->command_timeout)) { yield |= 1; @@ -963,25 +965,28 @@ if (addr) sx->sync_addr = addr->next; /* Handle a response to DATA. If we have not had any good recipients, either previously or in this block, the response is ignored. */ -if (pending_DATA != 0 && - !smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), - '3', ob->command_timeout)) +if (pending_DATA != 0) { - int code; - uschar *msg; - BOOL pass_message; - if (pending_DATA > 0 || (yield & 1) != 0) + DEBUG(D_transport) debug_printf("%s expect data\n", __FUNCTION__); + if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), + '3', ob->command_timeout)) { - if (errno == 0 && sx->buffer[0] == '4') + int code; + uschar *msg; + BOOL pass_message; + if (pending_DATA > 0 || (yield & 1) != 0) { - errno = ERRNO_DATA4XX; - sx->first_addr->more_errno |= ((sx->buffer[1] - '0')*10 + sx->buffer[2] - '0') << 8; + if (errno == 0 && sx->buffer[0] == '4') + { + errno = ERRNO_DATA4XX; + sx->first_addr->more_errno |= ((sx->buffer[1] - '0')*10 + sx->buffer[2] - '0') << 8; + } + return -3; } - return -3; + (void)check_response(sx->host, &errno, 0, sx->buffer, &code, &msg, &pass_message); + DEBUG(D_transport) debug_printf("%s\nerror for DATA ignored: pipelining " + "is in use and there were no good recipients\n", msg); } - (void)check_response(sx->host, &errno, 0, sx->buffer, &code, &msg, &pass_message); - DEBUG(D_transport) debug_printf("%s\nerror for DATA ignored: pipelining " - "is in use and there were no good recipients\n", msg); } /* All responses read and handled; MAIL (if present) received 2xx and DATA (if @@ -996,11 +1001,8 @@ return yield; /* Do the client side of smtp-level authentication */ /* Arguments: + sx smtp connection buffer EHLO response from server (gets overwritten) - addrlist chain of potential addresses to deliver - host host to deliver to - ob transport options - ibp, obp comms channel control blocks Returns: OK Success, or failed (but not required): global "smtp_authenticated" set @@ -1011,23 +1013,22 @@ Returns: FAIL - response */ -int -smtp_auth(uschar *buffer, unsigned bufsize, address_item *addrlist, host_item *host, - smtp_transport_options_block *ob, BOOL is_esmtp, - smtp_inblock *ibp, smtp_outblock *obp) +static int +smtp_auth(smtp_context * sx, uschar * buffer, unsigned bufsize) { +smtp_transport_options_block * ob = sx->ob; int require_auth; uschar *fail_reason = US"server did not advertise AUTH support"; -smtp_authenticated = FALSE; +f.smtp_authenticated = FALSE; client_authenticator = client_authenticated_id = client_authenticated_sender = NULL; -require_auth = verify_check_given_host(&ob->hosts_require_auth, host); +require_auth = verify_check_given_host(&ob->hosts_require_auth, sx->host); -if (is_esmtp && !regex_AUTH) regex_AUTH = +if (sx->esmtp && !regex_AUTH) regex_AUTH = regex_must_compile(US"\\n250[\\s\\-]AUTH\\s+([\\-\\w\\s]+)(?:\\n|$)", FALSE, TRUE); -if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) +if (sx->esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) { uschar *names = string_copyn(expand_nstring[1], expand_nlength[1]); expand_nmax = -1; /* reset */ @@ -1036,7 +1037,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) regex match above. */ if (require_auth == OK || - verify_check_given_host(&ob->hosts_try_auth, host) == OK) + verify_check_given_host(&ob->hosts_try_auth, sx->host) == OK) { auth_instance *au; fail_reason = US"no common mechanisms were found"; @@ -1049,7 +1050,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) If one is found, attempt to authenticate by calling its client function. */ - for (au = auths; !smtp_authenticated && au; au = au->next) + for (au = auths; !f.smtp_authenticated && au; au = au->next) { uschar *p = names; if (!au->client || @@ -1084,10 +1085,10 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) that reflections don't show it. */ fail_reason = US"authentication attempt(s) failed"; - obp->authenticating = TRUE; - rc = (au->info->clientcode)(au, ibp, obp, + sx->outblock.authenticating = TRUE; + rc = (au->info->clientcode)(au, sx, ob->command_timeout, buffer, bufsize); - obp->authenticating = FALSE; + sx->outblock.authenticating = FALSE; DEBUG(D_transport) debug_printf("%s authenticator yielded %d\n", au->name, rc); @@ -1099,7 +1100,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) switch(rc) { case OK: - smtp_authenticated = TRUE; /* stops the outer loop */ + f.smtp_authenticated = TRUE; /* stops the outer loop */ client_authenticator = au->name; if (au->set_client_id != NULL) client_authenticated_id = expand_string(au->set_client_id); @@ -1115,7 +1116,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) case FAIL: if (errno != 0 || buffer[0] != '5') return FAIL; log_write(0, LOG_MAIN, "%s authenticator failed H=%s [%s] %s", - au->name, host->name, host->address, buffer); + au->name, sx->host->name, sx->host->address, buffer); break; /* Failure by some other means. In effect, the authenticator @@ -1127,14 +1128,14 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) case CANCELLED: if (*buffer != 0) log_write(0, LOG_MAIN, "%s authenticator cancelled " - "authentication H=%s [%s] %s", au->name, host->name, - host->address, buffer); + "authentication H=%s [%s] %s", au->name, sx->host->name, + sx->host->address, buffer); break; /* Internal problem, message in buffer. */ case ERROR: - set_errno_nohost(addrlist, ERRNO_AUTHPROB, string_copy(buffer), + set_errno_nohost(sx->addrlist, ERRNO_AUTHPROB, string_copy(buffer), DEFER, FALSE); return ERROR; } @@ -1147,9 +1148,9 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1)) /* If we haven't authenticated, but are required to, give up. */ -if (require_auth == OK && !smtp_authenticated) +if (require_auth == OK && !f.smtp_authenticated) { - set_errno_nohost(addrlist, ERRNO_AUTHFAIL, + set_errno_nohost(sx->addrlist, ERRNO_AUTHFAIL, string_sprintf("authentication required but %s", fail_reason), DEFER, FALSE); return DEFER; @@ -1166,7 +1167,7 @@ Arguments addrlist chain of potential addresses to deliver ob transport options -Globals smtp_authenticated +Globals f.smtp_authenticated client_authenticated_sender Return True on error, otherwise buffer has (possibly empty) terminated string */ @@ -1178,7 +1179,7 @@ smtp_mail_auth_str(uschar *buffer, unsigned bufsize, address_item *addrlist, uschar *local_authenticated_sender = authenticated_sender; #ifdef notdef - debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, smtp_authenticated?"Y":"N"); + debug_printf("smtp_mail_auth_str: as<%s> os<%s> SA<%s>\n", authenticated_sender, ob->authenticated_sender, f.smtp_authenticated?"Y":"N"); #endif if (ob->authenticated_sender != NULL) @@ -1186,7 +1187,7 @@ if (ob->authenticated_sender != NULL) uschar *new = expand_string(ob->authenticated_sender); if (new == NULL) { - if (!expand_string_forcedfail) + if (!f.expand_string_forcedfail) { uschar *message = string_sprintf("failed to expand " "authenticated_sender: %s", expand_string_message); @@ -1199,7 +1200,7 @@ if (ob->authenticated_sender != NULL) /* Add the authenticated sender address if present */ -if ((smtp_authenticated || ob->authenticated_sender_force) && +if ((f.smtp_authenticated || ob->authenticated_sender_force) && local_authenticated_sender != NULL) { string_format(buffer, bufsize, " AUTH=%s", @@ -1246,7 +1247,29 @@ switch (rc) return DEFER; /* just defer this TLS'd conn */ case DNS_SUCCEED: - if (sec) return OK; + if (sec) + { + DEBUG(D_transport) + { + dns_scan dnss; + dns_record * rr; + for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == T_TLSA) + { + uint16_t payload_length = rr->size - 3; + uschar s[MAX_TLSA_EXPANDED_SIZE], * sp = s, * p = US rr->data; + + sp += sprintf(CS sp, "%d ", *p++); /* usage */ + sp += sprintf(CS sp, "%d ", *p++); /* selector */ + sp += sprintf(CS sp, "%d ", *p++); /* matchtype */ + while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4)) + sp += sprintf(CS sp, "%02x", *p++); + + debug_printf(" %s\n", s); + } + } + return OK; + } log_write(0, LOG_MAIN, "DANE error: TLSA lookup for %s not DNSSEC", host->name); /*FALLTRHOUGH*/ @@ -1431,7 +1454,7 @@ there may be more writes (like, the chunk data) done soon. */ if (chunk_size > 0) { - if((cmd_count = smtp_write_command(&sx->outblock, + if((cmd_count = smtp_write_command(sx, flags & tc_reap_prev ? SCMD_FLUSH : SCMD_MORE, "BDAT %u%s\r\n", chunk_size, flags & tc_chunk_last ? " LAST" : "") ) < 0) return ERROR; @@ -1474,7 +1497,7 @@ if (sx->pending_BDAT) { DEBUG(D_transport) debug_printf("look for one response for BDAT\n"); - if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2', + if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', ob->command_timeout)) { if (errno == 0 && sx->buffer[0] == '4') @@ -1724,7 +1747,7 @@ if (!continue_hostname) #ifdef TCP_QUICKACK (void) setsockopt(sx->cctx.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off)); #endif - good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), + good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', sx->ob->command_timeout); #ifdef EXPERIMENTAL_DSN_INFO sx->smtp_greeting = string_copy(sx->buffer); @@ -1814,11 +1837,11 @@ goto SEND_QUIT; if (sx->esmtp) { - if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "%s %s\r\n", + if (smtp_write_command(sx, SCMD_FLUSH, "%s %s\r\n", sx->lmtp ? "LHLO" : "EHLO", sx->helo_data) < 0) goto SEND_FAILED; sx->esmtp_sent = TRUE; - if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2', + if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', sx->ob->command_timeout)) { if (errno != 0 || sx->buffer[0] == 0 || sx->lmtp) @@ -1847,10 +1870,9 @@ goto SEND_QUIT; if (sx->esmtp_sent && (n = Ustrlen(sx->buffer)) < sizeof(sx->buffer)/2) { rsp = sx->buffer + n + 1; n = sizeof(sx->buffer) - n; } - if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "HELO %s\r\n", sx->helo_data) < 0) + if (smtp_write_command(sx, SCMD_FLUSH, "HELO %s\r\n", sx->helo_data) < 0) goto SEND_FAILED; - good_response = smtp_read_response(&sx->inblock, rsp, n, - '2', sx->ob->command_timeout); + good_response = smtp_read_response(sx, rsp, n, '2', sx->ob->command_timeout); #ifdef EXPERIMENTAL_DSN_INFO sx->helo_response = string_copy(rsp); #endif @@ -1925,7 +1947,7 @@ else ) { sx->peer_offered = smtp_peer_options; - pipelining_active = !!(smtp_peer_options & OPTION_PIPE); + sx->pipelining_used = pipelining_active = !!(smtp_peer_options & OPTION_PIPE); HDEBUG(D_transport) debug_printf("continued connection, %s TLS\n", continue_proxy_cipher ? "proxied" : "verify conn with"); return OK; @@ -1950,7 +1972,7 @@ if ( smtp_peer_options & OPTION_TLS ) ) { uschar buffer2[4096]; - if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "STARTTLS\r\n") < 0) + if (smtp_write_command(sx, SCMD_FLUSH, "STARTTLS\r\n") < 0) goto SEND_FAILED; /* If there is an I/O error, transmission of this message is deferred. If @@ -1960,7 +1982,7 @@ if ( smtp_peer_options & OPTION_TLS STARTTLS, we carry on. This means we will try to send the message in clear, unless the host is in hosts_require_tls (tested below). */ - if (!smtp_read_response(&sx->inblock, buffer2, sizeof(buffer2), '2', + if (!smtp_read_response(sx, buffer2, sizeof(buffer2), '2', sx->ob->command_timeout)) { if ( errno != 0 @@ -2055,7 +2077,7 @@ if (tls_out.active.sock >= 0) /* For SMTPS we need to wait for the initial OK response. */ if (sx->smtps) { - good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), + good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', sx->ob->command_timeout); #ifdef EXPERIMENTAL_DSN_INFO sx->smtp_greeting = string_copy(sx->buffer); @@ -2072,10 +2094,10 @@ if (tls_out.active.sock >= 0) debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n"); } - if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "%s %s\r\n", + if (smtp_write_command(sx, SCMD_FLUSH, "%s %s\r\n", sx->lmtp ? "LHLO" : greeting_cmd, sx->helo_data) < 0) goto SEND_FAILED; - good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), + good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', sx->ob->command_timeout); #ifdef EXPERIMENTAL_DSN_INFO sx->helo_response = string_copy(sx->buffer); @@ -2204,8 +2226,7 @@ if (continue_hostname == NULL the business. The host name and address must be available when the authenticator's client driver is running. */ - switch (yield = smtp_auth(sx->buffer, sizeof(sx->buffer), sx->addrlist, sx->host, - sx->ob, sx->esmtp, &sx->inblock, &sx->outblock)) + switch (yield = smtp_auth(sx, sx->buffer, sizeof(sx->buffer))) { default: goto SEND_QUIT; case OK: break; @@ -2214,7 +2235,7 @@ if (continue_hostname == NULL } } } -pipelining_active = !!(smtp_peer_options & OPTION_PIPE); +sx->pipelining_used = pipelining_active = !!(smtp_peer_options & OPTION_PIPE); /* The setting up of the SMTP call is now complete. Any subsequent errors are message-specific. */ @@ -2368,7 +2389,7 @@ FAILED: SEND_QUIT: if (sx->send_quit) - (void)smtp_write_command(&sx->outblock, SCMD_FLUSH, "QUIT\r\n"); + (void)smtp_write_command(sx, SCMD_FLUSH, "QUIT\r\n"); #ifdef SUPPORT_TLS if (sx->cctx.tls_ctx) @@ -2606,7 +2627,7 @@ sx->pending_MAIL = TRUE; /* The block starts with MAIL */ } #endif - rc = smtp_write_command(&sx->outblock, pipelining_active ? SCMD_BUFFER : SCMD_FLUSH, + rc = smtp_write_command(sx, pipelining_active ? SCMD_BUFFER : SCMD_FLUSH, "MAIL FROM:<%s>%s\r\n", s, sx->buffer); } @@ -2618,7 +2639,7 @@ switch(rc) return -5; case +1: /* Cmd was sent */ - if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2', + if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2', sx->ob->command_timeout)) { if (errno == 0 && sx->buffer[0] == '4') @@ -2657,7 +2678,7 @@ for (addr = sx->first_addr, address_count = 0; BOOL no_flush; uschar * rcpt_addr; - if (tcp_out_fastopen && !tcp_out_fastopen_logged) + if (tcp_out_fastopen && !f.tcp_out_fastopen_logged) { setflag(addr, af_tcp_fastopen_conn); if (tcp_out_fastopen > 1) setflag(addr, af_tcp_fastopen); @@ -2690,7 +2711,7 @@ for (addr = sx->first_addr, address_count = 0; } #endif - count = smtp_write_command(&sx->outblock, no_flush ? SCMD_BUFFER : SCMD_FLUSH, + count = smtp_write_command(sx, no_flush ? SCMD_BUFFER : SCMD_FLUSH, "RCPT TO:<%s>%s%s\r\n", rcpt_addr, sx->igquotstr, sx->buffer); if (count < 0) return -5; @@ -2716,7 +2737,7 @@ for (addr = sx->first_addr, address_count = 0; } } /* Loop for next address */ -tcp_out_fastopen_logged = TRUE; +f.tcp_out_fastopen_logged = TRUE; sx->next_addr = addr; return 0; } @@ -2756,7 +2777,7 @@ if ((rc = fork())) _exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } -if (running_in_test_harness) millisleep(100); /* let parent debug out */ +if (f.running_in_test_harness) millisleep(100); /* let parent debug out */ set_process_info("proxying TLS connection for continued transport"); FD_ZERO(&rfds); FD_SET(tls_out.active.sock, &rfds); @@ -2830,7 +2851,7 @@ for (fd_bits = 3; fd_bits; ) } done: - if (running_in_test_harness) millisleep(100); /* let logging complete */ + if (f.running_in_test_harness) millisleep(100); /* let logging complete */ exim_exit(0, US"TLS proxy"); } #endif @@ -3028,7 +3049,7 @@ to send is. */ if ( !(sx.peer_offered & OPTION_CHUNKING) && (sx.ok || (pipelining_active && !mua_wrapper))) { - int count = smtp_write_command(&sx.outblock, SCMD_FLUSH, "DATA\r\n"); + int count = smtp_write_command(&sx, SCMD_FLUSH, "DATA\r\n"); if (count < 0) goto SEND_FAILED; switch(sync_responses(&sx, count, sx.ok ? +1 : -1)) @@ -3122,7 +3143,7 @@ else { if (!(sx.ob->dkim.arc_signspec = s = expand_string(s))) { - if (!expand_string_forcedfail) + if (!f.expand_string_forcedfail) { message = US"failed to expand arc_sign"; sx.ok = FALSE; @@ -3191,7 +3212,7 @@ else * with per non-PRDR. */ if(sx.prdr_active) { - sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '3', + sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '3', sx.ob->final_timeout); if (!sx.ok && errno == 0) switch(sx.buffer[0]) { @@ -3212,7 +3233,7 @@ else if (!sx.lmtp) { - sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2', + sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', sx.ob->final_timeout); if (!sx.ok && errno == 0 && sx.buffer[0] == '4') { @@ -3276,7 +3297,7 @@ else if (sx.lmtp) #endif { - if (!smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2', + if (!smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', sx.ob->final_timeout)) { if (errno != 0 || sx.buffer[0] == 0) goto RESPONSE_FAILED; @@ -3320,6 +3341,8 @@ else addr->host_used = host; addr->special_action = flag; addr->message = conf; + + if (sx.pipelining_used) setflag(addr, af_pipelining); #ifndef DISABLE_PRDR if (sx.prdr_active) setflag(addr, af_prdr_used); #endif @@ -3356,7 +3379,7 @@ else /* PRDR - get the final, overall response. For any non-success upgrade all the address statuses. */ - sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2', + sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', sx.ob->final_timeout); if (!sx.ok) { @@ -3564,7 +3587,7 @@ hosts_nopass_tls. */ DEBUG(D_transport) debug_printf("ok=%d send_quit=%d send_rset=%d continue_more=%d " "yield=%d first_address is %sNULL\n", sx.ok, sx.send_quit, - sx.send_rset, continue_more, yield, sx.first_addr ? "not " : ""); + sx.send_rset, f.continue_more, yield, sx.first_addr ? "not " : ""); if (sx.completed_addr && sx.ok && sx.send_quit) { @@ -3575,7 +3598,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit) t_compare.current_sender_address = sender_address; if ( sx.first_addr != NULL - || continue_more + || f.continue_more || ( #ifdef SUPPORT_TLS ( tls_out.active.sock < 0 && !continue_proxy_cipher @@ -3592,13 +3615,13 @@ if (sx.completed_addr && sx.ok && sx.send_quit) BOOL pass_message; if (sx.send_rset) - if (! (sx.ok = smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0)) + if (! (sx.ok = smtp_write_command(&sx, SCMD_FLUSH, "RSET\r\n") >= 0)) { msg = US string_sprintf("send() to %s [%s] failed: %s", host->name, host->address, strerror(errno)); sx.send_quit = FALSE; } - else if (! (sx.ok = smtp_read_response(&sx.inblock, sx.buffer, + else if (! (sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', sx.ob->command_timeout))) { int code; @@ -3615,7 +3638,9 @@ if (sx.completed_addr && sx.ok && sx.send_quit) if (sx.ok) { +#ifdef SUPPORT_TLS int pfd[2]; +#endif int socket_fd = sx.cctx.sock; @@ -3632,7 +3657,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit) #ifdef SUPPORT_TLS if (tls_out.active.sock >= 0) - if ( continue_more + if ( f.continue_more || verify_check_given_host(&sx.ob->hosts_noproxy_tls, host) == OK) { /* Before passing the socket on, or returning to caller with it still @@ -3645,12 +3670,12 @@ if (sx.completed_addr && sx.ok && sx.send_quit) sx.cctx.tls_ctx = NULL; smtp_peer_options = smtp_peer_options_wrap; sx.ok = !sx.smtps - && smtp_write_command(&sx.outblock, SCMD_FLUSH, - "EHLO %s\r\n", sx.helo_data) >= 0 - && smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), + && smtp_write_command(&sx, SCMD_FLUSH, "EHLO %s\r\n", sx.helo_data) + >= 0 + && smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', sx.ob->command_timeout); - if (sx.ok && continue_more) + if (sx.ok && f.continue_more) return yield; /* More addresses for another run */ } else @@ -3670,7 +3695,7 @@ if (sx.completed_addr && sx.ok && sx.send_quit) } else #endif - if (continue_more) + if (f.continue_more) return yield; /* More addresses for another run */ /* If the socket is successfully passed, we mustn't send QUIT (or @@ -3695,7 +3720,7 @@ propagate it from the initial int pid = fork(); if (pid == 0) /* child; fork again to disconnect totally */ { - if (running_in_test_harness) millisleep(100); /* let parent debug out */ + if (f.running_in_test_harness) millisleep(100); /* let parent debug out */ /* does not return */ smtp_proxy_tls(sx.cctx.tls_ctx, sx.buffer, sizeof(sx.buffer), pfd, sx.ob->command_timeout); @@ -3750,7 +3775,7 @@ This change is being made on 31-Jul-98. After over a year of trouble-free operation, the old commented-out code was removed on 17-Sep-99. */ SEND_QUIT: -if (sx.send_quit) (void)smtp_write_command(&sx.outblock, SCMD_FLUSH, "QUIT\r\n"); +if (sx.send_quit) (void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n"); END_OFF: @@ -3814,8 +3839,7 @@ smtp_transport_closedown(transport_instance *tblock) smtp_transport_options_block *ob = (smtp_transport_options_block *)tblock->options_block; client_conn_ctx cctx; -smtp_inblock inblock; -smtp_outblock outblock; +smtp_context sx; uschar buffer[256]; uschar inbuffer[4096]; uschar outbuffer[16]; @@ -3824,22 +3848,21 @@ uschar outbuffer[16]; cctx.sock = fileno(stdin); cctx.tls_ctx = cctx.sock == tls_out.active.sock ? tls_out.active.tls_ctx : NULL; -inblock.cctx = &cctx; -inblock.buffer = inbuffer; -inblock.buffersize = sizeof(inbuffer); -inblock.ptr = inbuffer; -inblock.ptrend = inbuffer; - -outblock.cctx = &cctx; -outblock.buffersize = sizeof(outbuffer); -outblock.buffer = outbuffer; -outblock.ptr = outbuffer; -outblock.cmd_count = 0; -outblock.authenticating = FALSE; - -(void)smtp_write_command(&outblock, SCMD_FLUSH, "QUIT\r\n"); -(void)smtp_read_response(&inblock, buffer, sizeof(buffer), '2', - ob->command_timeout); +sx.inblock.cctx = &cctx; +sx.inblock.buffer = inbuffer; +sx.inblock.buffersize = sizeof(inbuffer); +sx.inblock.ptr = inbuffer; +sx.inblock.ptrend = inbuffer; + +sx.outblock.cctx = &cctx; +sx.outblock.buffersize = sizeof(outbuffer); +sx.outblock.buffer = outbuffer; +sx.outblock.ptr = outbuffer; +sx.outblock.cmd_count = 0; +sx.outblock.authenticating = FALSE; + +(void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n"); +(void)smtp_read_response(&sx, buffer, sizeof(buffer), '2', ob->command_timeout); (void)close(cctx.sock); } @@ -3993,7 +4016,7 @@ if (!hostlist || (ob->hosts_override && ob->hosts)) { addrlist->message = string_sprintf("failed to expand list of hosts " "\"%s\" in %s transport: %s", s, tblock->name, expand_string_message); - addrlist->transport_return = search_find_defer ? DEFER : PANIC; + addrlist->transport_return = f.search_find_defer ? DEFER : PANIC; return FALSE; /* Only top address has status */ } DEBUG(D_transport) debug_printf("expanded list of hosts \"%s\" to " @@ -4281,7 +4304,7 @@ retry_non_continued: were not in it. We don't want to hold up all SMTP deliveries! Except when doing a two-stage queue run, don't do this if forcing. */ - if ((!deliver_force || queue_2stage) && (queue_smtp || + if ((!f.deliver_force || f.queue_2stage) && (f.queue_smtp || match_isinlist(addrlist->domain, (const uschar **)&queue_smtp_domains, 0, &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK)) @@ -4445,7 +4468,7 @@ retry_non_continued: /* This is not for real; don't do the delivery. If there are any remaining hosts, list them. */ - if (dont_deliver) + if (f.dont_deliver) { host_item *host2; set_errno_nohost(addrlist, 0, NULL, OK, FALSE); @@ -4816,7 +4839,7 @@ for (addr = addrlist; addr; addr = addr->next) setflag(addr, af_retry_skipped); } - if (queue_smtp) /* no deliveries attempted */ + if (f.queue_smtp) /* no deliveries attempted */ { addr->transport_return = DEFER; addr->basic_errno = 0;