X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/d6453af2c864d0bd57785f5f808bc366d6f18970..f7572e5a358cd3d9581140b87e590d58b6c278f0:/src/src/tls-openssl.c diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 951e46c25..a9b67dcdd 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/tls-openssl.c,v 1.2 2004/11/25 15:29:37 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tls-openssl.c,v 1.12 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ /* This module provides the TLS (aka SSL) support for Exim using the OpenSSL @@ -182,9 +182,6 @@ else tls_peerdn = txt; } - -debug_printf("+++verify_callback_called=%d\n", verify_callback_called); - if (!verify_callback_called) tls_certificate_verified = TRUE; verify_callback_called = TRUE; @@ -293,8 +290,8 @@ Returns: OK/DEFER/FAIL */ static int -tls_init(host_item *host, uschar *dhparam, uschar *certificate, uschar *privatekey, - address_item *addr) +tls_init(host_item *host, uschar *dhparam, uschar *certificate, + uschar *privatekey, address_item *addr) { SSL_load_error_strings(); /* basic set up */ OpenSSL_add_ssl_algorithms(); @@ -346,8 +343,7 @@ if (!RAND_status()) /* Set up the information callback, which outputs if debugging is at a suitable level. */ -if (!(SSL_CTX_set_info_callback(ctx, (void (*)())info_callback))) - return tls_error(US"SSL_CTX_set_info_callback", host); +SSL_CTX_set_info_callback(ctx, (void (*)())info_callback); /* The following patch was supplied by Robert Roselius */ @@ -389,7 +385,11 @@ if (certificate != NULL) !expand_check(privatekey, US"tls_privatekey", &expanded)) return DEFER; - if (expanded != NULL) + /* If expansion was forced to fail, key_expanded will be NULL. If the result + of the expansion is an empty string, ignore it also, and assume the private + key is in the same file as the certificate. */ + + if (expanded != NULL && *expanded != 0) { DEBUG(D_tls) debug_printf("tls_privatekey file %s\n", expanded); if (!SSL_CTX_use_PrivateKey_file(ctx, CS expanded, SSL_FILETYPE_PEM)) @@ -526,34 +526,51 @@ if (expcerts != NULL) #if OPENSSL_VERSION_NUMBER > 0x00907000L + /* This bit of code is now the version supplied by Lars Mainka. (I have + * merely reformatted it into the Exim code style.) + + * "From here I changed the code to add support for multiple crl's + * in pem format in one file or to support hashed directory entries in + * pem format instead of a file. This method now uses the library function + * X509_STORE_load_locations to add the CRL location to the SSL context. + * OpenSSL will then handle the verify against CA certs and CRLs by + * itself in the verify callback." */ + if (!expand_check(crl, US"tls_crl", &expcrl)) return DEFER; if (expcrl != NULL && *expcrl != 0) { - BIO *crl_bio; - X509_CRL *crl_x509; - X509_STORE *cvstore; - - cvstore = SSL_CTX_get_cert_store(ctx); /* cert validation store */ - - crl_bio = BIO_new(BIO_s_file_internal()); - if (crl_bio != NULL) + struct stat statbufcrl; + if (Ustat(expcrl, &statbufcrl) < 0) { - if (BIO_read_filename(crl_bio, expcrl)) + log_write(0, LOG_MAIN|LOG_PANIC, + "failed to stat %s for certificates revocation lists", expcrl); + return DEFER; + } + else + { + /* is it a file or directory? */ + uschar *file, *dir; + X509_STORE *cvstore = SSL_CTX_get_cert_store(ctx); + if ((statbufcrl.st_mode & S_IFMT) == S_IFDIR) { - crl_x509 = PEM_read_bio_X509_CRL(crl_bio, NULL, NULL, NULL); - BIO_free(crl_bio); - X509_STORE_add_crl(cvstore, crl_x509); - X509_CRL_free(crl_x509); - X509_STORE_set_flags(cvstore, - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + file = NULL; + dir = expcrl; + DEBUG(D_tls) debug_printf("SSL CRL value is a directory %s\n", dir); } else { - BIO_free(crl_bio); - return tls_error(US"BIO_read_filename", host); + file = expcrl; + dir = NULL; + DEBUG(D_tls) debug_printf("SSL CRL value is a file %s\n", file); } + if (X509_STORE_load_locations(cvstore, CS file, CS dir) == 0) + return tls_error(US"X509_STORE_load_locations", host); + + /* setting the flags to check against the complete crl chain */ + + X509_STORE_set_flags(cvstore, + X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); } - else return tls_error(US"BIO_new", host); } #endif /* OPENSSL_VERSION_NUMBER > 0x00907000L */ @@ -580,6 +597,11 @@ a TLS session. Arguments: require_ciphers allowed ciphers + ------------------------------------------------------ + require_mac list of allowed MACs ) Not used + require_kx list of allowed key_exchange methods ) for + require_proto list of allowed protocols ) OpenSSL + ------------------------------------------------------ Returns: OK on success DEFER for errors before the start of the negotiation @@ -588,7 +610,8 @@ Returns: OK on success */ int -tls_server_start(uschar *require_ciphers) +tls_server_start(uschar *require_ciphers, uschar *require_mac, + uschar *require_kx, uschar *require_proto) { int rc; uschar *expciphers; @@ -666,7 +689,8 @@ if (!tls_on_connect) /* Now negotiate the TLS session. We put our own timer on it, since it seems that the OpenSSL library doesn't. */ -SSL_set_fd(ssl, fileno(smtp_out)); +SSL_set_wfd(ssl, fileno(smtp_out)); +SSL_set_rfd(ssl, fileno(smtp_in)); SSL_set_accept_state(ssl); DEBUG(D_tls) debug_printf("Calling SSL_accept\n"); @@ -709,6 +733,7 @@ receive_getc = tls_getc; receive_ungetc = tls_ungetc; receive_feof = tls_feof; receive_ferror = tls_ferror; +receive_smtp_buffered = tls_smtp_buffered; tls_active = fileno(smtp_out); return OK; @@ -727,12 +752,19 @@ return OK; Argument: fd the fd of the connection host connected host (for messages) + addr the first address dhparam DH parameter file certificate certificate file privatekey private key file verify_certs file for certificate verify crl file containing CRL require_ciphers list of allowed ciphers + ------------------------------------------------------ + require_mac list of allowed MACs ) Not used + require_kx list of allowed key_exchange methods ) for + require_proto list of allowed protocols ) OpenSSL + ------------------------------------------------------ + timeout startup timeout Returns: OK on success FAIL otherwise - note that tls_error() will not give DEFER @@ -742,7 +774,8 @@ Returns: OK on success int tls_client_start(int fd, host_item *host, address_item *addr, uschar *dhparam, uschar *certificate, uschar *privatekey, uschar *verify_certs, uschar *crl, - uschar *require_ciphers, int timeout) + uschar *require_ciphers, uschar *require_mac, uschar *require_kx, + uschar *require_proto, int timeout) { static uschar txt[256]; uschar *expciphers; @@ -854,6 +887,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; + receive_smtp_buffered = smtp_buffered; SSL_free(ssl); ssl = NULL;