X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/b1c749bb7f147e7f9215fe6067c848cf02938b92..184e88237dea64ce48076cdd0184612d057cbafd:/src/src/tls-gnu.c diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index aedf09bc2..891d1ea00 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/tls-gnu.c,v 1.8 2005/06/16 14:10:13 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tls-gnu.c,v 1.17 2007/01/08 10:50:18 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ /* This module provides TLS (aka SSL) support for Exim using the GnuTLS @@ -22,8 +22,7 @@ functions from the GnuTLS library. */ #define UNKNOWN_NAME "unknown" -#define DH_BITS 768 -#define RSA_BITS 512 +#define DH_BITS 1024 #define PARAM_SIZE 2*1024 @@ -37,7 +36,6 @@ enum { INITIALIZED_NOT, INITIALIZED_SERVER, INITIALIZED_CLIENT }; static BOOL initialized = INITIALIZED_NOT; static host_item *client_host; -static gnutls_rsa_params rsa_params = NULL; static gnutls_dh_params dh_params = NULL; static gnutls_certificate_server_credentials x509_cred = NULL; @@ -57,7 +55,6 @@ static const int kx_priority[16] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, - GNUTLS_KX_RSA_EXPORT, 0 }; static int default_cipher_priority[16] = { @@ -233,10 +230,10 @@ return TRUE; /* accept */ /************************************************* -* Setup up RSA and DH parameters * +* Setup up DH parameters * *************************************************/ -/* Generating the RSA and D-H parameters takes a long time. They only need to +/* Generating the D-H parameters may take a long time. They only need to be re-generated every so often, depending on security policy. What we do is to keep these parameters in a file in the spool directory. If the file does not exist, we generate them. This means that it is easy to cause a regeneration. @@ -253,18 +250,15 @@ Returns: OK/DEFER/FAIL */ static int -init_rsa_dh(host_item *host) +init_dh(host_item *host) { int fd; -int ret = -1; +int ret; gnutls_datum m; uschar filename[200]; /* Initialize the data structures for holding the parameters */ -ret = gnutls_rsa_params_init(&rsa_params); -if (ret < 0) return tls_error(US"init rsa_params", host, ret); - ret = gnutls_dh_params_init(&dh_params); if (ret < 0) return tls_error(US"init dh_params", host, ret); @@ -275,10 +269,7 @@ if (!string_format(filename, sizeof(filename), "%s/gnutls-params", return tls_error(US"overlong filename", host, 0); /* Open the cache file for reading and if successful, read it and set up the -parameters. If we can't set up the RSA parameters, assume that we are dealing -with an old-style cache file that is in another format, and fall through to -compute new values. However, if we correctly get RSA parameters, a failure to -set up D-H parameters is treated as an error. */ +parameters. */ fd = Uopen(filename, O_RDONLY, 0); if (fd >= 0) @@ -298,19 +289,9 @@ if (fd >= 0) return tls_error(US"TLS cache read failed", host, 0); (void)close(fd); - ret = gnutls_rsa_params_import_pkcs1(rsa_params, &m, GNUTLS_X509_FMT_PEM); - if (ret < 0) - { - DEBUG(D_tls) - debug_printf("RSA params import failed: assume old-style cache file\n"); - } - else - { - ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM); - if (ret < 0) - return tls_error(US"DH params import", host, ret); - DEBUG(D_tls) debug_printf("read RSA and D-H parameters from file\n"); - } + ret = gnutls_dh_params_import_pkcs3(dh_params, &m, GNUTLS_X509_FMT_PEM); + if (ret < 0) return tls_error(US"DH params import", host, ret); + DEBUG(D_tls) debug_printf("read D-H parameters from file\n"); free(m.data); } @@ -318,7 +299,13 @@ if (fd >= 0) /* If the file does not exist, fall through to compute new data and cache it. If there was any other opening error, it is serious. */ -else if (errno != ENOENT) +else if (errno == ENOENT) + { + ret = -1; + DEBUG(D_tls) + debug_printf("parameter cache file %s does not exist\n", filename); + } +else return tls_error(string_open_failed(errno, "%s for reading", filename), host, 0); @@ -332,10 +319,6 @@ if (ret < 0) { uschar tempfilename[sizeof(filename) + 10]; - DEBUG(D_tls) debug_printf("generating %d bit RSA key...\n", RSA_BITS); - ret = gnutls_rsa_params_generate2(rsa_params, RSA_BITS); - if (ret < 0) return tls_error(US"RSA key generation", host, ret); - DEBUG(D_tls) debug_printf("generating %d bit Diffie-Hellman key...\n", DH_BITS); ret = gnutls_dh_params_generate2(dh_params, DH_BITS); @@ -355,9 +338,7 @@ if (ret < 0) * certtool or other programs. * * The commands for certtool are: - * $ certtool --generate-privkey --bits 512 >params - * $ echo "" >>params - * $ certtool --generate-dh-params --bits 1024 >> params + * $ certtool --generate-dh-params --bits 1024 > params */ m.size = PARAM_SIZE; @@ -365,16 +346,6 @@ if (ret < 0) if (m.data == NULL) return tls_error(US"memory allocation failed", host, 0); - ret = gnutls_rsa_params_export_pkcs1(rsa_params, GNUTLS_X509_FMT_PEM, - m.data, &m.size); - if (ret < 0) return tls_error(US"RSA params export", host, ret); - - /* Do not write the null termination byte. */ - - m.size = Ustrlen(m.data); - if (write(fd, m.data, m.size) != m.size || write(fd, "\n", 1) != 1) - return tls_error(US"TLS cache write failed", host, 0); - m.size = PARAM_SIZE; ret = gnutls_dh_params_export_pkcs3(dh_params, GNUTLS_X509_FMT_PEM, m.data, &m.size); @@ -391,10 +362,10 @@ if (ret < 0) return tls_error(string_sprintf("failed to rename %s as %s: %s", tempfilename, filename, strerror(errno)), host, 0); - DEBUG(D_tls) debug_printf("wrote RSA and D-H parameters to file\n"); + DEBUG(D_tls) debug_printf("wrote D-H parameters to file %s\n", filename); } -DEBUG(D_tls) debug_printf("initialized RSA and D-H parameters\n"); +DEBUG(D_tls) debug_printf("initialized D-H parameters\n"); return OK; } @@ -430,10 +401,10 @@ initialized = (host == NULL)? INITIALIZED_SERVER : INITIALIZED_CLIENT; rc = gnutls_global_init(); if (rc < 0) return tls_error(US"tls-init", host, rc); -/* Create RSA and D-H parameters, or read them from the cache file. This -function does its own SMTP error messaging. */ +/* Create D-H parameters, or read them from the cache file. This function does +its own SMTP error messaging. */ -rc = init_rsa_dh(host); +rc = init_dh(host); if (rc != OK) return rc; /* Create the credentials structure */ @@ -447,12 +418,19 @@ may be required for different sessions. */ if (!expand_check(certificate, US"tls_certificate", &cert_expanded)) return DEFER; +key_expanded = NULL; if (privatekey != NULL) { if (!expand_check(privatekey, US"tls_privatekey", &key_expanded)) return DEFER; } -else key_expanded = cert_expanded; + +/* 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 that the private +key is in the same file as the certificate. */ + +if (key_expanded == NULL || *key_expanded == 0) + key_expanded = cert_expanded; /* Set the certificate and private keys */ @@ -525,7 +503,6 @@ if (cas != NULL) /* Associate the parameters with the x509 credentials structure. */ gnutls_certificate_set_dh_params(x509_cred, dh_params); -gnutls_certificate_set_rsa_export_params(x509_cred, rsa_params); DEBUG(D_tls) debug_printf("initialized certificate stuff\n"); return OK; @@ -832,7 +809,8 @@ if (!tls_on_connect) /* Now negotiate the TLS session. We put our own timer on it, since it seems that the GnuTLS library doesn't. */ -gnutls_transport_set_ptr(tls_session, (gnutls_transport_ptr)fileno(smtp_out)); +gnutls_transport_set_ptr2(tls_session, (gnutls_transport_ptr)fileno(smtp_in), + (gnutls_transport_ptr)fileno(smtp_out)); sigalrm_seen = FALSE; if (smtp_receive_timeout > 0) alarm(smtp_receive_timeout); @@ -856,8 +834,8 @@ if (rc < 0) if (!sigalrm_seen) { - fclose(smtp_out); - fclose(smtp_in); + (void)fclose(smtp_out); + (void)fclose(smtp_in); } return FAIL;