BUG/MEDIUM: ssl: Fix a memory leak in DHE key exchange

OpenSSL does not free the DH * value returned by the callback specified with SSL_CTX_set_tmp_dh_callback(),
leading to a memory leak for SSL/TLS connections using Diffie Hellman Ephemeral key exchange.
This patch fixes the leak by allocating the DH * structs holding the DH parameters once, at configuration time.

Note: this fix must be backported to 1.5.
This commit is contained in:
Remi Gacogne 2014-07-15 11:36:40 +02:00 committed by Willy Tarreau
parent e63a1eb290
commit 8de5415b85

View File

@ -105,6 +105,13 @@ enum {
int sslconns = 0;
int totalsslconns = 0;
#ifndef OPENSSL_NO_DH
static DH *local_dh_1024 = NULL;
static DH *local_dh_2048 = NULL;
static DH *local_dh_4096 = NULL;
static DH *local_dh_8192 = NULL;
#endif /* OPENSSL_NO_DH */
#ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB
struct certificate_ocsp {
struct ebmb_node key;
@ -1034,16 +1041,16 @@ static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
}
if (keylen >= 8192) {
dh = ssl_get_dh_8192();
dh = local_dh_8192;
}
else if (keylen >= 4096) {
dh = ssl_get_dh_4096();
dh = local_dh_4096;
}
else if (keylen >= 2048) {
dh = ssl_get_dh_2048();
dh = local_dh_2048;
}
else {
dh = ssl_get_dh_1024();
dh = local_dh_1024;
}
return dh;
@ -1079,11 +1086,11 @@ int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
if (global.tune.ssl_default_dh_param <= 1024) {
/* we are limited to DH parameter of 1024 bits anyway */
dh = ssl_get_dh_1024();
if (dh == NULL)
local_dh_1024 = ssl_get_dh_1024();
if (local_dh_1024 == NULL)
goto end;
SSL_CTX_set_tmp_dh(ctx, dh);
SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
}
else {
SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
@ -1594,6 +1601,28 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy
global.tune.ssl_default_dh_param = 1024;
}
#ifndef OPENSSL_NO_DH
if (global.tune.ssl_default_dh_param >= 1024) {
if (local_dh_1024 == NULL) {
local_dh_1024 = ssl_get_dh_1024();
}
if (global.tune.ssl_default_dh_param >= 2048) {
if (local_dh_2048 == NULL) {
local_dh_2048 = ssl_get_dh_2048();
}
if (global.tune.ssl_default_dh_param >= 4096) {
if (local_dh_4096 == NULL) {
local_dh_4096 = ssl_get_dh_4096();
}
if (global.tune.ssl_default_dh_param >= 8192 &&
local_dh_8192 == NULL) {
local_dh_8192 = ssl_get_dh_8192();
}
}
}
}
#endif /* OPENSSL_NO_DH */
SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);