* 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 */
/* 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() ? */
int save_options = tctx->options;
BOOL save_wireformat = spool_file_wireformat;
uschar * hdrs;
-blob * dkim_signature;
+gstring * dkim_signature;
int hsize;
const uschar * errstr;
+uschar * verrstr;
BOOL rc;
DEBUG(D_transport) debug_printf("dkim signing direct-mode\n");
| 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;
/* Get signatures for headers plus spool data file */
-dkim->dot_stuffed = !!(save_options & topt_end_dot);
+#ifdef EXPERIMENTAL_ARC
+arc_sign_init();
+#endif
+dkim->dot_stuffed = !!(save_options & topt_end_dot);
if (!(dkim_signature = dkim_exim_sign(deliver_datafile, SPOOL_DATA_START_OFFSET,
hdrs, dkim, &errstr)))
if (!(rc = dkt_sign_fail(dkim, &errno)))
return FALSE;
}
+#ifdef EXPERIMENTAL_ARC
+if (dkim->arc_signspec) /* Prepend ARC headers */
+ if (!(dkim_signature =
+ arc_sign(dkim->arc_signspec, dkim_signature, &verrstr)))
+ {
+ *err = verrstr;
+ 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
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)
)
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;
goto CLEANUP;
}
+#ifdef EXPERIMENTAL_ARC
+arc_sign_init();
+#endif
+
/* Feed the file to the goats^W DKIM lib */
dkim->dot_stuffed = !!(options & topt_end_dot);
}
}
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)
{
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;
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;
{
/* 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