1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23/* 24 * Source file for all NSS-specific code for the TLS/SSL layer. No code 25 * but vtls.c should ever call or use these functions. 26 */ 27 28#include "curl_setup.h" 29 30#ifdef USE_NSS 31 32#include "urldata.h" 33#include "sendf.h" 34#include "formdata.h" /* for the boundary function */ 35#include "url.h" /* for the ssl config check function */ 36#include "connect.h" 37#include "strequal.h" 38#include "select.h" 39#include "vtls.h" 40#include "llist.h" 41 42#define _MPRINTF_REPLACE /* use the internal *printf() functions */ 43#include <curl/mprintf.h> 44 45#include "nssg.h" 46#include <nspr.h> 47#include <nss.h> 48#include <ssl.h> 49#include <sslerr.h> 50#include <secerr.h> 51#include <secmod.h> 52#include <sslproto.h> 53#include <prtypes.h> 54#include <pk11pub.h> 55#include <prio.h> 56#include <secitem.h> 57#include <secport.h> 58#include <certdb.h> 59#include <base64.h> 60#include <cert.h> 61#include <prerror.h> 62 63#include "curl_memory.h" 64#include "rawstr.h" 65#include "warnless.h" 66#include "x509asn1.h" 67 68/* The last #include file should be: */ 69#include "memdebug.h" 70 71#define SSL_DIR "/etc/pki/nssdb" 72 73/* enough to fit the string "PEM Token #[0|1]" */ 74#define SLOTSIZE 13 75 76PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); 77 78PRLock * nss_initlock = NULL; 79PRLock * nss_crllock = NULL; 80struct curl_llist *nss_crl_list = NULL; 81NSSInitContext * nss_context = NULL; 82 83volatile int initialized = 0; 84 85typedef struct { 86 const char *name; 87 int num; 88} cipher_s; 89 90#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \ 91 CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \ 92 ptr->type = (_type); \ 93 ptr->pValue = (_val); \ 94 ptr->ulValueLen = (_len); \ 95} WHILE_FALSE 96 97#define CERT_NewTempCertificate __CERT_NewTempCertificate 98 99#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0]) 100static const cipher_s cipherlist[] = { 101 /* SSL2 cipher suites */ 102 {"rc4", SSL_EN_RC4_128_WITH_MD5}, 103 {"rc4-md5", SSL_EN_RC4_128_WITH_MD5}, 104 {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5}, 105 {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5}, 106 {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5}, 107 {"des", SSL_EN_DES_64_CBC_WITH_MD5}, 108 {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5}, 109 /* SSL3/TLS cipher suites */ 110 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5}, 111 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA}, 112 {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA}, 113 {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA}, 114 {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5}, 115 {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5}, 116 {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5}, 117 {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA}, 118 {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA}, 119 {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA}, 120 {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA}, 121 {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA}, 122 {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA}, 123 /* TLS 1.0: Exportable 56-bit Cipher Suites. */ 124 {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, 125 {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, 126 /* AES ciphers. */ 127 {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, 128 {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, 129 {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, 130 {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, 131 {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, 132 {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, 133 /* ECC ciphers. */ 134 {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, 135 {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, 136 {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA}, 137 {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA}, 138 {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA}, 139 {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA}, 140 {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA}, 141 {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA}, 142 {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA}, 143 {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}, 144 {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA}, 145 {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA}, 146 {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, 147 {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, 148 {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, 149 {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, 150 {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, 151 {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, 152 {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, 153 {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, 154 {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA}, 155 {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA}, 156 {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA}, 157 {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA}, 158 {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, 159#ifdef TLS_RSA_WITH_NULL_SHA256 160 /* new HMAC-SHA256 cipher suites specified in RFC */ 161 {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256}, 162 {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256}, 163 {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256}, 164 {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, 165 {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, 166 {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, 167 {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, 168#endif 169#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256 170 /* AES GCM cipher suites in RFC 5288 and RFC 5289 */ 171 {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256}, 172 {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, 173 {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256}, 174 {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, 175 {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256}, 176 {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, 177 {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256}, 178#endif 179}; 180 181static const char* pem_library = "libnsspem.so"; 182SECMODModule* mod = NULL; 183 184/* NSPR I/O layer we use to detect blocking direction during SSL handshake */ 185static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; 186static PRIOMethods nspr_io_methods; 187 188static const char* nss_error_to_name(PRErrorCode code) 189{ 190 const char *name = PR_ErrorToName(code); 191 if(name) 192 return name; 193 194 return "unknown error"; 195} 196 197static void nss_print_error_message(struct SessionHandle *data, PRUint32 err) 198{ 199 failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); 200} 201 202static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, 203 char *cipher_list) 204{ 205 unsigned int i; 206 PRBool cipher_state[NUM_OF_CIPHERS]; 207 PRBool found; 208 char *cipher; 209 210 /* First disable all ciphers. This uses a different max value in case 211 * NSS adds more ciphers later we don't want them available by 212 * accident 213 */ 214 for(i=0; i<SSL_NumImplementedCiphers; i++) { 215 SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], PR_FALSE); 216 } 217 218 /* Set every entry in our list to false */ 219 for(i=0; i<NUM_OF_CIPHERS; i++) { 220 cipher_state[i] = PR_FALSE; 221 } 222 223 cipher = cipher_list; 224 225 while(cipher_list && (cipher_list[0])) { 226 while((*cipher) && (ISSPACE(*cipher))) 227 ++cipher; 228 229 if((cipher_list = strchr(cipher, ','))) { 230 *cipher_list++ = '\0'; 231 } 232 233 found = PR_FALSE; 234 235 for(i=0; i<NUM_OF_CIPHERS; i++) { 236 if(Curl_raw_equal(cipher, cipherlist[i].name)) { 237 cipher_state[i] = PR_TRUE; 238 found = PR_TRUE; 239 break; 240 } 241 } 242 243 if(found == PR_FALSE) { 244 failf(data, "Unknown cipher in list: %s", cipher); 245 return SECFailure; 246 } 247 248 if(cipher_list) { 249 cipher = cipher_list; 250 } 251 } 252 253 /* Finally actually enable the selected ciphers */ 254 for(i=0; i<NUM_OF_CIPHERS; i++) { 255 if(!cipher_state[i]) 256 continue; 257 258 if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) { 259 failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name); 260 return SECFailure; 261 } 262 } 263 264 return SECSuccess; 265} 266 267/* 268 * Get the number of ciphers that are enabled. We use this to determine 269 * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers. 270 */ 271static int num_enabled_ciphers(void) 272{ 273 PRInt32 policy = 0; 274 int count = 0; 275 unsigned int i; 276 277 for(i=0; i<NUM_OF_CIPHERS; i++) { 278 SSL_CipherPolicyGet(cipherlist[i].num, &policy); 279 if(policy) 280 count++; 281 } 282 return count; 283} 284 285/* 286 * Determine whether the nickname passed in is a filename that needs to 287 * be loaded as a PEM or a regular NSS nickname. 288 * 289 * returns 1 for a file 290 * returns 0 for not a file (NSS nickname) 291 */ 292static int is_file(const char *filename) 293{ 294 struct_stat st; 295 296 if(filename == NULL) 297 return 0; 298 299 if(stat(filename, &st) == 0) 300 if(S_ISREG(st.st_mode)) 301 return 1; 302 303 return 0; 304} 305 306/* Check if the given string is filename or nickname of a certificate. If the 307 * given string is recognized as filename, return NULL. If the given string is 308 * recognized as nickname, return a duplicated string. The returned string 309 * should be later deallocated using free(). If the OOM failure occurs, we 310 * return NULL, too. 311 */ 312static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind) 313{ 314 const char *str = data->set.str[cert_kind]; 315 const char *n; 316 317 if(!is_file(str)) 318 /* no such file exists, use the string as nickname */ 319 return strdup(str); 320 321 /* search the last slash; we require at least one slash in a file name */ 322 n = strrchr(str, '/'); 323 if(!n) { 324 infof(data, "warning: certificate file name \"%s\" handled as nickname; " 325 "please use \"./%s\" to force file name\n", str, str); 326 return strdup(str); 327 } 328 329 /* we'll use the PEM reader to read the certificate from file */ 330 return NULL; 331} 332 333/* Call PK11_CreateGenericObject() with the given obj_class and filename. If 334 * the call succeeds, append the object handle to the list of objects so that 335 * the object can be destroyed in Curl_nss_close(). */ 336static CURLcode nss_create_object(struct ssl_connect_data *ssl, 337 CK_OBJECT_CLASS obj_class, 338 const char *filename, bool cacert) 339{ 340 PK11SlotInfo *slot; 341 PK11GenericObject *obj; 342 CK_BBOOL cktrue = CK_TRUE; 343 CK_BBOOL ckfalse = CK_FALSE; 344 CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; 345 int attr_cnt = 0; 346 CURLcode err = (cacert) 347 ? CURLE_SSL_CACERT_BADFILE 348 : CURLE_SSL_CERTPROBLEM; 349 350 const int slot_id = (cacert) ? 0 : 1; 351 char *slot_name = aprintf("PEM Token #%d", slot_id); 352 if(!slot_name) 353 return CURLE_OUT_OF_MEMORY; 354 355 slot = PK11_FindSlotByName(slot_name); 356 free(slot_name); 357 if(!slot) 358 return err; 359 360 PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); 361 PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); 362 PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename, 363 strlen(filename) + 1); 364 365 if(CKO_CERTIFICATE == obj_class) { 366 CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse); 367 PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); 368 } 369 370 obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE); 371 PK11_FreeSlot(slot); 372 if(!obj) 373 return err; 374 375 if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) { 376 PK11_DestroyGenericObject(obj); 377 return CURLE_OUT_OF_MEMORY; 378 } 379 380 if(!cacert && CKO_CERTIFICATE == obj_class) 381 /* store reference to a client certificate */ 382 ssl->obj_clicert = obj; 383 384 return CURLE_OK; 385} 386 387/* Destroy the NSS object whose handle is given by ptr. This function is 388 * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy 389 * NSS objects in Curl_nss_close() */ 390static void nss_destroy_object(void *user, void *ptr) 391{ 392 PK11GenericObject *obj = (PK11GenericObject *)ptr; 393 (void) user; 394 PK11_DestroyGenericObject(obj); 395} 396 397/* same as nss_destroy_object() but for CRL items */ 398static void nss_destroy_crl_item(void *user, void *ptr) 399{ 400 SECItem *crl_der = (SECItem *)ptr; 401 (void) user; 402 SECITEM_FreeItem(crl_der, PR_TRUE); 403} 404 405static CURLcode nss_load_cert(struct ssl_connect_data *ssl, 406 const char *filename, PRBool cacert) 407{ 408 CURLcode err = (cacert) 409 ? CURLE_SSL_CACERT_BADFILE 410 : CURLE_SSL_CERTPROBLEM; 411 412 /* libnsspem.so leaks memory if the requested file does not exist. For more 413 * details, go to <https://bugzilla.redhat.com/734760>. */ 414 if(is_file(filename)) 415 err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert); 416 417 if(CURLE_OK == err && !cacert) { 418 /* we have successfully loaded a client certificate */ 419 CERTCertificate *cert; 420 char *nickname = NULL; 421 char *n = strrchr(filename, '/'); 422 if(n) 423 n++; 424 425 /* The following undocumented magic helps to avoid a SIGSEGV on call 426 * of PK11_ReadRawAttribute() from SelectClientCert() when using an 427 * immature version of libnsspem.so. For more details, go to 428 * <https://bugzilla.redhat.com/733685>. */ 429 nickname = aprintf("PEM Token #1:%s", n); 430 if(nickname) { 431 cert = PK11_FindCertFromNickname(nickname, NULL); 432 if(cert) 433 CERT_DestroyCertificate(cert); 434 435 free(nickname); 436 } 437 } 438 439 return err; 440} 441 442/* add given CRL to cache if it is not already there */ 443static CURLcode nss_cache_crl(SECItem *crl_der) 444{ 445 CERTCertDBHandle *db = CERT_GetDefaultCertDB(); 446 CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0); 447 if(crl) { 448 /* CRL already cached */ 449 SEC_DestroyCrl(crl); 450 SECITEM_FreeItem(crl_der, PR_TRUE); 451 return CURLE_SSL_CRL_BADFILE; 452 } 453 454 /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */ 455 PR_Lock(nss_crllock); 456 457 /* store the CRL item so that we can free it in Curl_nss_cleanup() */ 458 if(!Curl_llist_insert_next(nss_crl_list, nss_crl_list->tail, crl_der)) { 459 SECITEM_FreeItem(crl_der, PR_TRUE); 460 PR_Unlock(nss_crllock); 461 return CURLE_OUT_OF_MEMORY; 462 } 463 464 if(SECSuccess != CERT_CacheCRL(db, crl_der)) { 465 /* unable to cache CRL */ 466 PR_Unlock(nss_crllock); 467 return CURLE_SSL_CRL_BADFILE; 468 } 469 470 /* we need to clear session cache, so that the CRL could take effect */ 471 SSL_ClearSessionCache(); 472 PR_Unlock(nss_crllock); 473 return CURLE_OK; 474} 475 476static CURLcode nss_load_crl(const char* crlfilename) 477{ 478 PRFileDesc *infile; 479 PRFileInfo info; 480 SECItem filedata = { 0, NULL, 0 }; 481 SECItem *crl_der = NULL; 482 char *body; 483 484 infile = PR_Open(crlfilename, PR_RDONLY, 0); 485 if(!infile) 486 return CURLE_SSL_CRL_BADFILE; 487 488 if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info)) 489 goto fail; 490 491 if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1)) 492 goto fail; 493 494 if(info.size != PR_Read(infile, filedata.data, info.size)) 495 goto fail; 496 497 crl_der = SECITEM_AllocItem(NULL, NULL, 0U); 498 if(!crl_der) 499 goto fail; 500 501 /* place a trailing zero right after the visible data */ 502 body = (char*)filedata.data; 503 body[--filedata.len] = '\0'; 504 505 body = strstr(body, "-----BEGIN"); 506 if(body) { 507 /* assume ASCII */ 508 char *trailer; 509 char *begin = PORT_Strchr(body, '\n'); 510 if(!begin) 511 begin = PORT_Strchr(body, '\r'); 512 if(!begin) 513 goto fail; 514 515 trailer = strstr(++begin, "-----END"); 516 if(!trailer) 517 goto fail; 518 519 /* retrieve DER from ASCII */ 520 *trailer = '\0'; 521 if(ATOB_ConvertAsciiToItem(crl_der, begin)) 522 goto fail; 523 524 SECITEM_FreeItem(&filedata, PR_FALSE); 525 } 526 else 527 /* assume DER */ 528 *crl_der = filedata; 529 530 PR_Close(infile); 531 return nss_cache_crl(crl_der); 532 533fail: 534 PR_Close(infile); 535 SECITEM_FreeItem(crl_der, PR_TRUE); 536 SECITEM_FreeItem(&filedata, PR_FALSE); 537 return CURLE_SSL_CRL_BADFILE; 538} 539 540static CURLcode nss_load_key(struct connectdata *conn, int sockindex, 541 char *key_file) 542{ 543 PK11SlotInfo *slot; 544 SECStatus status; 545 CURLcode rv; 546 struct ssl_connect_data *ssl = conn->ssl; 547 (void)sockindex; /* unused */ 548 549 rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE); 550 if(CURLE_OK != rv) { 551 PR_SetError(SEC_ERROR_BAD_KEY, 0); 552 return rv; 553 } 554 555 slot = PK11_FindSlotByName("PEM Token #1"); 556 if(!slot) 557 return CURLE_SSL_CERTPROBLEM; 558 559 /* This will force the token to be seen as re-inserted */ 560 SECMOD_WaitForAnyTokenEvent(mod, 0, 0); 561 PK11_IsPresent(slot); 562 563 status = PK11_Authenticate(slot, PR_TRUE, 564 conn->data->set.str[STRING_KEY_PASSWD]); 565 PK11_FreeSlot(slot); 566 return (SECSuccess == status) 567 ? CURLE_OK 568 : CURLE_SSL_CERTPROBLEM; 569} 570 571static int display_error(struct connectdata *conn, PRInt32 err, 572 const char *filename) 573{ 574 switch(err) { 575 case SEC_ERROR_BAD_PASSWORD: 576 failf(conn->data, "Unable to load client key: Incorrect password"); 577 return 1; 578 case SEC_ERROR_UNKNOWN_CERT: 579 failf(conn->data, "Unable to load certificate %s", filename); 580 return 1; 581 default: 582 break; 583 } 584 return 0; /* The caller will print a generic error */ 585} 586 587static CURLcode cert_stuff(struct connectdata *conn, int sockindex, 588 char *cert_file, char *key_file) 589{ 590 struct SessionHandle *data = conn->data; 591 CURLcode rv; 592 593 if(cert_file) { 594 rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE); 595 if(CURLE_OK != rv) { 596 const PRErrorCode err = PR_GetError(); 597 if(!display_error(conn, err, cert_file)) { 598 const char *err_name = nss_error_to_name(err); 599 failf(data, "unable to load client cert: %d (%s)", err, err_name); 600 } 601 602 return rv; 603 } 604 } 605 606 if(key_file || (is_file(cert_file))) { 607 if(key_file) 608 rv = nss_load_key(conn, sockindex, key_file); 609 else 610 /* In case the cert file also has the key */ 611 rv = nss_load_key(conn, sockindex, cert_file); 612 if(CURLE_OK != rv) { 613 const PRErrorCode err = PR_GetError(); 614 if(!display_error(conn, err, key_file)) { 615 const char *err_name = nss_error_to_name(err); 616 failf(data, "unable to load client key: %d (%s)", err, err_name); 617 } 618 619 return rv; 620 } 621 } 622 623 return CURLE_OK; 624} 625 626static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) 627{ 628 (void)slot; /* unused */ 629 if(retry || NULL == arg) 630 return NULL; 631 else 632 return (char *)PORT_Strdup((char *)arg); 633} 634 635/* bypass the default SSL_AuthCertificate() hook in case we do not want to 636 * verify peer */ 637static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, 638 PRBool isServer) 639{ 640 struct connectdata *conn = (struct connectdata *)arg; 641 if(!conn->data->set.ssl.verifypeer) { 642 infof(conn->data, "skipping SSL peer certificate verification\n"); 643 return SECSuccess; 644 } 645 646 return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer); 647} 648 649/** 650 * Inform the application that the handshake is complete. 651 */ 652static void HandshakeCallback(PRFileDesc *sock, void *arg) 653{ 654#ifdef USE_NGHTTP2 655 struct connectdata *conn = (struct connectdata*) arg; 656 unsigned int buflenmax = 50; 657 unsigned char buf[50]; 658 unsigned int buflen; 659 SSLNextProtoState state; 660 661 if(!conn->data->set.ssl_enable_npn && !conn->data->set.ssl_enable_alpn) { 662 return; 663 } 664 665 if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { 666 667 switch(state) { 668 case SSL_NEXT_PROTO_NO_SUPPORT: 669 case SSL_NEXT_PROTO_NO_OVERLAP: 670 infof(conn->data, "TLS, neither ALPN nor NPN succeeded\n"); 671 return; 672#ifdef SSL_ENABLE_ALPN 673 case SSL_NEXT_PROTO_SELECTED: 674 infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf); 675 break; 676#endif 677 case SSL_NEXT_PROTO_NEGOTIATED: 678 infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf); 679 break; 680 } 681 682 if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN && 683 memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN) 684 == 0) { 685 conn->negnpn = NPN_HTTP2; 686 } 687 else if(buflen == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1, buf, 688 ALPN_HTTP_1_1_LENGTH)) { 689 conn->negnpn = NPN_HTTP1_1; 690 } 691 } 692#else 693 (void)sock; 694 (void)arg; 695#endif 696} 697 698static void display_cert_info(struct SessionHandle *data, 699 CERTCertificate *cert) 700{ 701 char *subject, *issuer, *common_name; 702 PRExplodedTime printableTime; 703 char timeString[256]; 704 PRTime notBefore, notAfter; 705 706 subject = CERT_NameToAscii(&cert->subject); 707 issuer = CERT_NameToAscii(&cert->issuer); 708 common_name = CERT_GetCommonName(&cert->subject); 709 infof(data, "\tsubject: %s\n", subject); 710 711 CERT_GetCertTimes(cert, ¬Before, ¬After); 712 PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime); 713 PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); 714 infof(data, "\tstart date: %s\n", timeString); 715 PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime); 716 PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime); 717 infof(data, "\texpire date: %s\n", timeString); 718 infof(data, "\tcommon name: %s\n", common_name); 719 infof(data, "\tissuer: %s\n", issuer); 720 721 PR_Free(subject); 722 PR_Free(issuer); 723 PR_Free(common_name); 724} 725 726static void display_conn_info(struct connectdata *conn, PRFileDesc *sock) 727{ 728 SSLChannelInfo channel; 729 SSLCipherSuiteInfo suite; 730 CERTCertificate *cert; 731 CERTCertificate *cert2; 732 CERTCertificate *cert3; 733 PRTime now; 734 int i; 735 736 if(SSL_GetChannelInfo(sock, &channel, sizeof channel) == 737 SECSuccess && channel.length == sizeof channel && 738 channel.cipherSuite) { 739 if(SSL_GetCipherSuiteInfo(channel.cipherSuite, 740 &suite, sizeof suite) == SECSuccess) { 741 infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName); 742 } 743 } 744 745 cert = SSL_PeerCertificate(sock); 746 747 if(cert) { 748 infof(conn->data, "Server certificate:\n"); 749 750 if(!conn->data->set.ssl.certinfo) { 751 display_cert_info(conn->data, cert); 752 CERT_DestroyCertificate(cert); 753 } 754 else { 755 /* Count certificates in chain. */ 756 now = PR_Now(); 757 i = 1; 758 if(!cert->isRoot) { 759 cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); 760 while(cert2) { 761 i++; 762 if(cert2->isRoot) { 763 CERT_DestroyCertificate(cert2); 764 break; 765 } 766 cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA); 767 CERT_DestroyCertificate(cert2); 768 cert2 = cert3; 769 } 770 } 771 Curl_ssl_init_certinfo(conn->data, i); 772 for(i = 0; cert; cert = cert2) { 773 Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data, 774 (char *)cert->derCert.data + cert->derCert.len); 775 if(cert->isRoot) { 776 CERT_DestroyCertificate(cert); 777 break; 778 } 779 cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA); 780 CERT_DestroyCertificate(cert); 781 } 782 } 783 } 784 785 return; 786} 787 788static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) 789{ 790 struct connectdata *conn = (struct connectdata *)arg; 791 struct SessionHandle *data = conn->data; 792 PRErrorCode err = PR_GetError(); 793 CERTCertificate *cert; 794 795 /* remember the cert verification result */ 796 data->set.ssl.certverifyresult = err; 797 798 if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost) 799 /* we are asked not to verify the host name */ 800 return SECSuccess; 801 802 /* print only info about the cert, the error is printed off the callback */ 803 cert = SSL_PeerCertificate(sock); 804 if(cert) { 805 infof(data, "Server certificate:\n"); 806 display_cert_info(data, cert); 807 CERT_DestroyCertificate(cert); 808 } 809 810 return SECFailure; 811} 812 813/** 814 * 815 * Check that the Peer certificate's issuer certificate matches the one found 816 * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the 817 * issuer check, so we provide comments that mimic the OpenSSL 818 * X509_check_issued function (in x509v3/v3_purp.c) 819 */ 820static SECStatus check_issuer_cert(PRFileDesc *sock, 821 char *issuer_nickname) 822{ 823 CERTCertificate *cert,*cert_issuer,*issuer; 824 SECStatus res=SECSuccess; 825 void *proto_win = NULL; 826 827 /* 828 PRArenaPool *tmpArena = NULL; 829 CERTAuthKeyID *authorityKeyID = NULL; 830 SECITEM *caname = NULL; 831 */ 832 833 cert = SSL_PeerCertificate(sock); 834 cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner); 835 836 proto_win = SSL_RevealPinArg(sock); 837 issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win); 838 839 if((!cert_issuer) || (!issuer)) 840 res = SECFailure; 841 else if(SECITEM_CompareItem(&cert_issuer->derCert, 842 &issuer->derCert)!=SECEqual) 843 res = SECFailure; 844 845 CERT_DestroyCertificate(cert); 846 CERT_DestroyCertificate(issuer); 847 CERT_DestroyCertificate(cert_issuer); 848 return res; 849} 850 851/** 852 * 853 * Callback to pick the SSL client certificate. 854 */ 855static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, 856 struct CERTDistNamesStr *caNames, 857 struct CERTCertificateStr **pRetCert, 858 struct SECKEYPrivateKeyStr **pRetKey) 859{ 860 struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; 861 struct SessionHandle *data = connssl->data; 862 const char *nickname = connssl->client_nickname; 863 864 if(connssl->obj_clicert) { 865 /* use the cert/key provided by PEM reader */ 866 static const char pem_slotname[] = "PEM Token #1"; 867 SECItem cert_der = { 0, NULL, 0 }; 868 void *proto_win = SSL_RevealPinArg(sock); 869 struct CERTCertificateStr *cert; 870 struct SECKEYPrivateKeyStr *key; 871 872 PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); 873 if(NULL == slot) { 874 failf(data, "NSS: PK11 slot not found: %s", pem_slotname); 875 return SECFailure; 876 } 877 878 if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE, 879 &cert_der) != SECSuccess) { 880 failf(data, "NSS: CKA_VALUE not found in PK11 generic object"); 881 PK11_FreeSlot(slot); 882 return SECFailure; 883 } 884 885 cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win); 886 SECITEM_FreeItem(&cert_der, PR_FALSE); 887 if(NULL == cert) { 888 failf(data, "NSS: client certificate from file not found"); 889 PK11_FreeSlot(slot); 890 return SECFailure; 891 } 892 893 key = PK11_FindPrivateKeyFromCert(slot, cert, NULL); 894 PK11_FreeSlot(slot); 895 if(NULL == key) { 896 failf(data, "NSS: private key from file not found"); 897 CERT_DestroyCertificate(cert); 898 return SECFailure; 899 } 900 901 infof(data, "NSS: client certificate from file\n"); 902 display_cert_info(data, cert); 903 904 *pRetCert = cert; 905 *pRetKey = key; 906 return SECSuccess; 907 } 908 909 /* use the default NSS hook */ 910 if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames, 911 pRetCert, pRetKey) 912 || NULL == *pRetCert) { 913 914 if(NULL == nickname) 915 failf(data, "NSS: client certificate not found (nickname not " 916 "specified)"); 917 else 918 failf(data, "NSS: client certificate not found: %s", nickname); 919 920 return SECFailure; 921 } 922 923 /* get certificate nickname if any */ 924 nickname = (*pRetCert)->nickname; 925 if(NULL == nickname) 926 nickname = "[unknown]"; 927 928 if(NULL == *pRetKey) { 929 failf(data, "NSS: private key not found for certificate: %s", nickname); 930 return SECFailure; 931 } 932 933 infof(data, "NSS: using client certificate: %s\n", nickname); 934 display_cert_info(data, *pRetCert); 935 return SECSuccess; 936} 937 938/* This function is supposed to decide, which error codes should be used 939 * to conclude server is TLS intolerant. 940 * 941 * taken from xulrunner - nsNSSIOLayer.cpp 942 */ 943static PRBool 944isTLSIntoleranceError(PRInt32 err) 945{ 946 switch (err) { 947 case SSL_ERROR_BAD_MAC_ALERT: 948 case SSL_ERROR_BAD_MAC_READ: 949 case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: 950 case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: 951 case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE: 952 case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: 953 case SSL_ERROR_NO_CYPHER_OVERLAP: 954 case SSL_ERROR_BAD_SERVER: 955 case SSL_ERROR_BAD_BLOCK_PADDING: 956 case SSL_ERROR_UNSUPPORTED_VERSION: 957 case SSL_ERROR_PROTOCOL_VERSION_ALERT: 958 case SSL_ERROR_RX_MALFORMED_FINISHED: 959 case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE: 960 case SSL_ERROR_DECODE_ERROR_ALERT: 961 case SSL_ERROR_RX_UNKNOWN_ALERT: 962 return PR_TRUE; 963 default: 964 return PR_FALSE; 965 } 966} 967 968/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ 969static void nss_update_connecting_state(ssl_connect_state state, void *secret) 970{ 971 struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret; 972 if(PR_GetError() != PR_WOULD_BLOCK_ERROR) 973 /* an unrelated error is passing by */ 974 return; 975 976 switch(connssl->connecting_state) { 977 case ssl_connect_2: 978 case ssl_connect_2_reading: 979 case ssl_connect_2_writing: 980 break; 981 default: 982 /* we are not called from an SSL handshake */ 983 return; 984 } 985 986 /* update the state accordingly */ 987 connssl->connecting_state = state; 988} 989 990/* recv() wrapper we use to detect blocking direction during SSL handshake */ 991static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, 992 PRIntn flags, PRIntervalTime timeout) 993{ 994 const PRRecvFN recv_fn = fd->lower->methods->recv; 995 const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout); 996 if(rv < 0) 997 /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ 998 nss_update_connecting_state(ssl_connect_2_reading, fd->secret); 999 return rv; 1000} 1001 1002/* send() wrapper we use to detect blocking direction during SSL handshake */ 1003static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, 1004 PRIntn flags, PRIntervalTime timeout) 1005{ 1006 const PRSendFN send_fn = fd->lower->methods->send; 1007 const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout); 1008 if(rv < 0) 1009 /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ 1010 nss_update_connecting_state(ssl_connect_2_writing, fd->secret); 1011 return rv; 1012} 1013 1014/* close() wrapper to avoid assertion failure due to fd->secret != NULL */ 1015static PRStatus nspr_io_close(PRFileDesc *fd) 1016{ 1017 const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close; 1018 fd->secret = NULL; 1019 return close_fn(fd); 1020} 1021 1022static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) 1023{ 1024 NSSInitParameters initparams; 1025 1026 if(nss_context != NULL) 1027 return CURLE_OK; 1028 1029 memset((void *) &initparams, '\0', sizeof(initparams)); 1030 initparams.length = sizeof(initparams); 1031 1032 if(cert_dir) { 1033 const bool use_sql = NSS_VersionCheck("3.12.0"); 1034 char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir); 1035 if(!certpath) 1036 return CURLE_OUT_OF_MEMORY; 1037 1038 infof(data, "Initializing NSS with certpath: %s\n", certpath); 1039 nss_context = NSS_InitContext(certpath, "", "", "", &initparams, 1040 NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); 1041 free(certpath); 1042 1043 if(nss_context != NULL) 1044 return CURLE_OK; 1045 1046 infof(data, "Unable to initialize NSS database\n"); 1047 } 1048 1049 infof(data, "Initializing NSS with certpath: none\n"); 1050 nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY 1051 | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN 1052 | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); 1053 if(nss_context != NULL) 1054 return CURLE_OK; 1055 1056 infof(data, "Unable to initialize NSS\n"); 1057 return CURLE_SSL_CACERT_BADFILE; 1058} 1059 1060static CURLcode nss_init(struct SessionHandle *data) 1061{ 1062 char *cert_dir; 1063 struct_stat st; 1064 CURLcode rv; 1065 1066 if(initialized) 1067 return CURLE_OK; 1068 1069 /* list of all CRL items we need to destroy in Curl_nss_cleanup() */ 1070 nss_crl_list = Curl_llist_alloc(nss_destroy_crl_item); 1071 if(!nss_crl_list) 1072 return CURLE_OUT_OF_MEMORY; 1073 1074 /* First we check if $SSL_DIR points to a valid dir */ 1075 cert_dir = getenv("SSL_DIR"); 1076 if(cert_dir) { 1077 if((stat(cert_dir, &st) != 0) || 1078 (!S_ISDIR(st.st_mode))) { 1079 cert_dir = NULL; 1080 } 1081 } 1082 1083 /* Now we check if the default location is a valid dir */ 1084 if(!cert_dir) { 1085 if((stat(SSL_DIR, &st) == 0) && 1086 (S_ISDIR(st.st_mode))) { 1087 cert_dir = (char *)SSL_DIR; 1088 } 1089 } 1090 1091 if(nspr_io_identity == PR_INVALID_IO_LAYER) { 1092 /* allocate an identity for our own NSPR I/O layer */ 1093 nspr_io_identity = PR_GetUniqueIdentity("libcurl"); 1094 if(nspr_io_identity == PR_INVALID_IO_LAYER) 1095 return CURLE_OUT_OF_MEMORY; 1096 1097 /* the default methods just call down to the lower I/O layer */ 1098 memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods); 1099 1100 /* override certain methods in the table by our wrappers */ 1101 nspr_io_methods.recv = nspr_io_recv; 1102 nspr_io_methods.send = nspr_io_send; 1103 nspr_io_methods.close = nspr_io_close; 1104 } 1105 1106 rv = nss_init_core(data, cert_dir); 1107 if(rv) 1108 return rv; 1109 1110 if(num_enabled_ciphers() == 0) 1111 NSS_SetDomesticPolicy(); 1112 1113 initialized = 1; 1114 return CURLE_OK; 1115} 1116 1117/** 1118 * Global SSL init 1119 * 1120 * @retval 0 error initializing SSL 1121 * @retval 1 SSL initialized successfully 1122 */ 1123int Curl_nss_init(void) 1124{ 1125 /* curl_global_init() is not thread-safe so this test is ok */ 1126 if(nss_initlock == NULL) { 1127 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); 1128 nss_initlock = PR_NewLock(); 1129 nss_crllock = PR_NewLock(); 1130 } 1131 1132 /* We will actually initialize NSS later */ 1133 1134 return 1; 1135} 1136 1137CURLcode Curl_nss_force_init(struct SessionHandle *data) 1138{ 1139 CURLcode rv; 1140 if(!nss_initlock) { 1141 failf(data, 1142 "unable to initialize NSS, curl_global_init() should have been " 1143 "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL"); 1144 return CURLE_FAILED_INIT; 1145 } 1146 1147 PR_Lock(nss_initlock); 1148 rv = nss_init(data); 1149 PR_Unlock(nss_initlock); 1150 return rv; 1151} 1152 1153/* Global cleanup */ 1154void Curl_nss_cleanup(void) 1155{ 1156 /* This function isn't required to be threadsafe and this is only done 1157 * as a safety feature. 1158 */ 1159 PR_Lock(nss_initlock); 1160 if(initialized) { 1161 /* Free references to client certificates held in the SSL session cache. 1162 * Omitting this hampers destruction of the security module owning 1163 * the certificates. */ 1164 SSL_ClearSessionCache(); 1165 1166 if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) { 1167 SECMOD_DestroyModule(mod); 1168 mod = NULL; 1169 } 1170 NSS_ShutdownContext(nss_context); 1171 nss_context = NULL; 1172 } 1173 1174 /* destroy all CRL items */ 1175 Curl_llist_destroy(nss_crl_list, NULL); 1176 nss_crl_list = NULL; 1177 1178 PR_Unlock(nss_initlock); 1179 1180 PR_DestroyLock(nss_initlock); 1181 PR_DestroyLock(nss_crllock); 1182 nss_initlock = NULL; 1183 1184 initialized = 0; 1185} 1186 1187/* 1188 * This function uses SSL_peek to determine connection status. 1189 * 1190 * Return codes: 1191 * 1 means the connection is still in place 1192 * 0 means the connection has been closed 1193 * -1 means the connection status is unknown 1194 */ 1195int 1196Curl_nss_check_cxn(struct connectdata *conn) 1197{ 1198 int rc; 1199 char buf; 1200 1201 rc = 1202 PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK, 1203 PR_SecondsToInterval(1)); 1204 if(rc > 0) 1205 return 1; /* connection still in place */ 1206 1207 if(rc == 0) 1208 return 0; /* connection has been closed */ 1209 1210 return -1; /* connection status unknown */ 1211} 1212 1213/* 1214 * This function is called when an SSL connection is closed. 1215 */ 1216void Curl_nss_close(struct connectdata *conn, int sockindex) 1217{ 1218 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1219 1220 if(connssl->handle) { 1221 /* NSS closes the socket we previously handed to it, so we must mark it 1222 as closed to avoid double close */ 1223 fake_sclose(conn->sock[sockindex]); 1224 conn->sock[sockindex] = CURL_SOCKET_BAD; 1225 1226 if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL)) 1227 /* A server might require different authentication based on the 1228 * particular path being requested by the client. To support this 1229 * scenario, we must ensure that a connection will never reuse the 1230 * authentication data from a previous connection. */ 1231 SSL_InvalidateSession(connssl->handle); 1232 1233 if(connssl->client_nickname != NULL) { 1234 free(connssl->client_nickname); 1235 connssl->client_nickname = NULL; 1236 } 1237 /* destroy all NSS objects in order to avoid failure of NSS shutdown */ 1238 Curl_llist_destroy(connssl->obj_list, NULL); 1239 connssl->obj_list = NULL; 1240 connssl->obj_clicert = NULL; 1241 1242 PR_Close(connssl->handle); 1243 connssl->handle = NULL; 1244 } 1245} 1246 1247/* 1248 * This function is called when the 'data' struct is going away. Close 1249 * down everything and free all resources! 1250 */ 1251int Curl_nss_close_all(struct SessionHandle *data) 1252{ 1253 (void)data; 1254 return 0; 1255} 1256 1257/* return true if NSS can provide error code (and possibly msg) for the 1258 error */ 1259static bool is_nss_error(CURLcode err) 1260{ 1261 switch(err) { 1262 case CURLE_PEER_FAILED_VERIFICATION: 1263 case CURLE_SSL_CACERT: 1264 case CURLE_SSL_CERTPROBLEM: 1265 case CURLE_SSL_CONNECT_ERROR: 1266 case CURLE_SSL_ISSUER_ERROR: 1267 return true; 1268 1269 default: 1270 return false; 1271 } 1272} 1273 1274/* return true if the given error code is related to a client certificate */ 1275static bool is_cc_error(PRInt32 err) 1276{ 1277 switch(err) { 1278 case SSL_ERROR_BAD_CERT_ALERT: 1279 case SSL_ERROR_EXPIRED_CERT_ALERT: 1280 case SSL_ERROR_REVOKED_CERT_ALERT: 1281 return true; 1282 1283 default: 1284 return false; 1285 } 1286} 1287 1288static Curl_recv nss_recv; 1289static Curl_send nss_send; 1290 1291static CURLcode nss_load_ca_certificates(struct connectdata *conn, 1292 int sockindex) 1293{ 1294 struct SessionHandle *data = conn->data; 1295 const char *cafile = data->set.ssl.CAfile; 1296 const char *capath = data->set.ssl.CApath; 1297 1298 if(cafile) { 1299 CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); 1300 if(CURLE_OK != rv) 1301 return rv; 1302 } 1303 1304 if(capath) { 1305 struct_stat st; 1306 if(stat(capath, &st) == -1) 1307 return CURLE_SSL_CACERT_BADFILE; 1308 1309 if(S_ISDIR(st.st_mode)) { 1310 PRDirEntry *entry; 1311 PRDir *dir = PR_OpenDir(capath); 1312 if(!dir) 1313 return CURLE_SSL_CACERT_BADFILE; 1314 1315 while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) { 1316 char *fullpath = aprintf("%s/%s", capath, entry->name); 1317 if(!fullpath) { 1318 PR_CloseDir(dir); 1319 return CURLE_OUT_OF_MEMORY; 1320 } 1321 1322 if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE)) 1323 /* This is purposefully tolerant of errors so non-PEM files can 1324 * be in the same directory */ 1325 infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath); 1326 1327 free(fullpath); 1328 } 1329 1330 PR_CloseDir(dir); 1331 } 1332 else 1333 infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath); 1334 } 1335 1336 infof(data, " CAfile: %s\n CApath: %s\n", 1337 cafile ? cafile : "none", 1338 capath ? capath : "none"); 1339 1340 return CURLE_OK; 1341} 1342 1343static CURLcode nss_init_sslver(SSLVersionRange *sslver, 1344 struct SessionHandle *data) 1345{ 1346 switch (data->set.ssl.version) { 1347 default: 1348 case CURL_SSLVERSION_DEFAULT: 1349 sslver->min = SSL_LIBRARY_VERSION_3_0; 1350 if(data->state.ssl_connect_retry) { 1351 infof(data, "TLS disabled due to previous handshake failure\n"); 1352 sslver->max = SSL_LIBRARY_VERSION_3_0; 1353 return CURLE_OK; 1354 } 1355 /* intentional fall-through to default to highest TLS version if possible */ 1356 1357 case CURL_SSLVERSION_TLSv1: 1358#ifdef SSL_LIBRARY_VERSION_TLS_1_2 1359 sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; 1360#elif defined SSL_LIBRARY_VERSION_TLS_1_1 1361 sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; 1362#else 1363 sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; 1364#endif 1365 return CURLE_OK; 1366 1367 case CURL_SSLVERSION_SSLv2: 1368 sslver->min = SSL_LIBRARY_VERSION_2; 1369 sslver->max = SSL_LIBRARY_VERSION_2; 1370 return CURLE_OK; 1371 1372 case CURL_SSLVERSION_SSLv3: 1373 sslver->min = SSL_LIBRARY_VERSION_3_0; 1374 sslver->max = SSL_LIBRARY_VERSION_3_0; 1375 return CURLE_OK; 1376 1377 case CURL_SSLVERSION_TLSv1_0: 1378 sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; 1379 sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; 1380 return CURLE_OK; 1381 1382 case CURL_SSLVERSION_TLSv1_1: 1383#ifdef SSL_LIBRARY_VERSION_TLS_1_1 1384 sslver->min = SSL_LIBRARY_VERSION_TLS_1_1; 1385 sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; 1386 return CURLE_OK; 1387#endif 1388 break; 1389 1390 case CURL_SSLVERSION_TLSv1_2: 1391#ifdef SSL_LIBRARY_VERSION_TLS_1_2 1392 sslver->min = SSL_LIBRARY_VERSION_TLS_1_2; 1393 sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; 1394 return CURLE_OK; 1395#endif 1396 break; 1397 } 1398 1399 failf(data, "TLS minor version cannot be set"); 1400 return CURLE_SSL_CONNECT_ERROR; 1401} 1402 1403static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, 1404 struct SessionHandle *data, 1405 CURLcode curlerr) 1406{ 1407 SSLVersionRange sslver; 1408 PRErrorCode err = 0; 1409 1410 /* reset the flag to avoid an infinite loop */ 1411 data->state.ssl_connect_retry = FALSE; 1412 1413 if(is_nss_error(curlerr)) { 1414 /* read NSPR error code */ 1415 err = PR_GetError(); 1416 if(is_cc_error(err)) 1417 curlerr = CURLE_SSL_CERTPROBLEM; 1418 1419 /* print the error number and error string */ 1420 infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); 1421 1422 /* print a human-readable message describing the error if available */ 1423 nss_print_error_message(data, err); 1424 } 1425 1426 /* cleanup on connection failure */ 1427 Curl_llist_destroy(connssl->obj_list, NULL); 1428 connssl->obj_list = NULL; 1429 1430 if(connssl->handle 1431 && (SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess) 1432 && (sslver.min == SSL_LIBRARY_VERSION_3_0) 1433 && (sslver.max != SSL_LIBRARY_VERSION_3_0) 1434 && isTLSIntoleranceError(err)) { 1435 /* schedule reconnect through Curl_retry_request() */ 1436 data->state.ssl_connect_retry = TRUE; 1437 infof(data, "Error in TLS handshake, trying SSLv3...\n"); 1438 return CURLE_OK; 1439 } 1440 1441 return curlerr; 1442} 1443 1444/* Switch the SSL socket into non-blocking mode. */ 1445static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, 1446 struct SessionHandle *data) 1447{ 1448 static PRSocketOptionData sock_opt; 1449 sock_opt.option = PR_SockOpt_Nonblocking; 1450 sock_opt.value.non_blocking = PR_TRUE; 1451 1452 if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) 1453 return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); 1454 1455 return CURLE_OK; 1456} 1457 1458static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) 1459{ 1460 PRFileDesc *model = NULL; 1461 PRFileDesc *nspr_io = NULL; 1462 PRFileDesc *nspr_io_stub = NULL; 1463 PRBool ssl_no_cache; 1464 PRBool ssl_cbc_random_iv; 1465 struct SessionHandle *data = conn->data; 1466 curl_socket_t sockfd = conn->sock[sockindex]; 1467 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1468 CURLcode curlerr; 1469 1470 SSLVersionRange sslver = { 1471 SSL_LIBRARY_VERSION_TLS_1_0, /* min */ 1472 SSL_LIBRARY_VERSION_TLS_1_0 /* max */ 1473 }; 1474 1475#ifdef USE_NGHTTP2 1476#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) 1477 unsigned int alpn_protos_len = NGHTTP2_PROTO_VERSION_ID_LEN + 1478 ALPN_HTTP_1_1_LENGTH + 2; 1479 unsigned char alpn_protos[NGHTTP2_PROTO_VERSION_ID_LEN + ALPN_HTTP_1_1_LENGTH 1480 + 2]; 1481 int cur = 0; 1482#endif 1483#endif 1484 1485 1486 if(connssl->state == ssl_connection_complete) 1487 return CURLE_OK; 1488 1489 connssl->data = data; 1490 1491 /* list of all NSS objects we need to destroy in Curl_nss_close() */ 1492 connssl->obj_list = Curl_llist_alloc(nss_destroy_object); 1493 if(!connssl->obj_list) 1494 return CURLE_OUT_OF_MEMORY; 1495 1496 /* FIXME. NSS doesn't support multiple databases open at the same time. */ 1497 PR_Lock(nss_initlock); 1498 curlerr = nss_init(conn->data); 1499 if(CURLE_OK != curlerr) { 1500 PR_Unlock(nss_initlock); 1501 goto error; 1502 } 1503 1504 curlerr = CURLE_SSL_CONNECT_ERROR; 1505 1506 if(!mod) { 1507 char *configstring = aprintf("library=%s name=PEM", pem_library); 1508 if(!configstring) { 1509 PR_Unlock(nss_initlock); 1510 goto error; 1511 } 1512 mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE); 1513 free(configstring); 1514 1515 if(!mod || !mod->loaded) { 1516 if(mod) { 1517 SECMOD_DestroyModule(mod); 1518 mod = NULL; 1519 } 1520 infof(data, "WARNING: failed to load NSS PEM library %s. Using " 1521 "OpenSSL PEM certificates will not work.\n", pem_library); 1522 } 1523 } 1524 1525 PK11_SetPasswordFunc(nss_get_password); 1526 PR_Unlock(nss_initlock); 1527 1528 model = PR_NewTCPSocket(); 1529 if(!model) 1530 goto error; 1531 model = SSL_ImportFD(NULL, model); 1532 1533 if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) 1534 goto error; 1535 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) 1536 goto error; 1537 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) 1538 goto error; 1539 1540 /* do not use SSL cache if disabled or we are not going to verify peer */ 1541 ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ? 1542 PR_FALSE : PR_TRUE; 1543 if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) 1544 goto error; 1545 1546 /* enable/disable the requested SSL version(s) */ 1547 if(nss_init_sslver(&sslver, data) != CURLE_OK) 1548 goto error; 1549 if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) 1550 goto error; 1551 1552 ssl_cbc_random_iv = !data->set.ssl_enable_beast; 1553#ifdef SSL_CBC_RANDOM_IV 1554 /* unless the user explicitly asks to allow the protocol vulnerability, we 1555 use the work-around */ 1556 if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess) 1557 infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n", 1558 ssl_cbc_random_iv); 1559#else 1560 if(ssl_cbc_random_iv) 1561 infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); 1562#endif 1563 1564 /* reset the flag to avoid an infinite loop */ 1565 data->state.ssl_connect_retry = FALSE; 1566 1567 if(data->set.ssl.cipher_list) { 1568 if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { 1569 curlerr = CURLE_SSL_CIPHER; 1570 goto error; 1571 } 1572 } 1573 1574 if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost) 1575 infof(data, "warning: ignoring value of ssl.verifyhost\n"); 1576 1577 /* bypass the default SSL_AuthCertificate() hook in case we do not want to 1578 * verify peer */ 1579 if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) 1580 goto error; 1581 1582 data->set.ssl.certverifyresult=0; /* not checked yet */ 1583 if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) 1584 goto error; 1585 1586 if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) 1587 goto error; 1588 1589 if(data->set.ssl.verifypeer) { 1590 const CURLcode rv = nss_load_ca_certificates(conn, sockindex); 1591 if(CURLE_OK != rv) { 1592 curlerr = rv; 1593 goto error; 1594 } 1595 } 1596 1597 if(data->set.ssl.CRLfile) { 1598 const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile); 1599 if(CURLE_OK != rv) { 1600 curlerr = rv; 1601 goto error; 1602 } 1603 infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile); 1604 } 1605 1606 if(data->set.str[STRING_CERT]) { 1607 char *nickname = dup_nickname(data, STRING_CERT); 1608 if(nickname) { 1609 /* we are not going to use libnsspem.so to read the client cert */ 1610 connssl->obj_clicert = NULL; 1611 } 1612 else { 1613 CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], 1614 data->set.str[STRING_KEY]); 1615 if(CURLE_OK != rv) { 1616 /* failf() is already done in cert_stuff() */ 1617 curlerr = rv; 1618 goto error; 1619 } 1620 } 1621 1622 /* store the nickname for SelectClientCert() called during handshake */ 1623 connssl->client_nickname = nickname; 1624 } 1625 else 1626 connssl->client_nickname = NULL; 1627 1628 if(SSL_GetClientAuthDataHook(model, SelectClientCert, 1629 (void *)connssl) != SECSuccess) { 1630 curlerr = CURLE_SSL_CERTPROBLEM; 1631 goto error; 1632 } 1633 1634 /* wrap OS file descriptor by NSPR's file descriptor abstraction */ 1635 nspr_io = PR_ImportTCPSocket(sockfd); 1636 if(!nspr_io) 1637 goto error; 1638 1639 /* create our own NSPR I/O layer */ 1640 nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); 1641 if(!nspr_io_stub) { 1642 PR_Close(nspr_io); 1643 goto error; 1644 } 1645 1646 /* make the per-connection data accessible from NSPR I/O callbacks */ 1647 nspr_io_stub->secret = (void *)connssl; 1648 1649 /* push our new layer to the NSPR I/O stack */ 1650 if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { 1651 PR_Close(nspr_io); 1652 PR_Close(nspr_io_stub); 1653 goto error; 1654 } 1655 1656 /* import our model socket onto the current I/O stack */ 1657 connssl->handle = SSL_ImportFD(model, nspr_io); 1658 if(!connssl->handle) { 1659 PR_Close(nspr_io); 1660 goto error; 1661 } 1662 1663 PR_Close(model); /* We don't need this any more */ 1664 model = NULL; 1665 1666 /* This is the password associated with the cert that we're using */ 1667 if(data->set.str[STRING_KEY_PASSWD]) { 1668 SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); 1669 } 1670 1671#ifdef USE_NGHTTP2 1672 if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { 1673#ifdef SSL_ENABLE_NPN 1674 if(data->set.ssl_enable_npn) { 1675 if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, PR_TRUE) != SECSuccess) 1676 goto error; 1677 } 1678#endif 1679 1680#ifdef SSL_ENABLE_ALPN 1681 if(data->set.ssl_enable_alpn) { 1682 if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, PR_TRUE) 1683 != SECSuccess) 1684 goto error; 1685 } 1686#endif 1687 1688#if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN) 1689 if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) { 1690 alpn_protos[cur] = NGHTTP2_PROTO_VERSION_ID_LEN; 1691 cur++; 1692 memcpy(&alpn_protos[cur], NGHTTP2_PROTO_VERSION_ID, 1693 NGHTTP2_PROTO_VERSION_ID_LEN); 1694 cur += NGHTTP2_PROTO_VERSION_ID_LEN; 1695 alpn_protos[cur] = ALPN_HTTP_1_1_LENGTH; 1696 cur++; 1697 memcpy(&alpn_protos[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH); 1698 1699 if(SSL_SetNextProtoNego(connssl->handle, alpn_protos, alpn_protos_len) 1700 != SECSuccess) 1701 goto error; 1702 } 1703 else { 1704 infof(data, "SSL, can't negotiate HTTP/2.0 with neither NPN nor ALPN\n"); 1705 } 1706#endif 1707 } 1708#endif 1709 1710 1711 /* Force handshake on next I/O */ 1712 SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); 1713 1714 SSL_SetURL(connssl->handle, conn->host.name); 1715 1716 return CURLE_OK; 1717 1718error: 1719 if(model) 1720 PR_Close(model); 1721 1722 return nss_fail_connect(connssl, data, curlerr); 1723} 1724 1725static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) 1726{ 1727 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1728 struct SessionHandle *data = conn->data; 1729 CURLcode curlerr = CURLE_SSL_CONNECT_ERROR; 1730 PRUint32 timeout; 1731 1732 /* check timeout situation */ 1733 const long time_left = Curl_timeleft(data, NULL, TRUE); 1734 if(time_left < 0L) { 1735 failf(data, "timed out before SSL handshake"); 1736 curlerr = CURLE_OPERATION_TIMEDOUT; 1737 goto error; 1738 } 1739 1740 /* Force the handshake now */ 1741 timeout = PR_MillisecondsToInterval((PRUint32) time_left); 1742 if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { 1743 if(PR_GetError() == PR_WOULD_BLOCK_ERROR) 1744 /* blocking direction is updated by nss_update_connecting_state() */ 1745 return CURLE_AGAIN; 1746 else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) 1747 curlerr = CURLE_PEER_FAILED_VERIFICATION; 1748 else if(conn->data->set.ssl.certverifyresult!=0) 1749 curlerr = CURLE_SSL_CACERT; 1750 goto error; 1751 } 1752 1753 connssl->state = ssl_connection_complete; 1754 conn->recv[sockindex] = nss_recv; 1755 conn->send[sockindex] = nss_send; 1756 1757 display_conn_info(conn, connssl->handle); 1758 1759 if(data->set.str[STRING_SSL_ISSUERCERT]) { 1760 SECStatus ret = SECFailure; 1761 char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT); 1762 if(nickname) { 1763 /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ 1764 ret = check_issuer_cert(connssl->handle, nickname); 1765 free(nickname); 1766 } 1767 1768 if(SECFailure == ret) { 1769 infof(data,"SSL certificate issuer check failed\n"); 1770 curlerr = CURLE_SSL_ISSUER_ERROR; 1771 goto error; 1772 } 1773 else { 1774 infof(data, "SSL certificate issuer check ok\n"); 1775 } 1776 } 1777 1778 return CURLE_OK; 1779 1780error: 1781 return nss_fail_connect(connssl, data, curlerr); 1782} 1783 1784static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, 1785 bool *done) 1786{ 1787 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 1788 struct SessionHandle *data = conn->data; 1789 const bool blocking = (done == NULL); 1790 CURLcode rv; 1791 1792 if(connssl->connecting_state == ssl_connect_1) { 1793 rv = nss_setup_connect(conn, sockindex); 1794 if(rv) 1795 /* we do not expect CURLE_AGAIN from nss_setup_connect() */ 1796 return rv; 1797 1798 if(!blocking) { 1799 /* in non-blocking mode, set NSS non-blocking mode before handshake */ 1800 rv = nss_set_nonblock(connssl, data); 1801 if(rv) 1802 return rv; 1803 } 1804 1805 connssl->connecting_state = ssl_connect_2; 1806 } 1807 1808 rv = nss_do_connect(conn, sockindex); 1809 switch(rv) { 1810 case CURLE_OK: 1811 break; 1812 case CURLE_AGAIN: 1813 if(!blocking) 1814 /* CURLE_AGAIN in non-blocking mode is not an error */ 1815 return CURLE_OK; 1816 /* fall through */ 1817 default: 1818 return rv; 1819 } 1820 1821 if(blocking) { 1822 /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ 1823 rv = nss_set_nonblock(connssl, data); 1824 if(rv) 1825 return rv; 1826 } 1827 else 1828 /* signal completed SSL handshake */ 1829 *done = TRUE; 1830 1831 connssl->connecting_state = ssl_connect_done; 1832 return CURLE_OK; 1833} 1834 1835CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) 1836{ 1837 return nss_connect_common(conn, sockindex, /* blocking */ NULL); 1838} 1839 1840CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, 1841 int sockindex, bool *done) 1842{ 1843 return nss_connect_common(conn, sockindex, done); 1844} 1845 1846static ssize_t nss_send(struct connectdata *conn, /* connection data */ 1847 int sockindex, /* socketindex */ 1848 const void *mem, /* send this data */ 1849 size_t len, /* amount to write */ 1850 CURLcode *curlcode) 1851{ 1852 ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0, 1853 PR_INTERVAL_NO_WAIT); 1854 if(rc < 0) { 1855 PRInt32 err = PR_GetError(); 1856 if(err == PR_WOULD_BLOCK_ERROR) 1857 *curlcode = CURLE_AGAIN; 1858 else { 1859 /* print the error number and error string */ 1860 const char *err_name = nss_error_to_name(err); 1861 infof(conn->data, "SSL write: error %d (%s)\n", err, err_name); 1862 1863 /* print a human-readable message describing the error if available */ 1864 nss_print_error_message(conn->data, err); 1865 1866 *curlcode = (is_cc_error(err)) 1867 ? CURLE_SSL_CERTPROBLEM 1868 : CURLE_SEND_ERROR; 1869 } 1870 return -1; 1871 } 1872 return rc; /* number of bytes */ 1873} 1874 1875static ssize_t nss_recv(struct connectdata * conn, /* connection data */ 1876 int num, /* socketindex */ 1877 char *buf, /* store read data here */ 1878 size_t buffersize, /* max amount to read */ 1879 CURLcode *curlcode) 1880{ 1881 ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0, 1882 PR_INTERVAL_NO_WAIT); 1883 if(nread < 0) { 1884 /* failed SSL read */ 1885 PRInt32 err = PR_GetError(); 1886 1887 if(err == PR_WOULD_BLOCK_ERROR) 1888 *curlcode = CURLE_AGAIN; 1889 else { 1890 /* print the error number and error string */ 1891 const char *err_name = nss_error_to_name(err); 1892 infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name); 1893 1894 /* print a human-readable message describing the error if available */ 1895 nss_print_error_message(conn->data, err); 1896 1897 *curlcode = (is_cc_error(err)) 1898 ? CURLE_SSL_CERTPROBLEM 1899 : CURLE_RECV_ERROR; 1900 } 1901 return -1; 1902 } 1903 return nread; 1904} 1905 1906size_t Curl_nss_version(char *buffer, size_t size) 1907{ 1908 return snprintf(buffer, size, "NSS/%s", NSS_VERSION); 1909} 1910 1911int Curl_nss_seed(struct SessionHandle *data) 1912{ 1913 /* make sure that NSS is initialized */ 1914 return !!Curl_nss_force_init(data); 1915} 1916 1917void Curl_nss_random(struct SessionHandle *data, 1918 unsigned char *entropy, 1919 size_t length) 1920{ 1921 Curl_nss_seed(data); /* Initiate the seed if not already done */ 1922 if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length))) { 1923 /* no way to signal a failure from here, we have to abort */ 1924 failf(data, "PK11_GenerateRandom() failed, calling abort()..."); 1925 abort(); 1926 } 1927} 1928 1929void Curl_nss_md5sum(unsigned char *tmp, /* input */ 1930 size_t tmplen, 1931 unsigned char *md5sum, /* output */ 1932 size_t md5len) 1933{ 1934 PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); 1935 unsigned int MD5out; 1936 PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen)); 1937 PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len)); 1938 PK11_DestroyContext(MD5pw, PR_TRUE); 1939} 1940 1941#endif /* USE_NSS */ 1942