Test development
[users/heiko/exim.git] / src / src / verify.c
index cd91b0560966474fb71c122dab31ce47926c2456..c2ee4789288620bcee27469cc42497453cd9cfd2 100644 (file)
@@ -373,10 +373,13 @@ if (!addr->transport)
   {
   HDEBUG(D_verify) debug_printf("cannot callout via null transport\n");
   }
+else if (Ustrcmp(addr->transport->driver_name, "smtp") != 0)
+  log_write(0, LOG_MAIN|LOG_PANIC|LOG_CONFIG_FOR, "callout transport '%s': %s is non-smtp",
+    addr->transport->name, addr->transport->driver_name);
 else
   {
   smtp_transport_options_block *ob =
-    (smtp_transport_options_block *)(addr->transport->options_block);
+    (smtp_transport_options_block *)addr->transport->options_block;
 
   /* The information wasn't available in the cache, so we have to do a real
   callout and save the result in the cache for next time, unless no_cache is set,
@@ -521,9 +524,6 @@ else
       else active_hostname = s;
       }
 
-    deliver_host = deliver_host_address = NULL;
-    deliver_domain = save_deliver_domain;
-
     /* Wait for initial response, and send HELO. The smtp_write_command()
     function leaves its command in big_buffer. This is used in error responses.
     Initialize it in case the connection is rejected. */
@@ -633,24 +633,27 @@ else
        /* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
       else
         {
-        int rc = tls_client_start(inblock.sock, host, addr,
-        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, callout,
-         ob->tls_verify_hosts, ob->tls_try_verify_hosts);
+       int oldtimeout = ob->command_timeout;
+       int rc;
+
+       ob->command_timeout = callout;
+        rc = tls_client_start(inblock.sock, host, addr, ob);
+       ob->command_timeout = oldtimeout;
 
         /* TLS negotiation failed; give an error.  Try in clear on a new connection,
            if the options permit it for this host. */
         if (rc != OK)
           {
-       if (rc == DEFER && ob->tls_tempfail_tryclear && !smtps &&
-          verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
-            host->address, NULL) != OK)
+       if (  rc == DEFER
+          && ob->tls_tempfail_tryclear
+          && !smtps
+          && verify_check_this_host(&(ob->hosts_require_tls), NULL,
+            host->name, host->address, NULL) != OK
+#ifdef EXPERIMENTAL_DANE
+          && verify_check_this_host(&(ob->hosts_require_dane), NULL,
+            host->name, host->address, NULL) != OK
+#endif
+          )
          {
             (void)close(inblock.sock);
          log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
@@ -680,8 +683,13 @@ else
 
     /* If the host is required to use a secure channel, ensure that we have one. */
     if (tls_out.active < 0)
-      if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
-       host->address, NULL) == OK)
+      if (  verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
+             host->address, NULL) == OK
+#ifdef EXPERIMENTAL_DANE
+        || verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name,
+             host->address, NULL) == OK
+#endif
+        )
         {
         /*save_errno = ERRNO_TLSREQUIRED;*/
         log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
@@ -721,7 +729,6 @@ else
     ;
     /* Clear down of the TLS, SMTP and TCP layers on error is handled below.  */
 
-
     /* Failure to accept HELO is cached; this blocks the whole domain for all
     senders. I/O errors and defer responses are not cached. */
 
@@ -759,6 +766,9 @@ else
       smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
         '2', callout);
 
+    deliver_host = deliver_host_address = NULL;
+    deliver_domain = save_deliver_domain;
+
     /* If the host does not accept MAIL FROM:<>, arrange to cache this
     information, but again, don't record anything for an I/O error or a defer. Do
     not cache rejections of MAIL when a non-empty sender has been used, because
@@ -976,6 +986,7 @@ else
       {
       cutthrough_fd= outblock.sock;    /* We assume no buffer in use in the outblock */
       cutthrough_addr = *addr;         /* Save the address_item for later logging */
+      cutthrough_addr.next =     NULL;
       cutthrough_addr.host_used = store_get(sizeof(host_item));
       cutthrough_addr.host_used->name =    host->name;
       cutthrough_addr.host_used->address = host->address;
@@ -1244,27 +1255,43 @@ return cutthrough_response('3', NULL) == '3';
 }
 
 
+/* fd and use_crlf args only to match write_chunk() */
+static BOOL
+cutthrough_write_chunk(int fd, uschar * s, int len, BOOL use_crlf)
+{
+uschar * s2;
+while(s && (s2 = Ustrchr(s, '\n')))
+ {
+ if(!cutthrough_puts(s, s2-s) || !cutthrough_put_nl())
+  return FALSE;
+ s = s2+1;
+ }
+return TRUE;
+}
+
+
 /* Buffered send of headers.  Return success boolean. */
 /* Expands newlines to wire format (CR,NL).           */
 /* Also sends header-terminating blank line.          */
 BOOL
 cutthrough_headers_send( void )
 {
-header_line * h;
-uschar * cp1, * cp2;
-
 if(cutthrough_fd < 0)
   return FALSE;
 
-for(h= header_list; h != NULL; h= h->next)
-  if(h->type != htype_old  &&  h->text != NULL)
-    for (cp1 = h->text; *cp1 && (cp2 = Ustrchr(cp1, '\n')); cp1 = cp2+1)
-      if(  !cutthrough_puts(cp1, cp2-cp1)
-        || !cutthrough_put_nl())
-        return FALSE;
+/* We share a routine with the mainline transport to handle header add/remove/rewrites,
+   but having a separate buffered-output function (for now)
+*/
+HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>>(nl)\n");
-return cutthrough_put_nl();
+if (!transport_headers_send(&cutthrough_addr, cutthrough_fd,
+       cutthrough_addr.transport->add_headers, cutthrough_addr.transport->remove_headers,
+       &cutthrough_write_chunk, TRUE,
+       cutthrough_addr.transport->rewrite_rules, cutthrough_addr.transport->rewrite_existflags))
+  return FALSE;
+
+HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
+return TRUE;
 }
 
 
@@ -1556,13 +1583,7 @@ if (address[0] == 0) return OK;
 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
+tls_modify_variables(&tls_out);
 
 /* 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). */
@@ -1735,8 +1756,20 @@ while (addr_new != NULL)
                   string_is_ip_address(host->name, NULL) != 0)
                 (void)host_find_byname(host, NULL, flags, &canonical_name, TRUE);
               else
+               {
+               uschar * d_request = NULL, * d_require = NULL;
+               if (Ustrcmp(addr->transport->driver_name, "smtp") == 0)
+                 {
+                 smtp_transport_options_block * ob =
+                     (smtp_transport_options_block *)
+                       addr->transport->options_block;
+                 d_request = ob->dnssec_request_domains;
+                 d_require = ob->dnssec_require_domains;
+                 }
+
                 (void)host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
-                  &canonical_name, NULL);
+                 d_request, d_require, &canonical_name, NULL);
+               }
               }
             }
           }
@@ -2021,14 +2054,7 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
 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
+tls_modify_variables(&tls_in);
 
 return yield;
 }
@@ -3539,7 +3565,7 @@ revadd[0] = 0;
 
 /* In case this is the first time the DNS resolver is being used. */
 
-dns_init(FALSE, FALSE);
+dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
 
 /* Loop through all the domains supplied, until something matches */
 
@@ -3710,4 +3736,6 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL
 return FAIL;
 }
 
+/* vi: aw ai sw=2
+*/
 /* End of verify.c */