--- contrib/mod_tls.c
+++ contrib/mod_tls.c
@@ -461,7 +461,7 @@ static tls_sess_cache_t *tls_sess_cache
static SSL *ctrl_ssl = NULL;
static SSL_CTX *ssl_ctx = NULL;
static X509_STORE *tls_crl_store = NULL;
-static DH *tls_tmp_dh = NULL;
+static array_header *tls_tmp_dhs = NULL;
static RSA *tls_tmp_rsa = NULL;
/* SSL/TLS support functions */
@@ -1952,58 +1952,60 @@ static int tls_ctrl_renegotiate_cb(CALLB
#endif
static DH *tls_dh_cb(SSL *ssl, int is_export, int keylength) {
- FILE *fp = NULL;
-
- if (tls_tmp_dh) {
- return tls_tmp_dh;
- }
+ DH *dh = NULL;
- if (tls_dhparam_file) {
- fp = fopen(tls_dhparam_file, "r");
- if (fp) {
- tls_tmp_dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
- fclose(fp);
+ if (tls_tmp_dhs != NULL &&
+ tls_tmp_dhs->nelts > 0) {
+ register unsigned int i;
+ DH **dhs;
- if (tls_tmp_dh) {
- return tls_tmp_dh;
+ dhs = tls_tmp_dhs->elts;
+ for (i = 0; i < tls_tmp_dhs->nelts; i++) {
+ /* Note: the keylength argument is in BITS, but DH_size() returns
+ * the number of BYTES.
+ */
+ if (DH_size(dhs[i]) == (keylength / 8)) {
+ return dhs[i];
}
-
- } else {
- pr_log_debug(DEBUG3, MOD_TLS_VERSION
- ": unable to open TLSDHParamFile '%s': %s", tls_dhparam_file,
- strerror(errno));
}
}
switch (keylength) {
case 512:
- tls_tmp_dh = get_dh512();
+ dh = get_dh512();
break;
case 768:
- tls_tmp_dh = get_dh768();
+ dh = get_dh768();
break;
case 1024:
- tls_tmp_dh = get_dh1024();
+ dh = get_dh1024();
break;
case 1536:
- tls_tmp_dh = get_dh1536();
+ dh = get_dh1536();
break;
case 2048:
- tls_tmp_dh = get_dh2048();
+ dh = get_dh2048();
break;
default:
tls_log("unsupported DH key length %d requested, returning 1024 bits",
keylength);
- tls_tmp_dh = get_dh1024();
+ dh = get_dh1024();
break;
}
- return tls_tmp_dh;
+ /* Add this DH to the list, so that it can be freed properly later. */
+ if (tls_tmp_dhs == NULL) {
+ tls_tmp_dhs = make_array(session.pool, 1, sizeof(DH *));
+ }
+
+ *((DH **) push_array(tls_tmp_dhs)) = dh;
+
+ return dh;
}
/* Post 0.9.7a, RSA blinding is turned on by default, so there is no need to
@@ -3018,9 +3020,16 @@ static void tls_cleanup(int flags) {
ssl_ctx = NULL;
}
- if (tls_tmp_dh) {
- DH_free(tls_tmp_dh);
- tls_tmp_dh = NULL;
+ if (tls_tmp_dhs) {
+ register unsigned int i;
+ DH **dhs;
+
+ dhs = tls_tmp_dhs->elts;
+ for (i = 0; i < tls_tmp_dhs->nelts; i++) {
+ DH_free(dhs[i]);
+ }
+
+ tls_tmp_dhs = NULL;
}
if (tls_tmp_rsa) {
@@ -7320,6 +7329,38 @@ static int tls_sess_init(void) {
tls_crl_path = get_param_ptr(main_server->conf, "TLSCARevocationPath", FALSE);
tls_dhparam_file = get_param_ptr(main_server->conf, "TLSDHParamFile", FALSE);
+ if (tls_dhparam_file != NULL) {
+ FILE *fp;
+ int xerrno;
+
+ /* Load the DH params from the file. */
+ PRIVS_ROOT
+ fp = fopen(tls_dhparam_file, "r");
+ xerrno = errno;
+ PRIVS_RELINQUISH
+
+ if (fp != NULL) {
+ DH *dh;
+
+ dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
+ if (dh != NULL) {
+ tls_tmp_dhs = make_array(session.pool, 1, sizeof(DH *));
+ }
+
+ while (dh != NULL) {
+ pr_signals_handle();
+ *((DH **) push_array(tls_tmp_dhs)) = dh;
+ dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
+ }
+
+ fclose(fp);
+
+ } else {
+ pr_log_debug(DEBUG3, MOD_TLS_VERSION
+ ": unable to open TLSDHParamFile '%s': %s", tls_dhparam_file,
+ strerror(xerrno));
+ }
+ }
tls_dsa_cert_file = get_param_ptr(main_server->conf, "TLSDSACertificateFile",
FALSE);