TLS: refactor client-start interface
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 28 Dec 2018 11:52:43 +0000 (11:52 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Tue, 19 Feb 2019 22:42:54 +0000 (22:42 +0000)
doc/doc-txt/ChangeLog
src/src/expand.c
src/src/functions.h
src/src/structs.h
src/src/tls-gnu.c
src/src/tls-openssl.c
src/src/transports/smtp.c
src/src/transports/smtp.h

index 6b60cf0737cf90c1c39c35849d0ce9e24d20a7bd..5a42f0e7cecea42032c3e39238e684585bc0679c 100644 (file)
@@ -32,7 +32,7 @@ JH/07 GnuTLS: Our use of late (post-handshake) certificate verification, under
       TLS connection attempt, so that the normal retry-in-clear can work (if
       suitably configured).
 
       TLS connection attempt, so that the normal retry-in-clear can work (if
       suitably configured).
 
-JB/01 Big 2375: fix expansions of 822 addresses having comments in local-part
+JB/01 Bug 2375: fix expansions of 822 addresses having comments in local-part
       and/or domain.  Found and fixed by Jason Betts.
 
 
       and/or domain.  Found and fixed by Jason Betts.
 
 
index 6e0ba93d6cc8197e07c1999de966f1192a9eeeb3..14d7ce451471a8d734311c565360c16ac437e3bb 100644 (file)
@@ -4934,7 +4934,7 @@ while (*s != 0)
 
     case EITEM_READSOCK:
       {
 
     case EITEM_READSOCK:
       {
-      int fd;
+      client_conn_ctx cctx;
       int timeout = 5;
       int save_ptr = yield->ptr;
       FILE * fp;
       int timeout = 5;
       int save_ptr = yield->ptr;
       FILE * fp;
@@ -4944,7 +4944,6 @@ while (*s != 0)
       host_item host;
       BOOL do_shutdown = TRUE;
       BOOL do_tls = FALSE;     /* Only set under SUPPORT_TLS */
       host_item host;
       BOOL do_shutdown = TRUE;
       BOOL do_tls = FALSE;     /* Only set under SUPPORT_TLS */
-      void * tls_ctx = NULL;   /* ditto                      */
       blob reqstr;
 
       if (expand_forbid & RDO_READSOCK)
       blob reqstr;
 
       if (expand_forbid & RDO_READSOCK)
@@ -5045,11 +5044,11 @@ while (*s != 0)
             }
 
          /*XXX we trust that the request is idempotent.  Hmm. */
             }
 
          /*XXX we trust that the request is idempotent.  Hmm. */
-         fd = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
+         cctx.sock = ip_connectedsocket(SOCK_STREAM, server_name, port, port,
                  timeout, &host, &expand_string_message,
                  do_tls ? NULL : &reqstr);
          callout_address = NULL;
                  timeout, &host, &expand_string_message,
                  do_tls ? NULL : &reqstr);
          callout_address = NULL;
-         if (fd < 0)
+         if (cctx.sock < 0)
            goto SOCK_FAIL;
          if (!do_tls)
            reqstr.len = 0;
            goto SOCK_FAIL;
          if (!do_tls)
            reqstr.len = 0;
@@ -5062,7 +5061,7 @@ while (*s != 0)
          struct sockaddr_un sockun;         /* don't call this "sun" ! */
           int rc;
 
          struct sockaddr_un sockun;         /* don't call this "sun" ! */
           int rc;
 
-          if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+          if ((cctx.sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
             {
             expand_string_message = string_sprintf("failed to create socket: %s",
               strerror(errno));
             {
             expand_string_message = string_sprintf("failed to create socket: %s",
               strerror(errno));
@@ -5076,7 +5075,7 @@ while (*s != 0)
 
           sigalrm_seen = FALSE;
           ALARM(timeout);
 
           sigalrm_seen = FALSE;
           ALARM(timeout);
-          rc = connect(fd, (struct sockaddr *)(&sockun), sizeof(sockun));
+          rc = connect(cctx.sock, (struct sockaddr *)(&sockun), sizeof(sockun));
           ALARM_CLR(0);
           if (sigalrm_seen)
             {
           ALARM_CLR(0);
           if (sigalrm_seen)
             {
@@ -5098,14 +5097,11 @@ while (*s != 0)
 #ifdef SUPPORT_TLS
        if (do_tls)
          {
 #ifdef SUPPORT_TLS
        if (do_tls)
          {
+         smtp_connect_args conn_args = {.host = &host };
          tls_support tls_dummy = {.sni=NULL};
          uschar * errstr;
 
          tls_support tls_dummy = {.sni=NULL};
          uschar * errstr;
 
-         if (!(tls_ctx = tls_client_start(fd, &host, NULL, NULL,
-# ifdef SUPPORT_DANE
-                               NULL,
-# endif
-                               &tls_dummy, &errstr)))
+         if (!tls_client_start(&cctx, &conn_args, NULL, &tls_dummy, &errstr))
            {
            expand_string_message = string_sprintf("TLS connect failed: %s", errstr);
            goto SOCK_FAIL;
            {
            expand_string_message = string_sprintf("TLS connect failed: %s", errstr);
            goto SOCK_FAIL;
@@ -5124,9 +5120,9 @@ while (*s != 0)
             reqstr.data);
           if ( (
 #ifdef SUPPORT_TLS
             reqstr.data);
           if ( (
 #ifdef SUPPORT_TLS
-             tls_ctx ? tls_write(tls_ctx, reqstr.data, reqstr.len, FALSE) :
+             cctx.tls_ctx ? tls_write(cctx.tls_ctx, reqstr.data, reqstr.len, FALSE) :
 #endif
 #endif
-                       write(fd, reqstr.data, reqstr.len)) != reqstr.len)
+                       write(cctx.sock, reqstr.data, reqstr.len)) != reqstr.len)
             {
             expand_string_message = string_sprintf("request write to socket "
               "failed: %s", strerror(errno));
             {
             expand_string_message = string_sprintf("request write to socket "
               "failed: %s", strerror(errno));
@@ -5139,7 +5135,7 @@ while (*s != 0)
         system doesn't have this function, make it conditional. */
 
 #ifdef SHUT_WR
         system doesn't have this function, make it conditional. */
 
 #ifdef SHUT_WR
-       if (!tls_ctx && do_shutdown) shutdown(fd, SHUT_WR);
+       if (!cctx.tls_ctx && do_shutdown) shutdown(cctx.sock, SHUT_WR);
 #endif
 
        if (f.running_in_test_harness) millisleep(100);
 #endif
 
        if (f.running_in_test_harness) millisleep(100);
@@ -5147,22 +5143,22 @@ while (*s != 0)
         /* Now we need to read from the socket, under a timeout. The function
         that reads a file can be used. */
 
         /* Now we need to read from the socket, under a timeout. The function
         that reads a file can be used. */
 
-       if (!tls_ctx)
-         fp = fdopen(fd, "rb");
+       if (!cctx.tls_ctx)
+         fp = fdopen(cctx.sock, "rb");
         sigalrm_seen = FALSE;
         ALARM(timeout);
         yield =
 #ifdef SUPPORT_TLS
         sigalrm_seen = FALSE;
         ALARM(timeout);
         yield =
 #ifdef SUPPORT_TLS
-         tls_ctx ? cat_file_tls(tls_ctx, yield, sub_arg[3]) :
+         cctx.tls_ctx ? cat_file_tls(cctx.tls_ctx, yield, sub_arg[3]) :
 #endif
                    cat_file(fp, yield, sub_arg[3]);
         ALARM_CLR(0);
 
 #ifdef SUPPORT_TLS
 #endif
                    cat_file(fp, yield, sub_arg[3]);
         ALARM_CLR(0);
 
 #ifdef SUPPORT_TLS
-       if (tls_ctx)
+       if (cctx.tls_ctx)
          {
          {
-         tls_close(tls_ctx, TRUE);
-         close(fd);
+         tls_close(cctx.tls_ctx, TRUE);
+         close(cctx.sock);
          }
        else
 #endif
          }
        else
 #endif
index 27981db107aa96ce3b676fbdd45b13d3a5d15a2c..f8c0bbf8a2e4ab8b20c1271e70c33e4d952fefbe 100644 (file)
@@ -44,12 +44,9 @@ extern uschar * tls_cert_fprt_md5(void *);
 extern uschar * tls_cert_fprt_sha1(void *);
 extern uschar * tls_cert_fprt_sha256(void *);
 
 extern uschar * tls_cert_fprt_sha1(void *);
 extern uschar * tls_cert_fprt_sha256(void *);
 
-extern void *  tls_client_start(int, host_item *, address_item *,
-                transport_instance *,
-# ifdef SUPPORT_DANE
-               dns_answer *,
-# endif
-               tls_support *, uschar **);
+extern BOOL    tls_client_start(client_conn_ctx *, smtp_connect_args *,
+                 void *, tls_support *, uschar **);
+
 extern void    tls_close(void *, int);
 extern BOOL    tls_could_read(void);
 extern int     tls_export_cert(uschar *, size_t, void *);
 extern void    tls_close(void *, int);
 extern BOOL    tls_could_read(void);
 extern int     tls_export_cert(uschar *, size_t, void *);
index ac3efa587633c0ef66857713401751265e7dc845..8c229236c7340615d1fd0d835f491dcc096dcfb4 100644 (file)
@@ -800,6 +800,11 @@ typedef struct {
   host_item *           host;
   int                   host_af;
   uschar *              interface;
   host_item *           host;
   int                   host_af;
   uschar *              interface;
+
+#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
+  BOOL dane:1;                 /* connection must do dane */
+  dns_answer           tlsa_dnsa;
+#endif
 } smtp_connect_args;
 
 /* A client-initiated connection. If TLS, the second element is non-NULL */
 } smtp_connect_args;
 
 /* A client-initiated connection. If TLS, the second element is non-NULL */
index 1752bf3d8ecf603b8f2223857e4112a838097b87..44a20adf83a499a5fcdf00d8f4e2344d11886384 100644 (file)
@@ -2324,36 +2324,29 @@ return TRUE;
 /* Called from the smtp transport after STARTTLS has been accepted.
 
 Arguments:
 /* Called from the smtp transport after STARTTLS has been accepted.
 
 Arguments:
-  fd                the fd of the connection
-  host              connected host (for messages and option-tests)
-  addr              the first address (not used)
-  tb                transport (always smtp)
-  tlsa_dnsa        non-NULL, either request or require dane for this host, and
-                   a TLSA record found.  Therefore, dane verify required.
-                   Which implies cert must be requested and supplied, dane
-                   verify must pass, and cert verify irrelevant (incl.
-                   hostnames), and (caller handled) require_tls
-  tlsp             record details of channel configuration
-  errstr           error string pointer
-
-Returns:            Pointer to TLS session context, or NULL on error
+  cctx         connection context
+  conn_args    connection details
+  cookie       datum for randomness (not used)
+  tlsp          record details of channel configuration here; must be non-NULL
+  errstr        error string pointer
+
+Returns:        TRUE for success with TLS session context set in smtp context,
+               FALSE on error
 */
 
 */
 
-void *
-tls_client_start(int fd, host_item *host,
-    address_item *addr ARG_UNUSED,
-    transport_instance * tb,
-#ifdef SUPPORT_DANE
-    dns_answer * tlsa_dnsa,
-#endif
-    tls_support * tlsp, uschar ** errstr)
+BOOL
+tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args,
+  void * cookie ARG_UNUSED,
+  tls_support * tlsp, uschar ** errstr)
 {
 {
-smtp_transport_options_block *ob = tb
+host_item * host = conn_args->host;          /* for msgs and option-tests */
+transport_instance * tb = conn_args->tblock; /* always smtp or NULL */
+smtp_transport_options_block * ob = tb
   ? (smtp_transport_options_block *)tb->options_block
   : &smtp_transport_option_defaults;
 int rc;
 exim_gnutls_state_st * state = NULL;
   ? (smtp_transport_options_block *)tb->options_block
   : &smtp_transport_option_defaults;
 int rc;
 exim_gnutls_state_st * state = NULL;
-uschar *cipher_list = NULL;
+uschar * cipher_list = NULL;
 
 #ifndef DISABLE_OCSP
 BOOL require_ocsp =
 
 #ifndef DISABLE_OCSP
 BOOL require_ocsp =
@@ -2362,15 +2355,20 @@ BOOL request_ocsp = require_ocsp ? TRUE
   : verify_check_given_host(CUSS &ob->hosts_request_ocsp, host) == OK;
 #endif
 
   : verify_check_given_host(CUSS &ob->hosts_request_ocsp, host) == OK;
 #endif
 
-DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", fd);
+DEBUG(D_tls) debug_printf("initialising GnuTLS as a client on fd %d\n", cctx->sock);
 
 #ifdef SUPPORT_DANE
 
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa && ob->dane_require_tls_ciphers)
+/* If dane is flagged, have either request or require dane for this host, and
+a TLSA record found.  Therefore, dane verify required.  Which implies cert must
+be requested and supplied, dane verify must pass, and cert verify irrelevant
+(incl.  hostnames), and (caller handled) require_tls */
+
+if (conn_args->dane && ob->dane_require_tls_ciphers)
   {
   /* not using expand_check_tlsvar because not yet in state */
   if (!expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers",
       &cipher_list, errstr))
   {
   /* not using expand_check_tlsvar because not yet in state */
   if (!expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers",
       &cipher_list, errstr))
-    return NULL;
+    return FALSE;
   cipher_list = cipher_list && *cipher_list
     ? ob->dane_require_tls_ciphers : ob->tls_require_ciphers;
   }
   cipher_list = cipher_list && *cipher_list
     ? ob->dane_require_tls_ciphers : ob->tls_require_ciphers;
   }
@@ -2382,7 +2380,7 @@ if (!cipher_list)
 if (tls_init(host, ob->tls_certificate, ob->tls_privatekey,
     ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl,
     cipher_list, &state, tlsp, errstr) != OK)
 if (tls_init(host, ob->tls_certificate, ob->tls_privatekey,
     ob->tls_sni, ob->tls_verify_certificates, ob->tls_crl,
     cipher_list, &state, tlsp, errstr) != OK)
-  return NULL;
+  return FALSE;
 
   {
   int dh_min_bits = ob->tls_dh_min_bits;
 
   {
   int dh_min_bits = ob->tls_dh_min_bits;
@@ -2406,7 +2404,7 @@ set but both tls_verify_hosts and tls_try_verify_hosts are unset. Check only
 the specified host patterns if one of them is defined */
 
 #ifdef SUPPORT_DANE
 the specified host patterns if one of them is defined */
 
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa && dane_tlsa_load(state, tlsa_dnsa))
+if (conn_args->dane && dane_tlsa_load(state, &conn_args->tlsa_dnsa))
   {
   DEBUG(D_tls)
     debug_printf("TLS: server certificate DANE required.\n");
   {
   DEBUG(D_tls)
     debug_printf("TLS: server certificate DANE required.\n");
@@ -2453,7 +2451,7 @@ if (request_ocsp)
                    NULL, 0, NULL)) != OK)
     {
     tls_error(US"cert-status-req", US gnutls_strerror(rc), state->host, errstr);
                    NULL, 0, NULL)) != OK)
     {
     tls_error(US"cert-status-req", US gnutls_strerror(rc), state->host, errstr);
-    return NULL;
+    return FALSE;
     }
   tlsp->ocsp = OCSP_NOT_RESP;
   }
     }
   tlsp->ocsp = OCSP_NOT_RESP;
   }
@@ -2468,9 +2466,9 @@ if (tb && tb->event_action)
   }
 #endif
 
   }
 #endif
 
-gnutls_transport_set_ptr(state->session, (gnutls_transport_ptr_t)(long) fd);
-state->fd_in = fd;
-state->fd_out = fd;
+gnutls_transport_set_ptr(state->session, (gnutls_transport_ptr_t)(long) cctx->sock);
+state->fd_in = cctx->sock;
+state->fd_out = cctx->sock;
 
 DEBUG(D_tls) debug_printf("about to gnutls_handshake\n");
 /* There doesn't seem to be a built-in timeout on connection. */
 
 DEBUG(D_tls) debug_printf("about to gnutls_handshake\n");
 /* There doesn't seem to be a built-in timeout on connection. */
@@ -2491,7 +2489,7 @@ if (rc != GNUTLS_E_SUCCESS)
     }
   else
     tls_error(US"gnutls_handshake", US gnutls_strerror(rc), state->host, errstr);
     }
   else
     tls_error(US"gnutls_handshake", US gnutls_strerror(rc), state->host, errstr);
-  return NULL;
+  return FALSE;
   }
 
 DEBUG(D_tls)
   }
 
 DEBUG(D_tls)
@@ -2518,7 +2516,7 @@ DEBUG(D_tls)
 if (!verify_certificate(state, errstr))
   {
   tls_error(US"certificate verification failed", *errstr, state->host, errstr);
 if (!verify_certificate(state, errstr))
   {
   tls_error(US"certificate verification failed", *errstr, state->host, errstr);
-  return NULL;
+  return FALSE;
   }
 
 #ifndef DISABLE_OCSP
   }
 
 #ifndef DISABLE_OCSP
@@ -2546,7 +2544,7 @@ if (require_ocsp)
     {
     tlsp->ocsp = OCSP_FAILED;
     tls_error(US"certificate status check failed", NULL, state->host, errstr);
     {
     tlsp->ocsp = OCSP_FAILED;
     tls_error(US"certificate status check failed", NULL, state->host, errstr);
-    return NULL;
+    return FALSE;
     }
   DEBUG(D_tls) debug_printf("Passed OCSP checking\n");
   tlsp->ocsp = OCSP_VFIED;
     }
   DEBUG(D_tls) debug_printf("Passed OCSP checking\n");
   tlsp->ocsp = OCSP_VFIED;
@@ -2556,13 +2554,14 @@ if (require_ocsp)
 /* Figure out peer DN, and if authenticated, etc. */
 
 if (peer_status(state, errstr) != OK)
 /* Figure out peer DN, and if authenticated, etc. */
 
 if (peer_status(state, errstr) != OK)
-  return NULL;
+  return FALSE;
 
 /* Sets various Exim expansion variables; may need to adjust for ACL callouts */
 
 extract_exim_vars_from_tls_state(state);
 
 
 /* Sets various Exim expansion variables; may need to adjust for ACL callouts */
 
 extract_exim_vars_from_tls_state(state);
 
-return state;
+cctx->tls_ctx = state;
+return TRUE;
 }
 
 
 }
 
 
index ba9e7da11b1e06d738187751ca17bef75cc929dd..306877f22f039c0d83ccb555826f71afa368b309 100644 (file)
@@ -2490,33 +2490,30 @@ return DEFER;
 
 /* Called from the smtp transport after STARTTLS has been accepted.
 
 
 /* Called from the smtp transport after STARTTLS has been accepted.
 
-Argument:
-  fd               the fd of the connection
-  host             connected host (for messages and option-tests)
-  addr             the first address (for some randomness; can be NULL)
-  tb               transport (always smtp)
-  tlsa_dnsa        tlsa lookup, if DANE, else null
-  tlsp            record details of channel configuration here; must be non-NULL
-  errstr          error string pointer
-
-Returns:           Pointer to TLS session context, or NULL on error
+Arguments:
+  cctx         connection context
+  conn_args    connection details
+  cookie       datum for randomness; can be NULL
+  tlsp         record details of TLS channel configuration here; must be non-NULL
+  errstr       error string pointer
+
+Returns:       TRUE for success with TLS session context set in connection context,
+               FALSE on error
 */
 
 */
 
-void *
-tls_client_start(int fd, host_item *host, address_item *addr,
-  transport_instance * tb,
-#ifdef SUPPORT_DANE
-  dns_answer * tlsa_dnsa,
-#endif
-  tls_support * tlsp, uschar ** errstr)
+BOOL
+tls_client_start(client_conn_ctx * cctx, smtp_connect_args * conn_args,
+  void * cookie, tls_support * tlsp, uschar ** errstr)
 {
 {
+host_item * host = conn_args->host;            /* for msgs and option-tests */
+transport_instance * tb = conn_args->tblock;   /* always smtp or NULL */
 smtp_transport_options_block * ob = tb
   ? (smtp_transport_options_block *)tb->options_block
   : &smtp_transport_option_defaults;
 exim_openssl_client_tls_ctx * exim_client_ctx;
 smtp_transport_options_block * ob = tb
   ? (smtp_transport_options_block *)tb->options_block
   : &smtp_transport_option_defaults;
 exim_openssl_client_tls_ctx * exim_client_ctx;
-static uschar peerdn[256];
 uschar * expciphers;
 int rc;
 uschar * expciphers;
 int rc;
+static uschar peerdn[256];
 
 #ifndef DISABLE_OCSP
 BOOL request_ocsp = FALSE;
 
 #ifndef DISABLE_OCSP
 BOOL request_ocsp = FALSE;
@@ -2535,7 +2532,7 @@ tlsp->tlsa_usage = 0;
 #ifndef DISABLE_OCSP
   {
 # ifdef SUPPORT_DANE
 #ifndef DISABLE_OCSP
   {
 # ifdef SUPPORT_DANE
-  if (  tlsa_dnsa
+  if (  conn_args->dane
      && ob->hosts_request_ocsp[0] == '*'
      && ob->hosts_request_ocsp[1] == '\0'
      )
      && ob->hosts_request_ocsp[0] == '*'
      && ob->hosts_request_ocsp[1] == '\0'
      )
@@ -2565,22 +2562,22 @@ rc = tls_init(&exim_client_ctx->ctx, host, NULL,
 #ifndef DISABLE_OCSP
     (void *)(long)request_ocsp,
 #endif
 #ifndef DISABLE_OCSP
     (void *)(long)request_ocsp,
 #endif
-    addr, &client_static_cbinfo, errstr);
-if (rc != OK) return NULL;
+    cookie, &client_static_cbinfo, errstr);
+if (rc != OK) return FALSE;
 
 tlsp->certificate_verified = FALSE;
 client_verify_callback_called = FALSE;
 
 expciphers = NULL;
 #ifdef SUPPORT_DANE
 
 tlsp->certificate_verified = FALSE;
 client_verify_callback_called = FALSE;
 
 expciphers = NULL;
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa)
+if (conn_args->dane)
   {
   /* We fall back to tls_require_ciphers if unset, empty or forced failure, but
   other failures should be treated as problems. */
   if (ob->dane_require_tls_ciphers &&
       !expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers",
         &expciphers, errstr))
   {
   /* We fall back to tls_require_ciphers if unset, empty or forced failure, but
   other failures should be treated as problems. */
   if (ob->dane_require_tls_ciphers &&
       !expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers",
         &expciphers, errstr))
-    return NULL;
+    return FALSE;
   if (expciphers && *expciphers == '\0')
     expciphers = NULL;
   }
   if (expciphers && *expciphers == '\0')
     expciphers = NULL;
   }
@@ -2588,7 +2585,7 @@ if (tlsa_dnsa)
 if (!expciphers &&
     !expand_check(ob->tls_require_ciphers, US"tls_require_ciphers",
       &expciphers, errstr))
 if (!expciphers &&
     !expand_check(ob->tls_require_ciphers, US"tls_require_ciphers",
       &expciphers, errstr))
-  return NULL;
+  return FALSE;
 
 /* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they
 are separated by underscores. So that I can use either form in my tests, and
 
 /* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they
 are separated by underscores. So that I can use either form in my tests, and
@@ -2602,12 +2599,12 @@ if (expciphers)
   if (!SSL_CTX_set_cipher_list(exim_client_ctx->ctx, CS expciphers))
     {
     tls_error(US"SSL_CTX_set_cipher_list", host, NULL, errstr);
   if (!SSL_CTX_set_cipher_list(exim_client_ctx->ctx, CS expciphers))
     {
     tls_error(US"SSL_CTX_set_cipher_list", host, NULL, errstr);
-    return NULL;
+    return FALSE;
     }
   }
 
 #ifdef SUPPORT_DANE
     }
   }
 
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa)
+if (conn_args->dane)
   {
   SSL_CTX_set_verify(exim_client_ctx->ctx,
     SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
   {
   SSL_CTX_set_verify(exim_client_ctx->ctx,
     SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
@@ -2616,12 +2613,12 @@ if (tlsa_dnsa)
   if (!DANESSL_library_init())
     {
     tls_error(US"library init", host, NULL, errstr);
   if (!DANESSL_library_init())
     {
     tls_error(US"library init", host, NULL, errstr);
-    return NULL;
+    return FALSE;
     }
   if (DANESSL_CTX_init(exim_client_ctx->ctx) <= 0)
     {
     tls_error(US"context init", host, NULL, errstr);
     }
   if (DANESSL_CTX_init(exim_client_ctx->ctx) <= 0)
     {
     tls_error(US"context init", host, NULL, errstr);
-    return NULL;
+    return FALSE;
     }
   }
 else
     }
   }
 else
@@ -2630,21 +2627,21 @@ else
 
   if (tls_client_basic_ctx_init(exim_client_ctx->ctx, host, ob,
        client_static_cbinfo, errstr) != OK)
 
   if (tls_client_basic_ctx_init(exim_client_ctx->ctx, host, ob,
        client_static_cbinfo, errstr) != OK)
-    return NULL;
+    return FALSE;
 
 if (!(exim_client_ctx->ssl = SSL_new(exim_client_ctx->ctx)))
   {
   tls_error(US"SSL_new", host, NULL, errstr);
 
 if (!(exim_client_ctx->ssl = SSL_new(exim_client_ctx->ctx)))
   {
   tls_error(US"SSL_new", host, NULL, errstr);
-  return NULL;
+  return FALSE;
   }
 SSL_set_session_id_context(exim_client_ctx->ssl, sid_ctx, Ustrlen(sid_ctx));
   }
 SSL_set_session_id_context(exim_client_ctx->ssl, sid_ctx, Ustrlen(sid_ctx));
-SSL_set_fd(exim_client_ctx->ssl, fd);
+SSL_set_fd(exim_client_ctx->ssl, cctx->sock);
 SSL_set_connect_state(exim_client_ctx->ssl);
 
 if (ob->tls_sni)
   {
   if (!expand_check(ob->tls_sni, US"tls_sni", &tlsp->sni, errstr))
 SSL_set_connect_state(exim_client_ctx->ssl);
 
 if (ob->tls_sni)
   {
   if (!expand_check(ob->tls_sni, US"tls_sni", &tlsp->sni, errstr))
-    return NULL;
+    return FALSE;
   if (!tlsp->sni)
     {
     DEBUG(D_tls) debug_printf("Setting TLS SNI forced to fail, not sending\n");
   if (!tlsp->sni)
     {
     DEBUG(D_tls) debug_printf("Setting TLS SNI forced to fail, not sending\n");
@@ -2664,9 +2661,9 @@ if (ob->tls_sni)
   }
 
 #ifdef SUPPORT_DANE
   }
 
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa)
-  if (dane_tlsa_load(exim_client_ctx->ssl, host, tlsa_dnsa, errstr) != OK)
-    return NULL;
+if (conn_args->dane)
+  if (dane_tlsa_load(exim_client_ctx->ssl, host, &conn_args->tlsa_dnsa, errstr) != OK)
+    return FALSE;
 #endif
 
 #ifndef DISABLE_OCSP
 #endif
 
 #ifndef DISABLE_OCSP
@@ -2710,14 +2707,14 @@ rc = SSL_connect(exim_client_ctx->ssl);
 ALARM_CLR(0);
 
 #ifdef SUPPORT_DANE
 ALARM_CLR(0);
 
 #ifdef SUPPORT_DANE
-if (tlsa_dnsa)
+if (conn_args->dane)
   DANESSL_cleanup(exim_client_ctx->ssl);
 #endif
 
 if (rc <= 0)
   {
   tls_error(US"SSL_connect", host, sigalrm_seen ? US"timed out" : NULL, errstr);
   DANESSL_cleanup(exim_client_ctx->ssl);
 #endif
 
 if (rc <= 0)
   {
   tls_error(US"SSL_connect", host, sigalrm_seen ? US"timed out" : NULL, errstr);
-  return NULL;
+  return FALSE;
   }
 
 DEBUG(D_tls)
   }
 
 DEBUG(D_tls)
@@ -2747,9 +2744,10 @@ tlsp->cipher_stdname = cipher_stdname_ssl(exim_client_ctx->ssl);
   tlsp->ourcert = crt ? X509_dup(crt) : NULL;
   }
 
   tlsp->ourcert = crt ? X509_dup(crt) : NULL;
   }
 
-tlsp->active.sock = fd;
+tlsp->active.sock = cctx->sock;
 tlsp->active.tls_ctx = exim_client_ctx;
 tlsp->active.tls_ctx = exim_client_ctx;
-return exim_client_ctx;
+cctx->tls_ctx = exim_client_ctx;
+return TRUE;
 }
 
 
 }
 
 
index 6ff993d571f51dd6bdb9d768b9db5080bd279e1c..5fd278e1d334865e3cbd06684cbbabff56453fe0 100644 (file)
@@ -1949,9 +1949,6 @@ Returns:          OK    - the connection was made and the delivery attempted;
 int
 smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
 {
 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;
 smtp_transport_options_block * ob = sx->conn_args.tblock->options_block;
 BOOL pass_message = FALSE;
 uschar * message = NULL;
@@ -1976,7 +1973,7 @@ sx->utf8_needed = FALSE;
 #endif
 sx->dsn_all_lasthop = TRUE;
 #if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
 #endif
 sx->dsn_all_lasthop = TRUE;
 #if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-sx->dane = FALSE;
+sx->conn_args.dane = FALSE;
 sx->dane_required =
   verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
 #endif
 sx->dane_required =
   verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
 #endif
@@ -2067,9 +2064,9 @@ if (!continue_hostname)
       if(  sx->dane_required
        || verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK
        )
       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;
                                ob->tls_tempfail_tryclear = FALSE;
                                break;
          case FAIL_FORCED:     break;
@@ -2500,14 +2497,7 @@ if (  smtp_peer_options & OPTION_TLS
   else
   TLS_NEGOTIATE:
     {
   else
   TLS_NEGOTIATE:
     {
-    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, &tls_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
       {
       /* 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
@@ -2516,7 +2506,7 @@ GNUTLS_CONN_FAILED:
       DEBUG(D_tls) debug_printf("TLS session fail: %s\n", tls_errstr);
 
 # ifdef SUPPORT_DANE
       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",
         {
        log_write(0, LOG_MAIN,
          "DANE attempt failed; TLS connection to %s [%s]: %s",
@@ -2652,7 +2642,7 @@ have one. */
 
 else if (  sx->smtps
 # ifdef SUPPORT_DANE
 
 else if (  sx->smtps
 # ifdef SUPPORT_DANE
-       || sx->dane
+       || sx->conn_args.dane
 # endif
 # ifdef EXPERIMENTAL_REQUIRETLS
        || tls_requiretls & REQUIRETLS_MSG
 # endif
 # ifdef EXPERIMENTAL_REQUIRETLS
        || tls_requiretls & REQUIRETLS_MSG
@@ -2669,7 +2659,7 @@ else if (  sx->smtps
     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)
     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 */
     (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 */
index 57f87a296c7e5be663f6c89adf6cc30e537b0bae..056efbcf7cf084c41d41cdc1aeecb2b9eeaca75d 100644 (file)
@@ -133,7 +133,6 @@ typedef struct {
 #endif
   BOOL dsn_all_lasthop:1;
 #if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
 #endif
   BOOL dsn_all_lasthop:1;
 #if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-  BOOL dane:1;
   BOOL dane_required:1;
 #endif
 #ifdef EXPERIMENTAL_PIPE_CONNECT
   BOOL dane_required:1;
 #endif
 #ifdef EXPERIMENTAL_PIPE_CONNECT