X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/bc338899110ea22098559081f77cbd0f7a8044bd..51424d0857ca09e1082aeacf177e2df6fea37eda:/src/src/tls-openssl.c diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 2b8d798c9..2f08e43c6 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2013 */ +/* Copyright (c) University of Cambridge 1995 - 2014 */ /* See the file NOTICE for conditions of use and distribution. */ /* Portions Copyright (c) The OpenSSL Project 1999 */ @@ -276,7 +276,11 @@ if (state == 0) txt); tlsp->certificate_verified = FALSE; *calledp = TRUE; - if (!*optionalp) return 0; /* reject */ + if (!*optionalp) + { + tlsp->peercert = X509_dup(x509ctx->current_cert); + return 0; /* reject */ + } DEBUG(D_tls) debug_printf("SSL verify failure overridden (host in " "tls_try_verify_hosts)\n"); return 1; /* accept */ @@ -303,6 +307,7 @@ else DEBUG(D_tls) debug_printf("SSL%s peer: %s\n", *calledp ? "" : " authenticated", txt); tlsp->peerdn = txt; + tlsp->peercert = X509_dup(x509ctx->current_cert); } /*XXX JGH: this looks bogus - we set "verified" first time through, which @@ -1137,37 +1142,9 @@ construct_cipher_name(SSL *ssl, uschar *cipherbuf, int bsize, int *bits) yet reflect that. It should be a safe change anyway, even 0.9.8 versions have the accessor functions use const in the prototype. */ const SSL_CIPHER *c; -uschar *ver; - -switch (ssl->session->ssl_version) - { - case SSL2_VERSION: - ver = US"SSLv2"; - break; +const uschar *ver; - case SSL3_VERSION: - ver = US"SSLv3"; - break; - - case TLS1_VERSION: - ver = US"TLSv1"; - break; - -#ifdef TLS1_1_VERSION - case TLS1_1_VERSION: - ver = US"TLSv1.1"; - break; -#endif - -#ifdef TLS1_2_VERSION - case TLS1_2_VERSION: - ver = US"TLSv1.2"; - break; -#endif - - default: - ver = US"UNKNOWN"; - } +ver = (const uschar *)SSL_get_version(ssl); c = (const SSL_CIPHER *) SSL_get_current_cipher(ssl); SSL_CIPHER_get_bits(c, bits); @@ -1461,6 +1438,11 @@ DEBUG(D_tls) debug_printf("Shared ciphers: %s\n", buf); } +/* Record the certificate we presented */ + { + X509 * crt = SSL_get_certificate(server_ssl); + tls_in.ourcert = crt ? X509_dup(crt) : NULL; + } /* Only used by the server-side tls (tls_in), including tls_getc. Client-side (tls_out) reads (seem to?) go via @@ -1504,6 +1486,8 @@ Argument: dh_min_bits minimum number of bits acceptable in server's DH prime (unused in OpenSSL) timeout startup timeout + verify_hosts mandatory client verification + try_verify_hosts optional client verification Returns: OK on success FAIL otherwise - note that tls_error() will not give DEFER @@ -1518,7 +1502,8 @@ tls_client_start(int fd, host_item *host, address_item *addr, #ifdef EXPERIMENTAL_OCSP uschar *hosts_require_ocsp, #endif - int dh_min_bits ARG_UNUSED, int timeout) + int dh_min_bits ARG_UNUSED, int timeout, + uschar *verify_hosts, uschar *try_verify_hosts) { static uschar txt[256]; uschar *expciphers; @@ -1556,8 +1541,22 @@ if (expciphers != NULL) return tls_error(US"SSL_CTX_set_cipher_list", host, NULL); } -rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, verify_callback_client); -if (rc != OK) return rc; +/* stick to the old behaviour for compatibility if tls_verify_certificates is + set but both tls_verify_hosts and tls_try_verify_hosts is not set. Check only + the specified host patterns if one of them is defined */ +if (((verify_hosts == NULL) && (try_verify_hosts == NULL)) || + (verify_check_host(&verify_hosts) == OK)) + { + rc = setup_certs(client_ctx, verify_certs, crl, host, FALSE, verify_callback_client); + if (rc != OK) return rc; + client_verify_optional = FALSE; + } +else if (verify_check_host(&try_verify_hosts) == OK) + { + rc = setup_certs(client_ctx, verify_certs, crl, host, TRUE, verify_callback_client); + if (rc != OK) return rc; + client_verify_optional = TRUE; + } if ((client_ssl = SSL_new(client_ctx)) == NULL) return tls_error(US"SSL_new", host, NULL); SSL_set_session_id_context(client_ssl, sid_ctx, Ustrlen(sid_ctx)); @@ -1608,12 +1607,13 @@ if (rc <= 0) DEBUG(D_tls) debug_printf("SSL_connect succeeded\n"); /* Beware anonymous ciphers which lead to server_cert being NULL */ +/*XXX server_cert is never freed... use X509_free() */ server_cert = SSL_get_peer_certificate (client_ssl); if (server_cert) { tls_out.peerdn = US X509_NAME_oneline(X509_get_subject_name(server_cert), CS txt, sizeof(txt)); - tls_out.peerdn = txt; + tls_out.peerdn = txt; /*XXX a static buffer... */ } else tls_out.peerdn = NULL; @@ -1621,6 +1621,12 @@ else construct_cipher_name(client_ssl, cipherbuf, sizeof(cipherbuf), &tls_out.bits); tls_out.cipher = cipherbuf; +/* Record the certificate we presented */ + { + X509 * crt = SSL_get_certificate(client_ssl); + tls_out.ourcert = crt ? X509_dup(crt) : NULL; + } + tls_out.active = fd; return OK; } @@ -1934,6 +1940,11 @@ one version of OpenSSL but the run-time linker picks up another version, it can result in serious failures, including crashing with a SIGSEGV. So report the version found by the compiler and the run-time version. +Note: some OS vendors backport security fixes without changing the version +number/string, and the version date remains unchanged. The _build_ date +will change, so we can more usefully assist with version diagnosis by also +reporting the build date. + Arguments: a FILE* to print the results to Returns: nothing */ @@ -1942,9 +1953,13 @@ void tls_version_report(FILE *f) { fprintf(f, "Library version: OpenSSL: Compile: %s\n" - " Runtime: %s\n", + " Runtime: %s\n" + " : %s\n", OPENSSL_VERSION_TEXT, - SSLeay_version(SSLEAY_VERSION)); + SSLeay_version(SSLEAY_VERSION), + SSLeay_version(SSLEAY_BUILT_ON)); +/* third line is 38 characters for the %s and the line is 73 chars long; +the OpenSSL output includes a "built on: " prefix already. */ } @@ -2252,4 +2267,6 @@ for (s=option_spec; *s != '\0'; /**/) return TRUE; } +/* vi: aw ai sw=2 +*/ /* End of tls-openssl.c */