X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/2e5b33cdf3591080e44862951f7c2ac9eced16de..abcc8901c087c4eac4b1b88fd6f8d8a97a2ab85b:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index 23eab0598..52404575f 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -407,13 +407,6 @@ else if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush(); - /* Precompile some regex that are used to recognize parameters in response - to an EHLO command, if they aren't already compiled. */ - #ifdef SUPPORT_TLS - if (regex_STARTTLS == NULL) regex_STARTTLS = - regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE); - #endif - /* Now make connections to the hosts and do real callouts. The list of hosts is passed in as an argument. */ @@ -505,7 +498,7 @@ else tls_retry_connection: inblock.sock = outblock.sock = - smtp_connect(host, host_af, port, interface, callout_connect, TRUE); + smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL); /* reconsider DSCP here */ if (inblock.sock < 0) { @@ -570,11 +563,11 @@ else goto SEND_FAILED; if (!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)) { - if (errno != 0 || responsebuffer[0] == 0 || lmtp || !esmtp || tls_out.active >= 0) - { - done= FALSE; - goto RESPONSE_FAILED; - } + if (errno != 0 || responsebuffer[0] == 0 || lmtp || !esmtp || tls_out.active >= 0) + { + done= FALSE; + goto RESPONSE_FAILED; + } #ifdef SUPPORT_TLS tls_offered = FALSE; #endif @@ -584,9 +577,16 @@ else /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */ #ifdef SUPPORT_TLS - tls_offered = esmtp && !suppress_tls && tls_out.active < 0 && - pcre_exec(regex_STARTTLS, NULL, CS responsebuffer, Ustrlen(responsebuffer), 0, - PCRE_EOPT, NULL, 0) >= 0; + if (esmtp && !suppress_tls && tls_out.active < 0) + { + if (regex_STARTTLS == NULL) regex_STARTTLS = + regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE); + + tls_offered = pcre_exec(regex_STARTTLS, NULL, CS responsebuffer, + Ustrlen(responsebuffer), 0, PCRE_EOPT, NULL, 0) >= 0; + } + else + tls_offered = FALSE; #endif } @@ -601,7 +601,10 @@ else #ifdef SUPPORT_TLS if (tls_offered && verify_check_this_host(&(ob->hosts_avoid_tls), NULL, host->name, - host->address, NULL) != OK) + host->address, NULL) != OK && + verify_check_this_host(&(ob->hosts_verify_avoid_tls), NULL, host->name, + host->address, NULL) != OK + ) { uschar buffer2[4096]; if ( !smtps @@ -631,13 +634,14 @@ else else { int rc = tls_client_start(inblock.sock, host, addr, - NULL, /* No DH param */ ob->tls_certificate, ob->tls_privatekey, ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl, ob->tls_require_ciphers, - ob->gnutls_require_mac, ob->gnutls_require_kx, ob->gnutls_require_proto, - callout); +#ifdef EXPERIMENTAL_OCSP + ob->hosts_require_ocsp, +#endif + ob->tls_dh_min_bits, callout); /* TLS negotiation failed; give an error. Try in clear on a new connection, if the options permit it for this host. */ @@ -1519,6 +1523,18 @@ addresses, such rewriting fails. */ if (address[0] == 0) return OK; +/* Flip the legacy TLS-related variables over to the outbound set in case +they're used in the context of a transport used by verification. Reset them +at exit from this routine. */ + +modify_variable(US"tls_bits", &tls_out.bits); +modify_variable(US"tls_certificate_verified", &tls_out.certificate_verified); +modify_variable(US"tls_cipher", &tls_out.cipher); +modify_variable(US"tls_peerdn", &tls_out.peerdn); +#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) +modify_variable(US"tls_sni", &tls_out.sni); +#endif + /* Save a copy of the sender address for re-instating if we change it to <> while verifying a sender address (a nice bit of self-reference there). */ @@ -1711,6 +1727,9 @@ while (addr_new != NULL) } else { +#ifdef SUPPORT_TLS + deliver_set_expansions(addr); +#endif rc = do_callout(addr, host_list, &tf, callout, callout_overall, callout_connect, options, se_mailfrom, pm_mailfrom); } @@ -1764,8 +1783,12 @@ while (addr_new != NULL) } cancel_cutthrough_connection("routing hard fail"); - if (!full_info) return copy_error(vaddr, addr, FAIL); - else yield = FAIL; + if (!full_info) + { + yield = copy_error(vaddr, addr, FAIL); + goto out; + } + else yield = FAIL; } /* Soft failure */ @@ -1799,8 +1822,12 @@ while (addr_new != NULL) } cancel_cutthrough_connection("routing soft fail"); - if (!full_info) return copy_error(vaddr, addr, DEFER); - else if (yield == OK) yield = DEFER; + if (!full_info) + { + yield = copy_error(vaddr, addr, DEFER); + goto out; + } + else if (yield == OK) yield = DEFER; } /* If we are handling EXPN, we do not want to continue to route beyond @@ -1823,7 +1850,8 @@ while (addr_new != NULL) if (addr_new == NULL) ok_prefix = US"250 "; respond_printf(f, "%s<%s>\r\n", ok_prefix, addr2->address); } - return OK; + yield = OK; + goto out; } /* Successful routing other than EXPN. */ @@ -1858,7 +1886,8 @@ while (addr_new != NULL) of $address_data to be that of the child */ vaddr->p.address_data = addr->p.address_data; - return OK; + yield = OK; + goto out; } } } /* Loop for generated addresses */ @@ -1875,7 +1904,7 @@ discarded, usually because of the use of :blackhole: in an alias file. */ if (allok && addr_local == NULL && addr_remote == NULL) { fprintf(f, "mail to %s is discarded\n", address); - return yield; + goto out; } for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++) @@ -1959,9 +1988,19 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++) } } -/* Will be DEFER or FAIL if any one address has, only for full_info (which is +/* Yield will be DEFER or FAIL if any one address has, only for full_info (which is the -bv or -bt case). */ +out: + +modify_variable(US"tls_bits", &tls_in.bits); +modify_variable(US"tls_certificate_verified", &tls_in.certificate_verified); +modify_variable(US"tls_cipher", &tls_in.cipher); +modify_variable(US"tls_peerdn", &tls_in.peerdn); +#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) +modify_variable(US"tls_sni", &tls_in.sni); +#endif + return yield; }