-/* $Cambridge: exim/src/src/tls-openssl.c,v 1.1 2004/10/07 10:39:01 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
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;
*/
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();
/* 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 */
{
DEBUG(D_tls) debug_printf("tls_certificate file %s\n", expanded);
if (!SSL_CTX_use_certificate_chain_file(ctx, CS expanded))
- return tls_error(US"SSL_CTX_use_certificate_chain_file", host);
+ return tls_error(string_sprintf(
+ "SSL_CTX_use_certificate_chain_file file=%s", expanded), host);
}
if (privatekey != 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))
- return tls_error(US"SSL_CTX_use_PrivateKey_file", host);
+ return tls_error(string_sprintf(
+ "SSL_CTX_use_PrivateKey_file file=%s", expanded), host);
}
}
#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 */
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
*/
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;
/* 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");
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;
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
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;
receive_ungetc = smtp_ungetc;
receive_feof = smtp_feof;
receive_ferror = smtp_ferror;
+ receive_smtp_buffered = smtp_buffered;
SSL_free(ssl);
ssl = NULL;