X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ee8b809061baea861fc87c41bcb72a62d76b0047..412885bdba907588c5ac8ea789e673c3198d381a:/src/src/tls-openssl.c diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index f0351451c..cc0ead02a 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -71,6 +71,8 @@ functions from the OpenSSL library. */ # 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 @@ -272,6 +274,7 @@ Server: typedef struct { SSL_CTX * ctx; SSL * ssl; + gstring * corked; } exim_openssl_client_tls_ctx; static SSL_CTX *server_ctx = NULL; @@ -368,7 +371,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; } @@ -1172,7 +1177,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 +1305,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 +1409,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 +1425,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 +1441,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 +1720,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 @@ -2120,7 +2128,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 +2282,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. */ @@ -2464,6 +2474,7 @@ BOOL require_ocsp = FALSE; rc = store_pool; store_pool = POOL_PERM; exim_client_ctx = store_get(sizeof(exim_openssl_client_tls_ctx)); +exim_client_ctx->corked = NULL; store_pool = rc; #ifdef SUPPORT_DANE @@ -2899,8 +2910,12 @@ int tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more) { int outbytes, error, left; -SSL * ssl = ct_ctx ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl; -static gstring * corked = NULL; +SSL * ssl = ct_ctx + ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl; +static gstring * server_corked = NULL; +gstring ** corkedp = ct_ctx + ? &((exim_openssl_client_tls_ctx *)ct_ctx)->corked : &server_corked; +gstring * corked = *corkedp; DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__, buff, (unsigned long)len, more ? ", more" : ""); @@ -2908,9 +2923,12 @@ DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__, /* 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 one stream does it, in one context (i.e. no store reset). Currently it is used -for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. */ -/*XXX + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's -a store reset there. */ +for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. +We support callouts done by the server process by using a separate client +context for the stashed information. */ +/* + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's +a store reset there, so use POOL_PERM. */ +/* + if CHUNKING, cmds EHLO,MAIL,RCPT(s),BDAT */ if (!ct_ctx && (more || corked)) { @@ -2926,10 +2944,13 @@ if (!ct_ctx && (more || corked)) #endif if (more) + { + *corkedp = corked; return len; + } buff = CUS corked->s; len = corked->ptr; - corked = NULL; + *corkedp = NULL; } for (left = len; left > 0;) @@ -3056,8 +3077,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. */