Revert "Update to 7.40.1"
[platform/upstream/curl.git] / lib / vtls / nss.c
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
76 PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
77
78 PRLock * nss_initlock = NULL;
79 PRLock * nss_crllock = NULL;
80 struct curl_llist *nss_crl_list = NULL;
81 NSSInitContext * nss_context = NULL;
82
83 volatile int initialized = 0;
84
85 typedef 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])
100 static 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
181 static const char* pem_library = "libnsspem.so";
182 SECMODModule* mod = NULL;
183
184 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
185 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
186 static PRIOMethods nspr_io_methods;
187
188 static 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
197 static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
198 {
199   failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
200 }
201
202 static 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  */
271 static 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  */
292 static 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  */
312 static 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(). */
336 static 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() */
390 static 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 */
398 static 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
405 static 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 */
443 static 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
476 static 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
533 fail:
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
540 static 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
571 static 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
587 static 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
626 static 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 */
637 static 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  */
652 static 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
698 static 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, &notBefore, &notAfter);
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
726 static 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
788 static 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  */
820 static 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  */
855 static 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  */
943 static PRBool
944 isTLSIntoleranceError(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 */
969 static 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 */
991 static 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 */
1003 static 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 */
1015 static 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
1022 static 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
1060 static 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  */
1123 int 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
1137 CURLcode 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 */
1154 void 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  */
1195 int
1196 Curl_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  */
1216 void 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  */
1251 int 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 */
1259 static 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 */
1275 static 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
1288 static Curl_recv nss_recv;
1289 static Curl_send nss_send;
1290
1291 static 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
1343 static 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
1403 static 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. */
1445 static 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
1458 static 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
1718 error:
1719   if(model)
1720     PR_Close(model);
1721
1722   return nss_fail_connect(connssl, data, curlerr);
1723 }
1724
1725 static 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
1780 error:
1781   return nss_fail_connect(connssl, data, curlerr);
1782 }
1783
1784 static 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
1835 CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
1836 {
1837   return nss_connect_common(conn, sockindex, /* blocking */ NULL);
1838 }
1839
1840 CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
1841                                       int sockindex, bool *done)
1842 {
1843   return nss_connect_common(conn, sockindex, done);
1844 }
1845
1846 static 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
1875 static 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
1906 size_t Curl_nss_version(char *buffer, size_t size)
1907 {
1908   return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
1909 }
1910
1911 int Curl_nss_seed(struct SessionHandle *data)
1912 {
1913   /* make sure that NSS is initialized */
1914   return !!Curl_nss_force_init(data);
1915 }
1916
1917 void 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
1929 void 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 */