diff options
| author | Jay Satiro <raysatiro@yahoo.com> | 2016-03-28 18:18:09 -0400 | 
|---|---|---|
| committer | Jay Satiro <raysatiro@yahoo.com> | 2016-03-28 18:18:09 -0400 | 
| commit | a43b22e05b726e7e080eda63f287f728392b7064 (patch) | |
| tree | c005b07299f9a0833067de91e4c7d0c20294a74a /lib | |
| parent | 67a762928ed33470e7423fd01e1860e9c61dedd7 (diff) | |
wolfssl: Add ALPN support
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vtls/cyassl.c | 104 | 
1 files changed, 99 insertions, 5 deletions
| diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c index f6b57af68..7fa853678 100644 --- a/lib/vtls/cyassl.c +++ b/lib/vtls/cyassl.c @@ -77,6 +77,41 @@ and that's a problem since options.h hasn't been included yet. */  #define CYASSL_MAX_ERROR_SZ 80  #endif +/* To determine what functions are available we rely on one or both of: +   - the user's options.h generated by CyaSSL/wolfSSL +   - the symbols detected by curl's configure +   Since they are markedly different from one another, and one or the other may +   not be available, we do some checking below to bring things in sync. */ + +/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */ +#ifndef HAVE_ALPN +#ifdef HAVE_WOLFSSL_USEALPN +#define HAVE_ALPN +#endif +#endif + +/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in +   options.h, but is only seen in >= 3.6.6 since that's when they started +   disabling SSLv3 by default. */ +#ifndef WOLFSSL_ALLOW_SSLV3 +#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \ +    defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#define WOLFSSL_ALLOW_SSLV3 +#endif +#endif + +/* KEEP_PEER_CERT is a product of the presence of build time symbol +   OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is +   in wolfSSL's settings.h, and the latter two are build time symbols in +   options.h. */ +#ifndef KEEP_PEER_CERT +#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \ +    defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \ +    (defined(OPENSSL_EXTRA) && !defined(NO_CERTS)) +#define KEEP_PEER_CERT +#endif +#endif +  static Curl_recv cyassl_recv;  static Curl_send cyassl_send; @@ -143,9 +178,7 @@ cyassl_connect_step1(struct connectdata *conn,      use_sni(TRUE);      break;    case CURL_SSLVERSION_SSLv3: -    /* before WolfSSL SSLv3 was enabled by default, and starting in WolfSSL -       we check for its presence since it is built without it by default */ -#if !defined(WOLFSSL_VERSION) || defined(HAVE_WOLFSSLV3_CLIENT_METHOD) +#ifdef WOLFSSL_ALLOW_SSLV3      req_method = SSLv3_client_method();      use_sni(FALSE);  #else @@ -309,6 +342,33 @@ cyassl_connect_step1(struct connectdata *conn,      return CURLE_OUT_OF_MEMORY;    } +#ifdef HAVE_ALPN +  if(data->set.ssl_enable_alpn) { +    char protocols[128]; +    *protocols = '\0'; + +    /* wolfSSL's ALPN protocol name list format is a comma separated string of +       protocols in descending order of preference, eg: "h2,http/1.1" */ + +#ifdef USE_NGHTTP2 +    if(data->set.httpversion >= CURL_HTTP_VERSION_2) { +      strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); +      infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); +    } +#endif + +    strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); +    infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + +    if(wolfSSL_UseALPN(conssl->handle, protocols, +                       (unsigned)strlen(protocols), +                       WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { +      failf(data, "SSL: failed setting ALPN protocols"); +      return CURLE_SSL_CONNECT_ERROR; +    } +  } +#endif /* HAVE_ALPN */ +    /* Check if there's a cached ID we can/should use here! */    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {      /* we got a session id, use it! */ @@ -413,8 +473,7 @@ cyassl_connect_step2(struct connectdata *conn,    }    if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { -#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) ||       \ -  defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) +#ifdef KEEP_PEER_CERT      X509 *x509;      const char *x509_der;      int x509_der_len; @@ -457,6 +516,41 @@ cyassl_connect_step2(struct connectdata *conn,  #endif    } +#ifdef HAVE_ALPN +  if(data->set.ssl_enable_alpn) { +    int rc; +    char *protocol = NULL; +    unsigned short protocol_len = 0; + +    rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len); + +    if(rc == SSL_SUCCESS) { +      infof(data, "ALPN, server accepted to use %.*s\n", protocol_len, +            protocol); + +      if(protocol_len == ALPN_HTTP_1_1_LENGTH && +         !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) +        conn->negnpn = CURL_HTTP_VERSION_1_1; +#ifdef USE_NGHTTP2 +      else if(data->set.httpversion >= CURL_HTTP_VERSION_2 && +              protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN && +              !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID, +                      NGHTTP2_PROTO_VERSION_ID_LEN)) +        conn->negnpn = CURL_HTTP_VERSION_2; +#endif +      else +        infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len, +              protocol); +    } +    else if(rc == SSL_ALPN_NOT_FOUND) +      infof(data, "ALPN, server did not agree to a protocol\n"); +    else { +      failf(data, "ALPN, failure getting protocol, error %d", rc); +      return CURLE_SSL_CONNECT_ERROR; +    } +  } +#endif /* HAVE_ALPN */ +    conssl->connecting_state = ssl_connect_3;    infof(data, "SSL connected\n"); | 
