BUG/MINOR: ssl: fix cipherlist captures with sustainable SSL calls

Use SSL_set_ex_data/SSL_get_ex_data standard API call to store capture.
We need to avoid internal structures/undocumented calls usage to try to
control the beast and limit painful compatibilities.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 25e6bf4..8246531 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -13880,14 +13880,12 @@
 ssl_fc_cipherlist_bin : binary
   Returns the binary form of the client hello cipher list. The maximum returned
   value length is according with the value of
-  "tune.ssl.capture-cipherlist-size". Note that this sample-fetch is available
-  only with OpenSSL > 0.9.7
+  "tune.ssl.capture-cipherlist-size".
 
 ssl_fc_cipherlist_hex : string
   Returns the binary form of the client hello cipher list encoded as
   hexadecimal. The maximum returned value length is according with the value of
-  "tune.ssl.capture-cipherlist-size". Note that this sample-fetch is available
-  only with OpenSSL > 0.9.7
+  "tune.ssl.capture-cipherlist-size".
 
 ssl_fc_cipherlist_str : string
   Returns the decoded text form of the client hello cipher list. The maximum
@@ -13900,8 +13898,7 @@
 ssl_fc_cipherlist_xxh : integer
   Returns a xxh64 of the cipher list. This hash can be return only is the value
   "tune.ssl.capture-cipherlist-size" is set greater than 0, however the hash
-  take in account all the data of the cipher list. Note that this sample-fetch is
-  avalaible only with OpenSSL > 0.9.7
+  take in account all the data of the cipher list.
 
 ssl_fc_has_crt : boolean
   Returns true if a client certificate is present in an incoming connection over
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index c6b59f9..fa5ad53 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -165,10 +165,7 @@
 	.capture_cipherlist = 0,
 };
 
-/* This memory pool is used for capturing clienthello parameters.
- * The message callback is only available after openssl 0.9.7,
- * so the memory pool is useless before this version.
- */
+/* This memory pool is used for capturing clienthello parameters. */
 struct ssl_capture {
 	struct connection *conn;
 	unsigned long long int xxh64;
@@ -176,17 +173,7 @@
 	char ciphersuite[0];
 };
 struct pool_head *pool2_ssl_capture = NULL;
-
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-/* This fu**ing funtion is announced in some OpenSSL manual pages,
- * but doesn't exists in the OpenSSL library !
- * eg. https://www.openssl.org/docs/man1.0.1/ssl/SSL_get_msg_callback_arg.html
- */
-static void *SSL_get_msg_callback_arg(SSL *ssl)
-{
-	return ssl->msg_callback_arg;
-}
-#endif
+static int ssl_capture_ptr_index = -1;
 
 #if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
 struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
@@ -1258,11 +1245,11 @@
 /* Callback is called for ssl protocol analyse */
 void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
 {
-	/* If the SSL connection doesn't had sufficient memory while
-	 * the structure was initialized, arg is NULL.
-	 */
-	if (global_ssl.capture_cipherlist && arg)
-		ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, arg);
+	if (global_ssl.capture_cipherlist) {
+			struct ssl_capture *capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
+			if (capture)
+				ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, capture);
+	}
 
 #ifdef TLS1_RT_HEARTBEAT
 	/* test heartbeat received (write_p is set to 0
@@ -3971,8 +3958,6 @@
  */
 static int ssl_sock_init(struct connection *conn)
 {
-	struct ssl_capture *capture;
-
 	/* already initialized */
 	if (conn->xprt_ctx)
 		return 0;
@@ -4080,19 +4065,15 @@
 			return -1;
 		}
 
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
 		/* Set capture struct as opaque argument for the msg callback. */
 		if (global_ssl.capture_cipherlist > 0) {
-			capture = pool_alloc_dirty(pool2_ssl_capture);
+			struct ssl_capture *capture = pool_alloc_dirty(pool2_ssl_capture);
 			if (capture) {
 				capture->conn = conn;
 				capture->ciphersuite_len = 0;
-				SSL_set_msg_callback_arg(conn->xprt_ctx, capture);
+				SSL_set_ex_data(conn->xprt_ctx, ssl_capture_ptr_index, capture);
 			}
-		} else {
-			SSL_set_msg_callback_arg(conn->xprt_ctx, NULL);
 		}
-#endif
 
 		SSL_set_accept_state(conn->xprt_ctx);
 
@@ -4541,13 +4522,8 @@
 }
 
 static void ssl_sock_close(struct connection *conn) {
-	struct ssl_capture *capture;
 
 	if (conn->xprt_ctx) {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-		capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
-		pool_free2(pool2_ssl_capture, capture);
-#endif
 		SSL_free(conn->xprt_ctx);
 		conn->xprt_ctx = NULL;
 		sslconns--;
@@ -5661,7 +5637,6 @@
 static int
 smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
 	struct connection *conn;
 	struct ssl_capture *capture;
 
@@ -5669,7 +5644,7 @@
 	if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
 		return 0;
 
-	capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
+	capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
 	if (!capture)
 		return 0;
 
@@ -5678,10 +5653,6 @@
 	smp->data.u.str.str = capture->ciphersuite;
 	smp->data.u.str.len = capture->ciphersuite_len;
 	return 1;
-
-#else
-	return 0;
-#endif
 }
 
 static int
@@ -5702,7 +5673,6 @@
 static int
 smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
 	struct connection *conn;
 	struct ssl_capture *capture;
 
@@ -5710,17 +5680,13 @@
 	if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
 		return 0;
 
-	capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
+	capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
 	if (!capture)
 		return 0;
 
 	smp->data.type = SMP_T_SINT;
 	smp->data.u.sint = capture->xxh64;
 	return 1;
-
-#else
-	return 0;
-#endif
 }
 
 static int
@@ -6910,7 +6876,6 @@
                                                struct proxy *defpx, const char *file, int line,
                                                char **err)
 {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
 	int ret;
 
 	ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
@@ -6928,10 +6893,6 @@
 		return -1;
 	}
 	return 0;
-#else
-	memprintf(err, "'%s' requires OpenSSL 0.9.7 or above.", args[0]);
-	return -1;
-#endif
 }
 
 /* parse "ssl.force-private-cache".
@@ -7482,6 +7443,10 @@
 }
 
 #endif
+static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
+{
+	pool_free2(pool2_ssl_capture, ptr);
+}
 
 __attribute__((constructor))
 static void __ssl_sock_init(void)
@@ -7502,6 +7467,7 @@
 #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
 	sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
 #endif
+	ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
 	sample_register_fetches(&sample_fetch_keywords);
 	acl_register_keywords(&acl_kws);
 	bind_register_keywords(&bind_kws);