- transport_write_block(fd, deliver_out_buffer, len);
-}
-
-
-#ifndef DISABLE_DKIM
-
-/***************************************************************************************************
-* External interface to write the message, while signing it with DKIM and/or Domainkeys *
-***************************************************************************************************/
-
-/* This function is a wrapper around transport_write_message().
- It is only called from the smtp transport if DKIM or Domainkeys support
- is compiled in. The function sets up a replacement fd into a -K file,
- then calls the normal function. This way, the exact bits that exim would
- have put "on the wire" will end up in the file (except for TLS
- encapsulation, which is the very very last thing). When we are done
- signing the file, send the signed message down the original fd (or TLS fd).
-
-Arguments:
- as for internal_transport_write_message() above, with additional arguments
- for DKIM.
-
-Returns: TRUE on success; FALSE (with errno) for any failure
-*/
-
-BOOL
-dkim_transport_write_message(int out_fd, transport_ctx * tctx,
- struct ob_dkim * dkim)
-{
-int dkim_fd;
-int save_errno = 0;
-BOOL rc;
-uschar * dkim_spool_name;
-int sread = 0;
-int wwritten = 0;
-uschar *dkim_signature = NULL;
-int siglen;
-off_t k_file_size;
-
-/* If we can't sign, just call the original function. */
-
-if (!(dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector))
- return transport_write_message(out_fd, tctx, 0);
-
-dkim_spool_name = spool_fname(US"input", message_subdir, message_id,
- string_sprintf("-%d-K", (int)getpid()));
-
-if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0)
- {
- /* Can't create spool file. Ugh. */
- rc = FALSE;
- save_errno = errno;
- goto CLEANUP;
- }
-
-/* Call original function to write the -K file; does the CRLF expansion */
-
-tctx->options &= ~topt_use_bdat;
-rc = transport_write_message(dkim_fd, tctx, 0);
-
-/* Save error state. We must clean up before returning. */
-if (!rc)
- {
- save_errno = errno;
- goto CLEANUP;
- }
-
-if (dkim->dkim_private_key && dkim->dkim_domain && dkim->dkim_selector)
- {
- /* Rewind file and feed it to the goats^W DKIM lib */
- lseek(dkim_fd, 0, SEEK_SET);
- dkim_signature = dkim_exim_sign(dkim_fd,
- dkim->dkim_private_key,
- dkim->dkim_domain,
- dkim->dkim_selector,
- dkim->dkim_canon,
- dkim->dkim_sign_headers);
- if (!dkim_signature)
- {
- 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) )
- {
- /* Set errno to something halfway meaningful */
- save_errno = EACCES;
- log_write(0, LOG_MAIN, "DKIM: message could not be signed,"
- " and dkim_strict is set. Deferring message delivery.");
- rc = FALSE;
- goto CLEANUP;
- }
- }
- }
-
- siglen = 0;
- }
-
-if (dkim_signature)
- {
- siglen = Ustrlen(dkim_signature);
- while(siglen > 0)
- {
-#ifdef SUPPORT_TLS
- wwritten = tls_out.active == out_fd
- ? tls_write(FALSE, dkim_signature, siglen)
- : write(out_fd, dkim_signature, siglen);
-#else
- wwritten = write(out_fd, dkim_signature, siglen);
-#endif
- if (wwritten == -1)
- {
- /* error, bail out */
- save_errno = errno;
- rc = FALSE;
- goto CLEANUP;
- }
- siglen -= wwritten;
- dkim_signature += wwritten;
- }
- }
-
-#ifdef HAVE_LINUX_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
- before the data finally hits the socket. */
-if (tls_out.active != out_fd)
- {
- ssize_t copied = 0;
- off_t offset = 0;
-
- k_file_size = lseek(dkim_fd, 0, SEEK_END); /* Fetch file size */
-
- /* Rewind file */
- lseek(dkim_fd, 0, SEEK_SET);
-
- while(copied >= 0 && offset < k_file_size)
- copied = sendfile(out_fd, dkim_fd, &offset, k_file_size - offset);
- if (copied < 0)
- {
- save_errno = errno;
- rc = FALSE;
- }
- }
-else
-
-#endif
-
- {
- /* Rewind file */
- lseek(dkim_fd, 0, SEEK_SET);
-
- /* Send file down the original fd */
- while((sread = read(dkim_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) >0)
- {
- char *p = deliver_out_buffer;
- /* write the chunk */
-
- while (sread)
- {
-#ifdef SUPPORT_TLS
- wwritten = tls_out.active == out_fd
- ? tls_write(FALSE, US p, sread)
- : write(out_fd, p, sread);
-#else
- wwritten = write(out_fd, p, sread);
-#endif
- if (wwritten == -1)
- {
- /* error, bail out */
- save_errno = errno;
- rc = FALSE;
- goto CLEANUP;
- }
- p += wwritten;
- sread -= wwritten;
- }
- }
-
- if (sread == -1)
- {
- save_errno = errno;
- rc = FALSE;
- }
- }
-
-CLEANUP:
-/* unlink -K file */
-(void)close(dkim_fd);
-Uunlink(dkim_spool_name);
-errno = save_errno;
-return rc;