mirror of
https://github.com/moparisthebest/curl
synced 2024-11-14 21:45:13 -05:00
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
This commit is contained in:
parent
6127e54f40
commit
4d8db595ca
@ -89,6 +89,15 @@ static bool gtls_inited = FALSE;
|
|||||||
# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
|
# if (GNUTLS_VERSION_NUMBER >= 0x020c03)
|
||||||
# define GNUTLS_MAPS_WINSOCK_ERRORS 1
|
# define GNUTLS_MAPS_WINSOCK_ERRORS 1
|
||||||
# endif
|
# 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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -374,6 +383,10 @@ gtls_connect_step1(struct connectdata *conn,
|
|||||||
const char* prioritylist;
|
const char* prioritylist;
|
||||||
const char *err;
|
const char *err;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAS_ALPN
|
||||||
|
int protocols_size = 2;
|
||||||
|
gnutls_datum_t protocols[2];
|
||||||
|
#endif
|
||||||
|
|
||||||
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
if(conn->ssl[sockindex].state == ssl_connection_complete)
|
||||||
/* to make us tolerant against being called more than once for the
|
/* 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);
|
rc = gnutls_priority_set_direct(session, prioritylist, &err);
|
||||||
#endif
|
#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) {
|
if(rc != GNUTLS_E_SUCCESS) {
|
||||||
failf(data, "Did you pass a valid GnuTLS cipher list?");
|
failf(data, "Did you pass a valid GnuTLS cipher list?");
|
||||||
@ -637,6 +659,9 @@ gtls_connect_step3(struct connectdata *conn,
|
|||||||
int rc;
|
int rc;
|
||||||
int incache;
|
int incache;
|
||||||
void *ssl_sessionid;
|
void *ssl_sessionid;
|
||||||
|
#ifdef HAS_ALPN
|
||||||
|
gnutls_datum_t proto;
|
||||||
|
#endif
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
/* This function will return the peer's raw certificate (chain) as sent by
|
/* 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));
|
ptr = gnutls_mac_get_name(gnutls_mac_get(session));
|
||||||
infof(data, "\t MAC: %s\n", ptr);
|
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->ssl[sockindex].state = ssl_connection_complete;
|
||||||
conn->recv[sockindex] = gtls_recv;
|
conn->recv[sockindex] = gtls_recv;
|
||||||
conn->send[sockindex] = gtls_send;
|
conn->send[sockindex] = gtls_send;
|
||||||
|
@ -1415,13 +1415,6 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
|
|||||||
#endif
|
#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
|
* 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.
|
* the protocol we want to use from the list and write its string into out.
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
#define MD5_DIGEST_LENGTH 16 /* fixed size */
|
#define MD5_DIGEST_LENGTH 16 /* fixed size */
|
||||||
#endif
|
#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,
|
bool Curl_ssl_config_matches(struct ssl_config_data* data,
|
||||||
struct ssl_config_data* needle);
|
struct ssl_config_data* needle);
|
||||||
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
bool Curl_clone_ssl_config(struct ssl_config_data* source,
|
||||||
|
Loading…
Reference in New Issue
Block a user