I would like to propose a little patch, based on current ssl_capture
(ssl_sock.c) scheme.
Purpose is to be able to sample/fetch TLS extensions, it could be useful
for debugging or fingerprinting purposes (for example, cURL and Firefox
provide different sets of extensions in ClientHello message).

it provides two hooks, which should be enough for further Lua
processing/request forwarding/analysis: smp_fetch_ssl_fc_exts_bin,
smp_fetch_ssl_fc_exts_hex
From 32a5d13b13b530199eb2fc568c035aa68481cefb Mon Sep 17 00:00:00 2001
From: Alexey Elymanov <strangeqa...@gmail.com>
Date: Tue, 16 Oct 2018 15:11:44 +0300
Subject: [PATCH] MEDIUM: Sample/Fetch hooks for TLS ClientHello Extensions

Provides two new hooks, which should be enough for further Lua
processing/request forwarding/analysis: smp_fetch_ssl_fc_exts_bin,
smp_fetch_ssl_fc_exts_hex.
---
 src/ssl_sock.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 41833768..b48057bd 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -271,6 +271,8 @@ struct ssl_capture {
 	unsigned long long int xxh64;
 	unsigned char ciphersuite_len;
 	char ciphersuite[0];
+	unsigned char extensions_len;
+    char extensions[0];
 };
 struct pool_head *pool_head_ssl_capture = NULL;
 static int ssl_capture_ptr_index = -1;
@@ -1586,6 +1588,18 @@ void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
 		global_ssl.capture_cipherlist : rec_len;
 	memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
 
+	/* Compression methods */
+    msg+=rec_len;
+	/* skip, jumping to extensions */
+    msg+=3;
+    /* Extensions methods */
+    rec_len = msg[0];
+    msg += 1;
+    capture->extensions_len = (global_ssl.capture_cipherlist < rec_len) ?
+		global_ssl.capture_cipherlist : rec_len;
+
+    memcpy(capture->extensions, msg, capture->extensions_len);
+
 	SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
 }
 
@@ -7086,6 +7100,42 @@ smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *
 #endif
 }
 
+static int
+smp_fetch_ssl_fc_exts_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+	struct connection *conn;
+	struct ssl_capture *capture;
+
+	conn = objt_conn(smp->sess->origin);
+	if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
+		return 0;
+
+	capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
+	if (!capture)
+		return 0;
+
+	smp->flags = SMP_F_CONST;
+	smp->data.type = SMP_T_BIN;
+	smp->data.u.str.area = capture->extensions;
+	smp->data.u.str.data = capture->extensions_len;
+	return 1;
+}
+
+static int
+smp_fetch_ssl_fc_exts_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+	struct buffer *data;
+
+	if (!smp_fetch_ssl_fc_exts_bin(args, smp, kw, private))
+		return 0;
+
+	data = get_trash_chunk();
+	dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
+	smp->data.type = SMP_T_BIN;
+	smp->data.u.str = *data;
+	return 1;
+}
+
 #if OPENSSL_VERSION_NUMBER > 0x0090800fL
 static int
 smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
@@ -8861,7 +8911,9 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
 	{ "ssl_fc_cipherlist_hex",  smp_fetch_ssl_fc_cl_hex,      0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_fc_cipherlist_str",  smp_fetch_ssl_fc_cl_str,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_fc_cipherlist_xxh",  smp_fetch_ssl_fc_cl_xxh64,    0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
-	{ NULL, NULL, 0, 0, 0 },
+	{ "ssl_fc_exts_bin",        smp_fetch_ssl_fc_exts_bin,    0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
+    { "ssl_fc_exts_hex",        smp_fetch_ssl_fc_exts_hex,    0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
+    { NULL, NULL, 0, 0, 0 },
 }};
 
 /* Note: must not be declared <const> as its list will be overwritten.
-- 
2.17.1

Reply via email to