From 16f9985f7df8455ee2906fcdc4fe0e516ded0532 Mon Sep 17 00:00:00 2001
From: Dirkjan Bussink <d.bussink@gmail.com>
Date: Thu, 13 Feb 2014 12:29:42 +0100
Subject: [PATCH] Use ALPN support as it will be available in OpenSSL 1.0.2

The current ALPN support is based on custom OpenSSL patches. These are
however not the same as what has landed on OpenSSL:

http://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=6f017a8f9db3a79f3a3406cf8d493ccd346db691

This patch change the code so it supports ALPN as it will be part of
OpenSSL.
---
 include/types/ssl_sock.h |  6 ++++++
 src/ssl_sock.c           | 16 ++++++++++------
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/include/types/ssl_sock.h b/include/types/ssl_sock.h
index a0b2d79..b533704 100644
--- a/include/types/ssl_sock.h
+++ b/include/types/ssl_sock.h
@@ -25,6 +25,12 @@
 #include <openssl/ssl.h>
 #include <ebmbtree.h>
 
+#ifndef OPENSSL_ALPN_NEGOTIATED
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+#define OPENSSL_ALPN_NEGOTIATED
+#endif
+#endif
+
 struct sni_ctx {
 	SSL_CTX *ctx;             /* context associated to the certificate */
 	int order;                /* load order for the certificate */
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 5ac2b06..48bbc0b 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -196,13 +196,17 @@ static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
 /* This callback is used so that the server advertises the list of
  * negociable protocols for ALPN.
  */
-static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **data,
-                                          unsigned int *len, void *arg)
+static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
+                                          unsigned char *outlen,
+                                          const unsigned char *server,
+                                          unsigned int server_len, void *arg)
 {
 	struct bind_conf *conf = arg;
 
-	*data = (const unsigned char *)conf->alpn_str;
-	*len = conf->alpn_len;
+	if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
+	                          conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
+		return SSL_TLSEXT_ERR_NOACK;
+	}
 	return SSL_TLSEXT_ERR_OK;
 }
 #endif
@@ -784,7 +788,7 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy
 #endif
 #ifdef OPENSSL_ALPN_NEGOTIATED
 	if (bind_conf->alpn_str)
-		SSL_CTX_set_alpn_advertised_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
+		SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, bind_conf);
 #endif
 
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
@@ -2691,7 +2695,7 @@ smp_fetch_ssl_fc_alpn(struct proxy *px, struct session *l4, void *l7, unsigned i
 		return 0;
 
 	smp->data.str.str = NULL;
-	SSL_get0_alpn_negotiated(conn->xprt_ctx,
+	SSL_get0_alpn_selected(conn->xprt_ctx,
 	                         (const unsigned char **)&smp->data.str.str, (unsigned *)&smp->data.str.len);
 
 	if (!smp->data.str.str)
-- 
1.8.2

