BUG/MINOR: ssl: fix management of the cache where forged certificates are stored

First, the LRU cache must be initialized after the configuration parsing to
correctly set its size.
Next, the function 'ssl_sock_set_generated_cert' returns -1 when an error occurs
(0 if success). In that case, the caller is responsible to free the memory
allocated for the certificate.
Finally, when a SSL certificate is generated by HAProxy but cannot be inserted
in the cache, it must be freed when the SSL connection is closed. This happens
when 'tune.ssl.ssl-ctx-cache-size' is set to 0.
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index c2156bb..1b6c081 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -72,7 +72,7 @@
 
 SSL_CTX *ssl_sock_create_cert(const char *servername, unsigned int serial, X509 *cacert, EVP_PKEY *capkey);
 SSL_CTX *ssl_sock_get_generated_cert(unsigned int serial, X509 *cacert);
-void ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int serial, X509 *cacert);
+int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int serial, X509 *cacert);
 unsigned int ssl_sock_generated_cert_serial(const void *data, size_t len);
 
 #endif /* _PROTO_SSL_SOCK_H */
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 401ff67..deb658e 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1127,8 +1127,9 @@
 	return NULL;
 }
 
-/* Set a certificate int the LRU cache used to store generated certificate. */
-void
+/* Set a certificate int the LRU cache used to store generated
+ * certificate. Return 0 on success, otherwise -1 */
+int
 ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int serial, X509 *cacert)
 {
 	struct lru64 *lru = NULL;
@@ -1136,11 +1137,13 @@
 	if (ssl_ctx_lru_tree) {
 		lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
 		if (!lru)
-			return;
+			return -1;
 		if (lru->domain && lru->data)
 			lru->free((SSL_CTX *)lru->data);
 		lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
+		return 0;
 	}
+	return -1;
 }
 
 /* Compute the serial that will be used to create/set/get a certificate. */
@@ -1164,13 +1167,13 @@
 		lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
 		if (lru && lru->domain)
 			ssl_ctx = (SSL_CTX *)lru->data;
-	}
-
-	if (!ssl_ctx) {
-		ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
-		if (lru)
+		if (!ssl_ctx && lru) {
+			ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
 			lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
+		}
 	}
+	else
+		ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
 	return ssl_ctx;
 }
 
@@ -2489,6 +2492,10 @@
 	if (!bind_conf || !bind_conf->generate_certs)
 		return err;
 
+	if (global.tune.ssl_ctx_cache)
+		ssl_ctx_lru_tree = lru64_new(global.tune.ssl_ctx_cache);
+	ssl_ctx_lru_seed = (unsigned int)time(NULL);
+
 	if (!bind_conf->ca_sign_file) {
 		Alert("Proxy '%s': cannot enable certificate generation, "
 		      "no CA certificate File configured at [%s:%d].\n",
@@ -2838,7 +2845,6 @@
 	}
 
 reneg_ok:
-
 	/* Handshake succeeded */
 	if (!SSL_session_reused(conn->xprt_ctx)) {
 		if (objt_server(conn->target)) {
@@ -3082,6 +3088,11 @@
 static void ssl_sock_close(struct connection *conn) {
 
 	if (conn->xprt_ctx) {
+		if (!ssl_ctx_lru_tree && objt_listener(conn->target)) {
+			SSL_CTX *ctx = SSL_get_SSL_CTX(conn->xprt_ctx);
+			if (ctx != objt_listener(conn->target)->bind_conf->default_ctx)
+				SSL_CTX_free(ctx);
+		}
 		SSL_free(conn->xprt_ctx);
 		conn->xprt_ctx = NULL;
 		sslconns--;
@@ -5344,21 +5355,12 @@
 #ifndef OPENSSL_NO_DH
 	ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 #endif
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-	/* Add a global parameter for the LRU cache size */
-	if (global.tune.ssl_ctx_cache)
-		ssl_ctx_lru_tree = lru64_new(global.tune.ssl_ctx_cache);
-	ssl_ctx_lru_seed = (unsigned int)time(NULL);
-#endif
 }
 
 __attribute__((destructor))
 static void __ssl_sock_deinit(void)
 {
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	lru64_destroy(ssl_ctx_lru_tree);
-#endif
 
 #ifndef OPENSSL_NO_DH
         if (local_dh_1024) {