X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Ftls-openssl.c;h=5cb1ac1e82b61dd58c04d64f7e3814cfe5bfbaec;hb=d7978c0f8af20ff4c3f770589b1bb81568aecff3;hp=f0351451c6ed5d8b48039eda84a351b51dcd1730;hpb=ee8b809061baea861fc87c41bcb72a62d76b0047;p=exim.git diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index f0351451c..5cb1ac1e8 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -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; itype == 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); } @@ -2274,6 +2276,8 @@ if (rc <= 0) } DEBUG(D_tls) debug_printf("SSL_accept was successful\n"); +ERR_clear_error(); /* Even success can leave errors in the stack. Seen with + anon-authentication ciphersuite negociated. */ /* TLS has been set up. Adjust the input functions to read via TLS, and initialize things. */ @@ -2366,7 +2370,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 +2377,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 +2900,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 +2934,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 +3058,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 +3169,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 +3226,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 +3294,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 +3314,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')