(void *)offsetof(smtp_transport_options_block, hosts_avoid_esmtp) },
{ "hosts_avoid_pipelining", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_avoid_pipelining) },
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
{ "hosts_avoid_tls", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_avoid_tls) },
#endif
(void *)offsetof(smtp_transport_options_block, hosts_max_try) },
{ "hosts_max_try_hardlimit", opt_int,
(void *)offsetof(smtp_transport_options_block, hosts_max_try_hardlimit) },
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
{ "hosts_nopass_tls", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_nopass_tls) },
{ "hosts_noproxy_tls", opt_stringptr,
#endif
{ "hosts_randomize", opt_bool,
(void *)offsetof(smtp_transport_options_block, hosts_randomize) },
-#if defined(SUPPORT_TLS) && !defined(DISABLE_OCSP)
+#if !defined(DISABLE_TLS) && !defined(DISABLE_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
+#ifndef DISABLE_TLS
# ifdef SUPPORT_DANE
{ "hosts_require_dane", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_require_dane) },
(void *)offsetof(smtp_transport_options_block, hosts_try_auth) },
{ "hosts_try_chunking", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_chunking) },
-#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
{ "hosts_try_dane", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_dane) },
#endif
{ "hosts_try_prdr", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_prdr) },
#endif
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
{ "hosts_verify_avoid_tls", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_verify_avoid_tls) },
#endif
{ "socks_proxy", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, socks_proxy) },
#endif
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
{ "tls_certificate", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, tls_certificate) },
{ "tls_crl", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, tls_privatekey) },
{ "tls_require_ciphers", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, tls_require_ciphers) },
+# ifdef EXPERIMENTAL_TLS_RESUME
+ { "tls_resumption_hosts", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tls_resumption_hosts) },
+# endif
{ "tls_sni", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, tls_sni) },
{ "tls_tempfail_tryclear", opt_bool,
.hosts_require_auth = NULL,
.hosts_try_chunking = US"*",
#ifdef SUPPORT_DANE
- .hosts_try_dane = NULL,
+ .hosts_try_dane = US"*",
.hosts_require_dane = NULL,
.dane_require_tls_ciphers = NULL,
#endif
.hosts_pipe_connect = NULL,
#endif
.hosts_avoid_esmtp = NULL,
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
.hosts_nopass_tls = NULL,
- .hosts_noproxy_tls = US"*",
+ .hosts_noproxy_tls = NULL,
#endif
.command_timeout = 5*60,
.connect_timeout = 5*60,
#ifdef SUPPORT_SOCKS
.socks_proxy = NULL,
#endif
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
.tls_certificate = NULL,
.tls_crl = NULL,
.tls_privatekey = NULL,
.tls_verify_certificates = US"system",
.tls_dh_min_bits = EXIM_CLIENT_DH_DEFAULT_MIN_BITS,
.tls_tempfail_tryclear = TRUE,
+# ifdef EXPERIMENTAL_TLS_RESUME
+ .tls_resumption_hosts = NULL,
+# endif
.tls_verify_hosts = NULL,
.tls_try_verify_hosts = US"*",
.tls_verify_cert_hostnames = US"*",
transport_count);
return FALSE;
+ case ECONNREFUSED: /* First-read error on a TFO conn */
+ if (verify_mode) *message = US strerror(*errno_value);
+ return FALSE; /* nonverify, do not set message */
+
case ERRNO_SMTPFORMAT: /* Handle malformed SMTP response */
s = string_printing(buffer);
while (isspace(*s)) s++;
pl, smtp_command, s);
return FALSE;
+ case ERRNO_TLSFAILURE: /* Handle bad first read; can happen with
+ GnuTLS and TLS1.3 */
+ *message = US"bad first read from TLS conn";
+ return TRUE;
+
case ERRNO_FILTER_FAIL: /* Handle a failed filter process error;
can't send QUIT as we mustn't end the DATA. */
*message = string_sprintf("transport filter process failed (%d)%s",
{
open_db dbblock, * dbm_file;
-if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE)))
+if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
{
uschar * ehlo_resp_key = ehlo_cache_key(sx);
dbdata_ehlo_resp er = { .data = sx->ehlo_resp };
open_db dbblock, * dbm_file;
if ( sx->early_pipe_active
- && (dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE)))
+ && (dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
{
uschar * ehlo_resp_key = ehlo_cache_key(sx);
dbfn_delete(dbm_file, ehlo_resp_key);
open_db dbblock;
open_db * dbm_file;
-if (!(dbm_file = dbfn_open(US"misc", O_RDONLY, &dbblock, FALSE)))
+if (!(dbm_file = dbfn_open(US"misc", O_RDONLY, &dbblock, FALSE, TRUE)))
{ DEBUG(D_transport) debug_printf("ehlo-cache: no misc DB\n"); }
else
{
{
DEBUG(D_transport) debug_printf("ehlo-resp record too old\n");
dbfn_close(dbm_file);
- if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE)))
+ if ((dbm_file = dbfn_open(US"misc", O_RDWR, &dbblock, TRUE, TRUE)))
dbfn_delete(dbm_file, ehlo_resp_key);
}
else
Return:
OK all well
+ DEFER error on first read of TLS'd conn
FAIL SMTP error in response
*/
int
{
BOOL pending_BANNER = sx->pending_BANNER;
BOOL pending_EHLO = sx->pending_EHLO;
+int rc = FAIL;
sx->pending_BANNER = FALSE; /* clear early to avoid recursion */
sx->pending_EHLO = FALSE;
if (!smtp_reap_banner(sx))
{
DEBUG(D_transport) debug_printf("bad banner\n");
+ if (tls_out.active.sock >= 0) rc = DEFER;
goto fail;
}
}
if (!smtp_reap_ehlo(sx))
{
DEBUG(D_transport) debug_printf("bad response for EHLO\n");
+ if (tls_out.active.sock >= 0) rc = DEFER;
goto fail;
}
? &sx->ehlo_resp.cleartext_auths : &sx->ehlo_resp.crypted_auths;
peer_offered = ehlo_response(sx->buffer,
- (tls_out.active.sock < 0 ? OPTION_TLS : OPTION_REQUIRETLS)
+ (tls_out.active.sock < 0 ? OPTION_TLS : 0)
| OPTION_CHUNKING | OPTION_PRDR | OPTION_DSN | OPTION_PIPE | OPTION_SIZE
| OPTION_UTF8 | OPTION_EARLY_PIPE
);
fail:
invalidate_ehlo_cache_entry(sx);
(void) smtp_discard_responses(sx, sx->conn_args.ob, *countp);
- return FAIL;
+ return rc;
}
#endif
-2 I/O or other non-response error for RCPT
-3 DATA or MAIL failed - errno and buffer set
-4 banner or EHLO failed (early-pipelining)
+ -5 banner or EHLO failed (early-pipelining, TLS)
*/
static int
int yield = 0;
#ifdef EXPERIMENTAL_PIPE_CONNECT
-if (smtp_reap_early_pipe(sx, &count) != OK)
- return -4;
+int rc;
+if ((rc = smtp_reap_early_pipe(sx, &count)) != OK)
+ return rc == FAIL ? -4 : -5;
#endif
/* Handle the response for a MAIL command. On error, reinstate the original
{
DEBUG(D_transport) debug_printf("bad response for MAIL\n");
Ustrcpy(big_buffer, mail_command); /* Fits, because it came from there! */
+ if (errno == ERRNO_TLSFAILURE)
+ return -5;
if (errno == 0 && sx->buffer[0] != 0)
{
int save_errno = 0;
}
}
+ /* Error on first TLS read */
+
+ else if (errno == ERRNO_TLSFAILURE)
+ return -5;
+
/* Timeout while reading the response */
else if (errno == ETIMEDOUT)
int code;
uschar *msg;
BOOL pass_message;
+
+ if (errno == ERRNO_TLSFAILURE) /* Error on first TLS read */
+ return -5;
+
if (pending_DATA > 0 || (yield & 1) != 0)
{
if (errno == 0 && sx->buffer[0] == '4')
if ( require_auth == OK
|| verify_check_given_host(CUSS &ob->hosts_try_auth, host) == OK)
{
- auth_instance * au;
-
DEBUG(D_transport) debug_printf("scanning authentication mechanisms\n");
fail_reason = US"no common mechanisms were found";
client function. We are limited to supporting up to 16 authenticator
public-names by the number of bits in a short. */
+ auth_instance * au;
uschar bitnum;
int rc;
address_item * addr1;
uschar * if1 = US"";
uschar * helo1 = US"";
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
uschar * tlsc1 = US"";
#endif
uschar * save_sender_address = sender_address;
if (ob->helo_data)
helo1 = expand_string(ob->helo_data);
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (ob->tls_certificate)
tlsc1 = expand_string(ob->tls_certificate);
local_identity = string_sprintf ("%s^%s^%s", if1, helo1, tlsc1);
/* debug_printf("%s: check for 0x%04x\n", __FUNCTION__, checks); */
-#ifdef SUPPORT_TLS
-# ifdef EXPERIMENTAL_REQUIRETLS
-if ( checks & OPTION_REQUIRETLS
- && pcre_exec(regex_REQUIRETLS, NULL, CS buf,bsize, 0, PCRE_EOPT, NULL,0) < 0)
-# endif
- checks &= ~OPTION_REQUIRETLS;
-
+#ifndef DISABLE_TLS
if ( checks & OPTION_TLS
&& pcre_exec(regex_STARTTLS, NULL, CS buf, bsize, 0, PCRE_EOPT, NULL, 0) < 0)
#endif
tc_chunk_last add LAST option to SMTP BDAT command
tc_reap_prev reap response to previous SMTP commands
-Returns: OK or ERROR
+Returns:
+ OK or ERROR
+ DEFER TLS error on first read (EHLO-resp); errno set
*/
static int
case 2: sx->completed_addr = TRUE; /* 5xx (only) => progress made */
case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: /* Timeout on RCPT */
+ case -5: errno = ERRNO_TLSFAILURE;
+ return DEFER;
#ifdef EXPERIMENTAL_PIPE_CONNECT
case -4: /* non-2xx for pipelined banner or EHLO */
#endif
+ case -1: /* Timeout on RCPT */
default: return ERROR; /* I/O error, or any MAIL/DATA error */
}
cmd_count = 1;
int
smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
{
-#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-dns_answer tlsa_dnsa;
-#endif
smtp_transport_options_block * ob = sx->conn_args.tblock->options_block;
BOOL pass_message = FALSE;
uschar * message = NULL;
int yield = OK;
int rc;
+#ifndef DISABLE_TLS
+uschar * tls_errstr;
+#endif
sx->conn_args.ob = ob;
sx->utf8_needed = FALSE;
#endif
sx->dsn_all_lasthop = TRUE;
-#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-sx->dane = FALSE;
+#ifdef SUPPORT_DANE
+sx->conn_args.dane = FALSE;
sx->dane_required =
verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
#endif
tls_out.ourcert = NULL;
tls_out.peercert = NULL;
tls_out.peerdn = NULL;
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+#ifdef USE_OPENSSL
tls_out.sni = NULL;
#endif
tls_out.ocsp = OCSP_NOT_REQ;
+#ifdef EXPERIMENTAL_TLS_RESUME
+tls_out.resumption = 0;
+#endif
/* 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
tls_modify_variables(&tls_out);
-#ifndef SUPPORT_TLS
+#ifdef DISABLE_TLS
if (sx->smtps)
{
set_errno_nohost(sx->addrlist, ERRNO_TLSFAILURE, US"TLS support not available",
smtp_port_for_connect(sx->conn_args.host, sx->port);
-#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
+#ifdef SUPPORT_DANE
/* Do TLSA lookup for DANE */
{
tls_out.dane_verified = FALSE;
if( sx->dane_required
|| verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK
)
- switch (rc = tlsa_lookup(sx->conn_args.host, &tlsa_dnsa, sx->dane_required))
+ switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required))
{
- case OK: sx->dane = TRUE;
+ case OK: sx->conn_args.dane = TRUE;
ob->tls_tempfail_tryclear = FALSE;
break;
case FAIL_FORCED: break;
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
- rc == DEFER ? "DEFER" : "FAIL"),
+ rc_to_string(rc)),
rc, FALSE);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
{
if ((sx->cctx.sock = smtp_connect(&sx->conn_args, NULL)) < 0)
{
- uschar * msg = NULL;
- if (sx->verify)
- {
- msg = US strerror(errno);
- HDEBUG(D_verify) debug_printf("connect: %s\n", msg);
- }
set_errno_nohost(sx->addrlist,
errno == ETIMEDOUT ? ERRNO_CONNECTTIMEOUT : errno,
- sx->verify ? string_sprintf("could not connect: %s", msg)
- : NULL,
+ sx->verify ? US strerror(errno) : NULL,
DEFER, FALSE);
sx->send_quit = FALSE;
return DEFER;
/* Alas; be careful, since this goto is not an error-out, so conceivably
we might set data between here and the target which we assume to exist
and be usable. I can see this coming back to bite us. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (sx->smtps)
{
smtp_peer_options |= OPTION_TLS;
/* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
smtp_peer_options |= sx->peer_offered & OPTION_TLS;
#endif
}
the client not be required to use TLS. If the response is bad, copy the buffer
for error analysis. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if ( smtp_peer_options & OPTION_TLS
&& !suppress_tls
&& verify_check_given_host(CUSS &ob->hosts_avoid_tls, sx->conn_args.host) != OK
else
TLS_NEGOTIATE:
{
- uschar * errstr;
- sx->cctx.tls_ctx = tls_client_start(sx->cctx.sock, sx->conn_args.host,
- sx->addrlist, sx->conn_args.tblock,
-# ifdef SUPPORT_DANE
- sx->dane ? &tlsa_dnsa : NULL,
-# endif
- &tls_out, &errstr);
-
- if (!sx->cctx.tls_ctx)
+ if (!tls_client_start(&sx->cctx, &sx->conn_args, sx->addrlist, &tls_out, &tls_errstr))
{
/* 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
it for this host. */
- DEBUG(D_tls) debug_printf("TLS session fail: %s\n", errstr);
+#ifdef USE_GNUTLS
+ GNUTLS_CONN_FAILED:
+#endif
+ DEBUG(D_tls) debug_printf("TLS session fail: %s\n", tls_errstr);
# ifdef SUPPORT_DANE
- if (sx->dane)
+ if (sx->conn_args.dane)
{
log_write(0, LOG_MAIN,
"DANE attempt failed; TLS connection to %s [%s]: %s",
- sx->conn_args.host->name, sx->conn_args.host->address, errstr);
+ sx->conn_args.host->name, sx->conn_args.host->address, tls_errstr);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
US"dane:fail", US"validation-failure"); /* could do with better detail */
# endif
errno = ERRNO_TLSFAILURE;
- message = string_sprintf("TLS session: %s", errstr);
+ message = string_sprintf("TLS session: %s", tls_errstr);
sx->send_quit = FALSE;
goto TLS_FAILED;
}
#endif
{
if (!smtp_reap_ehlo(sx))
+#ifdef USE_GNUTLS
+ {
+ /* The GnuTLS layer in Exim only spots a server-rejection of a client
+ cert late, under TLS1.3 - which means here; the first time we try to
+ receive crypted data. Treat it as if it was a connect-time failure.
+ See also the early-pipe equivalent... which will be hard; every call
+ to sync_responses will need to check the result.
+ It would be nicer to have GnuTLS check the cert during the handshake.
+ Can it do that, with all the flexibility we need? */
+
+ tls_errstr = US"error on first read";
+ goto GNUTLS_CONN_FAILED;
+ }
+#else
goto RESPONSE_FAILED;
+#endif
smtp_peer_options = 0;
}
}
else if ( sx->smtps
# ifdef SUPPORT_DANE
- || sx->dane
-# endif
-# ifdef EXPERIMENTAL_REQUIRETLS
- || tls_requiretls & REQUIRETLS_MSG
+ || sx->conn_args.dane
# endif
|| verify_check_given_host(CUSS &ob->hosts_require_tls, sx->conn_args.host) == OK
)
{
- errno =
-# ifdef EXPERIMENTAL_REQUIRETLS
- tls_requiretls & REQUIRETLS_MSG ? ERRNO_REQUIRETLS :
-# endif
- ERRNO_TLSREQUIRED;
+ errno = ERRNO_TLSREQUIRED;
message = string_sprintf("a TLS session is required, but %s",
smtp_peer_options & OPTION_TLS
? "an attempt to start TLS failed" : "the server did not offer TLS support");
# if defined(SUPPORT_DANE) && !defined(DISABLE_EVENT)
- if (sx->dane)
+ if (sx->conn_args.dane)
(void) event_raise(sx->conn_args.tblock->event_action, US"dane:fail",
smtp_peer_options & OPTION_TLS
? US"validation-failure" /* could do with better detail */
# endif
goto TLS_FAILED;
}
-#endif /*SUPPORT_TLS*/
+#endif /*DISABLE_TLS*/
/* If TLS is active, we have just started it up and re-done the EHLO command,
so its response needs to be analyzed. If TLS is not active and this is a
we skip this. */
if (continue_hostname == NULL
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
|| tls_out.active.sock >= 0
#endif
)
#ifdef EXPERIMENTAL_PIPE_CONNECT
| (sx->lmtp && ob->lmtp_ignore_quota ? OPTION_IGNQ : 0)
| OPTION_DSN | OPTION_PIPE | OPTION_SIZE
- | OPTION_CHUNKING | OPTION_PRDR | OPTION_UTF8 | OPTION_REQUIRETLS
+ | OPTION_CHUNKING | OPTION_PRDR | OPTION_UTF8
| (tls_out.active.sock >= 0 ? OPTION_EARLY_PIPE : 0) /* not for lmtp */
#else
| OPTION_DSN
| OPTION_PIPE
| (ob->size_addition >= 0 ? OPTION_SIZE : 0)
-# if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
- | (tls_requiretls & REQUIRETLS_MSG ? OPTION_REQUIRETLS : 0)
-# endif
#endif
);
#ifdef EXPERIMENTAL_PIPE_CONNECT
DEBUG(D_transport) debug_printf("%susing DSN\n",
sx->peer_offered & OPTION_DSN ? "" : "not ");
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
- if (sx->peer_offered & OPTION_REQUIRETLS)
- {
- smtp_peer_options |= OPTION_REQUIRETLS;
- DEBUG(D_transport) debug_printf(
- tls_requiretls & REQUIRETLS_MSG
- ? "using REQUIRETLS\n" : "REQUIRETLS offered\n");
- }
-#endif
-
#ifdef EXPERIMENTAL_PIPE_CONNECT
if ( sx->early_pipe_ok
&& !sx->early_pipe_active
}
#endif /*SUPPORT_I18N*/
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
- /*XXX should tls_requiretls actually be per-addr? */
-
-if ( tls_requiretls & REQUIRETLS_MSG
- && !(sx->peer_offered & OPTION_REQUIRETLS)
- )
- {
- sx->setting_up = TRUE;
- errno = ERRNO_REQUIRETLS;
- message = US"REQUIRETLS support is required from the server"
- " but it was not offered";
- DEBUG(D_transport) debug_printf("%s\n", message);
- goto TLS_FAILED;
- }
-#endif
-
return OK;
in message and errno, and setting_up will always be true. Treat as
a temporary error. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
TLS_FAILED:
-# ifdef EXPERIMENTAL_REQUIRETLS
- if (errno == ERRNO_REQUIRETLS)
- code = '5', yield = FAIL;
- /*XXX DSN will be labelled 500; prefer 530 5.7.4 */
- else
-# endif
- code = '4', yield = DEFER;
+ code = '4', yield = DEFER;
goto FAILED;
#endif
if (sx->send_quit)
(void)smtp_write_command(sx, SCMD_FLUSH, "QUIT\r\n");
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (sx->cctx.tls_ctx)
{
tls_close(sx->cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
Ustrcpy(p, " SMTPUTF8"), p += 9;
#endif
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-if (tls_requiretls & REQUIRETLS_MSG)
- Ustrcpy(p, " REQUIRETLS") , p += 11;
-#endif
-
/* check if all addresses have DSN-lasthop flag; do not send RET and ENVID if so */
for (sx->dsn_all_lasthop = TRUE, addr = addrlist, address_count = 0;
addr && address_count < sx->max_rcpt;
#ifdef EXPERIMENTAL_PIPE_CONNECT
case -4: return -1; /* non-2xx for pipelined banner or EHLO */
+ case -5: return -1; /* TLS first-read error */
#endif
}
sx->pending_MAIL = FALSE; /* Dealt with MAIL */
}
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
/*****************************************************
* Proxy TLS connection for another transport process *
******************************************************/
case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
if (!sx.lmtp) sx.completed_addr = TRUE; /* can't tell about progress yet */
- case 0: break; /* No 2xx or 5xx, but no probs */
+ case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: goto END_OFF; /* Timeout on RCPT */
+ case -1: goto END_OFF; /* Timeout on RCPT */
#ifdef EXPERIMENTAL_PIPE_CONNECT
+ case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
#endif
{
case 3: sx.ok = TRUE; /* 2xx & 5xx => OK & progress made */
case 2: sx.completed_addr = TRUE; /* 5xx (only) => progress made */
- break;
+ break;
- case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
+ case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
if (!sx.lmtp) sx.completed_addr = TRUE; /* can't tell about progress yet */
- case 0: break; /* No 2xx or 5xx, but no probs */
+ case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: goto END_OFF; /* Timeout on RCPT */
+ case -1: goto END_OFF; /* Timeout on RCPT */
#ifdef EXPERIMENTAL_PIPE_CONNECT
+ case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
#endif
- default: goto RESPONSE_FAILED; /* I/O error, or any MAIL/DATA error */
+ default: goto RESPONSE_FAILED; /* I/O error, or any MAIL/DATA error */
}
}
if ( sx.first_addr != NULL
|| f.continue_more
|| (
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
( tls_out.active.sock < 0 && !continue_proxy_cipher
|| verify_check_given_host(CUSS &ob->hosts_nopass_tls, host) != OK
)
if (sx.ok)
{
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
int pfd[2];
#endif
int socket_fd = sx.cctx.sock;
transport_pass_socket). If the caller has more ready, just return with
the connection still open. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (tls_out.active.sock >= 0)
if ( f.continue_more
|| verify_check_given_host(CUSS &ob->hosts_noproxy_tls, host) == OK)
just passed the baton to. Fork a child to to do it, and return to
get logging done asap. Which way to place the work makes assumptions
about post-fork prioritisation which may not hold on all platforms. */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if (tls_out.active.sock >= 0)
{
int pid = fork();
END_OFF:
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT);
sx.cctx.tls_ctx = NULL;
#endif
addr->basic_errno = 0;
addr->more_errno = (host->mx >= 0)? 'M' : 'A';
addr->message = NULL;
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
addr->cipher = NULL;
addr->ourcert = NULL;
addr->peercert = NULL;
a host list with hosts_override set, use the host list supplied with the
transport. It is an error for this not to exist. */
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
-if (tls_requiretls & REQUIRETLS_MSG)
- ob->tls_tempfail_tryclear = FALSE; /*XXX surely we should have a local for this
- rather than modifying the transport? */
-#endif
-
if (!hostlist || (ob->hosts_override && ob->hosts))
{
if (!ob->hosts)
{
int rc;
int host_af;
- uschar *rs;
BOOL host_is_expired = FALSE;
BOOL message_defer = FALSE;
BOOL some_deferred = FALSE;
treated separately. */
host_af = Ustrchr(host->address, ':') == NULL ? AF_INET : AF_INET6;
- if ((rs = ob->interface) && *rs)
{
- if (!smtp_get_interface(rs, host_af, addrlist, &interface, tid))
- return FALSE;
- pistring = string_sprintf("%s/%s", pistring, interface);
+ uschar * s = ob->interface;
+ if (s && *s)
+ {
+ if (!smtp_get_interface(s, host_af, addrlist, &interface, tid))
+ return FALSE;
+ pistring = string_sprintf("%s/%s", pistring, interface);
+ }
}
/* The first time round the outer loop, check the status of the host by
session, so the in-clear transmission after those errors, if permitted,
happens inside smtp_deliver().] */
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
if ( rc == DEFER
&& first_addr->basic_errno == ERRNO_TLSFAILURE
&& ob->tls_tempfail_tryclear
deferred_event_raise(first_addr, host);
# endif
}
-#endif /*SUPPORT_TLS*/
+#endif /*DISABLE_TLS*/
}
/* Delivery attempt finished */
- rs = rc == OK ? US"OK"
- : rc == DEFER ? US"DEFER"
- : rc == ERROR ? US"ERROR"
- : US"?";
-
set_process_info("delivering %s: just tried %s [%s]%s for %s%s: result %s",
message_id, host->name, host->address, pistring, addrlist->address,
- addrlist->next ? " (& others)" : "", rs);
+ addrlist->next ? " (& others)" : "", rc_to_string(rc));
/* Release serialization if set up */
int fd = cutthrough.cctx.sock >= 0 ? cutthrough.cctx.sock : 0;
DEBUG(D_transport) debug_printf("no hosts match already-open connection\n");
-#ifdef SUPPORT_TLS
+#ifndef DISABLE_TLS
/* A TLS conn could be open for a cutthrough, but not for a plain continued-
transport */
/*XXX doublecheck that! */