]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: add a get_alpn() method to ssl_sock
authorWilly Tarreau <w@1wt.eu>
Sun, 4 Dec 2016 17:44:29 +0000 (18:44 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 27 Jun 2017 12:38:02 +0000 (14:38 +0200)
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

index 368051506852e07b89b094f63d608be83cd8bd59..283b22b475f16c537456a8e7d314bd191c5c093f 100644 (file)
@@ -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 <str> and <len> 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",
 };