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