diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/nss.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/nss.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c index 2b44f05..5b7de9f 100644 --- a/Utilities/cmcurl/lib/vtls/nss.c +++ b/Utilities/cmcurl/lib/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -434,7 +434,7 @@ static char *dup_nickname(struct Curl_easy *data, const char *str) /* search the first slash; we require at least one slash in a file name */ n = strchr(str, '/'); if(!n) { - infof(data, "warning: certificate file name \"%s\" handled as nickname; " + infof(data, "WARNING: certificate file name \"%s\" handled as nickname; " "please use \"./%s\" to force file name", str, str); return strdup(str); } @@ -488,6 +488,9 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl, const int slot_id = (cacert) ? 0 : 1; char *slot_name = aprintf("PEM Token #%d", slot_id); struct ssl_backend_data *backend = connssl->backend; + + DEBUGASSERT(backend); + if(!slot_name) return CURLE_OUT_OF_MEMORY; @@ -859,11 +862,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) #endif case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: - infof(data, "ALPN/NPN, server did not agree to a protocol"); + infof(data, VTLS_INFOF_NO_ALPN); return; #ifdef SSL_ENABLE_ALPN case SSL_NEXT_PROTO_SELECTED: - infof(data, "ALPN, server accepted to use %.*s", buflen, buf); + infof(data, VTLS_INFOF_ALPN_ACCEPTED_LEN_1STR, buflen, buf); break; #endif case SSL_NEXT_PROTO_NEGOTIATED: @@ -871,7 +874,7 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) break; } -#ifdef USE_NGHTTP2 +#ifdef USE_HTTP2 if(buflen == ALPN_H2_LENGTH && !memcmp(ALPN_H2, buf, ALPN_H2_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_2; @@ -882,8 +885,14 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_1_1; } - Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? - BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); + + /* This callback might get called when PR_Recv() is used within + * close_one() during a connection shutdown. At that point there might not + * be any "bundle" associated with the connection anymore. + */ + if(conn->bundle) + Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? + BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } } @@ -1105,9 +1114,12 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, { CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; struct ssl_backend_data *backend = connssl->backend; - struct Curl_easy *data = backend->data; + struct Curl_easy *data = NULL; CERTCertificate *cert; + DEBUGASSERT(backend); + data = backend->data; + if(!pinnedpubkey) /* no pinned public key specified */ return CURLE_OK; @@ -1134,7 +1146,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, /* report the resulting status */ switch(result) { case CURLE_OK: - infof(data, "pinned public key verified successfully!"); + infof(data, "pinned public key verified successfully"); break; case CURLE_SSL_PINNEDPUBKEYNOTMATCH: failf(data, "failed to verify pinned public key"); @@ -1158,10 +1170,15 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, { struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; struct ssl_backend_data *backend = connssl->backend; - struct Curl_easy *data = backend->data; - const char *nickname = backend->client_nickname; + struct Curl_easy *data = NULL; + const char *nickname = NULL; static const char pem_slotname[] = "PEM Token #1"; + DEBUGASSERT(backend); + + data = backend->data; + nickname = backend->client_nickname; + if(backend->obj_clicert) { /* use the cert/key provided by PEM reader */ SECItem cert_der = { 0, NULL, 0 }; @@ -1529,6 +1546,8 @@ static int nss_check_cxn(struct connectdata *conn) int rc; char buf; + DEBUGASSERT(backend); + rc = PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK, PR_SecondsToInterval(1)); @@ -1545,7 +1564,11 @@ static void close_one(struct ssl_connect_data *connssl) { /* before the cleanup, check whether we are using a client certificate */ struct ssl_backend_data *backend = connssl->backend; - const bool client_cert = (backend->client_nickname != NULL) + bool client_cert = true; + + DEBUGASSERT(backend); + + client_cert = (backend->client_nickname != NULL) || (backend->obj_clicert != NULL); if(backend->handle) { @@ -1587,8 +1610,13 @@ static void nss_close(struct Curl_easy *data, struct connectdata *conn, struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; #endif struct ssl_backend_data *backend = connssl->backend; - (void)data; + + DEBUGASSERT(backend); +#ifndef CURL_DISABLE_PROXY + DEBUGASSERT(connssl_proxy->backend != NULL); +#endif + if(backend->handle #ifndef CURL_DISABLE_PROXY || connssl_proxy->backend->handle @@ -1720,7 +1748,7 @@ static CURLcode nss_load_ca_certificates(struct Curl_easy *data, PR_CloseDir(dir); } else - infof(data, "warning: CURLOPT_CAPATH not a directory (%s)", capath); + infof(data, "WARNING: CURLOPT_CAPATH not a directory (%s)", capath); } return CURLE_OK; @@ -1816,6 +1844,8 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, { struct ssl_backend_data *backend = connssl->backend; + DEBUGASSERT(backend); + if(is_nss_error(curlerr)) { /* read NSPR error code */ PRErrorCode err = PR_GetError(); @@ -1842,6 +1872,9 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, { PRSocketOptionData sock_opt; struct ssl_backend_data *backend = connssl->backend; + + DEBUGASSERT(backend); + sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.value.non_blocking = !blocking; @@ -1865,7 +1898,6 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, CURLcode result; bool second_layer = FALSE; SSLVersionRange sslver_supported; - SSLVersionRange sslver = { SSL_LIBRARY_VERSION_TLS_1_0, /* min */ #ifdef SSL_LIBRARY_VERSION_TLS_1_3 @@ -1878,6 +1910,13 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, SSL_LIBRARY_VERSION_TLS_1_0 #endif }; + char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL); + if(!snihost) { + failf(data, "Failed to set SNI"); + return CURLE_SSL_CONNECT_ERROR; + } + + DEBUGASSERT(backend); backend->data = data; @@ -1946,11 +1985,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, /* unless the user explicitly asks to allow the protocol vulnerability, we use the work-around */ if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) - infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d", + infof(data, "WARNING: failed to set SSL_CBC_RANDOM_IV = %d", ssl_cbc_random_iv); #else if(ssl_cbc_random_iv) - infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in"); + infof(data, "WARNING: support for SSL_CBC_RANDOM_IV not compiled in"); #endif if(SSL_CONN_CONFIG(cipher_list)) { @@ -1961,7 +2000,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, } if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) - infof(data, "warning: ignoring value of ssl.verifyhost"); + infof(data, "WARNING: ignoring value of ssl.verifyhost"); /* bypass the default SSL_AuthCertificate() hook in case we do not want to * verify peer */ @@ -1981,7 +2020,7 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, const CURLcode rv = nss_load_ca_certificates(data, conn, sockindex); if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer)) /* not a fatal error because we are not going to verify the peer */ - infof(data, "warning: CA certificates failed to load"); + infof(data, "WARNING: CA certificates failed to load"); else if(rv) { result = rv; goto error; @@ -2028,9 +2067,12 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { + struct ssl_backend_data *proxy_backend; + proxy_backend = conn->proxy_ssl[sockindex].backend; DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); - DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL); - nspr_io = conn->proxy_ssl[sockindex].backend->handle; + DEBUGASSERT(proxy_backend); + DEBUGASSERT(proxy_backend->handle); + nspr_io = proxy_backend->handle; second_layer = TRUE; } #endif @@ -2140,11 +2182,11 @@ static CURLcode nss_setup_connect(struct Curl_easy *data, goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(backend->handle, SSL_HOST_NAME()) != SECSuccess) + if(SSL_SetURL(backend->handle, snihost) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(backend->handle, SSL_HOST_NAME()) != SECSuccess) + if(SSL_SetSockPeerID(backend->handle, snihost) != SECSuccess) goto error; return CURLE_OK; @@ -2172,6 +2214,8 @@ static CURLcode nss_do_connect(struct Curl_easy *data, goto error; } + DEBUGASSERT(backend); + /* Force the handshake now */ timeout = PR_MillisecondsToInterval((PRUint32) time_left); if(SSL_ForceHandshakeWithTimeout(backend->handle, timeout) != SECSuccess) { @@ -2305,6 +2349,8 @@ static ssize_t nss_send(struct Curl_easy *data, /* transfer */ struct ssl_backend_data *backend = connssl->backend; ssize_t rc; + DEBUGASSERT(backend); + /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ backend->data = data; @@ -2344,6 +2390,8 @@ static ssize_t nss_recv(struct Curl_easy *data, /* transfer */ struct ssl_backend_data *backend = connssl->backend; ssize_t nread; + DEBUGASSERT(backend); + /* The SelectClientCert() hook uses this for infof() and failf() but the handle stored in nss_setup_connect() could have already been freed. */ backend->data = data; @@ -2442,6 +2490,7 @@ static void *nss_get_internals(struct ssl_connect_data *connssl, { struct ssl_backend_data *backend = connssl->backend; (void)info; + DEBUGASSERT(backend); return backend->handle; } |