Debug: internal consistency under testsuite
[exim.git] / src / src / dkim_transport.c
index 85a73dcaeb872c20b7c45ffbecf8a7bb6d36fbd2..c09c5059b871e5477204ababd9202a4b650f363b 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2016 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Transport shim for dkim signing */
@@ -21,8 +21,8 @@ if (dkim->dkim_strict)
   uschar * dkim_strict_result = expand_string(dkim->dkim_strict);
 
   if (dkim_strict_result)
-    if ( (strcmpic(dkim->dkim_strict, US"1") == 0) ||
-        (strcmpic(dkim->dkim_strict, US"true") == 0) )
+    if (  strcmpic(dkim_strict_result, US"1") == 0
+       || strcmpic(dkim_strict_result, US"true") == 0)
       {
       /* Set errno to something halfway meaningful */
       *errp = EACCES;
@@ -37,9 +37,17 @@ return TRUE;
 /* Send the file at in_fd down the output fd */
 
 static BOOL
-dkt_send_file(int out_fd, int in_fd, off_t off, size_t size)
+dkt_send_file(int out_fd, int in_fd, off_t off
+#ifdef OS_SENDFILE
+  , size_t size
+#endif
+  )
 {
+#ifdef OS_SENDFILE
 DEBUG(D_transport) debug_printf("send file fd=%d size=%u\n", out_fd, (unsigned)(size - off));
+#else
+DEBUG(D_transport) debug_printf("send file fd=%d\n", out_fd);
+#endif
 
 /*XXX should implement timeout, like transport_write_block_fd() ? */
 
@@ -48,7 +56,7 @@ DEBUG(D_transport) debug_printf("send file fd=%d size=%u\n", out_fd, (unsigned)(
    to the socket. However only if we don't use TLS,
    as then there's another layer of indirection
    before the data finally hits the socket. */
-if (tls_out.active != out_fd)
+if (tls_out.active.sock != out_fd)
   {
   ssize_t copied = 0;
 
@@ -75,9 +83,9 @@ else
 
     while (sread)
       {
-#ifdef SUPPORT_TLS
-      wwritten = tls_out.active == out_fd
-       ? tls_write(FALSE, p, sread, FALSE)
+#ifndef DISABLE_TLS
+      wwritten = tls_out.active.sock == out_fd
+       ? tls_write(tls_out.active.tls_ctx, p, sread, FALSE)
        : write(out_fd, CS p, sread);
 #else
       wwritten = write(out_fd, CS p, sread);
@@ -116,9 +124,9 @@ dkt_direct(transport_ctx * tctx, struct ob_dkim * dkim,
 {
 int save_fd = tctx->u.fd;
 int save_options = tctx->options;
-BOOL save_wireformat = spool_file_wireformat;
+BOOL save_wireformat = f.spool_file_wireformat;
 uschar * hdrs;
-blob * dkim_signature;
+gstring * dkim_signature;
 int hsize;
 const uschar * errstr;
 BOOL rc;
@@ -133,8 +141,8 @@ tctx->options = tctx->options & ~(topt_end_dot | topt_use_bdat)
   | topt_output_string | topt_no_body;
 
 rc = transport_write_message(tctx, 0);
-hdrs = tctx->u.msg;
-hdrs[hsize = tctx->msg_ptr] = '\0';
+hdrs = string_from_gstring(tctx->u.msg);
+hsize = tctx->u.msg->ptr;
 
 tctx->u.fd = save_fd;
 tctx->options = save_options;
@@ -142,8 +150,14 @@ if (!rc) return FALSE;
 
 /* Get signatures for headers plus spool data file */
 
-dkim->dot_stuffed = !!(save_options & topt_end_dot);
+#ifdef EXPERIMENTAL_ARC
+arc_sign_init();
+#endif
+
+/* The dotstuffed status of the datafile depends on whether it was stored
+in wireformat. */
 
+dkim->dot_stuffed = f.spool_file_wireformat;
 if (!(dkim_signature = dkim_exim_sign(deliver_datafile, SPOOL_DATA_START_OFFSET,
                                    hdrs, dkim, &errstr)))
   if (!(rc = dkt_sign_fail(dkim, &errno)))
@@ -152,6 +166,18 @@ if (!(dkim_signature = dkim_exim_sign(deliver_datafile, SPOOL_DATA_START_OFFSET,
     return FALSE;
     }
 
+#ifdef EXPERIMENTAL_ARC
+if (dkim->arc_signspec)                        /* Prepend ARC headers */
+  {
+  uschar * e;
+  if (!(dkim_signature = arc_sign(dkim->arc_signspec, dkim_signature, &e)))
+    {
+    *err = e;
+    return FALSE;
+    }
+  }
+#endif
+
 /* Write the signature and headers into the deliver-out-buffer.  This should
 mean they go out in the same packet as the MAIL, RCPT and (first) BDAT commands
 (transport_write_message() sizes the BDAT for the buffered amount) - for short
@@ -160,17 +186,17 @@ having already been done - but we have to say we want CRLF output format, and
 temporarily set the marker for possible already-CRLF input. */
 
 tctx->options &= ~topt_escape_headers;
-spool_file_wireformat = TRUE;
+f.spool_file_wireformat = TRUE;
 transport_write_reset(0);
 if (  (  dkim_signature
-      && dkim_signature->len > 0
-      && !write_chunk(tctx, dkim_signature->data, dkim_signature->len)
+      && dkim_signature->ptr > 0
+      && !write_chunk(tctx, dkim_signature->s, dkim_signature->ptr)
       )
    || !write_chunk(tctx, hdrs, hsize)
    )
   return FALSE;
 
-spool_file_wireformat = save_wireformat;
+f.spool_file_wireformat = save_wireformat;
 tctx->options = save_options | topt_no_headers | topt_continuation;
 
 if (!(transport_write_message(tctx, 0)))
@@ -204,7 +230,7 @@ int dkim_fd;
 int save_errno = 0;
 BOOL rc;
 uschar * dkim_spool_name;
-blob * dkim_signature;
+gstring * dkim_signature;
 int options, dlen;
 off_t k_file_size;
 const uschar * errstr;
@@ -245,7 +271,13 @@ if (!rc)
   goto CLEANUP;
   }
 
-/* Feed the file to the goats^W DKIM lib */
+#ifdef EXPERIMENTAL_ARC
+arc_sign_init();
+#endif
+
+/* Feed the file to the goats^W DKIM lib.  At this point the dotstuffed
+status of the file depends on the output of transport_write_message() just
+above, which should be the result of the end_dot flag in tctx->options. */
 
 dkim->dot_stuffed = !!(options & topt_end_dot);
 if (!(dkim_signature = dkim_exim_sign(dkim_fd, 0, NULL, dkim, &errstr)))
@@ -258,7 +290,16 @@ if (!(dkim_signature = dkim_exim_sign(dkim_fd, 0, NULL, dkim, &errstr)))
     }
   }
 else
-  dlen = dkim_signature->len;
+  dlen = dkim_signature->ptr;
+
+#ifdef EXPERIMENTAL_ARC
+if (dkim->arc_signspec)                                /* Prepend ARC headers */
+  {
+  if (!(dkim_signature = arc_sign(dkim->arc_signspec, dkim_signature, USS err)))
+    goto CLEANUP;
+  dlen = dkim_signature->ptr;
+  }
+#endif
 
 #ifndef OS_SENDFILE
 if (options & topt_use_bdat)
@@ -280,7 +321,7 @@ if (options & topt_use_bdat)
     {
     if (  tctx->chunk_cb(tctx, dlen, 0) != OK
        || !transport_write_block(tctx,
-                   dkim_signature->data, dlen, FALSE)
+                   dkim_signature->s, dlen, FALSE)
        || tctx->chunk_cb(tctx, 0, tc_reap_prev) != OK
        )
       goto err;
@@ -294,10 +335,14 @@ if (options & topt_use_bdat)
     goto err;
   }
 
-if(dlen > 0 && !transport_write_block(tctx, dkim_signature->data, dlen, TRUE))
+if(dlen > 0 && !transport_write_block(tctx, dkim_signature->s, dlen, TRUE))
   goto err;
 
-if (!dkt_send_file(tctx->u.fd, dkim_fd, 0, k_file_size))
+if (!dkt_send_file(tctx->u.fd, dkim_fd, 0
+#ifdef OS_SENDFILE
+  , k_file_size
+#endif
+  ))
   {
   save_errno = errno;
   rc = FALSE;
@@ -339,7 +384,8 @@ dkim_transport_write_message(transport_ctx * tctx,
 {
 /* If we can't sign, just call the original function. */
 
-if (!(dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector))
+if (  !(dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector)
+   && !dkim->force_bodyhash)
   return transport_write_message(tctx, 0);
 
 /* If there is no filter command set up, construct the message and calculate