X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fvtls%2Fnss.c;h=dd83a9d684a12448e867ae1fcae9eaed114c8d45;hb=7b6dca47a42828c0ae87eab0d8b68f97d1495b67;hp=91727c7c336f3c48ac7100b531ddb61585ded28e;hpb=8a08705db260779441360e959b97b6c172f8acb0;p=platform%2Fupstream%2Fcurl.git diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index 91727c7..dd83a9d 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -38,7 +38,10 @@ #include "select.h" #include "vtls.h" #include "llist.h" -#include "curl_printf.h" + +#define _MPRINTF_REPLACE /* use the internal *printf() functions */ +#include + #include "nssg.h" #include #include @@ -56,20 +59,13 @@ #include #include #include -#include /* for SECKEY_DestroyPublicKey() */ - -#define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH) - -#if NSSVERNUM >= 0x030f00 /* 3.15.0 */ -#include -#endif +#include "curl_memory.h" #include "rawstr.h" #include "warnless.h" #include "x509asn1.h" -/* The last #include files should be: */ -#include "curl_memory.h" +/* The last #include file should be: */ #include "memdebug.h" #define SSL_DIR "/etc/pki/nssdb" @@ -643,34 +639,6 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, PRBool isServer) { struct connectdata *conn = (struct connectdata *)arg; - -#ifdef SSL_ENABLE_OCSP_STAPLING - if(conn->data->set.ssl.verifystatus) { - SECStatus cacheResult; - - const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); - if(!csa) { - failf(conn->data, "Invalid OCSP response"); - return SECFailure; - } - - if(csa->len == 0) { - failf(conn->data, "No OCSP response received"); - return SECFailure; - } - - cacheResult = CERT_CacheOCSPResponseFromSideChannel( - CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd), - PR_Now(), &csa->items[0], arg - ); - - if(cacheResult != SECSuccess) { - failf(conn->data, "Invalid OCSP response"); - return cacheResult; - } - } -#endif - if(!conn->data->set.ssl.verifypeer) { infof(conn->data, "skipping SSL peer certificate verification\n"); return SECSuccess; @@ -684,6 +652,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, */ static void HandshakeCallback(PRFileDesc *sock, void *arg) { +#ifdef USE_NGHTTP2 struct connectdata *conn = (struct connectdata*) arg; unsigned int buflenmax = 50; unsigned char buf[50]; @@ -699,7 +668,8 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) switch(state) { case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: - infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); + if(connssl->asked_for_h2) + infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n"); return; #ifdef SSL_ENABLE_ALPN case SSL_NEXT_PROTO_SELECTED: @@ -711,79 +681,21 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) break; } -#ifdef USE_NGHTTP2 if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && - !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) { - conn->negnpn = CURL_HTTP_VERSION_2_0; + memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN) + == 0) { + conn->negnpn = NPN_HTTP2; } - else -#endif - if(buflen == ALPN_HTTP_1_1_LENGTH && - !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) { - conn->negnpn = CURL_HTTP_VERSION_1_1; + else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf, + ALPN_HTTP_1_1_LENGTH)) { + conn->negnpn = NPN_HTTP1_1; } } -} - -#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ -static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data, - PRBool *canFalseStart) -{ - struct connectdata *conn = client_data; - struct SessionHandle *data = conn->data; - - SSLChannelInfo channelInfo; - SSLCipherSuiteInfo cipherInfo; - - SECStatus rv; - PRBool negotiatedExtension; - - *canFalseStart = PR_FALSE; - - if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess) - return SECFailure; - - if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo, - sizeof(cipherInfo)) != SECSuccess) - return SECFailure; - - /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for - * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310 - */ - if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2) - goto end; - - /* Only allow ECDHE key exchange algorithm. - * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */ - if(cipherInfo.keaType != ssl_kea_ecdh) - goto end; - - /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC - * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt - * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */ - if(cipherInfo.symCipher != ssl_calg_aes_gcm) - goto end; - - /* Enforce ALPN or NPN to do False Start, as an indicator of server - * compatibility. */ - rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn, - &negotiatedExtension); - if(rv != SECSuccess || !negotiatedExtension) { - rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn, - &negotiatedExtension); - } - - if(rv != SECSuccess || !negotiatedExtension) - goto end; - - *canFalseStart = PR_TRUE; - - infof(data, "Trying TLS False Start\n"); - -end: - return SECSuccess; -} +#else + (void)sock; + (void)arg; #endif +} static void display_cert_info(struct SessionHandle *data, CERTCertificate *cert) @@ -918,7 +830,7 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) static SECStatus check_issuer_cert(PRFileDesc *sock, char *issuer_nickname) { - CERTCertificate *cert, *cert_issuer, *issuer; + CERTCertificate *cert,*cert_issuer,*issuer; SECStatus res=SECSuccess; void *proto_win = NULL; @@ -929,7 +841,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, */ cert = SSL_PeerCertificate(sock); - cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner); + cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); proto_win = SSL_RevealPinArg(sock); issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); @@ -946,53 +858,6 @@ static SECStatus check_issuer_cert(PRFileDesc *sock, return res; } -static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl, - const char *pinnedpubkey) -{ - CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; - struct SessionHandle *data = connssl->data; - CERTCertificate *cert; - - if(!pinnedpubkey) - /* no pinned public key specified */ - return CURLE_OK; - - /* get peer certificate */ - cert = SSL_PeerCertificate(connssl->handle); - if(cert) { - /* extract public key from peer certificate */ - SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert); - if(pubkey) { - /* encode the public key as DER */ - SECItem *cert_der = PK11_DEREncodePublicKey(pubkey); - if(cert_der) { - /* compare the public key with the pinned public key */ - result = Curl_pin_peer_pubkey(pinnedpubkey, - cert_der->data, - cert_der->len); - SECITEM_FreeItem(cert_der, PR_TRUE); - } - SECKEY_DestroyPublicKey(pubkey); - } - CERT_DestroyCertificate(cert); - } - - /* report the resulting status */ - switch(result) { - case CURLE_OK: - infof(data, "pinned public key verified successfully!\n"); - break; - case CURLE_SSL_PINNEDPUBKEYNOTMATCH: - failf(data, "failed to verify pinned public key"); - break; - default: - /* OOM, etc. */ - break; - } - - return result; -} - /** * * Callback to pick the SSL client certificate. @@ -1134,7 +999,6 @@ static PRStatus nspr_io_close(PRFileDesc *fd) return close_fn(fd); } -/* data might be NULL */ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) { NSSInitParameters initparams; @@ -1172,7 +1036,6 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) return CURLE_SSL_CACERT_BADFILE; } -/* data might be NULL */ static CURLcode nss_init(struct SessionHandle *data) { char *cert_dir; @@ -1251,14 +1114,12 @@ int Curl_nss_init(void) return 1; } -/* data might be NULL */ CURLcode Curl_nss_force_init(struct SessionHandle *data) { CURLcode result; if(!nss_initlock) { - if(data) - failf(data, "unable to initialize NSS, curl_global_init() should have " - "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); + failf(data, "unable to initialize NSS, curl_global_init() should have " + "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); return CURLE_FAILED_INIT; } @@ -1349,8 +1210,10 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) * authentication data from a previous connection. */ SSL_InvalidateSession(connssl->handle); - free(connssl->client_nickname); - connssl->client_nickname = NULL; + if(connssl->client_nickname != NULL) { + free(connssl->client_nickname); + connssl->client_nickname = NULL; + } /* destroy all NSS objects in order to avoid failure of NSS shutdown */ Curl_llist_destroy(connssl->obj_list, NULL); connssl->obj_list = NULL; @@ -1361,6 +1224,15 @@ void Curl_nss_close(struct connectdata *conn, int sockindex) } } +/* + * This function is called when the 'data' struct is going away. Close + * down everything and free all resources! + */ +void Curl_nss_close_all(struct SessionHandle *data) +{ + (void)data; +} + /* return true if NSS can provide error code (and possibly msg) for the error */ static bool is_nss_error(CURLcode err) @@ -1557,6 +1429,16 @@ static CURLcode nss_setup_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 + connssl->data = data; /* list of all NSS objects we need to destroy in Curl_nss_close() */ @@ -1736,57 +1618,43 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); } -#ifdef SSL_ENABLE_OCSP_STAPLING - if(data->set.ssl.verifystatus) { - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) - != SECSuccess) - goto error; - } -#endif - +#ifdef USE_NGHTTP2 + if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { #ifdef SSL_ENABLE_NPN - if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, data->set.ssl_enable_npn - ? PR_TRUE : PR_FALSE) != SECSuccess) - goto error; + if(data->set.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, data->set.ssl_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) - != SECSuccess) - goto error; - - if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback, - conn) != SECSuccess) - goto error; - } + if(data->set.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) - if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { - int cur = 0; - unsigned char protocols[128]; - -#ifdef USE_NGHTTP2 - if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { - protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; - memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, + if(data->set.ssl_enable_npn || data->set.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; + connssl->asked_for_h2 = TRUE; + } + else { + infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n"); } #endif - protocols[cur++] = ALPN_HTTP_1_1_LENGTH; - 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) - goto error; } #endif @@ -1847,7 +1715,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } if(SECFailure == ret) { - infof(data, "SSL certificate issuer check failed\n"); + infof(data,"SSL certificate issuer check failed\n"); result = CURLE_SSL_ISSUER_ERROR; goto error; } @@ -1856,11 +1724,6 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } - result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); - if(result) - /* status already printed */ - goto error; - return CURLE_OK; error: @@ -2007,7 +1870,6 @@ 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 SessionHandle *data) { /* make sure that NSS is initialized */ @@ -2019,11 +1881,14 @@ int Curl_nss_random(struct SessionHandle *data, unsigned char *entropy, size_t length) { - Curl_nss_seed(data); /* Initiate the seed if not already done */ + if(data) + Curl_nss_seed(data); /* Initiate the seed if not already done */ - if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) - /* signal a failure */ - return -1; + if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) { + /* no way to signal a failure from here, we have to abort */ + failf(data, "PK11_GenerateRandom() failed, calling abort()..."); + abort(); + } return 0; } @@ -2041,34 +1906,4 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */ PK11_DestroyContext(MD5pw, PR_TRUE); } -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; - - PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen)); - PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len)); - PK11_DestroyContext(SHA256pw, PR_TRUE); -} - -bool Curl_nss_cert_status_request(void) -{ -#ifdef SSL_ENABLE_OCSP_STAPLING - return TRUE; -#else - return FALSE; -#endif -} - -bool Curl_nss_false_start(void) { -#if NSSVERNUM >= 0x030f04 /* 3.15.4 */ - return TRUE; -#else - return FALSE; -#endif -} - #endif /* USE_NSS */