From 8743f7e56763be2eef31443facbfd8afd0642166 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 4 Dec 2016 18:44:29 +0100 Subject: [PATCH] MINOR: ssl: add a get_alpn() method to ssl_sock This is used to retrieve the TLS ALPN information from a connection. We also support a fallback to NPN if ALPN doesn't find anything or is not available on the existing implementation. It happens that depending on the library version, either one or the other is available. NPN was present in openssl 1.0.1 (very common) while ALPN is in 1.0.2 and onwards (still uncommon at the time of writing). Clients are used to send either one or the other to ensure a smooth transition. --- src/ssl_sock.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 368051506..283b22b47 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -5426,6 +5426,32 @@ unsigned int ssl_sock_get_verify_result(struct connection *conn) return (unsigned int)SSL_get_verify_result(conn->xprt_ctx); } +/* Returns the application layer protocol name in and when known. + * Zero is returned if the protocol name was not found, otherwise non-zero is + * returned. The string is allocated in the SSL context and doesn't have to be + * freed by the caller. NPN is also checked if available since older versions + * of openssl (1.0.1) which are more common in field only support this one. + */ +static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len) +{ + if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock) + return 0; + + *str = NULL; + +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len); + if (*str) + return 1; +#endif +#ifdef OPENSSL_NPN_NEGOTIATED + SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len); + if (*str) + return 1; +#endif + return 0; +} + /***** Below are some sample fetching functions for ACL/patterns *****/ /* boolean, returns true if client cert was present */ @@ -8039,6 +8065,7 @@ static struct xprt_ops ssl_sock = { .destroy_bind_conf = ssl_sock_destroy_bind_conf, .prepare_srv = ssl_sock_prepare_srv_ctx, .destroy_srv = ssl_sock_free_srv_ctx, + .get_alpn = ssl_sock_get_alpn, .name = "SSL", };