X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/c0635b6dfe65ee24c2fb8d165beabc608d2fd1a5..a28050f855e0011e0b6f1b395d65e3cebcb277a2:/src/src/tls-openssl.c diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 71d748f5c..bfdfe211f 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -904,7 +904,7 @@ We do not free the stack since it could be needed a second time for SNI handling. Separately we might try to replace using OCSP_basic_verify() - which seems to not -be a public interface into the OpenSSL library (there's no manual entry) - +be a public interface into the OpenSSL library (there's no manual entry) - But what with? We also use OCSP_basic_verify in the client stapling callback. And there we NEED it; we must verify that status... unless the library does it for us anyway? */ @@ -1601,9 +1601,15 @@ if (init_options) else DEBUG(D_tls) debug_printf("no SSL CTX options to set\n"); -/* Disable session cache unconditionally */ - +/* We'd like to disable session cache unconditionally, but foolish Outlook +Express clients then give up the first TLS connection and make a second one +(which works). Only when there is an IMAP service on the same machine. +Presumably OE is trying to use the cache for A on B. Leave it enabled for +now, until we work out a decent way of presenting control to the config. It +will never be used because we use a new context every time. */ +#ifdef notdef (void) SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); +#endif /* Initialize with DH parameters if supplied */ /* Initialize ECDH temp key parameter selection */ @@ -1754,6 +1760,9 @@ chain_from_pem_file(const uschar * file, STACK_OF(X509) * verify_stack) BIO * bp; X509 * x; +while (sk_X509_num(verify_stack) > 0) + X509_free(sk_X509_pop(verify_stack)); + if (!(bp = BIO_new_file(CS file, "r"))) return FALSE; while ((x = PEM_read_bio_X509(bp, NULL, 0, NULL))) sk_X509_push(verify_stack, x); @@ -1763,7 +1772,8 @@ return TRUE; -/* Called by both client and server startup +/* Called by both client and server startup; on the server possibly +repeated after a Server Name Indication. Arguments: sctx SSL_CTX* to initialise @@ -1855,9 +1865,9 @@ if (expcerts && *expcerts) { STACK_OF(X509_NAME) * names = SSL_load_client_CA_file(CS file); + SSL_CTX_set_client_CA_list(sctx, names); DEBUG(D_tls) debug_printf("Added %d certificate authorities.\n", sk_X509_NAME_num(names)); - SSL_CTX_set_client_CA_list(sctx, names); } } } @@ -2095,9 +2105,9 @@ DEBUG(D_tls) smtp_read_response()/ip_recv(). Hence no need to duplicate for _in and _out. */ -ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size); +if (!ssl_xfer_buffer) ssl_xfer_buffer = store_malloc(ssl_xfer_buffer_size); ssl_xfer_buffer_lwm = ssl_xfer_buffer_hwm = 0; -ssl_xfer_eof = ssl_xfer_error = 0; +ssl_xfer_eof = ssl_xfer_error = FALSE; receive_getc = tls_getc; receive_getbuf = tls_getbuf; @@ -2296,8 +2306,23 @@ if (rc != OK) return rc; tls_out.certificate_verified = FALSE; client_verify_callback_called = FALSE; -if (!expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", - &expciphers, errstr)) +expciphers = NULL; +#ifdef SUPPORT_DANE +if (tlsa_dnsa) + { + /* We fall back to tls_require_ciphers if unset, empty or forced failure, but + other failures should be treated as problems. */ + if (ob->dane_require_tls_ciphers && + !expand_check(ob->dane_require_tls_ciphers, US"dane_require_tls_ciphers", + &expciphers, errstr)) + return FAIL; + if (expciphers && *expciphers == '\0') + expciphers = NULL; + } +#endif +if (!expciphers && + !expand_check(ob->tls_require_ciphers, US"tls_require_ciphers", + &expciphers, errstr)) return FAIL; /* In OpenSSL, cipher components are separated by hyphens. In GnuTLS, they @@ -2468,7 +2493,14 @@ if (error == SSL_ERROR_ZERO_RETURN) receive_ferror = smtp_ferror; receive_smtp_buffered = smtp_buffered; + if (SSL_get_shutdown(server_ssl) == SSL_RECEIVED_SHUTDOWN) + SSL_shutdown(server_ssl); + + sk_X509_pop_free(server_static_cbinfo->verify_stack, X509_free); SSL_free(server_ssl); + SSL_CTX_free(server_ctx); + server_static_cbinfo->verify_stack = NULL; + server_ctx = NULL; server_ssl = NULL; tls_in.active = -1; tls_in.bits = 0; @@ -2485,14 +2517,14 @@ else if (error == SSL_ERROR_SSL) { ERR_error_string(ERR_get_error(), ssl_errstring); log_write(0, LOG_MAIN, "TLS error (SSL_read): %s", ssl_errstring); - ssl_xfer_error = 1; + ssl_xfer_error = TRUE; return FALSE; } else if (error != SSL_ERROR_NONE) { DEBUG(D_tls) debug_printf("Got SSL error %d\n", error); - ssl_xfer_error = 1; + ssl_xfer_error = TRUE; return FALSE; } @@ -2702,15 +2734,19 @@ return len; daemon, to shut down the TLS library, without actually doing a shutdown (which would tamper with the SSL session in the parent process). -Arguments: TRUE if SSL_shutdown is to be called +Arguments: + shutdown 1 if TLS close-alert is to be sent, + 2 if also response to be waited for + Returns: nothing Used by both server-side and client-side TLS. */ void -tls_close(BOOL is_server, BOOL shutdown) +tls_close(BOOL is_server, int shutdown) { +SSL_CTX **ctxp = is_server ? &server_ctx : &client_ctx; SSL **sslp = is_server ? &server_ssl : &client_ssl; int *fdp = is_server ? &tls_in.active : &tls_out.active; @@ -2718,13 +2754,35 @@ if (*fdp < 0) return; /* TLS was not active */ if (shutdown) { - DEBUG(D_tls) debug_printf("tls_close(): shutting down SSL\n"); - SSL_shutdown(*sslp); + int rc; + DEBUG(D_tls) debug_printf("tls_close(): shutting down TLS%s\n", + shutdown > 1 ? " (with response-wait)" : ""); + + if ( (rc = SSL_shutdown(*sslp)) == 0 /* send "close notify" alert */ + && shutdown > 1) + { + alarm(2); + rc = SSL_shutdown(*sslp); /* wait for response */ + alarm(0); + } + + if (rc < 0) DEBUG(D_tls) + { + ERR_error_string(ERR_get_error(), ssl_errstring); + debug_printf("SSL_shutdown: %s\n", ssl_errstring); + } + } + +if (is_server) + { + sk_X509_pop_free(server_static_cbinfo->verify_stack, X509_free); + server_static_cbinfo->verify_stack = NULL; } +SSL_CTX_free(*ctxp); SSL_free(*sslp); +*ctxp = NULL; *sslp = NULL; - *fdp = -1; }