Make $tls_out_ocsp visible to TPDA (mostly testsuite)
[exim.git] / src / src / deliver.c
index 121f7c2e09efafc668e2183fc76dc4466a9c288c..dd7f888fb35b5a4c55d50baa50c0f6d2e0cf9af1 100644 (file)
@@ -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. */
 
 /* The main code for delivering a message. */
@@ -718,6 +718,7 @@ uschar *s;              /* building log lines;   */
 void *reset_point;      /* released afterwards.  */
 
 
+DEBUG(D_deliver) debug_printf("B cipher %s\n", addr->cipher);
 /* Log the delivery on the main log. We use an extensible string to build up
 the log line, and reset the store afterwards. Remote deliveries should always
 have a pointer to the host item that succeeded; local deliveries can have a
@@ -734,6 +735,7 @@ pointer to a single host item in their host list, for use by the transport. */
 
 s = reset_point = store_get(size);
 
+DEBUG(D_deliver) debug_printf("C cipher %s\n", addr->cipher);
 log_address = string_log_address(addr, (log_write_selector & L_all_parents) != 0, TRUE);
 if (msg)
   s = string_append(s, &size, &ptr, 3, host_and_ident(TRUE), US" ", log_address);
@@ -876,6 +878,7 @@ if (addr->transport->tpda_delivery_action)
   DEBUG(D_deliver)
     debug_printf("  TPDA(Delivery): tpda_deliver_action=|%s| tpda_delivery_IP=%s\n",
       addr->transport->tpda_delivery_action, tpda_delivery_ip);
+DEBUG(D_deliver) debug_printf("D cipher %s\n", addr->cipher);
 
   router_name =    addr->router->name;
   transport_name = addr->transport->name;
@@ -1057,7 +1060,7 @@ if (addr->return_file >= 0 && addr->return_filename != NULL)
   (void)close(addr->return_file);
   }
 
-/* The sucess case happens only after delivery by a transport. */
+/* The success case happens only after delivery by a transport. */
 
 if (result == OK)
   {
@@ -1073,10 +1076,8 @@ if (result == OK)
   DEBUG(D_deliver) debug_printf("%s delivered\n", addr->address);
 
   if (addr->parent == NULL)
-    {
     deliver_msglog("%s %s: %s%s succeeded\n", now, addr->address,
       driver_name, driver_kind);
-    }
   else
     {
     deliver_msglog("%s %s <%s>: %s%s succeeded\n", now, addr->address,
@@ -1084,7 +1085,36 @@ if (result == OK)
     child_done(addr, now);
     }
 
+  /* Certificates for logging (via TPDA) */
+  #ifdef SUPPORT_TLS
+  tls_out.ourcert = addr->ourcert;
+  addr->ourcert = NULL;
+  tls_out.peercert = addr->peercert;
+  addr->peercert = NULL;
+
+DEBUG(D_deliver) debug_printf("A cipher %s\n", addr->cipher);
+  tls_out.cipher = addr->cipher;
+  tls_out.peerdn = addr->peerdn;
+  tls_out.ocsp = addr->ocsp;
+  #endif
+
   delivery_log(LOG_MAIN, addr, logchar, NULL);
+
+  #ifdef SUPPORT_TLS
+  if (tls_out.ourcert)
+    {
+    tls_free_cert(tls_out.ourcert);
+    tls_out.ourcert = NULL;
+    }
+  if (tls_out.peercert)
+    {
+    tls_free_cert(tls_out.peercert);
+    tls_out.peercert = NULL;
+    }
+  tls_out.cipher = NULL;
+  tls_out.peerdn = NULL;
+  tls_out.ocsp = OCSP_NOT_REQ;
+  #endif
   }
 
 
@@ -2957,27 +2987,57 @@ while (!done)
 
     #ifdef SUPPORT_TLS
     case 'X':
-    if (addr == NULL) goto ADDR_MISMATCH;            /* Below, in 'A' handler */
-    addr->cipher = (*ptr)? string_copy(ptr) : NULL;
-    while (*ptr++);
-    addr->peerdn = (*ptr)? string_copy(ptr) : NULL;
+    if (addr == NULL) goto ADDR_MISMATCH;          /* Below, in 'A' handler */
+    switch (*ptr++)
+      {
+      case '1':
+      addr->cipher = NULL;
+      addr->peerdn = NULL;
+
+      if (*ptr)
+       addr->cipher = string_copy(ptr);
+      while (*ptr++);
+      if (*ptr)
+       addr->peerdn = string_copy(ptr);
+      break;
+
+      case '2':
+      addr->peercert = NULL;
+      if (*ptr)
+       (void) tls_import_cert(ptr, &addr->peercert);
+      break;
+
+      case '3':
+      addr->ourcert = NULL;
+      if (*ptr)
+       (void) tls_import_cert(ptr, &addr->ourcert);
+      break;
+
+      #ifdef EXPERIMENTAL_OCSP
+      case '4':
+      addr->ocsp = OCSP_NOT_REQ;
+      if (*ptr)
+       addr->ocsp = *ptr - '0';
+      break;
+      #endif
+      }
     while (*ptr++);
     break;
     #endif
 
     case 'C':  /* client authenticator information */
     switch (*ptr++)
-    {
-    case '1':
-      addr->authenticator = (*ptr)? string_copy(ptr) : NULL;
-      break;
-    case '2':
-      addr->auth_id = (*ptr)? string_copy(ptr) : NULL;
-      break;
-    case '3':
-      addr->auth_sndr = (*ptr)? string_copy(ptr) : NULL;
-      break;
-    }
+      {
+      case '1':
+       addr->authenticator = (*ptr)? string_copy(ptr) : NULL;
+       break;
+      case '2':
+       addr->auth_id = (*ptr)? string_copy(ptr) : NULL;
+       break;
+      case '3':
+       addr->auth_sndr = (*ptr)? string_copy(ptr) : NULL;
+       break;
+      }
     while (*ptr++);
     break;
 
@@ -4054,19 +4114,51 @@ for (delivery_count = 0; addr_remote != NULL; delivery_count++)
       /* Use an X item only if there's something to send */
 
       #ifdef SUPPORT_TLS
-      if (addr->cipher != NULL)
+      if (addr->cipher)
         {
         ptr = big_buffer;
-        sprintf(CS ptr, "X%.128s", addr->cipher);
+        sprintf(CS ptr, "X1%.128s", addr->cipher);
         while(*ptr++);
-        if (addr->peerdn == NULL) *ptr++ = 0; else
+        if (!addr->peerdn)
+         *ptr++ = 0;
+       else
           {
           sprintf(CS ptr, "%.512s", addr->peerdn);
           while(*ptr++);
           }
+
         rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
         }
-      #endif
+      if (addr->peercert)
+       {
+        ptr = big_buffer;
+       *ptr++ = 'X'; *ptr++ = '2';
+       if (!tls_export_cert(ptr, big_buffer_size-2, addr->peercert))
+         while(*ptr++);
+       else
+         *ptr++ = 0;
+        rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
+       }
+      if (addr->ourcert)
+       {
+        ptr = big_buffer;
+       *ptr++ = 'X'; *ptr++ = '3';
+       if (!tls_export_cert(ptr, big_buffer_size-2, addr->ourcert))
+         while(*ptr++);
+       else
+         *ptr++ = 0;
+        rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
+       }
+      # ifdef EXPERIMENTAL_OCSP
+      if (addr->ocsp > OCSP_NOT_REQ)
+       {
+       ptr = big_buffer;
+       sprintf(CS ptr, "X4%c", addr->ocsp + '0');
+       while(*ptr++);
+        rmt_dlv_checked_write(fd, big_buffer, ptr - big_buffer);
+       }
+      # endif
+      #endif   /*SUPPORT_TLS
 
       if (client_authenticator)
         {