Add $tls_in_* variables; note the old names as deprecated.
[exim.git] / src / src / verify.c
index 39ef337871cec9a7ab38afe159663c4ec875cb53..a1b8142a9e75346571e47685374cde0e36078105 100644 (file)
@@ -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
@@ -635,8 +638,7 @@ else
         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,
+        ob->tls_require_ciphers,     ob->tls_dh_min_bits,
         callout);
 
         /* TLS negotiation failed; give an error.  Try in clear on a new connection,
@@ -957,8 +959,9 @@ else
       }
     else
       {
+      /* Ensure no cutthrough on multiple address verifies */
       if (options & vopt_callout_recipsender)
-        cancel_cutthrough_connection();        /* Ensure no cutthrough on multiple address verifies */
+        cancel_cutthrough_connection("multiple verify calls");
       if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");
 
       #ifdef SUPPORT_TLS
@@ -1129,7 +1132,7 @@ cutthrough_puts(uschar * cp, int n)
 {
 if (cutthrough_fd < 0)       return TRUE;
 if (_cutthrough_puts(cp, n)) return TRUE;
-cancel_cutthrough_connection();
+cancel_cutthrough_connection("transmit failed");
 return FALSE;
 }
 
@@ -1151,7 +1154,7 @@ BOOL
 cutthrough_flush_send( void )
 {
 if (_cutthrough_flush_send()) return TRUE;
-cancel_cutthrough_connection();
+cancel_cutthrough_connection("transmit failed");
 return FALSE;
 }
 
@@ -1178,7 +1181,7 @@ inblock.ptrend = inbuffer;
 inblock.sock = cutthrough_fd;
 /* this relies on (inblock.sock == tls_out.active) */
 if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, CUTTHROUGH_DATA_TIMEOUT))
-  cancel_cutthrough_connection();
+  cancel_cutthrough_connection("target timeout on read");
 
 if(copy != NULL)
   {
@@ -1235,7 +1238,7 @@ return cutthrough_put_nl();
 
 
 static void
-close_cutthrough_connection( void )
+close_cutthrough_connection( const char * why )
 {
 if(cutthrough_fd >= 0)
   {
@@ -1254,15 +1257,15 @@ if(cutthrough_fd >= 0)
   #endif
   (void)close(cutthrough_fd);
   cutthrough_fd= -1;
-  HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown ------------\n");
+  HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown (%s) ------------\n", why);
   }
 ctblock.ptr = ctbuffer;
 }
 
 void
-cancel_cutthrough_connection( void )
+cancel_cutthrough_connection( const char * why )
 {
-close_cutthrough_connection();
+close_cutthrough_connection(why);
 cutthrough_delivery= FALSE;
 }
 
@@ -1287,7 +1290,7 @@ switch(cutthrough_response('2', &cutthrough_addr.message))
   {
   case '2':
     delivery_log(LOG_MAIN, &cutthrough_addr, (int)'>', NULL);
-    close_cutthrough_connection();
+    close_cutthrough_connection("delivered");
     break;
 
   case '4':
@@ -1518,6 +1521,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). */
 
@@ -1710,6 +1725,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);
           }
@@ -1761,10 +1779,14 @@ while (addr_new != NULL)
         }
       respond_printf(f, "%s\n", cr);
       }
-    cancel_cutthrough_connection();
+    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 */
@@ -1796,10 +1818,14 @@ while (addr_new != NULL)
         }
       respond_printf(f, "%s\n", cr);
       }
-    cancel_cutthrough_connection();
+    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
@@ -1822,7 +1848,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. */
@@ -1857,7 +1884,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 */
@@ -1874,7 +1902,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++)
@@ -1958,9 +1986,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;
 }