X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/42055a338593d66f0abb6eeb6b03f0eaf4439f57..d315eda12f25ca2f72ca56b777a427c9ee7188e1:/src/src/dkim_transport.c diff --git a/src/src/dkim_transport.c b/src/src/dkim_transport.c index c8ac92e16..a654c2516 100644 --- a/src/src/dkim_transport.c +++ b/src/src/dkim_transport.c @@ -7,13 +7,13 @@ /* Transport shim for dkim signing */ -#ifndef DISABLE_DKIM - #include "exim.h" +#ifndef DISABLE_DKIM /* rest of file */ + #ifdef HAVE_LINUX_SENDFILE -#include +# include #endif @@ -38,16 +38,15 @@ if (dkim->dkim_strict) 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) { -DEBUG(D_transport) debug_printf("send file fd=%d size=%d\n", out_fd, size - off); +DEBUG(D_transport) debug_printf("send file fd=%d size=%l\n", out_fd, size - off); /*XXX should implement timeout, like transport_write_block_fd() ? */ -/* Rewind file */ -lseek(in_fd, off, SEEK_SET); - #ifdef HAVE_LINUX_SENDFILE /* We can use sendfile() to shove the file contents to the socket. However only if we don't use TLS, @@ -58,7 +57,7 @@ if (tls_out.active != out_fd) ssize_t copied = 0; while(copied >= 0 && off < size) - copied = sendfile(tctx->u.fd, dkim_fd, &off, size - off); + copied = sendfile(out_fd, in_fd, &off, size - off); if (copied < 0) return FALSE; } @@ -69,8 +68,11 @@ else { int sread, wwritten; + /* Rewind file */ + if (lseek(in_fd, off, SEEK_SET) < 0) return FALSE; + /* Send file down the original fd */ - while((sread = read(in_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) >0) + while((sread = read(in_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) > 0) { uschar * p = deliver_out_buffer; /* write the chunk */ @@ -118,14 +120,16 @@ 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; uschar * hdrs, * dkim_signature; -int siglen, hsize; +int siglen = 0, hsize; const uschar * errstr; BOOL rc; DEBUG(D_transport) debug_printf("dkim signing direct-mode\n"); -/* Get headers in string for signing and transmission */ +/* Get headers in string for signing and transmission. Do CRLF +and dotstuffing (but no body nor dot-termination) */ tctx->u.msg = NULL; tctx->options = tctx->options & ~(topt_end_dot | topt_use_bdat) @@ -155,14 +159,18 @@ else if (!(rc = dkt_sign_fail(dkim, &errno))) /* 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 -messages, the BDAT LAST command. We want no CRLF or dotstuffing expansion */ +messages, the BDAT LAST command. We want no dotstuffing expansion here, it +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_use_crlf; +tctx->options &= ~topt_escape_headers; +spool_file_wireformat = TRUE; transport_write_reset(0); -if ( !write_chunk(tctx, dkim_signature, siglen) +if ( siglen > 0 && !write_chunk(tctx, dkim_signature, siglen) || !write_chunk(tctx, hdrs, hsize)) return FALSE; +spool_file_wireformat = save_wireformat; tctx->options = save_options | topt_no_headers | topt_continuation; if (!(transport_write_message(tctx, 0))) @@ -250,7 +258,11 @@ else if (!(rc = dkt_sign_fail(dkim, &save_errno))) #ifndef HAVE_LINUX_SENDFILE if (options & topt_use_bdat) #endif - k_file_size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */ + if ((k_file_size = lseek(dkim_fd, 0, SEEK_END)) < 0) + { + *err = string_sprintf("dkim spoolfile seek: %s", strerror(errno)); + goto CLEANUP; + } if (options & topt_use_bdat) { @@ -286,7 +298,7 @@ if (!dkt_send_file(tctx->u.fd, dkim_fd, 0, k_file_size)) CLEANUP: /* unlink -K file */ - (void)close(dkim_fd); + if (dkim_fd >= 0) (void)close(dkim_fd); Uunlink(dkim_spool_name); errno = save_errno; return rc;