summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodger Combs <rodger.combs@gmail.com>2018-07-11 02:45:14 -0500
committerNick Zitzmann <nickzman@gmail.com>2018-07-14 18:32:47 -0500
commit092f6815c808489f1cea3df8449e16dff2c35e6b (patch)
tree08a44f61e965ea7b1e11b2f60c1af372f504c003
parent8c00412428b3bbe4d56db7905372c7e6d416fbc0 (diff)
downloadcurl-092f6815c808489f1cea3df8449e16dff2c35e6b.tar.gz
darwinssl: add support for ALPN negotiation
-rw-r--r--docs/HTTP2.md17
-rw-r--r--lib/vtls/darwinssl.c62
2 files changed, 71 insertions, 8 deletions
diff --git a/docs/HTTP2.md b/docs/HTTP2.md
index efbe69991..e20ce0cab 100644
--- a/docs/HTTP2.md
+++ b/docs/HTTP2.md
@@ -55,14 +55,15 @@ The challenge is the ALPN and NPN support and all our different SSL
backends. You may need a fairly updated SSL library version for it to provide
the necessary TLS features. Right now we support:
- - OpenSSL: ALPN and NPN
- - libressl: ALPN and NPN
- - BoringSSL: ALPN and NPN
- - NSS: ALPN and NPN
- - GnuTLS: ALPN
- - mbedTLS: ALPN
- - SChannel: ALPN
- - wolfSSL: ALPN
+ - OpenSSL: ALPN and NPN
+ - libressl: ALPN and NPN
+ - BoringSSL: ALPN and NPN
+ - NSS: ALPN and NPN
+ - GnuTLS: ALPN
+ - mbedTLS: ALPN
+ - SChannel: ALPN
+ - wolfSSL: ALPN
+ - Secure Transport: ALPN
Multiplexing
------------
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index f29b5acad..1aea0dc3d 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -1573,6 +1573,35 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
}
#endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
+ &kCFTypeArrayCallBacks);
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ /* expects length prefixed preference ordered list of protocols in wire
+ * format
+ */
+ err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr);
+ if(err != noErr)
+ infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
+ err);
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
if(SSL_SET_OPTION(key)) {
infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
"Transport. The private key must be in the Keychain.\n");
@@ -2467,6 +2496,39 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
break;
}
+#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+ if(conn->bits.tls_enable_alpn) {
+ if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+ CFArrayRef alpnArr = NULL;
+ CFStringRef chosenProtocol = NULL;
+ err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr);
+
+ if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
+ chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
+
+#ifdef USE_NGHTTP2
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
+ 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_2;
+ }
+ else
+#endif
+ if(chosenProtocol &&
+ !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+
+ /* chosenProtocol is a reference to the string within alpnArr
+ and doesn't need to be freed separately */
+ if(alpnArr)
+ CFRelease(alpnArr);
+ }
+ }
+#endif
+
return CURLE_OK;
}
}