X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/42055a338593d66f0abb6eeb6b03f0eaf4439f57..a5ffa9b475a426bc73366db01f7cc92a3811bc3a:/src/src/dkim_transport.c diff --git a/src/src/dkim_transport.c b/src/src/dkim_transport.c index c8ac92e16..4d26f9291 100644 --- a/src/src/dkim_transport.c +++ b/src/src/dkim_transport.c @@ -7,14 +7,10 @@ /* Transport shim for dkim signing */ -#ifndef DISABLE_DKIM - #include "exim.h" -#ifdef HAVE_LINUX_SENDFILE -#include -#endif +#ifndef DISABLE_DKIM /* rest of file */ static BOOL @@ -38,17 +34,16 @@ 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=%u\n", out_fd, (unsigned)(size - off)); /*XXX should implement timeout, like transport_write_block_fd() ? */ -/* Rewind file */ -lseek(in_fd, off, SEEK_SET); - -#ifdef HAVE_LINUX_SENDFILE +#ifdef OS_SENDFILE /* We can use sendfile() to shove the file contents to the socket. However only if we don't use TLS, as then there's another layer of indirection @@ -58,7 +53,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 = os_sendfile(out_fd, in_fd, &off, size - off); if (copied < 0) return FALSE; } @@ -69,8 +64,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 */ @@ -79,7 +77,7 @@ else { #ifdef SUPPORT_TLS wwritten = tls_out.active == out_fd - ? tls_write(FALSE, p, sread) + ? tls_write(FALSE, p, sread, FALSE) : write(out_fd, CS p, sread); #else wwritten = write(out_fd, CS p, sread); @@ -118,14 +116,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 +155,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))) @@ -196,7 +200,7 @@ int dkim_fd; int save_errno = 0; BOOL rc; uschar * dkim_spool_name, * dkim_signature; -int sread = 0, wwritten = 0, siglen, options; +int sread = 0, wwritten = 0, siglen = 0, options; off_t k_file_size; const uschar * errstr; @@ -247,10 +251,14 @@ else if (!(rc = dkt_sign_fail(dkim, &save_errno))) goto CLEANUP; } -#ifndef HAVE_LINUX_SENDFILE +#ifndef OS_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 +294,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;