Multiple headers_add/remove options per router/transport - fixes bug 337
[exim.git] / src / src / transport.c
index 7c5c98149c21cb59775203c67bee1b0a3e16abe8..7c79bb0095b802fa845b2c82b041c846f50f7ff8 100644 (file)
@@ -1,10 +1,8 @@
-/* $Cambridge: exim/src/src/transport.c,v 1.22 2008/09/30 09:20:31 tom Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2007 */
+/* Copyright (c) University of Cambridge 1995 - 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* General functions concerned with transportation, and generic options for all
@@ -70,11 +68,11 @@ optionlist optionlist_transports[] = {
                  (void *)(offsetof(transport_instance, envelope_to_add)) },
   { "group",             opt_expand_gid|opt_public,
                  (void *)offsetof(transport_instance, gid) },
-  { "headers_add",      opt_stringptr|opt_public,
+  { "headers_add",      opt_stringptr|opt_public|opt_rep_str,
                  (void *)offsetof(transport_instance, add_headers) },
   { "headers_only",     opt_bool|opt_public,
                  (void *)offsetof(transport_instance, headers_only) },
-  { "headers_remove",   opt_stringptr|opt_public,
+  { "headers_remove",   opt_stringptr|opt_public|opt_rep_str,
                  (void *)offsetof(transport_instance, remove_headers) },
   { "headers_rewrite",  opt_rewrite|opt_public,
                  (void *)offsetof(transport_instance, headers_rewrite) },
@@ -221,7 +219,7 @@ for (i = 0; i < 100; i++)
   if (transport_write_timeout <= 0)   /* No timeout wanted */
     {
     #ifdef SUPPORT_TLS
-    if (tls_active == fd) rc = tls_write(block, len); else
+    if (tls_out.active == fd) rc = tls_write(FALSE, block, len); else
     #endif
     rc = write(fd, block, len);
     save_errno = errno;
@@ -233,7 +231,7 @@ for (i = 0; i < 100; i++)
     {
     alarm(local_timeout);
     #ifdef SUPPORT_TLS
-    if (tls_active == fd) rc = tls_write(block, len); else
+    if (tls_out.active == fd) rc = tls_write(FALSE, block, len); else
     #endif
     rc = write(fd, block, len);
     save_errno = errno;
@@ -324,7 +322,7 @@ Returns:      the yield of transport_write_block()
 */
 
 BOOL
-transport_write_string(int fd, char *format, ...)
+transport_write_string(int fd, const char *format, ...)
 {
 va_list ap;
 va_start(ap, format);
@@ -426,6 +424,7 @@ for (ptr = start; ptr < end; ptr++)
 
     if (use_crlf) *chunk_ptr++ = '\r';
     *chunk_ptr++ = '\n';
+    transport_newlines++;
 
     /* The check_string test (formerly "from hack") replaces the specific
     string at the start of a line with an escape string (e.g. "From " becomes
@@ -920,19 +919,19 @@ if ((options & topt_no_body) == 0)
       }
     }
 
-  /* Finished with the check string */
-
-  nl_check_length = nl_escape_length = 0;
-
   /* A read error on the body will have left len == -1 and errno set. */
 
   if (len != 0) return FALSE;
+  }
 
-  /* If requested, add a terminating "." line (SMTP output). */
+/* Finished with the check string */
 
-  if ((options & topt_end_dot) != 0 && !write_chunk(fd, US".\n", 2, use_crlf))
-    return FALSE;
-  }
+nl_check_length = nl_escape_length = 0;
+
+/* If requested, add a terminating "." line (SMTP output). */
+
+if ((options & topt_end_dot) != 0 && !write_chunk(fd, US".\n", 2, use_crlf))
+  return FALSE;
 
 /* Write out any remaining data in the buffer before returning. */
 
@@ -941,7 +940,7 @@ return (len = chunk_ptr - deliver_out_buffer) <= 0 ||
 }
 
 
-#if (defined EXPERIMENTAL_DOMAINKEYS) || (defined EXPERIMENTAL_DKIM)
+#ifndef DISABLE_DKIM
 
 /***************************************************************************************************
 *    External interface to write the message, while signing it with DKIM and/or Domainkeys         *
@@ -965,14 +964,6 @@ Arguments:     as for internal_transport_write_message() above, with additional
                                                                                    0/false => send anyway
                uschar *dkim_sign_headers        DKIM: List of headers that should be included in signature
                                                 generation
-               uschar *dk_private_key           Domainkeys: The private key to use (filename or plain data)
-               uschar *dk_domain                Domainkeys: Override domain (normally NULL)
-               uschar *dk_selector              Domainkeys: The selector to use.
-               uschar *dk_canon                 Domainkeys: The canonalization scheme to use, "simple" or "nofws"
-               uschar *dk_headers               Domainkeys: Colon-separated header list to include in the signing
-                                                process.
-               uschar *dk_strict                Domainkeys: What to do if signing fails: 1/true  => throw error
-                                                                                         0/false => send anyway
 
 Returns:       TRUE on success; FALSE (with errno) for any failure
 */
@@ -982,9 +973,7 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
   int size_limit, uschar *add_headers, uschar *remove_headers,
   uschar *check_string, uschar *escape_string, rewrite_rule *rewrite_rules,
   int rewrite_existflags, uschar *dkim_private_key, uschar *dkim_domain,
-  uschar *dkim_selector, uschar *dkim_canon, uschar *dkim_strict, uschar *dkim_sign_headers,
-  uschar *dk_private_key, uschar *dk_domain, uschar *dk_selector, uschar *dk_canon,
-  uschar *dk_headers, uschar *dk_strict
+  uschar *dkim_selector, uschar *dkim_canon, uschar *dkim_strict, uschar *dkim_sign_headers
   )
 {
   int dkim_fd;
@@ -995,12 +984,10 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
   int sread = 0;
   int wwritten = 0;
   uschar *dkim_signature = NULL;
-  uschar *dk_signature = NULL;
   off_t size = 0;
 
-  if ( !( ((dkim_private_key != NULL) && (dkim_domain != NULL) && (dkim_selector != NULL)) ||
-          ((dk_private_key != NULL) && (dk_selector != NULL)) ) ) {
-    /* If we can sign with neither method, just call the original function. */
+  if (!( ((dkim_private_key != NULL) && (dkim_domain != NULL) && (dkim_selector != NULL)) )) {
+    /* If we can't sign, just call the original function. */
     return transport_write_message(addr, fd, options,
               size_limit, add_headers, remove_headers,
               check_string, escape_string, rewrite_rules,
@@ -1031,8 +1018,6 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
     goto CLEANUP;
     }
 
-
-  #ifdef EXPERIMENTAL_DKIM
   if ( (dkim_private_key != NULL) && (dkim_domain != NULL) && (dkim_selector != NULL) ) {
     /* Rewind file and feed it to the goats^W DKIM lib */
     lseek(dkim_fd, 0, SEEK_SET);
@@ -1048,7 +1033,9 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
         if (dkim_strict_result != NULL) {
           if ( (strcmpic(dkim_strict,US"1") == 0) ||
                (strcmpic(dkim_strict,US"true") == 0) ) {
-            save_errno = errno;
+            /* 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;
           }
@@ -1059,7 +1046,7 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
       int siglen = Ustrlen(dkim_signature);
       while(siglen > 0) {
         #ifdef SUPPORT_TLS
-        if (tls_active == fd) wwritten = tls_write(dkim_signature, siglen); else
+        if (tls_out.active == fd) wwritten = tls_write(FALSE, dkim_signature, siglen); else
         #endif
         wwritten = write(fd,dkim_signature,siglen);
         if (wwritten == -1) {
@@ -1073,49 +1060,6 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
       }
     }
   }
-  #endif
-
-  #ifdef EXPERIMENTAL_DOMAINKEYS
-  if ( (dk_private_key != NULL) && (dk_selector != NULL) ) {
-    /* Rewind file and feed it to the goats^W DK lib */
-    lseek(dkim_fd, 0, SEEK_SET);
-    dk_signature = dk_exim_sign(dkim_fd,
-                                dk_private_key,
-                                dk_domain,
-                                dk_selector,
-                                dk_canon);
-    if (dk_signature == NULL) {
-      if (dk_strict != NULL) {
-        uschar *dk_strict_result = expand_string(dk_strict);
-        if (dk_strict_result != NULL) {
-          if ( (strcmpic(dk_strict,US"1") == 0) ||
-               (strcmpic(dk_strict,US"true") == 0) ) {
-            save_errno = errno;
-            rc = FALSE;
-            goto CLEANUP;
-          }
-        }
-      }
-    }
-    else {
-      int siglen = Ustrlen(dk_signature);
-      while(siglen > 0) {
-        #ifdef SUPPORT_TLS
-        if (tls_active == fd) wwritten = tls_write(dk_signature, siglen); else
-        #endif
-        wwritten = write(fd,dk_signature,siglen);
-        if (wwritten == -1) {
-          /* error, bail out */
-          save_errno = errno;
-          rc = FALSE;
-          goto CLEANUP;
-        }
-        siglen -= wwritten;
-        dk_signature += wwritten;
-      }
-    }
-  }
-  #endif
 
   /* Fetch file positition (the size) */
   size = lseek(dkim_fd,0,SEEK_CUR);
@@ -1128,7 +1072,7 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
      to the socket. However only if we don't use TLS,
      in which case theres another layer of indirection
      before the data finally hits the socket. */
-  if (tls_active != fd)
+  if (tls_out.active != fd)
     {
     ssize_t copied = 0;
     off_t offset = 0;
@@ -1152,7 +1096,7 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
     /* write the chunk */
     DKIM_WRITE:
     #ifdef SUPPORT_TLS
-    if (tls_active == fd) wwritten = tls_write(US p, sread); else
+    if (tls_out.active == fd) wwritten = tls_write(FALSE, US p, sread); else
     #endif
     wwritten = write(fd,p,sread);
     if (wwritten == -1)
@@ -1181,10 +1125,11 @@ dkim_transport_write_message(address_item *addr, int fd, int options,
   CLEANUP:
   /* unlink -K file */
   (void)close(dkim_fd);
-  //Uunlink(dkim_spool_name);
+  Uunlink(dkim_spool_name);
   errno = save_errno;
   return rc;
 }
+
 #endif