Use C99 initialisations for iterators
[exim.git] / src / src / tls-openssl.c
index f0351451c6ed5d8b48039eda84a351b51dcd1730..4566baa366897dab87df16a671d8eb9c4033a06d 100644 (file)
@@ -54,23 +54,24 @@ functions from the OpenSSL library. */
 # define EXIM_HAVE_SHA256
 #endif
 
-/*
- * X509_check_host provides sane certificate hostname checking, but was added
- * to OpenSSL late, after other projects forked off the code-base.  So in
- * addition to guarding against the base version number, beware that LibreSSL
- * does not (at this time) support this function.
- *
- * If LibreSSL gains a different API, perhaps via libtls, then we'll probably
- * opt to disentangle and ask a LibreSSL user to provide glue for a third
- * crypto provider for libtls instead of continuing to tie the OpenSSL glue
- * into even twistier knots.  If LibreSSL gains the same API, we can just
- * change this guard and punt the issue for a while longer.
- */
+/* X509_check_host provides sane certificate hostname checking, but was added
+to OpenSSL late, after other projects forked off the code-base.  So in
+addition to guarding against the base version number, beware that LibreSSL
+does not (at this time) support this function.
+
+If LibreSSL gains a different API, perhaps via libtls, then we'll probably
+opt to disentangle and ask a LibreSSL user to provide glue for a third
+crypto provider for libtls instead of continuing to tie the OpenSSL glue
+into even twistier knots.  If LibreSSL gains the same API, we can just
+change this guard and punt the issue for a while longer. */
+
 #ifndef LIBRESSL_VERSION_NUMBER
 # if OPENSSL_VERSION_NUMBER >= 0x010100000L
 #  define EXIM_HAVE_OPENSSL_CHECKHOST
 #  define EXIM_HAVE_OPENSSL_DH_BITS
 #  define EXIM_HAVE_OPENSSL_TLS_METHOD
+# else
+#  define EXIM_NEED_OPENSSL_INIT
 # endif
 # if OPENSSL_VERSION_NUMBER >= 0x010000000L \
     && (OPENSSL_VERSION_NUMBER & 0x0000ff000L) >= 0x000002000L
@@ -218,10 +219,9 @@ static int exim_openssl_options_size = nelem(exim_openssl_options);
 void
 options_tls(void)
 {
-struct exim_openssl_option * o;
 uschar buf[64];
 
-for (o = exim_openssl_options;
+for (struct exim_openssl_option * o = exim_openssl_options;
      o < exim_openssl_options + nelem(exim_openssl_options); o++)
   {
   /* Trailing X is workaround for problem with _OPT_OPENSSL_NO_TLSV1
@@ -368,7 +368,9 @@ if (!msg)
   msg = US ssl_errstring;
   }
 
-if (errstr) *errstr = string_sprintf("(%s): %s", prefix, msg);
+msg = string_sprintf("(%s): %s", prefix, msg);
+DEBUG(D_tls) debug_printf("TLS error '%s'\n", msg);
+if (errstr) *errstr = msg;
 return host ? FAIL : DEFER;
 }
 
@@ -424,10 +426,9 @@ void
 x509_store_dump_cert_s_names(X509_STORE * store)
 {
 STACK_OF(X509_OBJECT) * roots= store->objs;
-int i;
 static uschar name[256];
 
-for(i= 0; i<sk_X509_OBJECT_num(roots); i++)
+for (int i= 0; i < sk_X509_OBJECT_num(roots); i++)
   {
   X509_OBJECT * tmp_obj= sk_X509_OBJECT_value(roots, i);
   if(tmp_obj->type == X509_LU_X509)
@@ -1137,8 +1138,7 @@ bad:
   if (f.running_in_test_harness)
     {
     extern char ** environ;
-    uschar ** p;
-    if (environ) for (p = USS environ; *p; p++)
+    if (environ) for (uschar ** p = USS environ; *p; p++)
       if (Ustrncmp(*p, "EXIM_TESTHARNESS_DISABLE_OCSPVALIDITYCHECK", 42) == 0)
        {
        DEBUG(D_tls) debug_printf("Supplying known bad OCSP response\n");
@@ -1172,7 +1172,7 @@ if (!(x509 = X509_new()))
   goto err;
 
 where = US"generating pkey";
-if (!(rsa = rsa_callback(NULL, 0, 1024)))
+if (!(rsa = rsa_callback(NULL, 0, 2048)))
   goto err;
 
 where = US"assigning pkey";
@@ -1300,8 +1300,8 @@ else
       if ((err = tls_add_certfile(sctx, cbinfo, expanded, errstr)))
        return err;
 
-  if (cbinfo->privatekey != NULL &&
-      !expand_check(cbinfo->privatekey, US"tls_privatekey", &expanded, errstr))
+  if (  cbinfo->privatekey
+     && !expand_check(cbinfo->privatekey, US"tls_privatekey", &expanded, errstr))
     return DEFER;
 
   /* If expansion was forced to fail, key_expanded will be NULL. If the result
@@ -1404,7 +1404,7 @@ if (!(server_sni = SSL_CTX_new(SSLv23_server_method())))
   {
   ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
   DEBUG(D_tls) debug_printf("SSL_CTX_new() failed: %s\n", ssl_errstring);
-  return SSL_TLSEXT_ERR_NOACK;
+  goto bad;
   }
 
 /* Not sure how many of these are actually needed, since SSL object
@@ -1420,11 +1420,11 @@ SSL_CTX_set_tlsext_servername_arg(server_sni, cbinfo);
 if (  !init_dh(server_sni, cbinfo->dhparam, NULL, &dummy_errstr)
    || !init_ecdh(server_sni, NULL, &dummy_errstr)
    )
-  return SSL_TLSEXT_ERR_NOACK;
+  goto bad;
 
 if (  cbinfo->server_cipher_list
    && !SSL_CTX_set_cipher_list(server_sni, CS cbinfo->server_cipher_list))
-  return SSL_TLSEXT_ERR_NOACK;
+  goto bad;
 
 #ifndef DISABLE_OCSP
 if (cbinfo->u_ocsp.server.file)
@@ -1436,17 +1436,18 @@ if (cbinfo->u_ocsp.server.file)
 
 if ((rc = setup_certs(server_sni, tls_verify_certificates, tls_crl, NULL, FALSE,
                      verify_callback_server, &dummy_errstr)) != OK)
-  return SSL_TLSEXT_ERR_NOACK;
+  goto bad;
 
 /* do this after setup_certs, because this can require the certs for verifying
 OCSP information. */
 if ((rc = tls_expand_session_files(server_sni, cbinfo, &dummy_errstr)) != OK)
-  return SSL_TLSEXT_ERR_NOACK;
+  goto bad;
 
 DEBUG(D_tls) debug_printf("Switching SSL context.\n");
 SSL_set_SSL_CTX(s, server_sni);
-
 return SSL_TLSEXT_ERR_OK;
+
+bad: return SSL_TLSEXT_ERR_ALERT_FATAL;
 }
 #endif /* EXIM_HAVE_OPENSSL_TLSEXT */
 
@@ -1714,8 +1715,10 @@ cbinfo->host = host;
 cbinfo->event_action = NULL;
 #endif
 
+#ifdef EXIM_NEED_OPENSSL_INIT
 SSL_load_error_strings();          /* basic set up */
 OpenSSL_add_ssl_algorithms();
+#endif
 
 #ifdef EXIM_HAVE_SHA256
 /* SHA256 is becoming ever more popular. This makes sure it gets added to the
@@ -2045,14 +2048,13 @@ if (expcerts && *expcerts)
       /* Load the list of CAs for which we will accept certs, for sending
       to the client.  This is only for the one-file tls_verify_certificates
       variant.
-      If a list isn't loaded into the server, but
-      some verify locations are set, the server end appears to make
-      a wildcard request for client certs.
+      If a list isn't loaded into the server, but some verify locations are set,
+      the server end appears to make a wildcard request for client certs.
       Meanwhile, the client library as default behaviour *ignores* the list
       we send over the wire - see man SSL_CTX_set_client_cert_cb.
       Because of this, and that the dir variant is likely only used for
-      the public-CA bundle (not for a private CA), not worth fixing.
-      */
+      the public-CA bundle (not for a private CA), not worth fixing.  */
+
       if (file)
        {
        STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file);
@@ -2120,7 +2122,7 @@ if (expcerts && *expcerts)
   /* If verification is optional, don't fail if no certificate */
 
   SSL_CTX_set_verify(sctx,
-    SSL_VERIFY_PEER | (optional? 0 : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
+    SSL_VERIFY_PEER | (optional ? 0 : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),
     cert_vfy_cb);
   }
 
@@ -2366,7 +2368,6 @@ return OK;
 static int
 dane_tlsa_load(SSL * ssl, host_item * host, dns_answer * dnsa, uschar ** errstr)
 {
-dns_record * rr;
 dns_scan dnss;
 const char * hostnames[2] = { CS host->name, NULL };
 int found = 0;
@@ -2374,8 +2375,7 @@ int found = 0;
 if (DANESSL_init(ssl, NULL, hostnames) != 1)
   return tls_error(US"hostnames load", host, NULL, errstr);
 
-for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS);
-     rr;
+for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
      rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
     ) if (rr->type == T_TLSA && rr->size > 3)
   {
@@ -2898,7 +2898,7 @@ Used by both server-side and client-side TLS.
 int
 tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
 {
-int outbytes, error, left;
+int outbytes, error;
 SSL * ssl = ct_ctx ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
 static gstring * corked = NULL;
 
@@ -2932,7 +2932,7 @@ if (!ct_ctx && (more || corked))
   corked = NULL;
   }
 
-for (left = len; left > 0;)
+for (int left = len; left > 0;)
   {
   DEBUG(D_tls) debug_printf("SSL_write(%p, %p, %d)\n", ssl, buff, left);
   outbytes = SSL_write(ssl, CS buff, left);
@@ -3056,8 +3056,10 @@ uschar *s, *expciphers, *err;
 /* this duplicates from tls_init(), we need a better "init just global
 state, for no specific purpose" singleton function of our own */
 
+#ifdef EXIM_NEED_OPENSSL_INIT
 SSL_load_error_strings();
 OpenSSL_add_ssl_algorithms();
+#endif
 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
 /* SHA256 is becoming ever more popular. This makes sure it gets added to the
 list of available digests. */
@@ -3165,7 +3167,6 @@ unsigned int r;
 int i, needed_len;
 static pid_t pidlast = 0;
 pid_t pidnow;
-uschar *p;
 uschar smallbuf[sizeof(r)];
 
 if (max <= 1)
@@ -3223,11 +3224,8 @@ if (i < 0)
   }
 
 r = 0;
-for (p = smallbuf; needed_len; --needed_len, ++p)
-  {
-  r *= 256;
-  r += *p;
-  }
+for (uschar * p = smallbuf; needed_len; --needed_len, ++p)
+  r = 256 * r + *p;
 
 /* We don't particularly care about weighted results; if someone wants
 smooth distribution and cares enough then they should submit a patch then. */
@@ -3294,7 +3292,7 @@ BOOL
 tls_openssl_options_parse(uschar *option_spec, long *results)
 {
 long result, item;
-uschar *s, *end;
+uschar *end;
 uschar keep_c;
 BOOL adding, item_parsed;
 
@@ -3314,7 +3312,7 @@ if (!option_spec)
   return TRUE;
   }
 
-for (s=option_spec; *s != '\0'; /**/)
+for (uschar * s = option_spec; *s != '\0'; /**/)
   {
   while (isspace(*s)) ++s;
   if (*s == '\0')