diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/vtls/nss.c | 76 | 
1 files changed, 74 insertions, 2 deletions
| diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 617787e69..84e6d98d1 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -614,8 +614,43 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,   */  static void HandshakeCallback(PRFileDesc *sock, void *arg)  { +  struct connectdata *conn = (struct connectdata*) arg; + +#ifndef USE_NGHTTP2    (void)sock; -  (void)arg; +  (void)conn; +#else +  unsigned int buflenmax = 50; +  unsigned char buf[50]; +  unsigned int buflen; +  SSLNextProtoState state; + +  if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { + +    switch(state) { +      case SSL_NEXT_PROTO_NO_SUPPORT: +      case SSL_NEXT_PROTO_NO_OVERLAP: +        infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n"); +        return; +      case SSL_NEXT_PROTO_SELECTED: +        infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); +        break; +      case SSL_NEXT_PROTO_NEGOTIATED: +        infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); +        break; +    } + +    if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && +        memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN) +        == 0) { +      conn->negnpn = NPN_HTTP2_DRAFT09; +    } +    else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf, +        ALPN_HTTP_1_1_LENGTH)) { +      conn->negnpn = NPN_HTTP1_1; +    } +  } +#endif  }  static void display_cert_info(struct SessionHandle *data, @@ -1264,6 +1299,16 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)      SSL_LIBRARY_VERSION_TLS_1_0   /* max */    }; +#ifdef USE_NGHTTP2 +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) +  unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN + +      ALPN_HTTP_1_1_LENGTH + 2; +  unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH +      + 2]; +  int cur = 0; +#endif +#endif +    if(connssl->state == ssl_connection_complete)      return CURLE_OK; @@ -1374,7 +1419,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)    if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)      goto error; -  if(SSL_HandshakeCallback(model, HandshakeCallback, NULL) != SECSuccess) +  if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)      goto error;    if(data->set.ssl.verifypeer) { @@ -1437,6 +1482,33 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)      SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);    } +#ifdef USE_NGHTTP2 +#ifdef SSL_ENABLE_NPN +  if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess) +    goto error; +#endif + +#ifdef SSL_ENABLE_ALPN +  if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE) != SECSuccess) +    goto error; +#endif + +#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) +  alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN; +  cur++; +  memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID, +      NGHTTP2_PROTO_VERSION_ID_LEN); +  cur += NGHTTP2_PROTO_VERSION_ID_LEN; +  alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH; +  cur++; +  memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); + +  if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len) +      != SECSuccess) +    goto error; +#endif +#endif +    /* Force handshake on next I/O */    SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); | 
