[vlc-devel] [PATCH] securetransport: Add ALPN support

Thomas Guillem thomas at gllm.fr
Fri Apr 6 11:18:58 CEST 2018


Pushed after checking the SSLCopyALPNProtocols symbol availability too.

On Thu, Apr 5, 2018, at 20:32, Marvin Scholz wrote:
> ---
> 
> This new version adds _SSLCopyALPNProtocols and _SSLSetALPNProtocols
> to symbols that are allowed to be undefined. This will not be a
> problem as those are weak-linked (given that we target 10.10) and
> explicitly checked in the code for availability.
> 
> ---
>  modules/misc/Makefile.am       |   1 +
>  modules/misc/securetransport.c | 149 +++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 145 insertions(+), 5 deletions(-)
> 
> diff --git a/modules/misc/Makefile.am b/modules/misc/Makefile.am
> index f53fc4dabf..b5a8db5379 100644
> --- a/modules/misc/Makefile.am
> +++ b/modules/misc/Makefile.am
> @@ -42,6 +42,7 @@ libsecuretransport_plugin_la_SOURCES = misc/
> securetransport.c
>  libsecuretransport_plugin_la_CFLAGS = $(AM_CFLAGS) $
> (SECURETRANSPORT_CFLAGS)
>  libsecuretransport_plugin_la_LIBADD = $(SECURETRANSPORT_LIBS)
>  libsecuretransport_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$
> (miscdir)' -Wl,-framework,Security,-framework,CoreFoundation
> +libsecuretransport_plugin_la_LDFLAGS += -Wl,-U,_SSLCopyALPNProtocols,-
> U,_SSLSetALPNProtocols
>  misc_LTLIBRARIES += libsecuretransport_plugin.la
>  endif
>  
> diff --git a/modules/misc/securetransport.c b/modules/misc/securetransport.c
> index fcd5e8bc72..11bb43228d 100644
> --- a/modules/misc/securetransport.c
> +++ b/modules/misc/securetransport.c
> @@ -40,6 +40,80 @@
>  # define ioErr -36
>  #endif
>  
> +/
> *****************************************************************************
> + * ALPN helper functions
> + 
> *****************************************************************************/
> +
> +/* Converts the VLC ALPN C array (null-terminated) to a ALPN
> + * CFMutableArray as expected by the Secure Transport API
> + * Returns CFMutableArrayRef on success, else NULL.
> + */
> +static CFMutableArrayRef alpnToCFArray(const char *const *alpn)
> +{
> +    CFMutableArrayRef alpnValues =
> +            CFArrayCreateMutable(kCFAllocatorDefault, 0, 
> &kCFTypeArrayCallBacks);
> +
> +    for (size_t i = 0; alpn[i] != NULL; i++) {
> +        CFStringRef alpnVal =
> +                CFStringCreateWithCString(kCFAllocatorDefault, alpn[i], 
> kCFStringEncodingASCII);
> +        if (alpnVal == NULL) {
> +            // Failed to convert the ALPN value to CFString, error out.
> +            CFRelease(alpnValues);
> +            return NULL;
> +        }
> +        CFArrayAppendValue(alpnValues, alpnVal);
> +        CFRelease(alpnVal);
> +    }
> +    return alpnValues;
> +}
> +
> +/* Obtains a copy of the contents of a CFString in ASCII encoding.
> + * Returns char* (must be freed by caller) or NULL on failure.
> + */
> +static char* CFStringCopyASCIICString(CFStringRef cfString)
> +{
> +    // Try the quick way to obtain the buffer
> +    const char *tmpBuffer = CFStringGetCStringPtr(cfString, 
> kCFStringEncodingASCII);
> +
> +    if (tmpBuffer != NULL) {
> +       return strdup(tmpBuffer);
> +    }
> +
> +    // The quick way did not work, try the long way
> +    CFIndex length = CFStringGetLength(cfString);
> +    CFIndex maxSize =
> +        CFStringGetMaximumSizeForEncoding(length, 
> kCFStringEncodingASCII);
> +
> +    // If result would exceed LONG_MAX, kCFNotFound is returned
> +    if (unlikely(maxSize == kCFNotFound)) {
> +        return NULL;
> +    }
> +
> +    // Account for the null terminator
> +    maxSize++;
> +
> +    char *buffer = (char *)malloc(maxSize);
> +    Boolean success = CFStringGetCString(cfString, buffer, maxSize, 
> kCFStringEncodingASCII);
> +
> +    if (!success)
> +        FREENULL(buffer);
> +    return buffer;
> +}
> +
> +/* Returns the first entry copy of the ALPN array as char*
> + * or NULL on failure.
> + */
> +static char* CFArrayALPNCopyFirst(CFArrayRef alpnArray)
> +{
> +    CFIndex count = CFArrayGetCount(alpnArray);
> +
> +    if (count <= 0)
> +        return NULL;
> +
> +    CFStringRef alpnVal = CFArrayGetValueAtIndex(alpnArray, 0);
> +    return CFStringCopyASCIICString(alpnVal);
> +}
> +
>  /
> *****************************************************************************
>   * Module descriptor
>   
> *****************************************************************************/
> @@ -393,10 +467,39 @@ static int st_Handshake (vlc_tls_creds_t *crd, 
> vlc_tls_t *session,
>      VLC_UNUSED(service);
>  
>      OSStatus retValue = SSLHandshake(sys->p_context);
> +
> +// Only try to use ALPN on recent enough SDKs
> +// macOS 10.13.2, iOS 11, tvOS 11, watchOS 4
> +#if (TARGET_OS_OSX    && MAC_OS_X_VERSION_MAX_ALLOWED     >= 101302) || \
> +    (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED  >= 110000) || \
> +    (TARGET_OS_TV     && __TV_OS_VERSION_MAX_ALLOWED      >= 110000) || \
> +    (TARGET_OS_WATCH  && __WATCH_OS_VERSION_MAX_ALLOWED   >= 40000)
> +#pragma clang diagnostic push
> +#pragma clang diagnostic ignored "-Wpartial-availability"
> +
> +    /* Handle ALPN data */
> +    if (alp != NULL) {
> +        CFArrayRef alpnArray = NULL;
> +        OSStatus res = SSLCopyALPNProtocols(sys->p_context, &alpnArray);
> +        if (res == noErr && alpnArray) {
> +            *alp = CFArrayALPNCopyFirst(alpnArray);
> +            if (unlikely(*alp == NULL))
> +                return -1;
> +        } else {
> +            *alp = NULL;
> +        }
> +    }
> +
> +#pragma clang diagnostic pop
> +#else
> +
> +    /* No ALPN support */
>      if (alp != NULL) {
>          *alp = NULL;
>      }
>  
> +#endif
> +
>      if (retValue == errSSLWouldBlock) {
>          msg_Dbg(crd, "handshake is blocked, try again later");
>          return 1 + (sys->b_blocking_send ? 1 : 0);
> @@ -646,11 +749,6 @@ error:
>  static vlc_tls_t *st_ClientSessionOpen(vlc_tls_creds_t *crd, vlc_tls_t 
> *sock,
>                                   const char *hostname, const char 
> *const *alpn)
>  {
> -    if (alpn != NULL) {
> -        msg_Warn(crd, "Ignoring ALPN request due to lack of support in 
> the backend. Proxy behavior potentially undefined.");
> -#warning ALPN support missing, proxy behavior potentially undefined 
> (rdar://29127318, #17721)
> -    }
> -
>      msg_Dbg(crd, "open TLS session for %s", hostname);
>  
>      vlc_tls_t *tls = st_SessionOpenCommon(crd, sock, false);
> @@ -665,6 +763,47 @@ static vlc_tls_t 
> *st_ClientSessionOpen(vlc_tls_creds_t *crd, vlc_tls_t *sock,
>          goto error;
>      }
>  
> +// Only try to use ALPN on recent enough SDKs
> +// macOS 10.13.2, iOS 11, tvOS 11, watchOS 4
> +#if (TARGET_OS_OSX    && MAC_OS_X_VERSION_MAX_ALLOWED     >= 101302) || 
> \
> +    (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED  >= 110000) || 
> \
> +    (TARGET_OS_TV     && __TV_OS_VERSION_MAX_ALLOWED      >= 110000) || 
> \
> +    (TARGET_OS_WATCH  && __WATCH_OS_VERSION_MAX_ALLOWED   >= 40000)
> +#pragma clang diagnostic push
> +#pragma clang diagnostic ignored "-Wpartial-availability"
> +
> +    /* Handle ALPN */
> +    if (alpn != NULL) {
> +        if (SSLSetALPNProtocols != NULL) {
> +            CFMutableArrayRef alpnValues = alpnToCFArray(alpn);
> +
> +            if (alpnValues == NULL) {
> +                msg_Err(crd, "cannot create CFMutableArray for ALPN 
> values");
> +                goto error;
> +            }
> +
> +            OSStatus ret = SSLSetALPNProtocols(sys->p_context, 
> alpnValues);
> +            if (ret != noErr){
> +                msg_Err(crd, "failed setting ALPN protocols (%i)", 
> ret);
> +            }
> +            CFRelease(alpnValues);
> +        } else {
> +            msg_Warn(crd, "Ignoring ALPN request due to lack of support 
> in the backend. Proxy behavior potentially undefined.");
> +        }
> +    }
> +
> +#pragma clang diagnostic pop
> +#else
> +
> +    /* No ALPN support */
> +    if (alpn != NULL) {
> +        // Fallback if SDK does not has SSLSetALPNProtocols
> +        msg_Warn(crd, "Compiled in SDK without ALPN support. Proxy 
> behavior potentially undefined.");
> +        #warning ALPN support in your SDK version missing (need 
> 10.13.2), proxy behavior potentially undefined (rdar://29127318, #17721)
> +    }
> +
> +#endif
> +
>      /* disable automatic validation. We do so manually to also handle 
> invalid
>         certificates */
>  
> -- 
> 2.14.3 (Apple Git-98)
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list