DKIM: make verification results visible in data ACL
[exim.git] / src / src / tls-openssl.c
index 5aebfd4fe8669641d967438ea1a4cd690c7a771a..f1176a63e512484937abca78c772505991148a6b 100644 (file)
@@ -29,7 +29,7 @@ functions from the OpenSSL library. */
 # include <openssl/ocsp.h>
 #endif
 #ifdef EXPERIMENTAL_DANE
-# include <danessl.h>
+# include "danessl.h"
 #endif
 
 
@@ -1024,6 +1024,30 @@ err:
 
 
 
+static int
+tls_add_certfile(SSL_CTX * sctx, tls_ext_ctx_cb * cbinfo, uschar * file,
+  uschar ** errstr)
+{
+DEBUG(D_tls) debug_printf("tls_certificate file %s\n", file);
+if (!SSL_CTX_use_certificate_chain_file(sctx, CS file))
+  return tls_error(string_sprintf(
+    "SSL_CTX_use_certificate_chain_file file=%s", file),
+      cbinfo->host, NULL, errstr);
+return 0;
+}
+
+static int
+tls_add_pkeyfile(SSL_CTX * sctx, tls_ext_ctx_cb * cbinfo, uschar * file,
+  uschar ** errstr)
+{
+DEBUG(D_tls) debug_printf("tls_privatekey file %s\n", file);
+if (!SSL_CTX_use_PrivateKey_file(sctx, CS file, SSL_FILETYPE_PEM))
+  return tls_error(string_sprintf(
+    "SSL_CTX_use_PrivateKey_file file=%s", file), cbinfo->host, NULL, errstr);
+return 0;
+}
+
+
 /*************************************************
 *        Expand key and cert file specs          *
 *************************************************/
@@ -1048,7 +1072,7 @@ uschar *expanded;
 
 if (!cbinfo->certificate)
   {
-  if (cbinfo->host)                    /* client */
+  if (!cbinfo->is_server)              /* client */
     return OK;
                                        /* server */
   if (tls_install_selfsign(sctx, errstr) != OK)
@@ -1056,6 +1080,8 @@ if (!cbinfo->certificate)
   }
 else
   {
+  int err;
+
   if (Ustrstr(cbinfo->certificate, US"tls_sni") ||
       Ustrstr(cbinfo->certificate, US"tls_in_sni") ||
       Ustrstr(cbinfo->certificate, US"tls_out_sni")
@@ -1065,14 +1091,20 @@ else
   if (!expand_check(cbinfo->certificate, US"tls_certificate", &expanded, errstr))
     return DEFER;
 
-  if (expanded != NULL)
-    {
-    DEBUG(D_tls) debug_printf("tls_certificate file %s\n", expanded);
-    if (!SSL_CTX_use_certificate_chain_file(sctx, CS expanded))
-      return tls_error(string_sprintf(
-       "SSL_CTX_use_certificate_chain_file file=%s", expanded),
-         cbinfo->host, NULL, errstr);
-    }
+  if (expanded)
+    if (cbinfo->is_server)
+      {
+      const uschar * file_list = expanded;
+      int sep = 0;
+      uschar * file;
+
+      while (file = string_nextinlist(&file_list, &sep, NULL, 0))
+       if ((err = tls_add_certfile(sctx, cbinfo, file, errstr)))
+         return err;
+      }
+    else       /* would there ever be a need for multiple client certs? */
+      if ((err = tls_add_certfile(sctx, cbinfo, expanded, errstr)))
+       return err;
 
   if (cbinfo->privatekey != NULL &&
       !expand_check(cbinfo->privatekey, US"tls_privatekey", &expanded, errstr))
@@ -1083,12 +1115,19 @@ else
   key is in the same file as the certificate. */
 
   if (expanded && *expanded)
-    {
-    DEBUG(D_tls) debug_printf("tls_privatekey file %s\n", expanded);
-    if (!SSL_CTX_use_PrivateKey_file(sctx, CS expanded, SSL_FILETYPE_PEM))
-      return tls_error(string_sprintf(
-       "SSL_CTX_use_PrivateKey_file file=%s", expanded), cbinfo->host, NULL, errstr);
-    }
+    if (cbinfo->is_server)
+      {
+      const uschar * file_list = expanded;
+      int sep = 0;
+      uschar * file;
+
+      while (file = string_nextinlist(&file_list, &sep, NULL, 0))
+       if ((err = tls_add_pkeyfile(sctx, cbinfo, file, errstr)))
+         return err;
+      }
+    else       /* would there ever be a need for multiple client certs? */
+      if ((err = tls_add_pkeyfile(sctx, cbinfo, expanded, errstr)))
+       return err;
   }
 
 #ifndef DISABLE_OCSP
@@ -1499,9 +1538,9 @@ if (!RAND_status())
   gettimeofday(&r.tv, NULL);
   r.p = getpid();
 
-  RAND_seed((uschar *)(&r), sizeof(r));
-  RAND_seed((uschar *)big_buffer, big_buffer_size);
-  if (addr != NULL) RAND_seed((uschar *)addr, sizeof(addr));
+  RAND_seed(US (&r), sizeof(r));
+  RAND_seed(US big_buffer, big_buffer_size);
+  if (addr != NULL) RAND_seed(US addr, sizeof(addr));
 
   if (!RAND_status())
     return tls_error(US"RAND_status", host,
@@ -2573,8 +2612,7 @@ tls_write(BOOL is_server, const uschar *buff, size_t len, BOOL more)
 {
 int outbytes, error, left;
 SSL *ssl = is_server ? server_ssl : client_ssl;
-static uschar * corked = NULL;
-static int c_size = 0, c_len = 0;
+static gstring * corked = NULL;
 
 DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
   buff, (unsigned long)len, more ? ", more" : "");
@@ -2586,12 +2624,12 @@ for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. */
 
 if (is_server && (more || corked))
   {
-  corked = string_catn(corked, &c_size, &c_len, buff, len);
+  corked = string_catn(corked, buff, len);
   if (more)
     return len;
-  buff = CUS corked;
-  len = c_len;
-  corked = NULL; c_size = c_len = 0;
+  buff = CUS corked->s;
+  len = corked->ptr;
+  corked = NULL;
   }
 
 for (left = len; left > 0;)
@@ -2819,7 +2857,7 @@ if (!RAND_status())
   gettimeofday(&r.tv, NULL);
   r.p = getpid();
 
-  RAND_seed((uschar *)(&r), sizeof(r));
+  RAND_seed(US (&r), sizeof(r));
   }
 /* We're after pseudo-random, not random; if we still don't have enough data
 in the internal PRNG then our options are limited.  We could sleep and hope