BUG/MINOR: ssl: Fix memory leak of find_chain in ssl_sock_load_cert_chain

The certificate chain that gets passed in the SSL_CTX through
SSL_CTX_set1_chain has its reference counter increased by OpenSSL
itself. But since the ssl_sock_load_cert_chain function might create a
brand new certificate chain if none exists in the ckch_data
(sk_X509_new_null), then we ended up returning a new certificate chain
to the caller that was never destroyed.

This patch can be backported to all stable branches but it might need to
be reworked for branches older than 2.4 because of commit ec805a32b9
that refactorized the modified code.

(cherry picked from commit 4cf0d3f1e8e2ffc6901dc36644efa31b67d172f1)
[wla: struct member data was called ckch before]
Signed-off-by: William Lallemand <wlallemand@haproxy.org>
(cherry picked from commit 3fc061bf30b45bbcab66b8bd8b38ce7578bc9ae6)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit efde502b97cf2f99495525ecde138928c973c139)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 796435f97d38899b6bdc0440ae18df413c2bd085)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 4480a04..a103aff 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -3126,6 +3126,8 @@
  *     ERR_FATAL in any fatal error case
  *     ERR_ALERT if the reason of the error is available in err
  *     ERR_WARN if a warning is available into err
+ * The caller is responsible of freeing the newly built or newly refcounted
+ * find_chain element.
  * The value 0 means there is no error nor warning and
  * the operation succeed.
  */
@@ -3147,13 +3149,13 @@
 	}
 
 	if (ckch->chain) {
-		*find_chain = ckch->chain;
+		*find_chain = X509_chain_up_ref(ckch->chain);
 	} else {
 		/* Find Certificate Chain in global */
 		struct issuer_chain *issuer;
 		issuer = ssl_get0_issuer_chain(ckch->cert);
 		if (issuer)
-			*find_chain = issuer->chain;
+			*find_chain = X509_chain_up_ref(issuer->chain);
 	}
 
 	if (!*find_chain) {
@@ -3173,14 +3175,11 @@
 #else
 	{ /* legacy compat (< openssl 1.0.2) */
 		X509 *ca;
-		STACK_OF(X509) *chain;
-		chain = X509_chain_up_ref(*find_chain);
-		while ((ca = sk_X509_shift(chain)))
+		while ((ca = sk_X509_shift(*find_chain)))
 			if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
 				memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
 					  err && *err ? *err : "", path);
 				X509_free(ca);
-				sk_X509_pop_free(chain, X509_free);
 				errcode |= ERR_ALERT | ERR_FATAL;
 				goto end;
 			}
@@ -3268,6 +3267,7 @@
 #endif
 
  end:
+	sk_X509_pop_free(find_chain, X509_free);
 	return errcode;
 }
 
@@ -3305,6 +3305,7 @@
 	}
 
 end:
+	sk_X509_pop_free(find_chain, X509_free);
 	return errcode;
 }