aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFabian Frank <fabian@pagefault.de>2014-02-04 00:10:37 -0800
committerDaniel Stenberg <daniel@haxx.se>2014-02-04 09:48:27 +0100
commit4d8db595cab1222927a251a9b836ac4947b7d73d (patch)
treea86dd2664675ba71400bf804f019e7bc43b13c50 /lib
parent6127e54f4083af016e229568502de6e578aa973e (diff)
gtls: add ALPN support
Add ALPN support when using GnuTLS >= 3.2.0. This allows libcurl to negotiate HTTP/2.0 for https connections when built with GnuTLS. See: http://www.gnutls.org/manual/gnutls.html#Application-Layer-Protocol-Negotiation-_0028ALPN_0029 http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04
Diffstat (limited to 'lib')
-rw-r--r--lib/vtls/gtls.c45
-rw-r--r--lib/vtls/openssl.c7
-rw-r--r--lib/vtls/vtls.h4
3 files changed, 49 insertions, 7 deletions
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index cd410551c..326af386f 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -89,6 +89,15 @@ static bool gtls_inited = FALSE;
# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
# define GNUTLS_MAPS_WINSOCK_ERRORS 1
# endif
+
+# ifdef USE_NGHTTP2
+# undef HAS_ALPN
+# if (GNUTLS_VERSION_NUMBER >= 0x030200)
+# define HAS_ALPN
+# else
+# error http2 builds require GnuTLS >= 3.2.0 for ALPN support
+# endif
+# endif
#endif
/*
@@ -374,6 +383,10 @@ gtls_connect_step1(struct connectdata *conn,
const char* prioritylist;
const char *err;
#endif
+#ifdef HAS_ALPN
+ int protocols_size = 2;
+ gnutls_datum_t protocols[2];
+#endif
if(conn->ssl[sockindex].state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -556,6 +569,15 @@ gtls_connect_step1(struct connectdata *conn,
rc = gnutls_priority_set_direct(session, prioritylist, &err);
#endif
+#ifdef HAS_ALPN
+ protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
+ protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
+ protocols[1].data = ALPN_HTTP_1_1;
+ protocols[1].size = ALPN_HTTP_1_1_LENGTH;
+ gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
+ infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
+ ALPN_HTTP_1_1);
+#endif
if(rc != GNUTLS_E_SUCCESS) {
failf(data, "Did you pass a valid GnuTLS cipher list?");
@@ -637,6 +659,9 @@ gtls_connect_step3(struct connectdata *conn,
int rc;
int incache;
void *ssl_sessionid;
+#ifdef HAS_ALPN
+ gnutls_datum_t proto;
+#endif
CURLcode result = CURLE_OK;
/* This function will return the peer's raw certificate (chain) as sent by
@@ -841,6 +866,26 @@ gtls_connect_step3(struct connectdata *conn,
ptr = gnutls_mac_get_name(gnutls_mac_get(session));
infof(data, "\t MAC: %s\n", ptr);
+#ifdef HAS_ALPN
+ rc = gnutls_alpn_get_selected_protocol(session, &proto);
+ if(rc == 0) {
+ infof(data, "ALPN, server accepted to use %.*s\n", proto.size, proto.data);
+
+ if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
+ NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
+ conn->negnpn = NPN_HTTP2_DRAFT09;
+ }
+ else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
+ proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
+ conn->negnpn = NPN_HTTP1_1;
+ }
+ }
+ else {
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+#endif
+
conn->ssl[sockindex].state = ssl_connection_complete;
conn->recv[sockindex] = gtls_recv;
conn->send[sockindex] = gtls_send;
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 063945922..2f9f8a0e5 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -1415,13 +1415,6 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
#endif
-/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
-#ifdef HAS_ALPN
-#define ALPN_HTTP_1_1_LENGTH 8
-#define ALPN_HTTP_1_1 "http/1.0"
-#endif
-
-
/*
* in is a list of lenght prefixed strings. this function has to select
* the protocol we want to use from the list and write its string into out.
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 04ab60b18..823c041ed 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -27,6 +27,10 @@
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
+/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
+#define ALPN_HTTP_1_1_LENGTH 8
+#define ALPN_HTTP_1_1 "http/1.0"
+
bool Curl_ssl_config_matches(struct ssl_config_data* data,
struct ssl_config_data* needle);
bool Curl_clone_ssl_config(struct ssl_config_data* source,