From c1ad52e8f781c301f6308d27f788354b77da1610 Mon Sep 17 00:00:00 2001 From: David S <11235david@gmail.com> Date: Tue, 8 Apr 2014 18:48:47 -0400 Subject: [PATCH] MINOR: ssl: add ssl_fc_unique_id to fetch TLS Unique ID The TLS unique id, or unique channel binding, is a byte string that can be pulled from a TLS connection and it is unique to that connection. It is defined in RFC 5929 section 3. The value is used by various upper layer protocols as part of an extra layer of security. For example XMPP (RFC 6120) and EST (RFC 7030). Add the ssl_fc_unique_id keyword and corresponding sample fetch method. Value is retrieved from OpenSSL and base64 encoded as described in RFC 5929 section 3. --- doc/configuration.txt | 5 +++++ src/ssl_sock.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/doc/configuration.txt b/doc/configuration.txt index bc582c29e..5873fc3f4 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -10335,6 +10335,11 @@ ssl_fc_protocol : string ACL derivatives : ssl_fc_protocol : exact string match +ssl_fc_unique_id : string + When the incoming connection was made over an SSL/TLS transport layer, + returns a base64 encoded string containing the TLS unique ID as defined + in RFC5929 section 3. + ssl_fc_session_id : binary Returns the SSL ID of the front connection when the incoming connection was made over an SSL/TLS transport layer. It is useful to stick a given client to diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 7e036303a..a40b445c3 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -45,6 +45,7 @@ #include #include +#include #include #include #include @@ -2810,6 +2811,55 @@ smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned in #endif } +static int +smp_fetch_ssl_fc_unique_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + const struct arg *args, struct sample *smp, const char *kw) +{ +#if OPENSSL_VERSION_NUMBER > 0x0090800fL + struct connection *conn; + int finished_len; + int b64_len; + struct chunk *finished_trash; + struct chunk *smp_trash; + + smp->flags = 0; + + if (!l4) + return 0; + + conn = objt_conn(l4->si[0].end); + if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock) + return 0; + + if (!(conn->flags & CO_FL_CONNECTED)) { + smp->flags |= SMP_F_MAY_CHANGE; + return 0; + } + + finished_trash = get_trash_chunk(); + if (!SSL_session_reused(conn->xprt_ctx)) + finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size); + else + finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size); + + if (!finished_len) + return 0; + + smp_trash = get_trash_chunk(); + b64_len = a2base64(finished_trash->str, finished_len, smp_trash->str, smp_trash->size); + if (b64_len < 0) + return 0; + + smp->data.str.str = smp_trash->str; + smp->type = SMP_T_CSTR; + smp->data.str.len = b64_len; + + return 1; +#else + return 0; +#endif +} + /* integer, returns the first verify error in CA chain of client certificate chain. */ static int smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt, @@ -3536,6 +3586,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, #endif { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI }, { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI }, { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI }, { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },