Debug: fix coding in dnssec reporting. Bug 2205
[exim.git] / src / src / tls-openssl.c
index 66483704c93a25399432e2ea34e5b6ed39d4f1c0..9816f734f3018a0bcf0638139c759a9dc144d7fa 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
 
 
@@ -228,14 +228,13 @@ return host ? FAIL : DEFER;
 
 
 
-#ifdef EXIM_HAVE_EPHEM_RSA_KEX
 /*************************************************
 *        Callback to generate RSA key            *
 *************************************************/
 
 /*
 Arguments:
-  s          SSL connection
+  s          SSL connection (not used)
   export     not used
   keylength  keylength
 
@@ -270,7 +269,6 @@ if (!(rsa_key = RSA_generate_key(keylength, RSA_F4, NULL, NULL)))
   }
 return rsa_key;
 }
-#endif
 
 
 
@@ -977,8 +975,7 @@ if (!(x509 = X509_new()))
   goto err;
 
 where = US"generating pkey";
-               /* deprecated, use RSA_generate_key_ex() */
-if (!(rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL)))
+if (!(rsa = rsa_callback(NULL, 0, 1024)))
   goto err;
 
 where = US"assigning pkey";
@@ -1024,6 +1021,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 +1069,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 +1077,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 +1088,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 +1112,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 +1535,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,11 +2609,10 @@ 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, %d%s)\n", __FUNCTION__,
-  buff, left, more ? ", more" : "");
+DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
+  buff, (unsigned long)len, more ? ", more" : "");
 
 /* Lacking a CORK or MSG_MORE facility (such as GnuTLS has) we copy data when
 "more" is notified.  This hack is only ok if small amounts are involved AND only
@@ -2586,12 +2621,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 +2854,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