diff options
author | Curl Upstream <curl-library@lists.haxx.se> | 2022-12-21 07:00:59 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-01-27 20:58:30 (GMT) |
commit | dac458ddbf2b48168779821654a7e69cbd828c14 (patch) | |
tree | 8191fa2b92ceb3469c8ac5878b4ded3112f5f16c /lib/vquic | |
parent | ec122fff08ab9a8e56fb90126ecedb99c759011b (diff) | |
download | CMake-dac458ddbf2b48168779821654a7e69cbd828c14.zip CMake-dac458ddbf2b48168779821654a7e69cbd828c14.tar.gz CMake-dac458ddbf2b48168779821654a7e69cbd828c14.tar.bz2 |
curl 2022-12-21 (c12fb3dd)
Code extracted from:
https://github.com/curl/curl.git
at commit c12fb3ddaf48e709a7a4deaa55ec485e4df163ee (curl-7_87_0).
Diffstat (limited to 'lib/vquic')
-rw-r--r-- | lib/vquic/ngtcp2.c | 160 | ||||
-rw-r--r-- | lib/vquic/ngtcp2.h | 7 | ||||
-rw-r--r-- | lib/vquic/quiche.c | 5 |
3 files changed, 90 insertions, 82 deletions
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c index 097cca4..f16b469 100644 --- a/lib/vquic/ngtcp2.c +++ b/lib/vquic/ngtcp2.c @@ -27,6 +27,7 @@ #ifdef USE_NGTCP2 #include <ngtcp2/ngtcp2.h> #include <nghttp3/nghttp3.h> + #ifdef USE_OPENSSL #include <openssl/err.h> #ifdef OPENSSL_IS_BORINGSSL @@ -42,6 +43,7 @@ #include <ngtcp2/ngtcp2_crypto_wolfssl.h> #include "vtls/wolfssl.h" #endif + #include "urldata.h" #include "sendf.h" #include "strdup.h" @@ -49,6 +51,7 @@ #include "ngtcp2.h" #include "multiif.h" #include "strcase.h" +#include "cfilters.h" #include "connect.h" #include "strerror.h" #include "dynbuf.h" @@ -300,17 +303,19 @@ static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data) static CURLcode quic_set_client_cert(struct Curl_easy *data, struct quicsocket *qs) { - struct connectdata *conn = data->conn; SSL_CTX *ssl_ctx = qs->sslctx; - char *const ssl_cert = SSL_SET_OPTION(primary.clientcert); - const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob); - const char *const ssl_cert_type = SSL_SET_OPTION(cert_type); + const struct ssl_config_data *ssl_config; - if(ssl_cert || ssl_cert_blob || ssl_cert_type) { + ssl_config = Curl_ssl_get_config(data, FIRSTSOCKET); + DEBUGASSERT(ssl_config); + + if(ssl_config->primary.clientcert || ssl_config->primary.cert_blob + || ssl_config->cert_type) { return Curl_ossl_set_client_cert( - data, ssl_ctx, ssl_cert, ssl_cert_blob, ssl_cert_type, - SSL_SET_OPTION(key), SSL_SET_OPTION(key_blob), - SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd)); + data, ssl_ctx, ssl_config->primary.clientcert, + ssl_config->primary.cert_blob, ssl_config->cert_type, + ssl_config->key, ssl_config->key_blob, + ssl_config->key_type, ssl_config->key_passwd); } return CURLE_OK; @@ -318,13 +323,17 @@ static CURLcode quic_set_client_cert(struct Curl_easy *data, /** SSL callbacks ***/ -static int quic_init_ssl(struct quicsocket *qs) +static CURLcode quic_init_ssl(struct quicsocket *qs, + struct Curl_easy *data, + struct connectdata *conn) { const uint8_t *alpn = NULL; size_t alpnlen = 0; /* this will need some attention when HTTPS proxy over QUIC get fixed */ const char * const hostname = qs->conn->host.name; + (void)data; + (void)conn; DEBUGASSERT(!qs->ssl); qs->ssl = SSL_new(qs->sslctx); @@ -339,64 +348,49 @@ static int quic_init_ssl(struct quicsocket *qs) /* set SNI */ SSL_set_tlsext_host_name(qs->ssl, hostname); - return 0; + return CURLE_OK; } #elif defined(USE_GNUTLS) -static int quic_init_ssl(struct quicsocket *qs) +static CURLcode quic_init_ssl(struct quicsocket *qs, + struct Curl_easy *data, + struct connectdata *conn) { + CURLcode result; gnutls_datum_t alpn[2]; /* this will need some attention when HTTPS proxy over QUIC get fixed */ const char * const hostname = qs->conn->host.name; + long * const pverifyresult = &data->set.ssl.certverifyresult; int rc; - DEBUGASSERT(!qs->ssl); + DEBUGASSERT(qs->gtls == NULL); + qs->gtls = calloc(1, sizeof(*(qs->gtls))); + if(!qs->gtls) + return CURLE_OUT_OF_MEMORY; - gnutls_init(&qs->ssl, GNUTLS_CLIENT); - gnutls_session_set_ptr(qs->ssl, &qs->conn_ref); + result = gtls_client_init(data, &conn->ssl_config, &data->set.ssl, + hostname, qs->gtls, pverifyresult); + if(result) + return result; - if(ngtcp2_crypto_gnutls_configure_client_session(qs->ssl) != 0) { + gnutls_session_set_ptr(qs->gtls->session, &qs->conn_ref); + + if(ngtcp2_crypto_gnutls_configure_client_session(qs->gtls->session) != 0) { H3BUGF(fprintf(stderr, "ngtcp2_crypto_gnutls_configure_client_session failed\n")); - return 1; + return CURLE_QUIC_CONNECT_ERROR; } - rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL); + rc = gnutls_priority_set_direct(qs->gtls->session, QUIC_PRIORITY, NULL); if(rc < 0) { H3BUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n", gnutls_strerror(rc))); - return 1; + return CURLE_QUIC_CONNECT_ERROR; } /* Open the file if a TLS or QUIC backend has not done this before. */ Curl_tls_keylog_open(); if(Curl_tls_keylog_enabled()) { - gnutls_session_set_keylog_function(qs->ssl, keylog_callback); - } - - if(qs->cred) - gnutls_certificate_free_credentials(qs->cred); - - rc = gnutls_certificate_allocate_credentials(&qs->cred); - if(rc < 0) { - H3BUGF(fprintf(stderr, - "gnutls_certificate_allocate_credentials failed: %s\n", - gnutls_strerror(rc))); - return 1; - } - - rc = gnutls_certificate_set_x509_system_trust(qs->cred); - if(rc < 0) { - H3BUGF(fprintf(stderr, - "gnutls_certificate_set_x509_system_trust failed: %s\n", - gnutls_strerror(rc))); - return 1; - } - - rc = gnutls_credentials_set(qs->ssl, GNUTLS_CRD_CERTIFICATE, qs->cred); - if(rc < 0) { - H3BUGF(fprintf(stderr, "gnutls_credentials_set failed: %s\n", - gnutls_strerror(rc))); - return 1; + gnutls_session_set_keylog_function(qs->gtls->session, keylog_callback); } /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */ @@ -405,11 +399,9 @@ static int quic_init_ssl(struct quicsocket *qs) alpn[1].data = (unsigned char *)H3_ALPN_H3 + 1; alpn[1].size = sizeof(H3_ALPN_H3) - 2; - gnutls_alpn_set_protocols(qs->ssl, alpn, 2, GNUTLS_ALPN_MANDATORY); + gnutls_alpn_set_protocols(qs->gtls->session, alpn, 2, GNUTLS_ALPN_MANDATORY); - /* set SNI */ - gnutls_server_name_set(qs->ssl, GNUTLS_NAME_DNS, hostname, strlen(hostname)); - return 0; + return CURLE_OK; } #elif defined(USE_WOLFSSL) @@ -484,13 +476,17 @@ static WOLFSSL_CTX *quic_ssl_ctx(struct Curl_easy *data) /** SSL callbacks ***/ -static int quic_init_ssl(struct quicsocket *qs) +static CURLcode quic_init_ssl(struct quicsocket *qs, + struct Curl_easy *data, + struct connectdata *conn) { const uint8_t *alpn = NULL; size_t alpnlen = 0; /* this will need some attention when HTTPS proxy over QUIC get fixed */ const char * const hostname = qs->conn->host.name; + (void)data; + (void)conn; DEBUGASSERT(!qs->ssl); qs->ssl = SSL_new(qs->sslctx); @@ -507,7 +503,7 @@ static int quic_init_ssl(struct quicsocket *qs) wolfSSL_UseSNI(qs->ssl, WOLFSSL_SNI_HOST_NAME, hostname, (unsigned short)strlen(hostname)); - return 0; + return CURLE_OK; } #endif /* defined(USE_WOLFSSL) */ @@ -812,8 +808,9 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, return CURLE_QUIC_CONNECT_ERROR; #endif - if(quic_init_ssl(qs)) - return CURLE_QUIC_CONNECT_ERROR; + result = quic_init_ssl(qs, data, conn); + if(result) + return result; qs->dcid.datalen = NGTCP2_MAX_CIDLEN; result = Curl_rand(data, qs->dcid.data, NGTCP2_MAX_CIDLEN); @@ -845,7 +842,11 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, if(rc) return CURLE_QUIC_CONNECT_ERROR; +#ifdef USE_GNUTLS + ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->gtls->session); +#else ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl); +#endif ngtcp2_connection_close_error_default(&qs->last_error); @@ -894,7 +895,7 @@ static int ng_getsock(struct Curl_easy *data, struct connectdata *conn, socks[0] = conn->sock[FIRSTSOCKET]; - /* in a HTTP/2 connection we can basically always get a frame so we should + /* in an HTTP/2 connection we can basically always get a frame so we should always be ready for one */ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); @@ -932,29 +933,29 @@ static void qs_disconnect(struct quicsocket *qs) close(qs->qlogfd); qs->qlogfd = -1; } - if(qs->ssl) #ifdef USE_OPENSSL + if(qs->ssl) SSL_free(qs->ssl); + qs->ssl = NULL; + SSL_CTX_free(qs->sslctx); #elif defined(USE_GNUTLS) - gnutls_deinit(qs->ssl); + if(qs->gtls) { + if(qs->gtls->cred) + gnutls_certificate_free_credentials(qs->gtls->cred); + if(qs->gtls->session) + gnutls_deinit(qs->gtls->session); + free(qs->gtls); + qs->gtls = NULL; + } #elif defined(USE_WOLFSSL) + if(qs->ssl) wolfSSL_free(qs->ssl); -#endif qs->ssl = NULL; -#ifdef USE_GNUTLS - if(qs->cred) { - gnutls_certificate_free_credentials(qs->cred); - qs->cred = NULL; - } + wolfSSL_CTX_free(qs->sslctx); #endif free(qs->pktbuf); nghttp3_conn_del(qs->h3conn); ngtcp2_conn_del(qs->qconn); -#ifdef USE_OPENSSL - SSL_CTX_free(qs->sslctx); -#elif defined(USE_WOLFSSL) - wolfSSL_CTX_free(qs->sslctx); -#endif } void Curl_quic_disconnect(struct Curl_easy *data, @@ -1170,7 +1171,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id, } } else { - /* store as a HTTP1-style header */ + /* store as an HTTP1-style header */ result = write_data(stream, h3name.base, h3name.len); if(result) { return -1; @@ -1672,6 +1673,15 @@ static CURLcode ng_has_connected(struct Curl_easy *data, struct connectdata *conn, int tempindex) { CURLcode result = CURLE_OK; + const char *hostname, *disp_hostname; + int port; + char *snihost; + + Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port); + snihost = Curl_ssl_snihost(data, hostname, NULL); + if(!snihost) + return CURLE_PEER_FAILED_VERIFICATION; + conn->recv[FIRSTSOCKET] = ngh3_stream_recv; conn->send[FIRSTSOCKET] = ngh3_stream_send; conn->handler = &Curl_handler_http3; @@ -1691,16 +1701,18 @@ static CURLcode ng_has_connected(struct Curl_easy *data, X509_free(server_cert); if(result) return result; - infof(data, "Verified certificate just fine"); #elif defined(USE_GNUTLS) - result = Curl_gtls_verifyserver(data, conn, conn->quic->ssl, FIRSTSOCKET); + result = Curl_gtls_verifyserver(data, conn->quic->gtls->session, + &conn->ssl_config, &data->set.ssl, + hostname, disp_hostname, + data->set.str[STRING_SSL_PINNEDPUBLICKEY]); + if(result) + return result; #elif defined(USE_WOLFSSL) - char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL); - if(!snihost || - (wolfSSL_check_domain_name(conn->quic->ssl, snihost) == SSL_FAILURE)) + if(wolfSSL_check_domain_name(conn->quic->ssl, snihost) == SSL_FAILURE) return CURLE_PEER_FAILED_VERIFICATION; - infof(data, "Verified certificate just fine"); #endif + infof(data, "Verified certificate just fine"); } else infof(data, "Skipped certificate verification"); diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h index 6539f5f..2265999 100644 --- a/lib/vquic/ngtcp2.h +++ b/lib/vquic/ngtcp2.h @@ -36,14 +36,14 @@ #include <nghttp3/nghttp3.h> #ifdef USE_OPENSSL #include <openssl/ssl.h> -#elif defined(USE_GNUTLS) -#include <gnutls/gnutls.h> #elif defined(USE_WOLFSSL) #include <wolfssl/options.h> #include <wolfssl/ssl.h> #include <wolfssl/quic.h> #endif +struct gtls_instance; + struct blocked_pkt { const uint8_t *pkt; size_t pktlen; @@ -64,8 +64,7 @@ struct quicsocket { SSL_CTX *sslctx; SSL *ssl; #elif defined(USE_GNUTLS) - gnutls_certificate_credentials_t cred; - gnutls_session_t ssl; + struct gtls_instance *gtls; #elif defined(USE_WOLFSSL) WOLFSSL_CTX *sslctx; WOLFSSL *ssl; diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index a52a7e8..2b9a041 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -80,7 +80,7 @@ static int quiche_getsock(struct Curl_easy *data, socks[0] = conn->sock[FIRSTSOCKET]; - /* in a HTTP/2 connection we can basically always get a frame so we should + /* in an HTTP/2 connection we can basically always get a frame so we should always be ready for one */ bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); @@ -348,9 +348,6 @@ CURLcode Curl_quic_connect(struct Curl_easy *data, Curl_persistconninfo(data, conn, NULL, -1); - /* for connection reuse purposes: */ - conn->ssl[FIRSTSOCKET].state = ssl_connection_complete; - { unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL; unsigned alpn_len, offset = 0; |