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.
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 375225d..cf8adc7 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -105,6 +105,13 @@
 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 @@
 	}
 
 	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 @@
 
 		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);
@@ -1593,6 +1600,28 @@
 
 		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