From a33c654cb18339c8547ef0b5d52c6215113fb28e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 15 Oct 2012 13:19:06 +0200 Subject: [PATCH] MINOR: ssl: add 'ssl_npn' sample/acl to extract TLS/NPN information This may be used to distinguish between SPDY versions for example. --- doc/configuration.txt | 13 +++++++++++++ src/ssl_sock.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/doc/configuration.txt b/doc/configuration.txt index 208c43221..119f4401c 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -8339,6 +8339,12 @@ ssl_has_sni that the SSL library is build with support for TLS extensions enabled (check haproxy -vv). +ssl_npn + Returns true when the incoming connection was made over an SSL/TLS transport + layer which deciphered it and found a Next Protocol Negociation TLS extension + sent by the client, matching the specified string. This requires that the SSL + library is build with support for TLS extensions enabled (check haproxy -vv). + ssl_sni Returns true when the incoming connection was made over an SSL/TLS transport layer which deciphered it and found a Server Name Indication TLS extension @@ -8996,6 +9002,13 @@ The list of currently supported pattern fetch functions is the following : otherwise zero. This requires that the SSL library is build with support for TLS extensions enabled (check haproxy -vv). + ssl_npn This extracts the Next Protocol Negociation field from an + incoming connection made via an SSL/TLS transport layer and + locally deciphered by haproxy. The result is a string containing + the protocol name advertised by the client. The SSL library must + have been built with support for TLS extensions enabled (check + haproxy -vv). + ssl_sni This extracts the Server Name Indication field from an incoming connection made via an SSL/TLS transport layer and locally deciphered by haproxy. The result typically is a string matching diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 9aed91571..6121b1284 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1118,6 +1118,30 @@ smp_fetch_has_sni(struct proxy *px, struct session *l4, void *l7, unsigned int o #endif } +static int +smp_fetch_ssl_npn(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + const struct arg *args, struct sample *smp) +{ +#ifdef OPENSSL_NPN_NEGOTIATED + smp->flags = 0; + smp->type = SMP_T_CSTR; + + if (!l4 || !l4->si[0].conn.xprt_ctx || l4->si[0].conn.xprt != &ssl_sock) + return 0; + + smp->data.str.str = NULL; + SSL_get0_next_proto_negotiated(l4->si[0].conn.xprt_ctx, + (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len); + + if (!smp->data.str.str) + return 0; + + return 1; +#else + return 0; +#endif +} + static int smp_fetch_ssl_sni(struct proxy *px, struct session *l4, void *l7, unsigned int opt, const struct arg *args, struct sample *smp) @@ -1662,6 +1686,9 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{ { "client_crt", smp_fetch_client_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES }, { "is_ssl", smp_fetch_is_ssl, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_has_sni", smp_fetch_has_sni, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES }, +#ifdef OPENSSL_NPN_NEGOTIATED + { "ssl_npn", smp_fetch_ssl_npn, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES }, +#endif { "ssl_sni", smp_fetch_ssl_sni, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_verify_caerr", smp_fetch_verify_caerr, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_verify_caerr_depth", smp_fetch_verify_caerr_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES }, @@ -1677,6 +1704,9 @@ static struct acl_kw_list acl_kws = {{ },{ { "client_crt", acl_parse_int, smp_fetch_client_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "is_ssl", acl_parse_int, smp_fetch_is_ssl, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_has_sni", acl_parse_int, smp_fetch_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 }, +#ifdef OPENSSL_NPN_NEGOTIATED + { "ssl_npn", acl_parse_str, smp_fetch_ssl_npn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, +#endif { "ssl_sni", acl_parse_str, smp_fetch_ssl_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_sni_end", acl_parse_str, smp_fetch_ssl_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_sni_reg", acl_parse_str, smp_fetch_ssl_sni, acl_match_reg, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },