mirror of
https://github.com/curl/curl.git
synced 2025-01-18 14:04:30 +08:00
openssl: add ALPN support
Add ALPN support when using OpenSSL. This will offer ALPN and NPN to the
server, who can respond with either one or none of the two. OpenSSL >=
1.0.2 is required, which means as of today obtaining a snapshot from
ftp://ftp.openssl.org/snapshot/.
See:
http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04
ba168244a1/ssl/ssl_lib.c (L1787)
This commit is contained in:
parent
c35d05aa62
commit
8b6654224b
@ -1595,7 +1595,9 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
|
||||
CRYPTO_cleanup_all_ex_data \
|
||||
SSL_get_shutdown \
|
||||
SSLv2_client_method \
|
||||
SSL_CTX_set_next_proto_select_cb )
|
||||
SSL_CTX_set_next_proto_select_cb \
|
||||
SSL_CTX_set_alpn_protos \
|
||||
SSL_CTX_set_alpn_select_cb )
|
||||
|
||||
dnl Make an attempt to detect if this is actually yassl's headers and
|
||||
dnl OpenSSL emulation layer. We still leave everything else believing
|
||||
|
@ -1401,11 +1401,27 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
|
||||
#undef HAS_ALPN
|
||||
#if defined(HAVE_SSL_CTX_SET_ALPN_PROTOS) && \
|
||||
defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
|
||||
# define HAS_ALPN 1
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || \
|
||||
defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
#error http2 builds require OpenSSL with NPN support
|
||||
# if !defined(HAS_ALPN)
|
||||
# error http2 builds require OpenSSL with NPN or ALPN support
|
||||
# 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
|
||||
* the protocol we want to use from the list and write its string into out.
|
||||
@ -1456,6 +1472,9 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
#else
|
||||
struct in_addr addr;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAS_ALPN
|
||||
unsigned char protocols[128];
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
|
||||
@ -1656,6 +1675,25 @@ ossl_connect_step1(struct connectdata *conn,
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn);
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
protocols[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||
memcpy(&protocols[1], NGHTTP2_PROTO_VERSION_ID,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||
|
||||
protocols[NGHTTP2_PROTO_VERSION_ID_LEN+1] = ALPN_HTTP_1_1_LENGTH;
|
||||
memcpy(&protocols[NGHTTP2_PROTO_VERSION_ID_LEN+2], ALPN_HTTP_1_1,
|
||||
ALPN_HTTP_1_1_LENGTH);
|
||||
|
||||
/* expects length prefixed preference ordered list of protocols in wire
|
||||
* format
|
||||
*/
|
||||
SSL_CTX_set_alpn_protos(connssl->ctx, protocols,
|
||||
NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH + 2);
|
||||
|
||||
infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
|
||||
ALPN_HTTP_1_1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
|
||||
@ -1829,6 +1867,10 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
struct SessionHandle *data = conn->data;
|
||||
int err;
|
||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||
#ifdef HAS_ALPN
|
||||
char* neg_protocol;
|
||||
int len = 0;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|
||||
|| ssl_connect_2_reading == connssl->connecting_state
|
||||
@ -1925,6 +1967,28 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
|
||||
infof (data, "SSL connection using %s\n",
|
||||
SSL_get_cipher(connssl->handle));
|
||||
|
||||
#ifdef HAS_ALPN
|
||||
/* Sets data and len to negotiated protocol, len is 0 if no protocol was
|
||||
* negotiated
|
||||
*/
|
||||
SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
|
||||
if(len != 0) {
|
||||
infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
|
||||
|
||||
if(len == NGHTTP2_PROTO_VERSION_ID_LEN &&
|
||||
memcmp(NGHTTP2_PROTO_VERSION_ID, neg_protocol, len) == 0) {
|
||||
conn->negnpn = NPN_HTTP2_DRAFT09;
|
||||
}
|
||||
else if(len == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
|
||||
neg_protocol, ALPN_HTTP_1_1_LENGTH) == 0) {
|
||||
conn->negnpn = NPN_HTTP1_1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
infof(data, "ALPN, server did not agree to a protocol\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user