diff options
author | Curl Upstream <curl-library@cool.haxx.se> | 2017-10-04 05:52:15 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2017-10-10 15:15:03 (GMT) |
commit | de7c21d677db1ddaeece03c19e13e448f4031511 (patch) | |
tree | f812bbd3771bd01de9f7cd91a557766605f6ed2c /lib/vtls/nss.c | |
parent | 06d6d6c4aee149cd6560b919ef6935ef0867d921 (diff) | |
download | CMake-de7c21d677db1ddaeece03c19e13e448f4031511.zip CMake-de7c21d677db1ddaeece03c19e13e448f4031511.tar.gz CMake-de7c21d677db1ddaeece03c19e13e448f4031511.tar.bz2 |
curl 2017-10-04 (3ea76790)
Code extracted from:
https://github.com/curl/curl.git
at commit 3ea76790571c1f7cf1bed34fabffd3cc20ad3dd3 (curl-7_56_0).
Diffstat (limited to 'lib/vtls/nss.c')
-rw-r--r-- | lib/vtls/nss.c | 237 |
1 files changed, 153 insertions, 84 deletions
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index cd01389..c0b7e63 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -78,6 +78,16 @@ /* enough to fit the string "PEM Token #[0|1]" */ #define SLOTSIZE 13 +struct ssl_backend_data { + PRFileDesc *handle; + char *client_nickname; + struct Curl_easy *data; + struct curl_llist obj_list; + PK11GenericObject *obj_clicert; +}; + +#define BACKEND connssl->backend + static PRLock *nss_initlock = NULL; static PRLock *nss_crllock = NULL; static PRLock *nss_findslot_lock = NULL; @@ -271,7 +281,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, found = PR_FALSE; - for(i=0; i<NUM_OF_CIPHERS; i++) { + for(i = 0; i<NUM_OF_CIPHERS; i++) { if(strcasecompare(cipher, cipherlist[i].name)) { cipher_state[i] = PR_TRUE; found = PR_TRUE; @@ -290,7 +300,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, } /* Finally actually enable the selected ciphers */ - for(i=0; i<NUM_OF_CIPHERS; i++) { + for(i = 0; i<NUM_OF_CIPHERS; i++) { if(!cipher_state[i]) continue; @@ -311,7 +321,7 @@ static bool any_cipher_enabled(void) { unsigned int i; - for(i=0; i<NUM_OF_CIPHERS; i++) { + for(i = 0; i<NUM_OF_CIPHERS; i++) { PRInt32 policy = 0; SSL_CipherPolicyGet(cipherlist[i].num, &policy); if(policy) @@ -396,7 +406,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr) /* Call PK11_CreateGenericObject() with the given obj_class and filename. If * the call succeeds, append the object handle to the list of objects so that * the object can be destroyed in Curl_nss_close(). */ -static CURLcode nss_create_object(struct ssl_connect_data *ssl, +static CURLcode nss_create_object(struct ssl_connect_data *connssl, CK_OBJECT_CLASS obj_class, const char *filename, bool cacert) { @@ -435,14 +445,14 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, if(!obj) return result; - if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) { + if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) { PK11_DestroyGenericObject(obj); return CURLE_OUT_OF_MEMORY; } if(!cacert && CKO_CERTIFICATE == obj_class) /* store reference to a client certificate */ - ssl->obj_clicert = obj; + BACKEND->obj_clicert = obj; return CURLE_OK; } @@ -992,7 +1002,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, char *issuer_nickname) { CERTCertificate *cert, *cert_issuer, *issuer; - SECStatus res=SECSuccess; + SECStatus res = SECSuccess; void *proto_win = NULL; cert = SSL_PeerCertificate(sock); @@ -1004,7 +1014,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, if((!cert_issuer) || (!issuer)) res = SECFailure; else if(SECITEM_CompareItem(&cert_issuer->derCert, - &issuer->derCert)!=SECEqual) + &issuer->derCert) != SECEqual) res = SECFailure; CERT_DestroyCertificate(cert); @@ -1017,7 +1027,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, const char *pinnedpubkey) { CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - struct Curl_easy *data = connssl->data; + struct Curl_easy *data = BACKEND->data; CERTCertificate *cert; if(!pinnedpubkey) @@ -1025,7 +1035,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, return CURLE_OK; /* get peer certificate */ - cert = SSL_PeerCertificate(connssl->handle); + cert = SSL_PeerCertificate(BACKEND->handle); if(cert) { /* extract public key from peer certificate */ SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); @@ -1069,11 +1079,11 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, struct SECKEYPrivateKeyStr **pRetKey) { struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; - struct Curl_easy *data = connssl->data; - const char *nickname = connssl->client_nickname; + struct Curl_easy *data = BACKEND->data; + const char *nickname = BACKEND->client_nickname; static const char pem_slotname[] = "PEM Token #1"; - if(connssl->obj_clicert) { + if(BACKEND->obj_clicert) { /* use the cert/key provided by PEM reader */ SECItem cert_der = { 0, NULL, 0 }; void *proto_win = SSL_RevealPinArg(sock); @@ -1086,7 +1096,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, return SECFailure; } - if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE, + if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE, &cert_der) != SECSuccess) { failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); PK11_FreeSlot(slot); @@ -1351,7 +1361,7 @@ static CURLcode nss_init(struct Curl_easy *data) * @retval 0 error initializing SSL * @retval 1 SSL initialized successfully */ -int Curl_nss_init(void) +static int Curl_nss_init(void) { /* curl_global_init() is not thread-safe so this test is ok */ if(nss_initlock == NULL) { @@ -1386,7 +1396,7 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data) } /* Global cleanup */ -void Curl_nss_cleanup(void) +static void Curl_nss_cleanup(void) { /* This function isn't required to be threadsafe and this is only done * as a safety feature. @@ -1426,14 +1436,14 @@ void Curl_nss_cleanup(void) * 0 means the connection has been closed * -1 means the connection status is unknown */ -int -Curl_nss_check_cxn(struct connectdata *conn) +static int Curl_nss_check_cxn(struct connectdata *conn) { + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; int rc; char buf; rc = - PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK, + PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK, PR_SecondsToInterval(1)); if(rc > 0) return 1; /* connection still in place */ @@ -1447,48 +1457,49 @@ Curl_nss_check_cxn(struct connectdata *conn) static void nss_close(struct ssl_connect_data *connssl) { /* before the cleanup, check whether we are using a client certificate */ - const bool client_cert = (connssl->client_nickname != NULL) - || (connssl->obj_clicert != NULL); + const bool client_cert = (BACKEND->client_nickname != NULL) + || (BACKEND->obj_clicert != NULL); - free(connssl->client_nickname); - connssl->client_nickname = NULL; + free(BACKEND->client_nickname); + BACKEND->client_nickname = NULL; /* destroy all NSS objects in order to avoid failure of NSS shutdown */ - Curl_llist_destroy(&connssl->obj_list, NULL); - connssl->obj_clicert = NULL; + Curl_llist_destroy(&BACKEND->obj_list, NULL); + BACKEND->obj_clicert = NULL; - if(connssl->handle) { + if(BACKEND->handle) { if(client_cert) /* A server might require different authentication based on the * particular path being requested by the client. To support this * scenario, we must ensure that a connection will never reuse the * authentication data from a previous connection. */ - SSL_InvalidateSession(connssl->handle); + SSL_InvalidateSession(BACKEND->handle); - PR_Close(connssl->handle); - connssl->handle = NULL; + PR_Close(BACKEND->handle); + BACKEND->handle = NULL; } } /* * This function is called when an SSL connection is closed. */ -void Curl_nss_close(struct connectdata *conn, int sockindex) +static void Curl_nss_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; - if(connssl->handle || connssl_proxy->handle) { + if(BACKEND->handle || connssl_proxy->backend->handle) { /* NSS closes the socket we previously handed to it, so we must mark it as closed to avoid double close */ fake_sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; } - if(connssl->handle) - /* nss_close(connssl) will transitively close also connssl_proxy->handle - if both are used. Clear it to avoid a double close leading to crash. */ - connssl_proxy->handle = NULL; + if(BACKEND->handle) + /* nss_close(connssl) will transitively close also + connssl_proxy->backend->handle if both are used. Clear it to avoid + a double close leading to crash. */ + connssl_proxy->backend->handle = NULL; nss_close(connssl); nss_close(connssl_proxy); @@ -1732,7 +1743,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, } /* cleanup on connection failure */ - Curl_llist_destroy(&connssl->obj_list, NULL); + Curl_llist_destroy(&BACKEND->obj_list, NULL); return curlerr; } @@ -1746,7 +1757,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, sock_opt.option = PR_SockOpt_Nonblocking; sock_opt.value.non_blocking = !blocking; - if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) + if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS) return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); return CURLE_OK; @@ -1770,10 +1781,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) SSL_LIBRARY_VERSION_TLS_1_0 /* max */ }; - connssl->data = data; + BACKEND->data = data; /* list of all NSS objects we need to destroy in Curl_nss_close() */ - Curl_llist_init(&connssl->obj_list, nss_destroy_object); + Curl_llist_init(&BACKEND->obj_list, nss_destroy_object); /* FIXME. NSS doesn't support multiple databases open at the same time. */ PR_Lock(nss_initlock); @@ -1882,7 +1893,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ - connssl->obj_clicert = NULL; + BACKEND->obj_clicert = NULL; } else { CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), @@ -1895,10 +1906,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } /* store the nickname for SelectClientCert() called during handshake */ - connssl->client_nickname = nickname; + BACKEND->client_nickname = nickname; } else - connssl->client_nickname = NULL; + BACKEND->client_nickname = NULL; if(SSL_GetClientAuthDataHook(model, SelectClientCert, (void *)connssl) != SECSuccess) { @@ -1908,8 +1919,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) if(conn->proxy_ssl[sockindex].use) { DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); - DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); - nspr_io = conn->proxy_ssl[sockindex].handle; + DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL); + nspr_io = conn->proxy_ssl[sockindex].backend->handle; second_layer = TRUE; } else { @@ -1939,8 +1950,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } /* import our model socket onto the current I/O stack */ - connssl->handle = SSL_ImportFD(model, nspr_io); - if(!connssl->handle) { + BACKEND->handle = SSL_ImportFD(model, nspr_io); + if(!BACKEND->handle) { if(!second_layer) PR_Close(nspr_io); goto error; @@ -1951,36 +1962,36 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* This is the password associated with the cert that we're using */ if(SSL_SET_OPTION(key_passwd)) { - SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd)); + SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd)); } #ifdef SSL_ENABLE_OCSP_STAPLING if(SSL_CONN_CONFIG(verifystatus)) { - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) != SECSuccess) goto error; } #endif #ifdef SSL_ENABLE_NPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn ? PR_TRUE : PR_FALSE) != SECSuccess) goto error; #endif #ifdef SSL_ENABLE_ALPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn ? PR_TRUE : PR_FALSE) != SECSuccess) goto error; #endif #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ if(data->set.ssl.falsestart) { - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE) + if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE) != SECSuccess) goto error; - if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback, + if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback, conn) != SECSuccess) goto error; } @@ -1992,7 +2003,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) unsigned char protocols[128]; #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2 && + (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN); @@ -2003,24 +2015,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); cur += ALPN_HTTP_1_1_LENGTH; - if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess) + if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess) goto error; } #endif /* Force handshake on next I/O */ - if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE) + if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE) != SECSuccess) goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ? + if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name) != SECSuccess) goto error; @@ -2057,7 +2069,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) /* Force the handshake now */ timeout = PR_MillisecondsToInterval((PRUint32) time_left); - if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { + if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) { if(PR_GetError() == PR_WOULD_BLOCK_ERROR) /* blocking direction is updated by nss_update_connecting_state() */ return CURLE_AGAIN; @@ -2068,7 +2080,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) goto error; } - result = display_conn_info(conn, connssl->handle); + result = display_conn_info(conn, BACKEND->handle); if(result) goto error; @@ -2077,7 +2089,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); if(nickname) { /* we support only nicknames in case of issuercert for now */ - ret = check_issuer_cert(connssl->handle, nickname); + ret = check_issuer_cert(BACKEND->handle, nickname); free(nickname); } @@ -2163,13 +2175,13 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, return CURLE_OK; } -CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) +static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) { return nss_connect_common(conn, sockindex, /* blocking */ NULL); } -CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, - int sockindex, bool *done) +static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, + int sockindex, bool *done) { return nss_connect_common(conn, sockindex, done); } @@ -2180,8 +2192,14 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ size_t len, /* amount to write */ CURLcode *curlcode) { - ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, - PR_INTERVAL_NO_WAIT); + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t rc; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT); if(rc < 0) { PRInt32 err = PR_GetError(); if(err == PR_WOULD_BLOCK_ERROR) @@ -2205,14 +2223,21 @@ static ssize_t nss_send(struct connectdata *conn, /* connection data */ return rc; /* number of bytes */ } -static ssize_t nss_recv(struct connectdata * conn, /* connection data */ - int num, /* socketindex */ +static ssize_t nss_recv(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ char *buf, /* store read data here */ size_t buffersize, /* max amount to read */ CURLcode *curlcode) { - ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, - PR_INTERVAL_NO_WAIT); + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + ssize_t nread; + + /* The SelectClientCert() hook uses this for infof() and failf() but the + handle stored in nss_setup_connect() could have already been freed. */ + BACKEND->data = conn->data; + + nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0, + PR_INTERVAL_NO_WAIT); if(nread < 0) { /* failed SSL read */ PRInt32 err = PR_GetError(); @@ -2238,22 +2263,22 @@ static ssize_t nss_recv(struct connectdata * conn, /* connection data */ return nread; } -size_t Curl_nss_version(char *buffer, size_t size) +static size_t Curl_nss_version(char *buffer, size_t size) { return snprintf(buffer, size, "NSS/%s", NSS_VERSION); } /* data might be NULL */ -int Curl_nss_seed(struct Curl_easy *data) +static int Curl_nss_seed(struct Curl_easy *data) { /* make sure that NSS is initialized */ return !!Curl_nss_force_init(data); } /* data might be NULL */ -CURLcode Curl_nss_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +static CURLcode Curl_nss_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { Curl_nss_seed(data); /* Initiate the seed if not already done */ @@ -2264,10 +2289,10 @@ CURLcode Curl_nss_random(struct Curl_easy *data, return CURLE_OK; } -void Curl_nss_md5sum(unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *md5sum, /* output */ - size_t md5len) +static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len) { PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); unsigned int MD5out; @@ -2275,12 +2300,14 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */ PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); PK11_DestroyContext(MD5pw, PR_TRUE); + + return CURLE_OK; } -void Curl_nss_sha256sum(const unsigned char *tmp, /* input */ - size_t tmplen, - unsigned char *sha256sum, /* output */ - size_t sha256len) +static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *sha256sum, /* output */ + size_t sha256len) { PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256); unsigned int SHA256out; @@ -2290,7 +2317,7 @@ void Curl_nss_sha256sum(const unsigned char *tmp, /* input */ PK11_DestroyContext(SHA256pw, PR_TRUE); } -bool Curl_nss_cert_status_request(void) +static bool Curl_nss_cert_status_request(void) { #ifdef SSL_ENABLE_OCSP_STAPLING return TRUE; @@ -2299,7 +2326,7 @@ bool Curl_nss_cert_status_request(void) #endif } -bool Curl_nss_false_start(void) +static bool Curl_nss_false_start(void) { #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ return TRUE; @@ -2308,4 +2335,46 @@ bool Curl_nss_false_start(void) #endif } +static void *Curl_nss_get_internals(struct ssl_connect_data *connssl, + CURLINFO info UNUSED_PARAM) +{ + (void)info; + return BACKEND->handle; +} + +const struct Curl_ssl Curl_ssl_nss = { + { CURLSSLBACKEND_NSS, "nss" }, /* info */ + + 1, /* have_ca_path */ + 1, /* have_certinfo */ + 1, /* have_pinnedpubkey */ + 0, /* have_ssl_ctx */ + 1, /* support_https_proxy */ + + sizeof(struct ssl_backend_data), + + Curl_nss_init, /* init */ + Curl_nss_cleanup, /* cleanup */ + Curl_nss_version, /* version */ + Curl_nss_check_cxn, /* check_cxn */ + /* NSS has no shutdown function provided and thus always fail */ + Curl_none_shutdown, /* shutdown */ + Curl_none_data_pending, /* data_pending */ + Curl_nss_random, /* random */ + Curl_nss_cert_status_request, /* cert_status_request */ + Curl_nss_connect, /* connect */ + Curl_nss_connect_nonblocking, /* connect_nonblocking */ + Curl_nss_get_internals, /* get_internals */ + Curl_nss_close, /* close */ + Curl_none_close_all, /* close_all */ + /* NSS has its own session ID cache */ + Curl_none_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_nss_false_start, /* false_start */ + Curl_nss_md5sum, /* md5sum */ + Curl_nss_sha256sum /* sha256sum */ +}; + #endif /* USE_NSS */ |