1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2020, 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 https://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 "strcase.h"
38 #include "select.h"
39 #include "vtls.h"
40 #include "llist.h"
41 #include "multiif.h"
42 #include "curl_printf.h"
43 #include "nssg.h"
44 #include <nspr.h>
45 #include <nss.h>
46 #include <ssl.h>
47 #include <sslerr.h>
48 #include <secerr.h>
49 #include <secmod.h>
50 #include <sslproto.h>
51 #include <prtypes.h>
52 #include <pk11pub.h>
53 #include <prio.h>
54 #include <secitem.h>
55 #include <secport.h>
56 #include <certdb.h>
57 #include <base64.h>
58 #include <cert.h>
59 #include <prerror.h>
60 #include <keyhi.h> /* for SECKEY_DestroyPublicKey() */
61 #include <private/pprio.h> /* for PR_ImportTCPSocket */
62
63 #define NSSVERNUM ((NSS_VMAJOR<<16)|(NSS_VMINOR<<8)|NSS_VPATCH)
64
65 #if NSSVERNUM >= 0x030f00 /* 3.15.0 */
66 #include <ocsp.h>
67 #endif
68
69 #include "strcase.h"
70 #include "warnless.h"
71 #include "x509asn1.h"
72
73 /* The last #include files should be: */
74 #include "curl_memory.h"
75 #include "memdebug.h"
76
77 #define SSL_DIR "/etc/pki/nssdb"
78
79 /* enough to fit the string "PEM Token #[0|1]" */
80 #define SLOTSIZE 13
81
82 struct ssl_backend_data {
83 PRFileDesc *handle;
84 char *client_nickname;
85 struct Curl_easy *data;
86 struct curl_llist obj_list;
87 PK11GenericObject *obj_clicert;
88 };
89
90 static PRLock *nss_initlock = NULL;
91 static PRLock *nss_crllock = NULL;
92 static PRLock *nss_findslot_lock = NULL;
93 static PRLock *nss_trustload_lock = NULL;
94 static struct curl_llist nss_crl_list;
95 static NSSInitContext *nss_context = NULL;
96 static volatile int initialized = 0;
97
98 /* type used to wrap pointers as list nodes */
99 struct ptr_list_wrap {
100 void *ptr;
101 struct curl_llist_element node;
102 };
103
104 struct cipher_s {
105 const char *name;
106 int num;
107 };
108
109 #define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
110 CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
111 ptr->type = (_type); \
112 ptr->pValue = (_val); \
113 ptr->ulValueLen = (_len); \
114 } while(0)
115
116 #define CERT_NewTempCertificate __CERT_NewTempCertificate
117
118 #define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
119 static const struct cipher_s cipherlist[] = {
120 /* SSL2 cipher suites */
121 {"rc4", SSL_EN_RC4_128_WITH_MD5},
122 {"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
123 {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5},
124 {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5},
125 {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5},
126 {"des", SSL_EN_DES_64_CBC_WITH_MD5},
127 {"desede3", SSL_EN_DES_192_EDE3_CBC_WITH_MD5},
128 /* SSL3/TLS cipher suites */
129 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5},
130 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA},
131 {"rsa_3des_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA},
132 {"rsa_des_sha", SSL_RSA_WITH_DES_CBC_SHA},
133 {"rsa_rc4_40_md5", SSL_RSA_EXPORT_WITH_RC4_40_MD5},
134 {"rsa_rc2_40_md5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5},
135 {"rsa_null_md5", SSL_RSA_WITH_NULL_MD5},
136 {"rsa_null_sha", SSL_RSA_WITH_NULL_SHA},
137 {"fips_3des_sha", SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA},
138 {"fips_des_sha", SSL_RSA_FIPS_WITH_DES_CBC_SHA},
139 {"fortezza", SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA},
140 {"fortezza_rc4_128_sha", SSL_FORTEZZA_DMS_WITH_RC4_128_SHA},
141 {"fortezza_null", SSL_FORTEZZA_DMS_WITH_NULL_SHA},
142 /* TLS 1.0: Exportable 56-bit Cipher Suites. */
143 {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA},
144 {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA},
145 /* AES ciphers. */
146 {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA},
147 {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA},
148 {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
149 {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
150 {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA},
151 {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA},
152 /* ECC ciphers. */
153 {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA},
154 {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
155 {"ecdh_ecdsa_3des_sha", TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
156 {"ecdh_ecdsa_aes_128_sha", TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
157 {"ecdh_ecdsa_aes_256_sha", TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
158 {"ecdhe_ecdsa_null_sha", TLS_ECDHE_ECDSA_WITH_NULL_SHA},
159 {"ecdhe_ecdsa_rc4_128_sha", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
160 {"ecdhe_ecdsa_3des_sha", TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
161 {"ecdhe_ecdsa_aes_128_sha", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
162 {"ecdhe_ecdsa_aes_256_sha", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
163 {"ecdh_rsa_null_sha", TLS_ECDH_RSA_WITH_NULL_SHA},
164 {"ecdh_rsa_128_sha", TLS_ECDH_RSA_WITH_RC4_128_SHA},
165 {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
166 {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
167 {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
168 {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
169 {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
170 {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
171 {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
172 {"ecdhe_rsa_aes_256_sha", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
173 {"ecdh_anon_null_sha", TLS_ECDH_anon_WITH_NULL_SHA},
174 {"ecdh_anon_rc4_128sha", TLS_ECDH_anon_WITH_RC4_128_SHA},
175 {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
176 {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
177 {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
178 #ifdef TLS_RSA_WITH_NULL_SHA256
179 /* new HMAC-SHA256 cipher suites specified in RFC */
180 {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256},
181 {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256},
182 {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256},
183 {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
184 {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
185 {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
186 {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
187 #endif
188 #ifdef TLS_RSA_WITH_AES_128_GCM_SHA256
189 /* AES GCM cipher suites in RFC 5288 and RFC 5289 */
190 {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256},
191 {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
192 {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256},
193 {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
194 {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256},
195 {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
196 {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
197 #endif
198 #ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
199 /* cipher suites using SHA384 */
200 {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384},
201 {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
202 {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},
203 {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
204 {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
205 {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
206 {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
207 #endif
208 #ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
209 /* chacha20-poly1305 cipher suites */
210 {"ecdhe_rsa_chacha20_poly1305_sha_256",
211 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
212 {"ecdhe_ecdsa_chacha20_poly1305_sha_256",
213 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
214 {"dhe_rsa_chacha20_poly1305_sha_256",
215 TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
216 #endif
217 #ifdef TLS_AES_256_GCM_SHA384
218 {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256},
219 {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384},
220 {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256},
221 #endif
222 };
223
224 #if defined(WIN32)
225 static const char *pem_library = "nsspem.dll";
226 static const char *trust_library = "nssckbi.dll";
227 #elif defined(__APPLE__)
228 static const char *pem_library = "libnsspem.dylib";
229 static const char *trust_library = "libnssckbi.dylib";
230 #else
231 static const char *pem_library = "libnsspem.so";
232 static const char *trust_library = "libnssckbi.so";
233 #endif
234
235 static SECMODModule *pem_module = NULL;
236 static SECMODModule *trust_module = NULL;
237
238 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
239 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
240 static PRIOMethods nspr_io_methods;
241
nss_error_to_name(PRErrorCode code)242 static const char *nss_error_to_name(PRErrorCode code)
243 {
244 const char *name = PR_ErrorToName(code);
245 if(name)
246 return name;
247
248 return "unknown error";
249 }
250
nss_print_error_message(struct Curl_easy * data,PRUint32 err)251 static void nss_print_error_message(struct Curl_easy *data, PRUint32 err)
252 {
253 failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
254 }
255
nss_sslver_to_name(PRUint16 nssver)256 static char *nss_sslver_to_name(PRUint16 nssver)
257 {
258 switch(nssver) {
259 case SSL_LIBRARY_VERSION_2:
260 return strdup("SSLv2");
261 case SSL_LIBRARY_VERSION_3_0:
262 return strdup("SSLv3");
263 case SSL_LIBRARY_VERSION_TLS_1_0:
264 return strdup("TLSv1.0");
265 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
266 case SSL_LIBRARY_VERSION_TLS_1_1:
267 return strdup("TLSv1.1");
268 #endif
269 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
270 case SSL_LIBRARY_VERSION_TLS_1_2:
271 return strdup("TLSv1.2");
272 #endif
273 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
274 case SSL_LIBRARY_VERSION_TLS_1_3:
275 return strdup("TLSv1.3");
276 #endif
277 default:
278 return curl_maprintf("0x%04x", nssver);
279 }
280 }
281
set_ciphers(struct Curl_easy * data,PRFileDesc * model,char * cipher_list)282 static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
283 char *cipher_list)
284 {
285 unsigned int i;
286 PRBool cipher_state[NUM_OF_CIPHERS];
287 PRBool found;
288 char *cipher;
289
290 /* use accessors to avoid dynamic linking issues after an update of NSS */
291 const PRUint16 num_implemented_ciphers = SSL_GetNumImplementedCiphers();
292 const PRUint16 *implemented_ciphers = SSL_GetImplementedCiphers();
293 if(!implemented_ciphers)
294 return SECFailure;
295
296 /* First disable all ciphers. This uses a different max value in case
297 * NSS adds more ciphers later we don't want them available by
298 * accident
299 */
300 for(i = 0; i < num_implemented_ciphers; i++) {
301 SSL_CipherPrefSet(model, implemented_ciphers[i], PR_FALSE);
302 }
303
304 /* Set every entry in our list to false */
305 for(i = 0; i < NUM_OF_CIPHERS; i++) {
306 cipher_state[i] = PR_FALSE;
307 }
308
309 cipher = cipher_list;
310
311 while(cipher_list && (cipher_list[0])) {
312 while((*cipher) && (ISSPACE(*cipher)))
313 ++cipher;
314
315 cipher_list = strchr(cipher, ',');
316 if(cipher_list) {
317 *cipher_list++ = '\0';
318 }
319
320 found = PR_FALSE;
321
322 for(i = 0; i<NUM_OF_CIPHERS; i++) {
323 if(strcasecompare(cipher, cipherlist[i].name)) {
324 cipher_state[i] = PR_TRUE;
325 found = PR_TRUE;
326 break;
327 }
328 }
329
330 if(found == PR_FALSE) {
331 failf(data, "Unknown cipher in list: %s", cipher);
332 return SECFailure;
333 }
334
335 if(cipher_list) {
336 cipher = cipher_list;
337 }
338 }
339
340 /* Finally actually enable the selected ciphers */
341 for(i = 0; i<NUM_OF_CIPHERS; i++) {
342 if(!cipher_state[i])
343 continue;
344
345 if(SSL_CipherPrefSet(model, cipherlist[i].num, PR_TRUE) != SECSuccess) {
346 failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
347 return SECFailure;
348 }
349 }
350
351 return SECSuccess;
352 }
353
354 /*
355 * Return true if at least one cipher-suite is enabled. Used to determine
356 * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
357 */
any_cipher_enabled(void)358 static bool any_cipher_enabled(void)
359 {
360 unsigned int i;
361
362 for(i = 0; i<NUM_OF_CIPHERS; i++) {
363 PRInt32 policy = 0;
364 SSL_CipherPolicyGet(cipherlist[i].num, &policy);
365 if(policy)
366 return TRUE;
367 }
368
369 return FALSE;
370 }
371
372 /*
373 * Determine whether the nickname passed in is a filename that needs to
374 * be loaded as a PEM or a regular NSS nickname.
375 *
376 * returns 1 for a file
377 * returns 0 for not a file (NSS nickname)
378 */
is_file(const char * filename)379 static int is_file(const char *filename)
380 {
381 struct_stat st;
382
383 if(filename == NULL)
384 return 0;
385
386 if(stat(filename, &st) == 0)
387 if(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISCHR(st.st_mode))
388 return 1;
389
390 return 0;
391 }
392
393 /* Check if the given string is filename or nickname of a certificate. If the
394 * given string is recognized as filename, return NULL. If the given string is
395 * recognized as nickname, return a duplicated string. The returned string
396 * should be later deallocated using free(). If the OOM failure occurs, we
397 * return NULL, too.
398 */
dup_nickname(struct Curl_easy * data,const char * str)399 static char *dup_nickname(struct Curl_easy *data, const char *str)
400 {
401 const char *n;
402
403 if(!is_file(str))
404 /* no such file exists, use the string as nickname */
405 return strdup(str);
406
407 /* search the first slash; we require at least one slash in a file name */
408 n = strchr(str, '/');
409 if(!n) {
410 infof(data, "warning: certificate file name \"%s\" handled as nickname; "
411 "please use \"./%s\" to force file name\n", str, str);
412 return strdup(str);
413 }
414
415 /* we'll use the PEM reader to read the certificate from file */
416 return NULL;
417 }
418
419 /* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
420 * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
421 * details, go to <https://bugzilla.mozilla.org/1297397>.
422 */
nss_find_slot_by_name(const char * slot_name)423 static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
424 {
425 PK11SlotInfo *slot;
426 PR_Lock(nss_findslot_lock);
427 slot = PK11_FindSlotByName(slot_name);
428 PR_Unlock(nss_findslot_lock);
429 return slot;
430 }
431
432 /* wrap 'ptr' as list node and tail-insert into 'list' */
insert_wrapped_ptr(struct curl_llist * list,void * ptr)433 static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
434 {
435 struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
436 if(!wrap)
437 return CURLE_OUT_OF_MEMORY;
438
439 wrap->ptr = ptr;
440 Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
441 return CURLE_OK;
442 }
443
444 /* Call PK11_CreateGenericObject() with the given obj_class and filename. If
445 * the call succeeds, append the object handle to the list of objects so that
446 * the object can be destroyed in Curl_nss_close(). */
nss_create_object(struct ssl_connect_data * connssl,CK_OBJECT_CLASS obj_class,const char * filename,bool cacert)447 static CURLcode nss_create_object(struct ssl_connect_data *connssl,
448 CK_OBJECT_CLASS obj_class,
449 const char *filename, bool cacert)
450 {
451 PK11SlotInfo *slot;
452 PK11GenericObject *obj;
453 CK_BBOOL cktrue = CK_TRUE;
454 CK_BBOOL ckfalse = CK_FALSE;
455 CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
456 int attr_cnt = 0;
457 CURLcode result = (cacert)
458 ? CURLE_SSL_CACERT_BADFILE
459 : CURLE_SSL_CERTPROBLEM;
460
461 const int slot_id = (cacert) ? 0 : 1;
462 char *slot_name = aprintf("PEM Token #%d", slot_id);
463 struct ssl_backend_data *backend = connssl->backend;
464 if(!slot_name)
465 return CURLE_OUT_OF_MEMORY;
466
467 slot = nss_find_slot_by_name(slot_name);
468 free(slot_name);
469 if(!slot)
470 return result;
471
472 PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
473 PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
474 PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
475 (CK_ULONG)strlen(filename) + 1);
476
477 if(CKO_CERTIFICATE == obj_class) {
478 CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
479 PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
480 }
481
482 /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
483 * PK11_DestroyGenericObject() does not release resources allocated by
484 * PK11_CreateGenericObject() early enough. */
485 obj =
486 #ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
487 PK11_CreateManagedGenericObject
488 #else
489 PK11_CreateGenericObject
490 #endif
491 (slot, attrs, attr_cnt, PR_FALSE);
492
493 PK11_FreeSlot(slot);
494 if(!obj)
495 return result;
496
497 if(insert_wrapped_ptr(&backend->obj_list, obj) != CURLE_OK) {
498 PK11_DestroyGenericObject(obj);
499 return CURLE_OUT_OF_MEMORY;
500 }
501
502 if(!cacert && CKO_CERTIFICATE == obj_class)
503 /* store reference to a client certificate */
504 backend->obj_clicert = obj;
505
506 return CURLE_OK;
507 }
508
509 /* Destroy the NSS object whose handle is given by ptr. This function is
510 * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
511 * NSS objects in Curl_nss_close() */
nss_destroy_object(void * user,void * ptr)512 static void nss_destroy_object(void *user, void *ptr)
513 {
514 struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
515 PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
516 (void) user;
517 PK11_DestroyGenericObject(obj);
518 free(wrap);
519 }
520
521 /* same as nss_destroy_object() but for CRL items */
nss_destroy_crl_item(void * user,void * ptr)522 static void nss_destroy_crl_item(void *user, void *ptr)
523 {
524 struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
525 SECItem *crl_der = (SECItem *) wrap->ptr;
526 (void) user;
527 SECITEM_FreeItem(crl_der, PR_TRUE);
528 free(wrap);
529 }
530
nss_load_cert(struct ssl_connect_data * ssl,const char * filename,PRBool cacert)531 static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
532 const char *filename, PRBool cacert)
533 {
534 CURLcode result = (cacert)
535 ? CURLE_SSL_CACERT_BADFILE
536 : CURLE_SSL_CERTPROBLEM;
537
538 /* libnsspem.so leaks memory if the requested file does not exist. For more
539 * details, go to <https://bugzilla.redhat.com/734760>. */
540 if(is_file(filename))
541 result = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
542
543 if(!result && !cacert) {
544 /* we have successfully loaded a client certificate */
545 CERTCertificate *cert;
546 char *nickname = NULL;
547 char *n = strrchr(filename, '/');
548 if(n)
549 n++;
550
551 /* The following undocumented magic helps to avoid a SIGSEGV on call
552 * of PK11_ReadRawAttribute() from SelectClientCert() when using an
553 * immature version of libnsspem.so. For more details, go to
554 * <https://bugzilla.redhat.com/733685>. */
555 nickname = aprintf("PEM Token #1:%s", n);
556 if(nickname) {
557 cert = PK11_FindCertFromNickname(nickname, NULL);
558 if(cert)
559 CERT_DestroyCertificate(cert);
560
561 free(nickname);
562 }
563 }
564
565 return result;
566 }
567
568 /* add given CRL to cache if it is not already there */
nss_cache_crl(SECItem * crl_der)569 static CURLcode nss_cache_crl(SECItem *crl_der)
570 {
571 CERTCertDBHandle *db = CERT_GetDefaultCertDB();
572 CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crl_der, 0);
573 if(crl) {
574 /* CRL already cached */
575 SEC_DestroyCrl(crl);
576 SECITEM_FreeItem(crl_der, PR_TRUE);
577 return CURLE_OK;
578 }
579
580 /* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
581 PR_Lock(nss_crllock);
582
583 if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
584 /* unable to cache CRL */
585 SECITEM_FreeItem(crl_der, PR_TRUE);
586 PR_Unlock(nss_crllock);
587 return CURLE_SSL_CRL_BADFILE;
588 }
589
590 /* store the CRL item so that we can free it in Curl_nss_cleanup() */
591 if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
592 if(SECSuccess == CERT_UncacheCRL(db, crl_der))
593 SECITEM_FreeItem(crl_der, PR_TRUE);
594 PR_Unlock(nss_crllock);
595 return CURLE_OUT_OF_MEMORY;
596 }
597
598 /* we need to clear session cache, so that the CRL could take effect */
599 SSL_ClearSessionCache();
600 PR_Unlock(nss_crllock);
601 return CURLE_OK;
602 }
603
nss_load_crl(const char * crlfilename)604 static CURLcode nss_load_crl(const char *crlfilename)
605 {
606 PRFileDesc *infile;
607 PRFileInfo info;
608 SECItem filedata = { 0, NULL, 0 };
609 SECItem *crl_der = NULL;
610 char *body;
611
612 infile = PR_Open(crlfilename, PR_RDONLY, 0);
613 if(!infile)
614 return CURLE_SSL_CRL_BADFILE;
615
616 if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
617 goto fail;
618
619 if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
620 goto fail;
621
622 if(info.size != PR_Read(infile, filedata.data, info.size))
623 goto fail;
624
625 crl_der = SECITEM_AllocItem(NULL, NULL, 0U);
626 if(!crl_der)
627 goto fail;
628
629 /* place a trailing zero right after the visible data */
630 body = (char *)filedata.data;
631 body[--filedata.len] = '\0';
632
633 body = strstr(body, "-----BEGIN");
634 if(body) {
635 /* assume ASCII */
636 char *trailer;
637 char *begin = PORT_Strchr(body, '\n');
638 if(!begin)
639 begin = PORT_Strchr(body, '\r');
640 if(!begin)
641 goto fail;
642
643 trailer = strstr(++begin, "-----END");
644 if(!trailer)
645 goto fail;
646
647 /* retrieve DER from ASCII */
648 *trailer = '\0';
649 if(ATOB_ConvertAsciiToItem(crl_der, begin))
650 goto fail;
651
652 SECITEM_FreeItem(&filedata, PR_FALSE);
653 }
654 else
655 /* assume DER */
656 *crl_der = filedata;
657
658 PR_Close(infile);
659 return nss_cache_crl(crl_der);
660
661 fail:
662 PR_Close(infile);
663 SECITEM_FreeItem(crl_der, PR_TRUE);
664 SECITEM_FreeItem(&filedata, PR_FALSE);
665 return CURLE_SSL_CRL_BADFILE;
666 }
667
nss_load_key(struct connectdata * conn,int sockindex,char * key_file)668 static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
669 char *key_file)
670 {
671 PK11SlotInfo *slot, *tmp;
672 SECStatus status;
673 CURLcode result;
674 struct ssl_connect_data *ssl = conn->ssl;
675 struct Curl_easy *data = conn->data;
676
677 (void)sockindex; /* unused */
678
679 result = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
680 if(result) {
681 PR_SetError(SEC_ERROR_BAD_KEY, 0);
682 return result;
683 }
684
685 slot = nss_find_slot_by_name("PEM Token #1");
686 if(!slot)
687 return CURLE_SSL_CERTPROBLEM;
688
689 /* This will force the token to be seen as re-inserted */
690 tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
691 if(tmp)
692 PK11_FreeSlot(tmp);
693 if(!PK11_IsPresent(slot)) {
694 PK11_FreeSlot(slot);
695 return CURLE_SSL_CERTPROBLEM;
696 }
697
698 status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
699 PK11_FreeSlot(slot);
700
701 return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
702 }
703
display_error(struct connectdata * conn,PRInt32 err,const char * filename)704 static int display_error(struct connectdata *conn, PRInt32 err,
705 const char *filename)
706 {
707 switch(err) {
708 case SEC_ERROR_BAD_PASSWORD:
709 failf(conn->data, "Unable to load client key: Incorrect password");
710 return 1;
711 case SEC_ERROR_UNKNOWN_CERT:
712 failf(conn->data, "Unable to load certificate %s", filename);
713 return 1;
714 default:
715 break;
716 }
717 return 0; /* The caller will print a generic error */
718 }
719
cert_stuff(struct connectdata * conn,int sockindex,char * cert_file,char * key_file)720 static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
721 char *cert_file, char *key_file)
722 {
723 struct Curl_easy *data = conn->data;
724 CURLcode result;
725
726 if(cert_file) {
727 result = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
728 if(result) {
729 const PRErrorCode err = PR_GetError();
730 if(!display_error(conn, err, cert_file)) {
731 const char *err_name = nss_error_to_name(err);
732 failf(data, "unable to load client cert: %d (%s)", err, err_name);
733 }
734
735 return result;
736 }
737 }
738
739 if(key_file || (is_file(cert_file))) {
740 if(key_file)
741 result = nss_load_key(conn, sockindex, key_file);
742 else
743 /* In case the cert file also has the key */
744 result = nss_load_key(conn, sockindex, cert_file);
745 if(result) {
746 const PRErrorCode err = PR_GetError();
747 if(!display_error(conn, err, key_file)) {
748 const char *err_name = nss_error_to_name(err);
749 failf(data, "unable to load client key: %d (%s)", err, err_name);
750 }
751
752 return result;
753 }
754 }
755
756 return CURLE_OK;
757 }
758
nss_get_password(PK11SlotInfo * slot,PRBool retry,void * arg)759 static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
760 {
761 (void)slot; /* unused */
762
763 if(retry || NULL == arg)
764 return NULL;
765 else
766 return (char *)PORT_Strdup((char *)arg);
767 }
768
769 /* bypass the default SSL_AuthCertificate() hook in case we do not want to
770 * verify peer */
nss_auth_cert_hook(void * arg,PRFileDesc * fd,PRBool checksig,PRBool isServer)771 static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
772 PRBool isServer)
773 {
774 struct connectdata *conn = (struct connectdata *)arg;
775
776 #ifdef SSL_ENABLE_OCSP_STAPLING
777 if(SSL_CONN_CONFIG(verifystatus)) {
778 SECStatus cacheResult;
779
780 const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
781 if(!csa) {
782 failf(conn->data, "Invalid OCSP response");
783 return SECFailure;
784 }
785
786 if(csa->len == 0) {
787 failf(conn->data, "No OCSP response received");
788 return SECFailure;
789 }
790
791 cacheResult = CERT_CacheOCSPResponseFromSideChannel(
792 CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd),
793 PR_Now(), &csa->items[0], arg
794 );
795
796 if(cacheResult != SECSuccess) {
797 failf(conn->data, "Invalid OCSP response");
798 return cacheResult;
799 }
800 }
801 #endif
802
803 if(!SSL_CONN_CONFIG(verifypeer)) {
804 infof(conn->data, "skipping SSL peer certificate verification\n");
805 return SECSuccess;
806 }
807
808 return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
809 }
810
811 /**
812 * Inform the application that the handshake is complete.
813 */
HandshakeCallback(PRFileDesc * sock,void * arg)814 static void HandshakeCallback(PRFileDesc *sock, void *arg)
815 {
816 struct connectdata *conn = (struct connectdata*) arg;
817 unsigned int buflenmax = 50;
818 unsigned char buf[50];
819 unsigned int buflen;
820 SSLNextProtoState state;
821
822 if(!conn->bits.tls_enable_npn && !conn->bits.tls_enable_alpn) {
823 return;
824 }
825
826 if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
827
828 switch(state) {
829 #if NSSVERNUM >= 0x031a00 /* 3.26.0 */
830 /* used by NSS internally to implement 0-RTT */
831 case SSL_NEXT_PROTO_EARLY_VALUE:
832 /* fall through! */
833 #endif
834 case SSL_NEXT_PROTO_NO_SUPPORT:
835 case SSL_NEXT_PROTO_NO_OVERLAP:
836 infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
837 return;
838 #ifdef SSL_ENABLE_ALPN
839 case SSL_NEXT_PROTO_SELECTED:
840 infof(conn->data, "ALPN, server accepted to use %.*s\n", buflen, buf);
841 break;
842 #endif
843 case SSL_NEXT_PROTO_NEGOTIATED:
844 infof(conn->data, "NPN, server accepted to use %.*s\n", buflen, buf);
845 break;
846 }
847
848 #ifdef USE_NGHTTP2
849 if(buflen == NGHTTP2_PROTO_VERSION_ID_LEN &&
850 !memcmp(NGHTTP2_PROTO_VERSION_ID, buf, NGHTTP2_PROTO_VERSION_ID_LEN)) {
851 conn->negnpn = CURL_HTTP_VERSION_2;
852 }
853 else
854 #endif
855 if(buflen == ALPN_HTTP_1_1_LENGTH &&
856 !memcmp(ALPN_HTTP_1_1, buf, ALPN_HTTP_1_1_LENGTH)) {
857 conn->negnpn = CURL_HTTP_VERSION_1_1;
858 }
859 Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
860 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
861 }
862 }
863
864 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
CanFalseStartCallback(PRFileDesc * sock,void * client_data,PRBool * canFalseStart)865 static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
866 PRBool *canFalseStart)
867 {
868 struct connectdata *conn = client_data;
869 struct Curl_easy *data = conn->data;
870
871 SSLChannelInfo channelInfo;
872 SSLCipherSuiteInfo cipherInfo;
873
874 SECStatus rv;
875 PRBool negotiatedExtension;
876
877 *canFalseStart = PR_FALSE;
878
879 if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess)
880 return SECFailure;
881
882 if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
883 sizeof(cipherInfo)) != SECSuccess)
884 return SECFailure;
885
886 /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
887 * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310
888 */
889 if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2)
890 goto end;
891
892 /* Only allow ECDHE key exchange algorithm.
893 * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */
894 if(cipherInfo.keaType != ssl_kea_ecdh)
895 goto end;
896
897 /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
898 * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
899 * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */
900 if(cipherInfo.symCipher != ssl_calg_aes_gcm)
901 goto end;
902
903 /* Enforce ALPN or NPN to do False Start, as an indicator of server
904 * compatibility. */
905 rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
906 &negotiatedExtension);
907 if(rv != SECSuccess || !negotiatedExtension) {
908 rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn,
909 &negotiatedExtension);
910 }
911
912 if(rv != SECSuccess || !negotiatedExtension)
913 goto end;
914
915 *canFalseStart = PR_TRUE;
916
917 infof(data, "Trying TLS False Start\n");
918
919 end:
920 return SECSuccess;
921 }
922 #endif
923
display_cert_info(struct Curl_easy * data,CERTCertificate * cert)924 static void display_cert_info(struct Curl_easy *data,
925 CERTCertificate *cert)
926 {
927 char *subject, *issuer, *common_name;
928 PRExplodedTime printableTime;
929 char timeString[256];
930 PRTime notBefore, notAfter;
931
932 subject = CERT_NameToAscii(&cert->subject);
933 issuer = CERT_NameToAscii(&cert->issuer);
934 common_name = CERT_GetCommonName(&cert->subject);
935 infof(data, "\tsubject: %s\n", subject);
936
937 CERT_GetCertTimes(cert, ¬Before, ¬After);
938 PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
939 PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
940 infof(data, "\tstart date: %s\n", timeString);
941 PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
942 PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
943 infof(data, "\texpire date: %s\n", timeString);
944 infof(data, "\tcommon name: %s\n", common_name);
945 infof(data, "\tissuer: %s\n", issuer);
946
947 PR_Free(subject);
948 PR_Free(issuer);
949 PR_Free(common_name);
950 }
951
display_conn_info(struct connectdata * conn,PRFileDesc * sock)952 static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
953 {
954 CURLcode result = CURLE_OK;
955 SSLChannelInfo channel;
956 SSLCipherSuiteInfo suite;
957 CERTCertificate *cert;
958 CERTCertificate *cert2;
959 CERTCertificate *cert3;
960 PRTime now;
961 int i;
962
963 if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
964 SECSuccess && channel.length == sizeof(channel) &&
965 channel.cipherSuite) {
966 if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
967 &suite, sizeof(suite)) == SECSuccess) {
968 infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
969 }
970 }
971
972 cert = SSL_PeerCertificate(sock);
973 if(cert) {
974 infof(conn->data, "Server certificate:\n");
975
976 if(!conn->data->set.ssl.certinfo) {
977 display_cert_info(conn->data, cert);
978 CERT_DestroyCertificate(cert);
979 }
980 else {
981 /* Count certificates in chain. */
982 now = PR_Now();
983 i = 1;
984 if(!cert->isRoot) {
985 cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
986 while(cert2) {
987 i++;
988 if(cert2->isRoot) {
989 CERT_DestroyCertificate(cert2);
990 break;
991 }
992 cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
993 CERT_DestroyCertificate(cert2);
994 cert2 = cert3;
995 }
996 }
997
998 result = Curl_ssl_init_certinfo(conn->data, i);
999 if(!result) {
1000 for(i = 0; cert; cert = cert2) {
1001 result = Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
1002 (char *)cert->derCert.data +
1003 cert->derCert.len);
1004 if(result)
1005 break;
1006
1007 if(cert->isRoot) {
1008 CERT_DestroyCertificate(cert);
1009 break;
1010 }
1011
1012 cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
1013 CERT_DestroyCertificate(cert);
1014 }
1015 }
1016 }
1017 }
1018
1019 return result;
1020 }
1021
BadCertHandler(void * arg,PRFileDesc * sock)1022 static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
1023 {
1024 struct connectdata *conn = (struct connectdata *)arg;
1025 struct Curl_easy *data = conn->data;
1026 PRErrorCode err = PR_GetError();
1027 CERTCertificate *cert;
1028
1029 /* remember the cert verification result */
1030 if(SSL_IS_PROXY())
1031 data->set.proxy_ssl.certverifyresult = err;
1032 else
1033 data->set.ssl.certverifyresult = err;
1034
1035 if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
1036 /* we are asked not to verify the host name */
1037 return SECSuccess;
1038
1039 /* print only info about the cert, the error is printed off the callback */
1040 cert = SSL_PeerCertificate(sock);
1041 if(cert) {
1042 infof(data, "Server certificate:\n");
1043 display_cert_info(data, cert);
1044 CERT_DestroyCertificate(cert);
1045 }
1046
1047 return SECFailure;
1048 }
1049
1050 /**
1051 *
1052 * Check that the Peer certificate's issuer certificate matches the one found
1053 * by issuer_nickname. This is not exactly the way OpenSSL and GNU TLS do the
1054 * issuer check, so we provide comments that mimic the OpenSSL
1055 * X509_check_issued function (in x509v3/v3_purp.c)
1056 */
check_issuer_cert(PRFileDesc * sock,char * issuer_nickname)1057 static SECStatus check_issuer_cert(PRFileDesc *sock,
1058 char *issuer_nickname)
1059 {
1060 CERTCertificate *cert, *cert_issuer, *issuer;
1061 SECStatus res = SECSuccess;
1062 void *proto_win = NULL;
1063
1064 cert = SSL_PeerCertificate(sock);
1065 cert_issuer = CERT_FindCertIssuer(cert, PR_Now(), certUsageObjectSigner);
1066
1067 proto_win = SSL_RevealPinArg(sock);
1068 issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
1069
1070 if((!cert_issuer) || (!issuer))
1071 res = SECFailure;
1072 else if(SECITEM_CompareItem(&cert_issuer->derCert,
1073 &issuer->derCert) != SECEqual)
1074 res = SECFailure;
1075
1076 CERT_DestroyCertificate(cert);
1077 CERT_DestroyCertificate(issuer);
1078 CERT_DestroyCertificate(cert_issuer);
1079 return res;
1080 }
1081
cmp_peer_pubkey(struct ssl_connect_data * connssl,const char * pinnedpubkey)1082 static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
1083 const char *pinnedpubkey)
1084 {
1085 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1086 struct ssl_backend_data *backend = connssl->backend;
1087 struct Curl_easy *data = backend->data;
1088 CERTCertificate *cert;
1089
1090 if(!pinnedpubkey)
1091 /* no pinned public key specified */
1092 return CURLE_OK;
1093
1094 /* get peer certificate */
1095 cert = SSL_PeerCertificate(backend->handle);
1096 if(cert) {
1097 /* extract public key from peer certificate */
1098 SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
1099 if(pubkey) {
1100 /* encode the public key as DER */
1101 SECItem *cert_der = PK11_DEREncodePublicKey(pubkey);
1102 if(cert_der) {
1103 /* compare the public key with the pinned public key */
1104 result = Curl_pin_peer_pubkey(data, pinnedpubkey, cert_der->data,
1105 cert_der->len);
1106 SECITEM_FreeItem(cert_der, PR_TRUE);
1107 }
1108 SECKEY_DestroyPublicKey(pubkey);
1109 }
1110 CERT_DestroyCertificate(cert);
1111 }
1112
1113 /* report the resulting status */
1114 switch(result) {
1115 case CURLE_OK:
1116 infof(data, "pinned public key verified successfully!\n");
1117 break;
1118 case CURLE_SSL_PINNEDPUBKEYNOTMATCH:
1119 failf(data, "failed to verify pinned public key");
1120 break;
1121 default:
1122 /* OOM, etc. */
1123 break;
1124 }
1125
1126 return result;
1127 }
1128
1129 /**
1130 *
1131 * Callback to pick the SSL client certificate.
1132 */
SelectClientCert(void * arg,PRFileDesc * sock,struct CERTDistNamesStr * caNames,struct CERTCertificateStr ** pRetCert,struct SECKEYPrivateKeyStr ** pRetKey)1133 static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
1134 struct CERTDistNamesStr *caNames,
1135 struct CERTCertificateStr **pRetCert,
1136 struct SECKEYPrivateKeyStr **pRetKey)
1137 {
1138 struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
1139 struct ssl_backend_data *backend = connssl->backend;
1140 struct Curl_easy *data = backend->data;
1141 const char *nickname = backend->client_nickname;
1142 static const char pem_slotname[] = "PEM Token #1";
1143
1144 if(backend->obj_clicert) {
1145 /* use the cert/key provided by PEM reader */
1146 SECItem cert_der = { 0, NULL, 0 };
1147 void *proto_win = SSL_RevealPinArg(sock);
1148 struct CERTCertificateStr *cert;
1149 struct SECKEYPrivateKeyStr *key;
1150
1151 PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
1152 if(NULL == slot) {
1153 failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
1154 return SECFailure;
1155 }
1156
1157 if(PK11_ReadRawAttribute(PK11_TypeGeneric, backend->obj_clicert, CKA_VALUE,
1158 &cert_der) != SECSuccess) {
1159 failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
1160 PK11_FreeSlot(slot);
1161 return SECFailure;
1162 }
1163
1164 cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
1165 SECITEM_FreeItem(&cert_der, PR_FALSE);
1166 if(NULL == cert) {
1167 failf(data, "NSS: client certificate from file not found");
1168 PK11_FreeSlot(slot);
1169 return SECFailure;
1170 }
1171
1172 key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
1173 PK11_FreeSlot(slot);
1174 if(NULL == key) {
1175 failf(data, "NSS: private key from file not found");
1176 CERT_DestroyCertificate(cert);
1177 return SECFailure;
1178 }
1179
1180 infof(data, "NSS: client certificate from file\n");
1181 display_cert_info(data, cert);
1182
1183 *pRetCert = cert;
1184 *pRetKey = key;
1185 return SECSuccess;
1186 }
1187
1188 /* use the default NSS hook */
1189 if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
1190 pRetCert, pRetKey)
1191 || NULL == *pRetCert) {
1192
1193 if(NULL == nickname)
1194 failf(data, "NSS: client certificate not found (nickname not "
1195 "specified)");
1196 else
1197 failf(data, "NSS: client certificate not found: %s", nickname);
1198
1199 return SECFailure;
1200 }
1201
1202 /* get certificate nickname if any */
1203 nickname = (*pRetCert)->nickname;
1204 if(NULL == nickname)
1205 nickname = "[unknown]";
1206
1207 if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) {
1208 failf(data, "NSS: refusing previously loaded certificate from file: %s",
1209 nickname);
1210 return SECFailure;
1211 }
1212
1213 if(NULL == *pRetKey) {
1214 failf(data, "NSS: private key not found for certificate: %s", nickname);
1215 return SECFailure;
1216 }
1217
1218 infof(data, "NSS: using client certificate: %s\n", nickname);
1219 display_cert_info(data, *pRetCert);
1220 return SECSuccess;
1221 }
1222
1223 /* update blocking direction in case of PR_WOULD_BLOCK_ERROR */
nss_update_connecting_state(ssl_connect_state state,void * secret)1224 static void nss_update_connecting_state(ssl_connect_state state, void *secret)
1225 {
1226 struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret;
1227 if(PR_GetError() != PR_WOULD_BLOCK_ERROR)
1228 /* an unrelated error is passing by */
1229 return;
1230
1231 switch(connssl->connecting_state) {
1232 case ssl_connect_2:
1233 case ssl_connect_2_reading:
1234 case ssl_connect_2_writing:
1235 break;
1236 default:
1237 /* we are not called from an SSL handshake */
1238 return;
1239 }
1240
1241 /* update the state accordingly */
1242 connssl->connecting_state = state;
1243 }
1244
1245 /* recv() wrapper we use to detect blocking direction during SSL handshake */
nspr_io_recv(PRFileDesc * fd,void * buf,PRInt32 amount,PRIntn flags,PRIntervalTime timeout)1246 static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount,
1247 PRIntn flags, PRIntervalTime timeout)
1248 {
1249 const PRRecvFN recv_fn = fd->lower->methods->recv;
1250 const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout);
1251 if(rv < 0)
1252 /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
1253 nss_update_connecting_state(ssl_connect_2_reading, fd->secret);
1254 return rv;
1255 }
1256
1257 /* send() wrapper we use to detect blocking direction during SSL handshake */
nspr_io_send(PRFileDesc * fd,const void * buf,PRInt32 amount,PRIntn flags,PRIntervalTime timeout)1258 static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
1259 PRIntn flags, PRIntervalTime timeout)
1260 {
1261 const PRSendFN send_fn = fd->lower->methods->send;
1262 const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout);
1263 if(rv < 0)
1264 /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */
1265 nss_update_connecting_state(ssl_connect_2_writing, fd->secret);
1266 return rv;
1267 }
1268
1269 /* close() wrapper to avoid assertion failure due to fd->secret != NULL */
nspr_io_close(PRFileDesc * fd)1270 static PRStatus nspr_io_close(PRFileDesc *fd)
1271 {
1272 const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close;
1273 fd->secret = NULL;
1274 return close_fn(fd);
1275 }
1276
1277 /* load a PKCS #11 module */
nss_load_module(SECMODModule ** pmod,const char * library,const char * name)1278 static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
1279 const char *name)
1280 {
1281 char *config_string;
1282 SECMODModule *module = *pmod;
1283 if(module)
1284 /* already loaded */
1285 return CURLE_OK;
1286
1287 config_string = aprintf("library=%s name=%s", library, name);
1288 if(!config_string)
1289 return CURLE_OUT_OF_MEMORY;
1290
1291 module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
1292 free(config_string);
1293
1294 if(module && module->loaded) {
1295 /* loaded successfully */
1296 *pmod = module;
1297 return CURLE_OK;
1298 }
1299
1300 if(module)
1301 SECMOD_DestroyModule(module);
1302 return CURLE_FAILED_INIT;
1303 }
1304
1305 /* unload a PKCS #11 module */
nss_unload_module(SECMODModule ** pmod)1306 static void nss_unload_module(SECMODModule **pmod)
1307 {
1308 SECMODModule *module = *pmod;
1309 if(!module)
1310 /* not loaded */
1311 return;
1312
1313 if(SECMOD_UnloadUserModule(module) != SECSuccess)
1314 /* unload failed */
1315 return;
1316
1317 SECMOD_DestroyModule(module);
1318 *pmod = NULL;
1319 }
1320
1321 /* data might be NULL */
nss_init_core(struct Curl_easy * data,const char * cert_dir)1322 static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
1323 {
1324 NSSInitParameters initparams;
1325 PRErrorCode err;
1326 const char *err_name;
1327
1328 if(nss_context != NULL)
1329 return CURLE_OK;
1330
1331 memset((void *) &initparams, '\0', sizeof(initparams));
1332 initparams.length = sizeof(initparams);
1333
1334 if(cert_dir) {
1335 char *certpath = aprintf("sql:%s", cert_dir);
1336 if(!certpath)
1337 return CURLE_OUT_OF_MEMORY;
1338
1339 infof(data, "Initializing NSS with certpath: %s\n", certpath);
1340 nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
1341 NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
1342 free(certpath);
1343
1344 if(nss_context != NULL)
1345 return CURLE_OK;
1346
1347 err = PR_GetError();
1348 err_name = nss_error_to_name(err);
1349 infof(data, "Unable to initialize NSS database: %d (%s)\n", err, err_name);
1350 }
1351
1352 infof(data, "Initializing NSS with certpath: none\n");
1353 nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
1354 | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN
1355 | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
1356 if(nss_context != NULL)
1357 return CURLE_OK;
1358
1359 err = PR_GetError();
1360 err_name = nss_error_to_name(err);
1361 failf(data, "Unable to initialize NSS: %d (%s)", err, err_name);
1362 return CURLE_SSL_CACERT_BADFILE;
1363 }
1364
1365 /* data might be NULL */
nss_init(struct Curl_easy * data)1366 static CURLcode nss_init(struct Curl_easy *data)
1367 {
1368 char *cert_dir;
1369 struct_stat st;
1370 CURLcode result;
1371
1372 if(initialized)
1373 return CURLE_OK;
1374
1375 /* list of all CRL items we need to destroy in Curl_nss_cleanup() */
1376 Curl_llist_init(&nss_crl_list, nss_destroy_crl_item);
1377
1378 /* First we check if $SSL_DIR points to a valid dir */
1379 cert_dir = getenv("SSL_DIR");
1380 if(cert_dir) {
1381 if((stat(cert_dir, &st) != 0) ||
1382 (!S_ISDIR(st.st_mode))) {
1383 cert_dir = NULL;
1384 }
1385 }
1386
1387 /* Now we check if the default location is a valid dir */
1388 if(!cert_dir) {
1389 if((stat(SSL_DIR, &st) == 0) &&
1390 (S_ISDIR(st.st_mode))) {
1391 cert_dir = (char *)SSL_DIR;
1392 }
1393 }
1394
1395 if(nspr_io_identity == PR_INVALID_IO_LAYER) {
1396 /* allocate an identity for our own NSPR I/O layer */
1397 nspr_io_identity = PR_GetUniqueIdentity("libcurl");
1398 if(nspr_io_identity == PR_INVALID_IO_LAYER)
1399 return CURLE_OUT_OF_MEMORY;
1400
1401 /* the default methods just call down to the lower I/O layer */
1402 memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
1403 sizeof(nspr_io_methods));
1404
1405 /* override certain methods in the table by our wrappers */
1406 nspr_io_methods.recv = nspr_io_recv;
1407 nspr_io_methods.send = nspr_io_send;
1408 nspr_io_methods.close = nspr_io_close;
1409 }
1410
1411 result = nss_init_core(data, cert_dir);
1412 if(result)
1413 return result;
1414
1415 if(!any_cipher_enabled())
1416 NSS_SetDomesticPolicy();
1417
1418 initialized = 1;
1419
1420 return CURLE_OK;
1421 }
1422
1423 /**
1424 * Global SSL init
1425 *
1426 * @retval 0 error initializing SSL
1427 * @retval 1 SSL initialized successfully
1428 */
Curl_nss_init(void)1429 static int Curl_nss_init(void)
1430 {
1431 /* curl_global_init() is not thread-safe so this test is ok */
1432 if(nss_initlock == NULL) {
1433 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
1434 nss_initlock = PR_NewLock();
1435 nss_crllock = PR_NewLock();
1436 nss_findslot_lock = PR_NewLock();
1437 nss_trustload_lock = PR_NewLock();
1438 }
1439
1440 /* We will actually initialize NSS later */
1441
1442 return 1;
1443 }
1444
1445 /* data might be NULL */
Curl_nss_force_init(struct Curl_easy * data)1446 CURLcode Curl_nss_force_init(struct Curl_easy *data)
1447 {
1448 CURLcode result;
1449 if(!nss_initlock) {
1450 if(data)
1451 failf(data, "unable to initialize NSS, curl_global_init() should have "
1452 "been called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
1453 return CURLE_FAILED_INIT;
1454 }
1455
1456 PR_Lock(nss_initlock);
1457 result = nss_init(data);
1458 PR_Unlock(nss_initlock);
1459
1460 return result;
1461 }
1462
1463 /* Global cleanup */
Curl_nss_cleanup(void)1464 static void Curl_nss_cleanup(void)
1465 {
1466 /* This function isn't required to be threadsafe and this is only done
1467 * as a safety feature.
1468 */
1469 PR_Lock(nss_initlock);
1470 if(initialized) {
1471 /* Free references to client certificates held in the SSL session cache.
1472 * Omitting this hampers destruction of the security module owning
1473 * the certificates. */
1474 SSL_ClearSessionCache();
1475
1476 nss_unload_module(&pem_module);
1477 nss_unload_module(&trust_module);
1478 NSS_ShutdownContext(nss_context);
1479 nss_context = NULL;
1480 }
1481
1482 /* destroy all CRL items */
1483 Curl_llist_destroy(&nss_crl_list, NULL);
1484
1485 PR_Unlock(nss_initlock);
1486
1487 PR_DestroyLock(nss_initlock);
1488 PR_DestroyLock(nss_crllock);
1489 PR_DestroyLock(nss_findslot_lock);
1490 PR_DestroyLock(nss_trustload_lock);
1491 nss_initlock = NULL;
1492
1493 initialized = 0;
1494 }
1495
1496 /*
1497 * This function uses SSL_peek to determine connection status.
1498 *
1499 * Return codes:
1500 * 1 means the connection is still in place
1501 * 0 means the connection has been closed
1502 * -1 means the connection status is unknown
1503 */
Curl_nss_check_cxn(struct connectdata * conn)1504 static int Curl_nss_check_cxn(struct connectdata *conn)
1505 {
1506 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
1507 struct ssl_backend_data *backend = connssl->backend;
1508 int rc;
1509 char buf;
1510
1511 rc =
1512 PR_Recv(backend->handle, (void *)&buf, 1, PR_MSG_PEEK,
1513 PR_SecondsToInterval(1));
1514 if(rc > 0)
1515 return 1; /* connection still in place */
1516
1517 if(rc == 0)
1518 return 0; /* connection has been closed */
1519
1520 return -1; /* connection status unknown */
1521 }
1522
nss_close(struct ssl_connect_data * connssl)1523 static void nss_close(struct ssl_connect_data *connssl)
1524 {
1525 /* before the cleanup, check whether we are using a client certificate */
1526 struct ssl_backend_data *backend = connssl->backend;
1527 const bool client_cert = (backend->client_nickname != NULL)
1528 || (backend->obj_clicert != NULL);
1529
1530 free(backend->client_nickname);
1531 backend->client_nickname = NULL;
1532
1533 /* destroy all NSS objects in order to avoid failure of NSS shutdown */
1534 Curl_llist_destroy(&backend->obj_list, NULL);
1535 backend->obj_clicert = NULL;
1536
1537 if(backend->handle) {
1538 if(client_cert)
1539 /* A server might require different authentication based on the
1540 * particular path being requested by the client. To support this
1541 * scenario, we must ensure that a connection will never reuse the
1542 * authentication data from a previous connection. */
1543 SSL_InvalidateSession(backend->handle);
1544
1545 PR_Close(backend->handle);
1546 backend->handle = NULL;
1547 }
1548 }
1549
1550 /*
1551 * This function is called when an SSL connection is closed.
1552 */
Curl_nss_close(struct connectdata * conn,int sockindex)1553 static void Curl_nss_close(struct connectdata *conn, int sockindex)
1554 {
1555 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1556 struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
1557 struct ssl_backend_data *backend = connssl->backend;
1558
1559 if(backend->handle || connssl_proxy->backend->handle) {
1560 /* NSS closes the socket we previously handed to it, so we must mark it
1561 as closed to avoid double close */
1562 fake_sclose(conn->sock[sockindex]);
1563 conn->sock[sockindex] = CURL_SOCKET_BAD;
1564 }
1565
1566 if(backend->handle)
1567 /* nss_close(connssl) will transitively close also
1568 connssl_proxy->backend->handle if both are used. Clear it to avoid
1569 a double close leading to crash. */
1570 connssl_proxy->backend->handle = NULL;
1571
1572 nss_close(connssl);
1573 nss_close(connssl_proxy);
1574 }
1575
1576 /* return true if NSS can provide error code (and possibly msg) for the
1577 error */
is_nss_error(CURLcode err)1578 static bool is_nss_error(CURLcode err)
1579 {
1580 switch(err) {
1581 case CURLE_PEER_FAILED_VERIFICATION:
1582 case CURLE_SSL_CERTPROBLEM:
1583 case CURLE_SSL_CONNECT_ERROR:
1584 case CURLE_SSL_ISSUER_ERROR:
1585 return true;
1586
1587 default:
1588 return false;
1589 }
1590 }
1591
1592 /* return true if the given error code is related to a client certificate */
is_cc_error(PRInt32 err)1593 static bool is_cc_error(PRInt32 err)
1594 {
1595 switch(err) {
1596 case SSL_ERROR_BAD_CERT_ALERT:
1597 case SSL_ERROR_EXPIRED_CERT_ALERT:
1598 case SSL_ERROR_REVOKED_CERT_ALERT:
1599 return true;
1600
1601 default:
1602 return false;
1603 }
1604 }
1605
1606 static Curl_recv nss_recv;
1607 static Curl_send nss_send;
1608
nss_load_ca_certificates(struct connectdata * conn,int sockindex)1609 static CURLcode nss_load_ca_certificates(struct connectdata *conn,
1610 int sockindex)
1611 {
1612 struct Curl_easy *data = conn->data;
1613 const char *cafile = SSL_CONN_CONFIG(CAfile);
1614 const char *capath = SSL_CONN_CONFIG(CApath);
1615 bool use_trust_module;
1616 CURLcode result = CURLE_OK;
1617
1618 /* treat empty string as unset */
1619 if(cafile && !cafile[0])
1620 cafile = NULL;
1621 if(capath && !capath[0])
1622 capath = NULL;
1623
1624 infof(data, " CAfile: %s\n CApath: %s\n",
1625 cafile ? cafile : "none",
1626 capath ? capath : "none");
1627
1628 /* load libnssckbi.so if no other trust roots were specified */
1629 use_trust_module = !cafile && !capath;
1630
1631 PR_Lock(nss_trustload_lock);
1632 if(use_trust_module && !trust_module) {
1633 /* libnssckbi.so needed but not yet loaded --> load it! */
1634 result = nss_load_module(&trust_module, trust_library, "trust");
1635 infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
1636 trust_library);
1637 if(result == CURLE_FAILED_INIT)
1638 /* If libnssckbi.so is not available (or fails to load), one can still
1639 use CA certificates stored in NSS database. Ignore the failure. */
1640 result = CURLE_OK;
1641 }
1642 else if(!use_trust_module && trust_module) {
1643 /* libnssckbi.so not needed but already loaded --> unload it! */
1644 infof(data, "unloading %s\n", trust_library);
1645 nss_unload_module(&trust_module);
1646 }
1647 PR_Unlock(nss_trustload_lock);
1648
1649 if(cafile)
1650 result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
1651
1652 if(result)
1653 return result;
1654
1655 if(capath) {
1656 struct_stat st;
1657 if(stat(capath, &st) == -1)
1658 return CURLE_SSL_CACERT_BADFILE;
1659
1660 if(S_ISDIR(st.st_mode)) {
1661 PRDirEntry *entry;
1662 PRDir *dir = PR_OpenDir(capath);
1663 if(!dir)
1664 return CURLE_SSL_CACERT_BADFILE;
1665
1666 while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
1667 char *fullpath = aprintf("%s/%s", capath, entry->name);
1668 if(!fullpath) {
1669 PR_CloseDir(dir);
1670 return CURLE_OUT_OF_MEMORY;
1671 }
1672
1673 if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
1674 /* This is purposefully tolerant of errors so non-PEM files can
1675 * be in the same directory */
1676 infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
1677
1678 free(fullpath);
1679 }
1680
1681 PR_CloseDir(dir);
1682 }
1683 else
1684 infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
1685 }
1686
1687 return CURLE_OK;
1688 }
1689
nss_sslver_from_curl(PRUint16 * nssver,long version)1690 static CURLcode nss_sslver_from_curl(PRUint16 *nssver, long version)
1691 {
1692 switch(version) {
1693 case CURL_SSLVERSION_SSLv2:
1694 *nssver = SSL_LIBRARY_VERSION_2;
1695 return CURLE_OK;
1696
1697 case CURL_SSLVERSION_SSLv3:
1698 *nssver = SSL_LIBRARY_VERSION_3_0;
1699 return CURLE_OK;
1700
1701 case CURL_SSLVERSION_TLSv1_0:
1702 *nssver = SSL_LIBRARY_VERSION_TLS_1_0;
1703 return CURLE_OK;
1704
1705 case CURL_SSLVERSION_TLSv1_1:
1706 #ifdef SSL_LIBRARY_VERSION_TLS_1_1
1707 *nssver = SSL_LIBRARY_VERSION_TLS_1_1;
1708 return CURLE_OK;
1709 #else
1710 return CURLE_SSL_CONNECT_ERROR;
1711 #endif
1712
1713 case CURL_SSLVERSION_TLSv1_2:
1714 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
1715 *nssver = SSL_LIBRARY_VERSION_TLS_1_2;
1716 return CURLE_OK;
1717 #else
1718 return CURLE_SSL_CONNECT_ERROR;
1719 #endif
1720
1721 case CURL_SSLVERSION_TLSv1_3:
1722 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
1723 *nssver = SSL_LIBRARY_VERSION_TLS_1_3;
1724 return CURLE_OK;
1725 #else
1726 return CURLE_SSL_CONNECT_ERROR;
1727 #endif
1728
1729 default:
1730 return CURLE_SSL_CONNECT_ERROR;
1731 }
1732 }
1733
nss_init_sslver(SSLVersionRange * sslver,struct Curl_easy * data,struct connectdata * conn)1734 static CURLcode nss_init_sslver(SSLVersionRange *sslver,
1735 struct Curl_easy *data,
1736 struct connectdata *conn)
1737 {
1738 CURLcode result;
1739 const long min = SSL_CONN_CONFIG(version);
1740 const long max = SSL_CONN_CONFIG(version_max);
1741 SSLVersionRange vrange;
1742
1743 switch(min) {
1744 case CURL_SSLVERSION_TLSv1:
1745 case CURL_SSLVERSION_DEFAULT:
1746 /* Bump our minimum TLS version if NSS has stricter requirements. */
1747 if(SSL_VersionRangeGetDefault(ssl_variant_stream, &vrange) != SECSuccess)
1748 return CURLE_SSL_CONNECT_ERROR;
1749 if(sslver->min < vrange.min)
1750 sslver->min = vrange.min;
1751 break;
1752 default:
1753 result = nss_sslver_from_curl(&sslver->min, min);
1754 if(result) {
1755 failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
1756 return result;
1757 }
1758 }
1759
1760 switch(max) {
1761 case CURL_SSLVERSION_MAX_NONE:
1762 case CURL_SSLVERSION_MAX_DEFAULT:
1763 break;
1764 default:
1765 result = nss_sslver_from_curl(&sslver->max, max >> 16);
1766 if(result) {
1767 failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
1768 return result;
1769 }
1770 }
1771
1772 return CURLE_OK;
1773 }
1774
nss_fail_connect(struct ssl_connect_data * connssl,struct Curl_easy * data,CURLcode curlerr)1775 static CURLcode nss_fail_connect(struct ssl_connect_data *connssl,
1776 struct Curl_easy *data,
1777 CURLcode curlerr)
1778 {
1779 PRErrorCode err = 0;
1780 struct ssl_backend_data *backend = connssl->backend;
1781
1782 if(is_nss_error(curlerr)) {
1783 /* read NSPR error code */
1784 err = PR_GetError();
1785 if(is_cc_error(err))
1786 curlerr = CURLE_SSL_CERTPROBLEM;
1787
1788 /* print the error number and error string */
1789 infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
1790
1791 /* print a human-readable message describing the error if available */
1792 nss_print_error_message(data, err);
1793 }
1794
1795 /* cleanup on connection failure */
1796 Curl_llist_destroy(&backend->obj_list, NULL);
1797
1798 return curlerr;
1799 }
1800
1801 /* Switch the SSL socket into blocking or non-blocking mode. */
nss_set_blocking(struct ssl_connect_data * connssl,struct Curl_easy * data,bool blocking)1802 static CURLcode nss_set_blocking(struct ssl_connect_data *connssl,
1803 struct Curl_easy *data,
1804 bool blocking)
1805 {
1806 static PRSocketOptionData sock_opt;
1807 struct ssl_backend_data *backend = connssl->backend;
1808 sock_opt.option = PR_SockOpt_Nonblocking;
1809 sock_opt.value.non_blocking = !blocking;
1810
1811 if(PR_SetSocketOption(backend->handle, &sock_opt) != PR_SUCCESS)
1812 return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
1813
1814 return CURLE_OK;
1815 }
1816
nss_setup_connect(struct connectdata * conn,int sockindex)1817 static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
1818 {
1819 PRFileDesc *model = NULL;
1820 PRFileDesc *nspr_io = NULL;
1821 PRFileDesc *nspr_io_stub = NULL;
1822 PRBool ssl_no_cache;
1823 PRBool ssl_cbc_random_iv;
1824 struct Curl_easy *data = conn->data;
1825 curl_socket_t sockfd = conn->sock[sockindex];
1826 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1827 struct ssl_backend_data *backend = connssl->backend;
1828 CURLcode result;
1829 bool second_layer = FALSE;
1830 SSLVersionRange sslver_supported;
1831
1832 SSLVersionRange sslver = {
1833 SSL_LIBRARY_VERSION_TLS_1_0, /* min */
1834 #ifdef SSL_LIBRARY_VERSION_TLS_1_3
1835 SSL_LIBRARY_VERSION_TLS_1_3 /* max */
1836 #elif defined SSL_LIBRARY_VERSION_TLS_1_2
1837 SSL_LIBRARY_VERSION_TLS_1_2
1838 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
1839 SSL_LIBRARY_VERSION_TLS_1_1
1840 #else
1841 SSL_LIBRARY_VERSION_TLS_1_0
1842 #endif
1843 };
1844
1845 backend->data = data;
1846
1847 /* list of all NSS objects we need to destroy in Curl_nss_close() */
1848 Curl_llist_init(&backend->obj_list, nss_destroy_object);
1849
1850 PR_Lock(nss_initlock);
1851 result = nss_init(conn->data);
1852 if(result) {
1853 PR_Unlock(nss_initlock);
1854 goto error;
1855 }
1856
1857 PK11_SetPasswordFunc(nss_get_password);
1858
1859 result = nss_load_module(&pem_module, pem_library, "PEM");
1860 PR_Unlock(nss_initlock);
1861 if(result == CURLE_FAILED_INIT)
1862 infof(data, "WARNING: failed to load NSS PEM library %s. Using "
1863 "OpenSSL PEM certificates will not work.\n", pem_library);
1864 else if(result)
1865 goto error;
1866
1867 result = CURLE_SSL_CONNECT_ERROR;
1868
1869 model = PR_NewTCPSocket();
1870 if(!model)
1871 goto error;
1872 model = SSL_ImportFD(NULL, model);
1873
1874 if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
1875 goto error;
1876 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
1877 goto error;
1878 if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
1879 goto error;
1880
1881 /* do not use SSL cache if disabled or we are not going to verify peer */
1882 ssl_no_cache = (SSL_SET_OPTION(primary.sessionid)
1883 && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
1884 if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
1885 goto error;
1886
1887 /* enable/disable the requested SSL version(s) */
1888 if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
1889 goto error;
1890 if(SSL_VersionRangeGetSupported(ssl_variant_stream,
1891 &sslver_supported) != SECSuccess)
1892 goto error;
1893 if(sslver_supported.max < sslver.max && sslver_supported.max >= sslver.min) {
1894 char *sslver_req_str, *sslver_supp_str;
1895 sslver_req_str = nss_sslver_to_name(sslver.max);
1896 sslver_supp_str = nss_sslver_to_name(sslver_supported.max);
1897 if(sslver_req_str && sslver_supp_str)
1898 infof(data, "Falling back from %s to max supported SSL version (%s)\n",
1899 sslver_req_str, sslver_supp_str);
1900 free(sslver_req_str);
1901 free(sslver_supp_str);
1902 sslver.max = sslver_supported.max;
1903 }
1904 if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
1905 goto error;
1906
1907 ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
1908 #ifdef SSL_CBC_RANDOM_IV
1909 /* unless the user explicitly asks to allow the protocol vulnerability, we
1910 use the work-around */
1911 if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
1912 infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
1913 ssl_cbc_random_iv);
1914 #else
1915 if(ssl_cbc_random_iv)
1916 infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
1917 #endif
1918
1919 if(SSL_CONN_CONFIG(cipher_list)) {
1920 if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
1921 result = CURLE_SSL_CIPHER;
1922 goto error;
1923 }
1924 }
1925
1926 if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
1927 infof(data, "warning: ignoring value of ssl.verifyhost\n");
1928
1929 /* bypass the default SSL_AuthCertificate() hook in case we do not want to
1930 * verify peer */
1931 if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
1932 goto error;
1933
1934 /* not checked yet */
1935 if(SSL_IS_PROXY())
1936 data->set.proxy_ssl.certverifyresult = 0;
1937 else
1938 data->set.ssl.certverifyresult = 0;
1939
1940 if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
1941 goto error;
1942
1943 if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
1944 goto error;
1945
1946 {
1947 const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
1948 if((rv == CURLE_SSL_CACERT_BADFILE) && !SSL_CONN_CONFIG(verifypeer))
1949 /* not a fatal error because we are not going to verify the peer */
1950 infof(data, "warning: CA certificates failed to load\n");
1951 else if(rv) {
1952 result = rv;
1953 goto error;
1954 }
1955 }
1956
1957 if(SSL_SET_OPTION(CRLfile)) {
1958 const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
1959 if(rv) {
1960 result = rv;
1961 goto error;
1962 }
1963 infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
1964 }
1965
1966 if(SSL_SET_OPTION(cert)) {
1967 char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
1968 if(nickname) {
1969 /* we are not going to use libnsspem.so to read the client cert */
1970 backend->obj_clicert = NULL;
1971 }
1972 else {
1973 CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
1974 SSL_SET_OPTION(key));
1975 if(rv) {
1976 /* failf() is already done in cert_stuff() */
1977 result = rv;
1978 goto error;
1979 }
1980 }
1981
1982 /* store the nickname for SelectClientCert() called during handshake */
1983 backend->client_nickname = nickname;
1984 }
1985 else
1986 backend->client_nickname = NULL;
1987
1988 if(SSL_GetClientAuthDataHook(model, SelectClientCert,
1989 (void *)connssl) != SECSuccess) {
1990 result = CURLE_SSL_CERTPROBLEM;
1991 goto error;
1992 }
1993
1994 if(conn->proxy_ssl[sockindex].use) {
1995 DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
1996 DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
1997 nspr_io = conn->proxy_ssl[sockindex].backend->handle;
1998 second_layer = TRUE;
1999 }
2000 else {
2001 /* wrap OS file descriptor by NSPR's file descriptor abstraction */
2002 nspr_io = PR_ImportTCPSocket(sockfd);
2003 if(!nspr_io)
2004 goto error;
2005 }
2006
2007 /* create our own NSPR I/O layer */
2008 nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
2009 if(!nspr_io_stub) {
2010 if(!second_layer)
2011 PR_Close(nspr_io);
2012 goto error;
2013 }
2014
2015 /* make the per-connection data accessible from NSPR I/O callbacks */
2016 nspr_io_stub->secret = (void *)connssl;
2017
2018 /* push our new layer to the NSPR I/O stack */
2019 if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
2020 if(!second_layer)
2021 PR_Close(nspr_io);
2022 PR_Close(nspr_io_stub);
2023 goto error;
2024 }
2025
2026 /* import our model socket onto the current I/O stack */
2027 backend->handle = SSL_ImportFD(model, nspr_io);
2028 if(!backend->handle) {
2029 if(!second_layer)
2030 PR_Close(nspr_io);
2031 goto error;
2032 }
2033
2034 PR_Close(model); /* We don't need this any more */
2035 model = NULL;
2036
2037 /* This is the password associated with the cert that we're using */
2038 if(SSL_SET_OPTION(key_passwd)) {
2039 SSL_SetPKCS11PinArg(backend->handle, SSL_SET_OPTION(key_passwd));
2040 }
2041
2042 #ifdef SSL_ENABLE_OCSP_STAPLING
2043 if(SSL_CONN_CONFIG(verifystatus)) {
2044 if(SSL_OptionSet(backend->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
2045 != SECSuccess)
2046 goto error;
2047 }
2048 #endif
2049
2050 #ifdef SSL_ENABLE_NPN
2051 if(SSL_OptionSet(backend->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
2052 ? PR_TRUE : PR_FALSE) != SECSuccess)
2053 goto error;
2054 #endif
2055
2056 #ifdef SSL_ENABLE_ALPN
2057 if(SSL_OptionSet(backend->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
2058 ? PR_TRUE : PR_FALSE) != SECSuccess)
2059 goto error;
2060 #endif
2061
2062 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
2063 if(data->set.ssl.falsestart) {
2064 if(SSL_OptionSet(backend->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
2065 != SECSuccess)
2066 goto error;
2067
2068 if(SSL_SetCanFalseStartCallback(backend->handle, CanFalseStartCallback,
2069 conn) != SECSuccess)
2070 goto error;
2071 }
2072 #endif
2073
2074 #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
2075 if(conn->bits.tls_enable_npn || conn->bits.tls_enable_alpn) {
2076 int cur = 0;
2077 unsigned char protocols[128];
2078
2079 #ifdef USE_NGHTTP2
2080 if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
2081 (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
2082 protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
2083 memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
2084 NGHTTP2_PROTO_VERSION_ID_LEN);
2085 cur += NGHTTP2_PROTO_VERSION_ID_LEN;
2086 }
2087 #endif
2088 protocols[cur++] = ALPN_HTTP_1_1_LENGTH;
2089 memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
2090 cur += ALPN_HTTP_1_1_LENGTH;
2091
2092 if(SSL_SetNextProtoNego(backend->handle, protocols, cur) != SECSuccess)
2093 goto error;
2094 }
2095 #endif
2096
2097
2098 /* Force handshake on next I/O */
2099 if(SSL_ResetHandshake(backend->handle, /* asServer */ PR_FALSE)
2100 != SECSuccess)
2101 goto error;
2102
2103 /* propagate hostname to the TLS layer */
2104 if(SSL_SetURL(backend->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
2105 conn->host.name) != SECSuccess)
2106 goto error;
2107
2108 /* prevent NSS from re-using the session for a different hostname */
2109 if(SSL_SetSockPeerID(backend->handle, SSL_IS_PROXY() ?
2110 conn->http_proxy.host.name : conn->host.name)
2111 != SECSuccess)
2112 goto error;
2113
2114 return CURLE_OK;
2115
2116 error:
2117 if(model)
2118 PR_Close(model);
2119
2120 return nss_fail_connect(connssl, data, result);
2121 }
2122
nss_do_connect(struct connectdata * conn,int sockindex)2123 static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
2124 {
2125 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2126 struct ssl_backend_data *backend = connssl->backend;
2127 struct Curl_easy *data = conn->data;
2128 CURLcode result = CURLE_SSL_CONNECT_ERROR;
2129 PRUint32 timeout;
2130 long * const certverifyresult = SSL_IS_PROXY() ?
2131 &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
2132 const char * const pinnedpubkey = SSL_IS_PROXY() ?
2133 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
2134 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
2135
2136
2137 /* check timeout situation */
2138 const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
2139 if(time_left < 0) {
2140 failf(data, "timed out before SSL handshake");
2141 result = CURLE_OPERATION_TIMEDOUT;
2142 goto error;
2143 }
2144
2145 /* Force the handshake now */
2146 timeout = PR_MillisecondsToInterval((PRUint32) time_left);
2147 if(SSL_ForceHandshakeWithTimeout(backend->handle, timeout) != SECSuccess) {
2148 if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
2149 /* blocking direction is updated by nss_update_connecting_state() */
2150 return CURLE_AGAIN;
2151 else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
2152 result = CURLE_PEER_FAILED_VERIFICATION;
2153 else if(*certverifyresult != 0)
2154 result = CURLE_PEER_FAILED_VERIFICATION;
2155 goto error;
2156 }
2157
2158 result = display_conn_info(conn, backend->handle);
2159 if(result)
2160 goto error;
2161
2162 if(SSL_SET_OPTION(issuercert)) {
2163 SECStatus ret = SECFailure;
2164 char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
2165 if(nickname) {
2166 /* we support only nicknames in case of issuercert for now */
2167 ret = check_issuer_cert(backend->handle, nickname);
2168 free(nickname);
2169 }
2170
2171 if(SECFailure == ret) {
2172 infof(data, "SSL certificate issuer check failed\n");
2173 result = CURLE_SSL_ISSUER_ERROR;
2174 goto error;
2175 }
2176 else {
2177 infof(data, "SSL certificate issuer check ok\n");
2178 }
2179 }
2180
2181 result = cmp_peer_pubkey(connssl, pinnedpubkey);
2182 if(result)
2183 /* status already printed */
2184 goto error;
2185
2186 return CURLE_OK;
2187
2188 error:
2189 return nss_fail_connect(connssl, data, result);
2190 }
2191
nss_connect_common(struct connectdata * conn,int sockindex,bool * done)2192 static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
2193 bool *done)
2194 {
2195 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2196 struct Curl_easy *data = conn->data;
2197 const bool blocking = (done == NULL);
2198 CURLcode result;
2199
2200 if(connssl->state == ssl_connection_complete) {
2201 if(!blocking)
2202 *done = TRUE;
2203 return CURLE_OK;
2204 }
2205
2206 if(connssl->connecting_state == ssl_connect_1) {
2207 result = nss_setup_connect(conn, sockindex);
2208 if(result)
2209 /* we do not expect CURLE_AGAIN from nss_setup_connect() */
2210 return result;
2211
2212 connssl->connecting_state = ssl_connect_2;
2213 }
2214
2215 /* enable/disable blocking mode before handshake */
2216 result = nss_set_blocking(connssl, data, blocking);
2217 if(result)
2218 return result;
2219
2220 result = nss_do_connect(conn, sockindex);
2221 switch(result) {
2222 case CURLE_OK:
2223 break;
2224 case CURLE_AGAIN:
2225 if(!blocking)
2226 /* CURLE_AGAIN in non-blocking mode is not an error */
2227 return CURLE_OK;
2228 /* FALLTHROUGH */
2229 default:
2230 return result;
2231 }
2232
2233 if(blocking) {
2234 /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */
2235 result = nss_set_blocking(connssl, data, /* blocking */ FALSE);
2236 if(result)
2237 return result;
2238 }
2239 else
2240 /* signal completed SSL handshake */
2241 *done = TRUE;
2242
2243 connssl->state = ssl_connection_complete;
2244 conn->recv[sockindex] = nss_recv;
2245 conn->send[sockindex] = nss_send;
2246
2247 /* ssl_connect_done is never used outside, go back to the initial state */
2248 connssl->connecting_state = ssl_connect_1;
2249
2250 return CURLE_OK;
2251 }
2252
Curl_nss_connect(struct connectdata * conn,int sockindex)2253 static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
2254 {
2255 return nss_connect_common(conn, sockindex, /* blocking */ NULL);
2256 }
2257
Curl_nss_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)2258 static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
2259 int sockindex, bool *done)
2260 {
2261 return nss_connect_common(conn, sockindex, done);
2262 }
2263
nss_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)2264 static ssize_t nss_send(struct connectdata *conn, /* connection data */
2265 int sockindex, /* socketindex */
2266 const void *mem, /* send this data */
2267 size_t len, /* amount to write */
2268 CURLcode *curlcode)
2269 {
2270 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2271 struct ssl_backend_data *backend = connssl->backend;
2272 ssize_t rc;
2273
2274 /* The SelectClientCert() hook uses this for infof() and failf() but the
2275 handle stored in nss_setup_connect() could have already been freed. */
2276 backend->data = conn->data;
2277
2278 rc = PR_Send(backend->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
2279 if(rc < 0) {
2280 PRInt32 err = PR_GetError();
2281 if(err == PR_WOULD_BLOCK_ERROR)
2282 *curlcode = CURLE_AGAIN;
2283 else {
2284 /* print the error number and error string */
2285 const char *err_name = nss_error_to_name(err);
2286 infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
2287
2288 /* print a human-readable message describing the error if available */
2289 nss_print_error_message(conn->data, err);
2290
2291 *curlcode = (is_cc_error(err))
2292 ? CURLE_SSL_CERTPROBLEM
2293 : CURLE_SEND_ERROR;
2294 }
2295
2296 return -1;
2297 }
2298
2299 return rc; /* number of bytes */
2300 }
2301
nss_recv(struct connectdata * conn,int sockindex,char * buf,size_t buffersize,CURLcode * curlcode)2302 static ssize_t nss_recv(struct connectdata *conn, /* connection data */
2303 int sockindex, /* socketindex */
2304 char *buf, /* store read data here */
2305 size_t buffersize, /* max amount to read */
2306 CURLcode *curlcode)
2307 {
2308 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2309 struct ssl_backend_data *backend = connssl->backend;
2310 ssize_t nread;
2311
2312 /* The SelectClientCert() hook uses this for infof() and failf() but the
2313 handle stored in nss_setup_connect() could have already been freed. */
2314 backend->data = conn->data;
2315
2316 nread = PR_Recv(backend->handle, buf, (int)buffersize, 0,
2317 PR_INTERVAL_NO_WAIT);
2318 if(nread < 0) {
2319 /* failed SSL read */
2320 PRInt32 err = PR_GetError();
2321
2322 if(err == PR_WOULD_BLOCK_ERROR)
2323 *curlcode = CURLE_AGAIN;
2324 else {
2325 /* print the error number and error string */
2326 const char *err_name = nss_error_to_name(err);
2327 infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
2328
2329 /* print a human-readable message describing the error if available */
2330 nss_print_error_message(conn->data, err);
2331
2332 *curlcode = (is_cc_error(err))
2333 ? CURLE_SSL_CERTPROBLEM
2334 : CURLE_RECV_ERROR;
2335 }
2336
2337 return -1;
2338 }
2339
2340 return nread;
2341 }
2342
Curl_nss_version(char * buffer,size_t size)2343 static size_t Curl_nss_version(char *buffer, size_t size)
2344 {
2345 return msnprintf(buffer, size, "NSS/%s", NSS_VERSION);
2346 }
2347
2348 /* data might be NULL */
Curl_nss_seed(struct Curl_easy * data)2349 static int Curl_nss_seed(struct Curl_easy *data)
2350 {
2351 /* make sure that NSS is initialized */
2352 return !!Curl_nss_force_init(data);
2353 }
2354
2355 /* data might be NULL */
Curl_nss_random(struct Curl_easy * data,unsigned char * entropy,size_t length)2356 static CURLcode Curl_nss_random(struct Curl_easy *data,
2357 unsigned char *entropy,
2358 size_t length)
2359 {
2360 Curl_nss_seed(data); /* Initiate the seed if not already done */
2361
2362 if(SECSuccess != PK11_GenerateRandom(entropy, curlx_uztosi(length)))
2363 /* signal a failure */
2364 return CURLE_FAILED_INIT;
2365
2366 return CURLE_OK;
2367 }
2368
Curl_nss_md5sum(unsigned char * tmp,size_t tmplen,unsigned char * md5sum,size_t md5len)2369 static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
2370 size_t tmplen,
2371 unsigned char *md5sum, /* output */
2372 size_t md5len)
2373 {
2374 PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
2375 unsigned int MD5out;
2376
2377 if(!MD5pw)
2378 return CURLE_NOT_BUILT_IN;
2379
2380 PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
2381 PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
2382 PK11_DestroyContext(MD5pw, PR_TRUE);
2383
2384 return CURLE_OK;
2385 }
2386
Curl_nss_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)2387 static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
2388 size_t tmplen,
2389 unsigned char *sha256sum, /* output */
2390 size_t sha256len)
2391 {
2392 PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
2393 unsigned int SHA256out;
2394
2395 if(!SHA256pw)
2396 return CURLE_NOT_BUILT_IN;
2397
2398 PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
2399 PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
2400 PK11_DestroyContext(SHA256pw, PR_TRUE);
2401
2402 return CURLE_OK;
2403 }
2404
Curl_nss_cert_status_request(void)2405 static bool Curl_nss_cert_status_request(void)
2406 {
2407 #ifdef SSL_ENABLE_OCSP_STAPLING
2408 return TRUE;
2409 #else
2410 return FALSE;
2411 #endif
2412 }
2413
Curl_nss_false_start(void)2414 static bool Curl_nss_false_start(void)
2415 {
2416 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
2417 return TRUE;
2418 #else
2419 return FALSE;
2420 #endif
2421 }
2422
Curl_nss_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2423 static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
2424 CURLINFO info UNUSED_PARAM)
2425 {
2426 struct ssl_backend_data *backend = connssl->backend;
2427 (void)info;
2428 return backend->handle;
2429 }
2430
2431 const struct Curl_ssl Curl_ssl_nss = {
2432 { CURLSSLBACKEND_NSS, "nss" }, /* info */
2433
2434 SSLSUPP_CA_PATH |
2435 SSLSUPP_CERTINFO |
2436 SSLSUPP_PINNEDPUBKEY |
2437 SSLSUPP_HTTPS_PROXY,
2438
2439 sizeof(struct ssl_backend_data),
2440
2441 Curl_nss_init, /* init */
2442 Curl_nss_cleanup, /* cleanup */
2443 Curl_nss_version, /* version */
2444 Curl_nss_check_cxn, /* check_cxn */
2445 /* NSS has no shutdown function provided and thus always fail */
2446 Curl_none_shutdown, /* shutdown */
2447 Curl_none_data_pending, /* data_pending */
2448 Curl_nss_random, /* random */
2449 Curl_nss_cert_status_request, /* cert_status_request */
2450 Curl_nss_connect, /* connect */
2451 Curl_nss_connect_nonblocking, /* connect_nonblocking */
2452 Curl_nss_get_internals, /* get_internals */
2453 Curl_nss_close, /* close_one */
2454 Curl_none_close_all, /* close_all */
2455 /* NSS has its own session ID cache */
2456 Curl_none_session_free, /* session_free */
2457 Curl_none_set_engine, /* set_engine */
2458 Curl_none_set_engine_default, /* set_engine_default */
2459 Curl_none_engines_list, /* engines_list */
2460 Curl_nss_false_start, /* false_start */
2461 Curl_nss_md5sum, /* md5sum */
2462 Curl_nss_sha256sum /* sha256sum */
2463 };
2464
2465 #endif /* USE_NSS */
2466