X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/e8793bad207763b266bedcb9d859e238b6a3a04e..e51c7be22dfccad376659a1a46cee93c9979bbf7:/src/src/transports/smtp.c diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c index 938844799..c175d2ffe 100644 --- a/src/src/transports/smtp.c +++ b/src/src/transports/smtp.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2013 */ +/* Copyright (c) University of Cambridge 1995 - 2014 */ /* See the file NOTICE for conditions of use and distribution. */ #include "../exim.h" @@ -55,6 +55,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, dns_qualify_single) }, { "dns_search_parents", opt_bool, (void *)offsetof(smtp_transport_options_block, dns_search_parents) }, + { "dnssec_request_domains", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, dnssec_request_domains) }, + { "dnssec_require_domains", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, dnssec_require_domains) }, { "dscp", opt_stringptr, (void *)offsetof(smtp_transport_options_block, dscp) }, { "fallback_hosts", opt_stringptr, @@ -98,6 +102,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, hosts_override) }, { "hosts_randomize", opt_bool, (void *)offsetof(smtp_transport_options_block, hosts_randomize) }, +#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_OCSP) + { "hosts_request_ocsp", opt_stringptr, + (void *)offsetof(smtp_transport_options_block, hosts_request_ocsp) }, +#endif { "hosts_require_auth", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_require_auth) }, #ifdef SUPPORT_TLS @@ -110,7 +118,7 @@ optionlist smtp_transport_options[] = { #endif { "hosts_try_auth", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_try_auth) }, -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR { "hosts_try_prdr", opt_stringptr, (void *)offsetof(smtp_transport_options_block, hosts_try_prdr) }, #endif @@ -155,6 +163,10 @@ optionlist smtp_transport_options[] = { (void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) }, { "tls_try_verify_hosts", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) }, +#ifdef EXPERIMENTAL_CERTNAMES + { "tls_verify_cert_hostnames", opt_stringptr, + (void *)offsetof(smtp_transport_options_block,tls_verify_cert_hostnames)}, +#endif { "tls_verify_certificates", opt_stringptr, (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }, { "tls_verify_hosts", opt_stringptr, @@ -188,10 +200,11 @@ smtp_transport_options_block smtp_transport_option_defaults = { NULL, /* serialize_hosts */ NULL, /* hosts_try_auth */ NULL, /* hosts_require_auth */ -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR NULL, /* hosts_try_prdr */ #endif #ifdef EXPERIMENTAL_OCSP + US"*", /* hosts_request_ocsp */ NULL, /* hosts_require_ocsp */ #endif NULL, /* hosts_require_tls */ @@ -213,6 +226,8 @@ smtp_transport_options_block smtp_transport_option_defaults = { FALSE, /* gethostbyname */ TRUE, /* dns_qualify_single */ FALSE, /* dns_search_parents */ + NULL, /* dnssec_request_domains */ + NULL, /* dnssec_require_domains */ TRUE, /* delay_after_cutoff */ FALSE, /* hosts_override */ FALSE, /* hosts_randomize */ @@ -234,6 +249,9 @@ smtp_transport_options_block smtp_transport_option_defaults = { TRUE, /* tls_tempfail_tryclear */ NULL, /* tls_verify_hosts */ NULL /* tls_try_verify_hosts */ +# ifdef EXPERIMENTAL_CERTNAMES + ,NULL /* tls_verify_cert_hostnames */ +# endif #endif #ifndef DISABLE_DKIM ,NULL, /* dkim_canon */ @@ -625,7 +643,7 @@ tpda_defer_errstr = addr->message ? string_sprintf("%s: %s", addr->message, strerror(addr->basic_errno)) : string_copy(addr->message) : addr->basic_errno > 0 - ? string_copy(strerror(addr->basic_errno)) + ? string_copy(US strerror(addr->basic_errno)) : NULL; DEBUG(D_transport) @@ -1174,7 +1192,7 @@ BOOL completed_address = FALSE; BOOL esmtp = TRUE; BOOL pending_MAIL; BOOL pass_message = FALSE; -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR BOOL prdr_offered = FALSE; BOOL prdr_active; #endif @@ -1213,25 +1231,27 @@ outblock.authenticating = FALSE; /* Reset the parameters of a TLS session. */ -tls_in.bits = 0; -tls_in.cipher = NULL; /* for back-compatible behaviour */ -tls_in.peerdn = NULL; -#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) -tls_in.sni = NULL; -#endif - tls_out.bits = 0; tls_out.cipher = NULL; /* the one we may use for this transport */ +tls_out.ourcert = NULL; +tls_out.peercert = NULL; tls_out.peerdn = NULL; #if defined(SUPPORT_TLS) && !defined(USE_GNUTLS) tls_out.sni = NULL; #endif +tls_out.ocsp = OCSP_NOT_REQ; + +/* Flip the legacy TLS-related variables over to the outbound set in case +they're used in the context of the transport. Don't bother resetting +afterward as we're in a subprocess. */ + +tls_modify_variables(&tls_out); #ifndef SUPPORT_TLS if (smtps) { - set_errno(addrlist, 0, US"TLS support not available", DEFER, FALSE); - return ERROR; + set_errno(addrlist, 0, US"TLS support not available", DEFER, FALSE); + return ERROR; } #endif @@ -1373,7 +1393,7 @@ goto SEND_QUIT; PCRE_EOPT, NULL, 0) >= 0; #endif - #ifdef EXPERIMENTAL_PRDR + #ifndef DISABLE_PRDR prdr_offered = esmtp && (pcre_exec(regex_PRDR, NULL, CS buffer, Ustrlen(buffer), 0, PCRE_EOPT, NULL, 0) >= 0) && @@ -1439,22 +1459,7 @@ if (tls_offered && !suppress_tls && else TLS_NEGOTIATE: { - int rc = tls_client_start(inblock.sock, - host, - addrlist, - ob->tls_certificate, - ob->tls_privatekey, - ob->tls_sni, - ob->tls_verify_certificates, - ob->tls_crl, - ob->tls_require_ciphers, -#ifdef EXPERIMENTAL_OCSP - ob->hosts_require_ocsp, -#endif - ob->tls_dh_min_bits, - ob->command_timeout, - ob->tls_verify_hosts, - ob->tls_try_verify_hosts); + int rc = tls_client_start(inblock.sock, host, addrlist, ob); /* TLS negotiation failed; give an error. From outside, this function may be called again to try in clear on a new connection, if the options permit @@ -1475,7 +1480,10 @@ if (tls_offered && !suppress_tls && if (addr->transport_return == PENDING_DEFER) { addr->cipher = tls_out.cipher; + addr->ourcert = tls_out.ourcert; + addr->peercert = tls_out.peercert; addr->peerdn = tls_out.peerdn; + addr->ocsp = tls_out.ocsp; } } } @@ -1584,7 +1592,7 @@ if (continue_hostname == NULL DEBUG(D_transport) debug_printf("%susing PIPELINING\n", smtp_use_pipelining? "" : "not "); -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR prdr_offered = esmtp && pcre_exec(regex_PRDR, NULL, CS buffer, Ustrlen(CS buffer), 0, PCRE_EOPT, NULL, 0) >= 0 && @@ -1672,7 +1680,7 @@ if (smtp_use_size) while (*p) p++; } -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR prdr_active = FALSE; if (prdr_offered) { @@ -1908,7 +1916,7 @@ if (!ok) ok = TRUE; else smtp_command = US"end of data"; -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR /* For PRDR we optionally get a partial-responses warning * followed by the individual responses, before going on with * the overall response. If we don't get the warning then deal @@ -2003,7 +2011,7 @@ if (!ok) ok = TRUE; else address. For temporary errors, add a retry item for the address so that it doesn't get tried again too soon. */ -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR if (lmtp || prdr_active) #else if (lmtp) @@ -2014,7 +2022,7 @@ if (!ok) ok = TRUE; else { if (errno != 0 || buffer[0] == 0) goto RESPONSE_FAILED; addr->message = string_sprintf( -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR "%s error after %s: %s", prdr_active ? "PRDR":"LMTP", #else "LMTP error after %s: %s", @@ -2028,7 +2036,7 @@ if (!ok) ok = TRUE; else errno = ERRNO_DATA4XX; addr->more_errno |= ((buffer[1] - '0')*10 + buffer[2] - '0') << 8; addr->transport_return = DEFER; -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR if (!prdr_active) #endif retry_add_item(addr, addr->address_retry_key, 0); @@ -2051,12 +2059,12 @@ if (!ok) ok = TRUE; else addr->host_used = thost; addr->special_action = flag; addr->message = conf; -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR if (prdr_active) addr->flags |= af_prdr_used; #endif flag = '-'; -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR if (!prdr_active) #endif { @@ -2078,7 +2086,7 @@ if (!ok) ok = TRUE; else } } -#ifdef EXPERIMENTAL_PRDR +#ifndef DISABLE_PRDR if (prdr_active) { /* PRDR - get the final, overall response. For any non-success @@ -2412,8 +2420,6 @@ tls_close(FALSE, TRUE); #endif /* Close the socket, and return the appropriate value, first setting -continue_transport and continue_hostname NULL to prevent any other addresses -that may include the host from trying to re-use a continuation socket. This works because the NULL setting is passed back to the calling process, and remote_max_parallel is forced to 1 when delivering over an existing connection, @@ -2514,7 +2520,10 @@ for (addr = addrlist; addr != NULL; addr = addr->next) addr->message = NULL; #ifdef SUPPORT_TLS addr->cipher = NULL; + addr->ourcert = NULL; + addr->peercert = NULL; addr->peerdn = NULL; + addr->ocsp = OCSP_NOT_REQ; #endif } return first_addr; @@ -2817,6 +2826,7 @@ for (cutoff_retry = 0; expired && rc = host_find_byname(host, NULL, flags, &canonical_name, TRUE); else rc = host_find_bydns(host, NULL, flags, NULL, NULL, NULL, + ob->dnssec_request_domains, ob->dnssec_require_domains, &canonical_name, NULL); /* Update the host (and any additional blocks, resulting from @@ -2916,6 +2926,9 @@ for (cutoff_retry = 0; expired && deliver_host = host->name; deliver_host_address = host->address; + lookup_dnssec_authenticated = host->dnssec == DS_YES ? US"yes" + : host->dnssec == DS_NO ? US"no" + : US""; /* Set up a string for adding to the retry key if the port number is not the standard SMTP port. A host may have its own port setting that overrides @@ -3429,4 +3442,6 @@ DEBUG(D_transport) debug_printf("Leaving %s transport\n", tblock->name); return TRUE; /* Each address has its status */ } +/* vi: aw ai sw=2 +*/ /* End of transport/smtp.c */