]> granicus.if.org Git - curl/commitdiff
darwinssl: add support for ALPN negotiation
authorRodger Combs <rodger.combs@gmail.com>
Wed, 11 Jul 2018 07:45:14 +0000 (02:45 -0500)
committerNick Zitzmann <nickzman@gmail.com>
Sat, 14 Jul 2018 23:32:47 +0000 (18:32 -0500)
docs/HTTP2.md
lib/vtls/darwinssl.c

index efbe6999106f0f9718cf31a09fc6ea86049efc8b..e20ce0cab3ef4c8cd8e4a7666e1afdd7169cddc2 100644 (file)
@@ -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
 ------------
index f29b5acad822e3fe5936d5543e2a61c3ed75574f..1aea0dc3dd911cf5951cecb25ed31d730f49eb3f 100644 (file)
@@ -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;
   }
 }