cc3d9c91b9ed378aeff99022c0c5a4c45022dc39
[platform/upstream/curl.git] / lib / nss.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 sslgen.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 "sslgen.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
67 /* The last #include file should be: */
68 #include "memdebug.h"
69
70 #define SSL_DIR "/etc/pki/nssdb"
71
72 /* enough to fit the string "PEM Token #[0|1]" */
73 #define SLOTSIZE 13
74
75 PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
76
77 PRLock * nss_initlock = NULL;
78 PRLock * nss_crllock = NULL;
79 #ifdef HAVE_NSS_INITCONTEXT
80 NSSInitContext * nss_context = NULL;
81 #endif
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   {"rsa_aes_128_sha",            TLS_RSA_WITH_AES_128_CBC_SHA},
128   {"rsa_aes_256_sha",            TLS_RSA_WITH_AES_256_CBC_SHA},
129 #ifdef NSS_ENABLE_ECC
130   /* ECC ciphers. */
131   {"ecdh_ecdsa_null_sha",        TLS_ECDH_ECDSA_WITH_NULL_SHA},
132   {"ecdh_ecdsa_rc4_128_sha",     TLS_ECDH_ECDSA_WITH_RC4_128_SHA},
133   {"ecdh_ecdsa_3des_sha",        TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA},
134   {"ecdh_ecdsa_aes_128_sha",     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA},
135   {"ecdh_ecdsa_aes_256_sha",     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA},
136   {"ecdhe_ecdsa_null_sha",       TLS_ECDHE_ECDSA_WITH_NULL_SHA},
137   {"ecdhe_ecdsa_rc4_128_sha",    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
138   {"ecdhe_ecdsa_3des_sha",       TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA},
139   {"ecdhe_ecdsa_aes_128_sha",    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
140   {"ecdhe_ecdsa_aes_256_sha",    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
141   {"ecdh_rsa_null_sha",          TLS_ECDH_RSA_WITH_NULL_SHA},
142   {"ecdh_rsa_128_sha",           TLS_ECDH_RSA_WITH_RC4_128_SHA},
143   {"ecdh_rsa_3des_sha",          TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
144   {"ecdh_rsa_aes_128_sha",       TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
145   {"ecdh_rsa_aes_256_sha",       TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
146   {"echde_rsa_null",             TLS_ECDHE_RSA_WITH_NULL_SHA},
147   {"ecdhe_rsa_rc4_128_sha",      TLS_ECDHE_RSA_WITH_RC4_128_SHA},
148   {"ecdhe_rsa_3des_sha",         TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
149   {"ecdhe_rsa_aes_128_sha",      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
150   {"ecdhe_rsa_aes_256_sha",      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
151   {"ecdh_anon_null_sha",         TLS_ECDH_anon_WITH_NULL_SHA},
152   {"ecdh_anon_rc4_128sha",       TLS_ECDH_anon_WITH_RC4_128_SHA},
153   {"ecdh_anon_3des_sha",         TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA},
154   {"ecdh_anon_aes_128_sha",      TLS_ECDH_anon_WITH_AES_128_CBC_SHA},
155   {"ecdh_anon_aes_256_sha",      TLS_ECDH_anon_WITH_AES_256_CBC_SHA},
156 #endif
157 };
158
159 /* following ciphers are new in NSS 3.4 and not enabled by default, therefore
160    they are enabled explicitly */
161 static const int enable_ciphers_by_default[] = {
162   TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
163   TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
164   TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
165   TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
166   TLS_RSA_WITH_AES_128_CBC_SHA,
167   TLS_RSA_WITH_AES_256_CBC_SHA,
168   SSL_NULL_WITH_NULL_NULL
169 };
170
171 static const char* pem_library = "libnsspem.so";
172 SECMODModule* mod = NULL;
173
174 static const char* nss_error_to_name(PRErrorCode code)
175 {
176   const char *name = PR_ErrorToName(code);
177   if(name)
178     return name;
179
180   return "unknown error";
181 }
182
183 static void nss_print_error_message(struct SessionHandle *data, PRUint32 err)
184 {
185   failf(data, "%s", PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
186 }
187
188 static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
189                              char *cipher_list)
190 {
191   unsigned int i;
192   PRBool cipher_state[NUM_OF_CIPHERS];
193   PRBool found;
194   char *cipher;
195   SECStatus rv;
196
197   /* First disable all ciphers. This uses a different max value in case
198    * NSS adds more ciphers later we don't want them available by
199    * accident
200    */
201   for(i=0; i<SSL_NumImplementedCiphers; i++) {
202     SSL_CipherPrefSet(model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
203   }
204
205   /* Set every entry in our list to false */
206   for(i=0; i<NUM_OF_CIPHERS; i++) {
207     cipher_state[i] = PR_FALSE;
208   }
209
210   cipher = cipher_list;
211
212   while(cipher_list && (cipher_list[0])) {
213     while((*cipher) && (ISSPACE(*cipher)))
214       ++cipher;
215
216     if((cipher_list = strchr(cipher, ','))) {
217       *cipher_list++ = '\0';
218     }
219
220     found = PR_FALSE;
221
222     for(i=0; i<NUM_OF_CIPHERS; i++) {
223       if(Curl_raw_equal(cipher, cipherlist[i].name)) {
224         cipher_state[i] = PR_TRUE;
225         found = PR_TRUE;
226         break;
227       }
228     }
229
230     if(found == PR_FALSE) {
231       failf(data, "Unknown cipher in list: %s", cipher);
232       return SECFailure;
233     }
234
235     if(cipher_list) {
236       cipher = cipher_list;
237     }
238   }
239
240   /* Finally actually enable the selected ciphers */
241   for(i=0; i<NUM_OF_CIPHERS; i++) {
242     rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
243     if(rv != SECSuccess) {
244       failf(data, "cipher-suite not supported by NSS: %s", cipherlist[i].name);
245       return SECFailure;
246     }
247   }
248
249   return SECSuccess;
250 }
251
252 /*
253  * Get the number of ciphers that are enabled. We use this to determine
254  * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
255  */
256 static int num_enabled_ciphers(void)
257 {
258   PRInt32 policy = 0;
259   int count = 0;
260   unsigned int i;
261
262   for(i=0; i<NUM_OF_CIPHERS; i++) {
263     SSL_CipherPolicyGet(cipherlist[i].num, &policy);
264     if(policy)
265       count++;
266   }
267   return count;
268 }
269
270 /*
271  * Determine whether the nickname passed in is a filename that needs to
272  * be loaded as a PEM or a regular NSS nickname.
273  *
274  * returns 1 for a file
275  * returns 0 for not a file (NSS nickname)
276  */
277 static int is_file(const char *filename)
278 {
279   struct_stat st;
280
281   if(filename == NULL)
282     return 0;
283
284   if(stat(filename, &st) == 0)
285     if(S_ISREG(st.st_mode))
286       return 1;
287
288   return 0;
289 }
290
291 /* Check if the given string is filename or nickname of a certificate.  If the
292  * given string is recognized as filename, return NULL.  If the given string is
293  * recognized as nickname, return a duplicated string.  The returned string
294  * should be later deallocated using free().  If the OOM failure occurs, we
295  * return NULL, too.
296  */
297 static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
298 {
299   const char *str = data->set.str[cert_kind];
300   const char *n;
301
302   if(!is_file(str))
303     /* no such file exists, use the string as nickname */
304     return strdup(str);
305
306   /* search the last slash; we require at least one slash in a file name */
307   n = strrchr(str, '/');
308   if(!n) {
309     infof(data, "warning: certificate file name \"%s\" handled as nickname; "
310           "please use \"./%s\" to force file name\n", str, str);
311     return strdup(str);
312   }
313
314   /* we'll use the PEM reader to read the certificate from file */
315   return NULL;
316 }
317
318 /* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
319  * the call succeeds, append the object handle to the list of objects so that
320  * the object can be destroyed in Curl_nss_close(). */
321 static CURLcode nss_create_object(struct ssl_connect_data *ssl,
322                                   CK_OBJECT_CLASS obj_class,
323                                   const char *filename, bool cacert)
324 {
325   PK11SlotInfo *slot;
326   PK11GenericObject *obj;
327   CK_BBOOL cktrue = CK_TRUE;
328   CK_BBOOL ckfalse = CK_FALSE;
329   CK_ATTRIBUTE attrs[/* max count of attributes */ 4];
330   int attr_cnt = 0;
331   CURLcode err = (cacert)
332     ? CURLE_SSL_CACERT_BADFILE
333     : CURLE_SSL_CERTPROBLEM;
334
335   const int slot_id = (cacert) ? 0 : 1;
336   char *slot_name = aprintf("PEM Token #%d", slot_id);
337   if(!slot_name)
338     return CURLE_OUT_OF_MEMORY;
339
340   slot = PK11_FindSlotByName(slot_name);
341   free(slot_name);
342   if(!slot)
343     return err;
344
345   PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class));
346   PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL));
347   PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)filename,
348                 strlen(filename) + 1);
349
350   if(CKO_CERTIFICATE == obj_class) {
351     CK_BBOOL *pval = (cacert) ? (&cktrue) : (&ckfalse);
352     PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
353   }
354
355   obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
356   PK11_FreeSlot(slot);
357   if(!obj)
358     return err;
359
360   if(!Curl_llist_insert_next(ssl->obj_list, ssl->obj_list->tail, obj)) {
361     PK11_DestroyGenericObject(obj);
362     return CURLE_OUT_OF_MEMORY;
363   }
364
365   if(!cacert && CKO_CERTIFICATE == obj_class)
366     /* store reference to a client certificate */
367     ssl->obj_clicert = obj;
368
369   return CURLE_OK;
370 }
371
372 /* Destroy the NSS object whose handle is given by ptr.  This function is
373  * a callback of Curl_llist_alloc() used by Curl_llist_destroy() to destroy
374  * NSS objects in Curl_nss_close() */
375 static void nss_destroy_object(void *user, void *ptr)
376 {
377   PK11GenericObject *obj = (PK11GenericObject *)ptr;
378   (void) user;
379   PK11_DestroyGenericObject(obj);
380 }
381
382 static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
383                               const char *filename, PRBool cacert)
384 {
385   CURLcode err = (cacert)
386     ? CURLE_SSL_CACERT_BADFILE
387     : CURLE_SSL_CERTPROBLEM;
388
389   /* libnsspem.so leaks memory if the requested file does not exist.  For more
390    * details, go to <https://bugzilla.redhat.com/734760>. */
391   if(is_file(filename))
392     err = nss_create_object(ssl, CKO_CERTIFICATE, filename, cacert);
393
394   if(CURLE_OK == err && !cacert) {
395     /* we have successfully loaded a client certificate */
396     CERTCertificate *cert;
397     char *nickname = NULL;
398     char *n = strrchr(filename, '/');
399     if(n)
400       n++;
401
402     /* The following undocumented magic helps to avoid a SIGSEGV on call
403      * of PK11_ReadRawAttribute() from SelectClientCert() when using an
404      * immature version of libnsspem.so.  For more details, go to
405      * <https://bugzilla.redhat.com/733685>. */
406     nickname = aprintf("PEM Token #1:%s", n);
407     if(nickname) {
408       cert = PK11_FindCertFromNickname(nickname, NULL);
409       if(cert)
410         CERT_DestroyCertificate(cert);
411
412       free(nickname);
413     }
414   }
415
416   return err;
417 }
418
419 /* add given CRL to cache if it is not already there */
420 static SECStatus nss_cache_crl(SECItem *crlDER)
421 {
422   CERTCertDBHandle *db = CERT_GetDefaultCertDB();
423   CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0);
424   if(crl) {
425     /* CRL already cached */
426     SEC_DestroyCrl(crl);
427     SECITEM_FreeItem(crlDER, PR_FALSE);
428     return SECSuccess;
429   }
430
431   /* acquire lock before call of CERT_CacheCRL() */
432   PR_Lock(nss_crllock);
433   if(SECSuccess != CERT_CacheCRL(db, crlDER)) {
434     /* unable to cache CRL */
435     PR_Unlock(nss_crllock);
436     SECITEM_FreeItem(crlDER, PR_FALSE);
437     return SECFailure;
438   }
439
440   /* we need to clear session cache, so that the CRL could take effect */
441   SSL_ClearSessionCache();
442   PR_Unlock(nss_crllock);
443   return SECSuccess;
444 }
445
446 static SECStatus nss_load_crl(const char* crlfilename)
447 {
448   PRFileDesc *infile;
449   PRFileInfo  info;
450   SECItem filedata = { 0, NULL, 0 };
451   SECItem crlDER = { 0, NULL, 0 };
452   char *body;
453
454   infile = PR_Open(crlfilename, PR_RDONLY, 0);
455   if(!infile)
456     return SECFailure;
457
458   if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
459     goto fail;
460
461   if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
462     goto fail;
463
464   if(info.size != PR_Read(infile, filedata.data, info.size))
465     goto fail;
466
467   /* place a trailing zero right after the visible data */
468   body = (char*)filedata.data;
469   body[--filedata.len] = '\0';
470
471   body = strstr(body, "-----BEGIN");
472   if(body) {
473     /* assume ASCII */
474     char *trailer;
475     char *begin = PORT_Strchr(body, '\n');
476     if(!begin)
477       begin = PORT_Strchr(body, '\r');
478     if(!begin)
479       goto fail;
480
481     trailer = strstr(++begin, "-----END");
482     if(!trailer)
483       goto fail;
484
485     /* retrieve DER from ASCII */
486     *trailer = '\0';
487     if(ATOB_ConvertAsciiToItem(&crlDER, begin))
488       goto fail;
489
490     SECITEM_FreeItem(&filedata, PR_FALSE);
491   }
492   else
493     /* assume DER */
494     crlDER = filedata;
495
496   PR_Close(infile);
497   return nss_cache_crl(&crlDER);
498
499 fail:
500   PR_Close(infile);
501   SECITEM_FreeItem(&filedata, PR_FALSE);
502   return SECFailure;
503 }
504
505 static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
506                              char *key_file)
507 {
508   PK11SlotInfo *slot;
509   SECStatus status;
510   CURLcode rv;
511   struct ssl_connect_data *ssl = conn->ssl;
512   (void)sockindex; /* unused */
513
514   rv = nss_create_object(ssl, CKO_PRIVATE_KEY, key_file, FALSE);
515   if(CURLE_OK != rv) {
516     PR_SetError(SEC_ERROR_BAD_KEY, 0);
517     return rv;
518   }
519
520   slot = PK11_FindSlotByName("PEM Token #1");
521   if(!slot)
522     return CURLE_SSL_CERTPROBLEM;
523
524   /* This will force the token to be seen as re-inserted */
525   SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
526   PK11_IsPresent(slot);
527
528   status = PK11_Authenticate(slot, PR_TRUE,
529                              conn->data->set.str[STRING_KEY_PASSWD]);
530   PK11_FreeSlot(slot);
531   return (SECSuccess == status)
532     ? CURLE_OK
533     : CURLE_SSL_CERTPROBLEM;
534 }
535
536 static int display_error(struct connectdata *conn, PRInt32 err,
537                          const char *filename)
538 {
539   switch(err) {
540   case SEC_ERROR_BAD_PASSWORD:
541     failf(conn->data, "Unable to load client key: Incorrect password");
542     return 1;
543   case SEC_ERROR_UNKNOWN_CERT:
544     failf(conn->data, "Unable to load certificate %s", filename);
545     return 1;
546   default:
547     break;
548   }
549   return 0; /* The caller will print a generic error */
550 }
551
552 static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
553                            char *cert_file, char *key_file)
554 {
555   struct SessionHandle *data = conn->data;
556   CURLcode rv;
557
558   if(cert_file) {
559     rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
560     if(CURLE_OK != rv) {
561       const PRErrorCode err = PR_GetError();
562       if(!display_error(conn, err, cert_file)) {
563         const char *err_name = nss_error_to_name(err);
564         failf(data, "unable to load client cert: %d (%s)", err, err_name);
565       }
566
567       return rv;
568     }
569   }
570
571   if(key_file || (is_file(cert_file))) {
572     if(key_file)
573       rv = nss_load_key(conn, sockindex, key_file);
574     else
575       /* In case the cert file also has the key */
576       rv = nss_load_key(conn, sockindex, cert_file);
577     if(CURLE_OK != rv) {
578       const PRErrorCode err = PR_GetError();
579       if(!display_error(conn, err, key_file)) {
580         const char *err_name = nss_error_to_name(err);
581         failf(data, "unable to load client key: %d (%s)", err, err_name);
582       }
583
584       return rv;
585     }
586   }
587
588   return CURLE_OK;
589 }
590
591 static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
592 {
593   (void)slot; /* unused */
594   if(retry || NULL == arg)
595     return NULL;
596   else
597     return (char *)PORT_Strdup((char *)arg);
598 }
599
600 /* bypass the default SSL_AuthCertificate() hook in case we do not want to
601  * verify peer */
602 static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
603                                     PRBool isServer)
604 {
605   struct connectdata *conn = (struct connectdata *)arg;
606   if(!conn->data->set.ssl.verifypeer) {
607     infof(conn->data, "skipping SSL peer certificate verification\n");
608     return SECSuccess;
609   }
610
611   return SSL_AuthCertificate(CERT_GetDefaultCertDB(), fd, checksig, isServer);
612 }
613
614 /**
615  * Inform the application that the handshake is complete.
616  */
617 static void HandshakeCallback(PRFileDesc *sock, void *arg)
618 {
619   (void)sock;
620   (void)arg;
621 }
622
623 static void display_cert_info(struct SessionHandle *data,
624                               CERTCertificate *cert)
625 {
626   char *subject, *issuer, *common_name;
627   PRExplodedTime printableTime;
628   char timeString[256];
629   PRTime notBefore, notAfter;
630
631   subject = CERT_NameToAscii(&cert->subject);
632   issuer = CERT_NameToAscii(&cert->issuer);
633   common_name = CERT_GetCommonName(&cert->subject);
634   infof(data, "\tsubject: %s\n", subject);
635
636   CERT_GetCertTimes(cert, &notBefore, &notAfter);
637   PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
638   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
639   infof(data, "\tstart date: %s\n", timeString);
640   PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
641   PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
642   infof(data, "\texpire date: %s\n", timeString);
643   infof(data, "\tcommon name: %s\n", common_name);
644   infof(data, "\tissuer: %s\n", issuer);
645
646   PR_Free(subject);
647   PR_Free(issuer);
648   PR_Free(common_name);
649 }
650
651 static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
652 {
653   SSLChannelInfo channel;
654   SSLCipherSuiteInfo suite;
655   CERTCertificate *cert;
656
657   if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
658      SECSuccess && channel.length == sizeof channel &&
659      channel.cipherSuite) {
660     if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
661                               &suite, sizeof suite) == SECSuccess) {
662       infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
663     }
664   }
665
666   infof(conn->data, "Server certificate:\n");
667
668   cert = SSL_PeerCertificate(sock);
669   display_cert_info(conn->data, cert);
670   CERT_DestroyCertificate(cert);
671
672   return;
673 }
674
675 static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
676 {
677   struct connectdata *conn = (struct connectdata *)arg;
678   struct SessionHandle *data = conn->data;
679   PRErrorCode err = PR_GetError();
680   CERTCertificate *cert;
681
682   /* remember the cert verification result */
683   data->set.ssl.certverifyresult = err;
684
685   if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
686     /* we are asked not to verify the host name */
687     return SECSuccess;
688
689   /* print only info about the cert, the error is printed off the callback */
690   cert = SSL_PeerCertificate(sock);
691   if(cert) {
692     infof(data, "Server certificate:\n");
693     display_cert_info(data, cert);
694     CERT_DestroyCertificate(cert);
695   }
696
697   return SECFailure;
698 }
699
700 /**
701  *
702  * Check that the Peer certificate's issuer certificate matches the one found
703  * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
704  * issuer check, so we provide comments that mimic the OpenSSL
705  * X509_check_issued function (in x509v3/v3_purp.c)
706  */
707 static SECStatus check_issuer_cert(PRFileDesc *sock,
708                                    char *issuer_nickname)
709 {
710   CERTCertificate *cert,*cert_issuer,*issuer;
711   SECStatus res=SECSuccess;
712   void *proto_win = NULL;
713
714   /*
715     PRArenaPool   *tmpArena = NULL;
716     CERTAuthKeyID *authorityKeyID = NULL;
717     SECITEM       *caname = NULL;
718   */
719
720   cert = SSL_PeerCertificate(sock);
721   cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
722
723   proto_win = SSL_RevealPinArg(sock);
724   issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
725
726   if((!cert_issuer) || (!issuer))
727     res = SECFailure;
728   else if(SECITEM_CompareItem(&cert_issuer->derCert,
729                               &issuer->derCert)!=SECEqual)
730     res = SECFailure;
731
732   CERT_DestroyCertificate(cert);
733   CERT_DestroyCertificate(issuer);
734   CERT_DestroyCertificate(cert_issuer);
735   return res;
736 }
737
738 /**
739  *
740  * Callback to pick the SSL client certificate.
741  */
742 static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
743                                   struct CERTDistNamesStr *caNames,
744                                   struct CERTCertificateStr **pRetCert,
745                                   struct SECKEYPrivateKeyStr **pRetKey)
746 {
747   struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
748   struct SessionHandle *data = connssl->data;
749   const char *nickname = connssl->client_nickname;
750
751   if(connssl->obj_clicert) {
752     /* use the cert/key provided by PEM reader */
753     static const char pem_slotname[] = "PEM Token #1";
754     SECItem cert_der = { 0, NULL, 0 };
755     void *proto_win = SSL_RevealPinArg(sock);
756     struct CERTCertificateStr *cert;
757     struct SECKEYPrivateKeyStr *key;
758
759     PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
760     if(NULL == slot) {
761       failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
762       return SECFailure;
763     }
764
765     if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
766                              &cert_der) != SECSuccess) {
767       failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
768       PK11_FreeSlot(slot);
769       return SECFailure;
770     }
771
772     cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
773     SECITEM_FreeItem(&cert_der, PR_FALSE);
774     if(NULL == cert) {
775       failf(data, "NSS: client certificate from file not found");
776       PK11_FreeSlot(slot);
777       return SECFailure;
778     }
779
780     key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
781     PK11_FreeSlot(slot);
782     if(NULL == key) {
783       failf(data, "NSS: private key from file not found");
784       CERT_DestroyCertificate(cert);
785       return SECFailure;
786     }
787
788     infof(data, "NSS: client certificate from file\n");
789     display_cert_info(data, cert);
790
791     *pRetCert = cert;
792     *pRetKey = key;
793     return SECSuccess;
794   }
795
796   /* use the default NSS hook */
797   if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
798                                           pRetCert, pRetKey)
799       || NULL == *pRetCert) {
800
801     if(NULL == nickname)
802       failf(data, "NSS: client certificate not found (nickname not "
803             "specified)");
804     else
805       failf(data, "NSS: client certificate not found: %s", nickname);
806
807     return SECFailure;
808   }
809
810   /* get certificate nickname if any */
811   nickname = (*pRetCert)->nickname;
812   if(NULL == nickname)
813     nickname = "[unknown]";
814
815   if(NULL == *pRetKey) {
816     failf(data, "NSS: private key not found for certificate: %s", nickname);
817     return SECFailure;
818   }
819
820   infof(data, "NSS: using client certificate: %s\n", nickname);
821   display_cert_info(data, *pRetCert);
822   return SECSuccess;
823 }
824
825 /* This function is supposed to decide, which error codes should be used
826  * to conclude server is TLS intolerant.
827  *
828  * taken from xulrunner - nsNSSIOLayer.cpp
829  */
830 static PRBool
831 isTLSIntoleranceError(PRInt32 err)
832 {
833   switch (err) {
834   case SSL_ERROR_BAD_MAC_ALERT:
835   case SSL_ERROR_BAD_MAC_READ:
836   case SSL_ERROR_HANDSHAKE_FAILURE_ALERT:
837   case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT:
838   case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE:
839   case SSL_ERROR_ILLEGAL_PARAMETER_ALERT:
840   case SSL_ERROR_NO_CYPHER_OVERLAP:
841   case SSL_ERROR_BAD_SERVER:
842   case SSL_ERROR_BAD_BLOCK_PADDING:
843   case SSL_ERROR_UNSUPPORTED_VERSION:
844   case SSL_ERROR_PROTOCOL_VERSION_ALERT:
845   case SSL_ERROR_RX_MALFORMED_FINISHED:
846   case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE:
847   case SSL_ERROR_DECODE_ERROR_ALERT:
848   case SSL_ERROR_RX_UNKNOWN_ALERT:
849     return PR_TRUE;
850   default:
851     return PR_FALSE;
852   }
853 }
854
855 static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir)
856 {
857 #ifdef HAVE_NSS_INITCONTEXT
858   NSSInitParameters initparams;
859
860   if(nss_context != NULL)
861     return CURLE_OK;
862
863   memset((void *) &initparams, '\0', sizeof(initparams));
864   initparams.length = sizeof(initparams);
865 #else /* HAVE_NSS_INITCONTEXT */
866   SECStatus rv;
867
868   if(NSS_IsInitialized())
869     return CURLE_OK;
870 #endif
871
872   if(cert_dir) {
873     const bool use_sql = NSS_VersionCheck("3.12.0");
874     char *certpath = aprintf("%s%s", use_sql ? "sql:" : "", cert_dir);
875     if(!certpath)
876       return CURLE_OUT_OF_MEMORY;
877
878     infof(data, "Initializing NSS with certpath: %s\n", certpath);
879 #ifdef HAVE_NSS_INITCONTEXT
880     nss_context = NSS_InitContext(certpath, "", "", "", &initparams,
881             NSS_INIT_READONLY | NSS_INIT_PK11RELOAD);
882     free(certpath);
883
884     if(nss_context != NULL)
885       return CURLE_OK;
886 #else /* HAVE_NSS_INITCONTEXT */
887     rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
888     free(certpath);
889
890     if(rv == SECSuccess)
891       return CURLE_OK;
892 #endif
893
894     infof(data, "Unable to initialize NSS database\n");
895   }
896
897   infof(data, "Initializing NSS with certpath: none\n");
898 #ifdef HAVE_NSS_INITCONTEXT
899   nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY
900          | NSS_INIT_NOCERTDB   | NSS_INIT_NOMODDB       | NSS_INIT_FORCEOPEN
901          | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD);
902   if(nss_context != NULL)
903     return CURLE_OK;
904 #else /* HAVE_NSS_INITCONTEXT */
905   if(NSS_NoDB_Init(NULL) == SECSuccess)
906     return CURLE_OK;
907 #endif
908
909   infof(data, "Unable to initialize NSS\n");
910   return CURLE_SSL_CACERT_BADFILE;
911 }
912
913 static CURLcode nss_init(struct SessionHandle *data)
914 {
915   char *cert_dir;
916   struct_stat st;
917   CURLcode rv;
918
919   if(initialized)
920     return CURLE_OK;
921
922   /* First we check if $SSL_DIR points to a valid dir */
923   cert_dir = getenv("SSL_DIR");
924   if(cert_dir) {
925     if((stat(cert_dir, &st) != 0) ||
926         (!S_ISDIR(st.st_mode))) {
927       cert_dir = NULL;
928     }
929   }
930
931   /* Now we check if the default location is a valid dir */
932   if(!cert_dir) {
933     if((stat(SSL_DIR, &st) == 0) &&
934         (S_ISDIR(st.st_mode))) {
935       cert_dir = (char *)SSL_DIR;
936     }
937   }
938
939   rv = nss_init_core(data, cert_dir);
940   if(rv)
941     return rv;
942
943   if(num_enabled_ciphers() == 0)
944     NSS_SetDomesticPolicy();
945
946   initialized = 1;
947   return CURLE_OK;
948 }
949
950 /**
951  * Global SSL init
952  *
953  * @retval 0 error initializing SSL
954  * @retval 1 SSL initialized successfully
955  */
956 int Curl_nss_init(void)
957 {
958   /* curl_global_init() is not thread-safe so this test is ok */
959   if(nss_initlock == NULL) {
960     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
961     nss_initlock = PR_NewLock();
962     nss_crllock = PR_NewLock();
963   }
964
965   /* We will actually initialize NSS later */
966
967   return 1;
968 }
969
970 CURLcode Curl_nss_force_init(struct SessionHandle *data)
971 {
972   CURLcode rv;
973   if(!nss_initlock) {
974     failf(data,
975           "unable to initialize NSS, curl_global_init() should have been "
976           "called with CURL_GLOBAL_SSL or CURL_GLOBAL_ALL");
977     return CURLE_FAILED_INIT;
978   }
979
980   PR_Lock(nss_initlock);
981   rv = nss_init(data);
982   PR_Unlock(nss_initlock);
983   return rv;
984 }
985
986 /* Global cleanup */
987 void Curl_nss_cleanup(void)
988 {
989   /* This function isn't required to be threadsafe and this is only done
990    * as a safety feature.
991    */
992   PR_Lock(nss_initlock);
993   if(initialized) {
994     /* Free references to client certificates held in the SSL session cache.
995      * Omitting this hampers destruction of the security module owning
996      * the certificates. */
997     SSL_ClearSessionCache();
998
999     if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
1000       SECMOD_DestroyModule(mod);
1001       mod = NULL;
1002     }
1003 #ifdef HAVE_NSS_INITCONTEXT
1004     NSS_ShutdownContext(nss_context);
1005     nss_context = NULL;
1006 #else /* HAVE_NSS_INITCONTEXT */
1007     NSS_Shutdown();
1008 #endif
1009   }
1010   PR_Unlock(nss_initlock);
1011
1012   PR_DestroyLock(nss_initlock);
1013   PR_DestroyLock(nss_crllock);
1014   nss_initlock = NULL;
1015
1016   initialized = 0;
1017 }
1018
1019 /*
1020  * This function uses SSL_peek to determine connection status.
1021  *
1022  * Return codes:
1023  *     1 means the connection is still in place
1024  *     0 means the connection has been closed
1025  *    -1 means the connection status is unknown
1026  */
1027 int
1028 Curl_nss_check_cxn(struct connectdata *conn)
1029 {
1030   int rc;
1031   char buf;
1032
1033   rc =
1034     PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
1035             PR_SecondsToInterval(1));
1036   if(rc > 0)
1037     return 1; /* connection still in place */
1038
1039   if(rc == 0)
1040     return 0; /* connection has been closed */
1041
1042   return -1;  /* connection status unknown */
1043 }
1044
1045 /*
1046  * This function is called when an SSL connection is closed.
1047  */
1048 void Curl_nss_close(struct connectdata *conn, int sockindex)
1049 {
1050   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1051
1052   if(connssl->handle) {
1053     /* NSS closes the socket we previously handed to it, so we must mark it
1054        as closed to avoid double close */
1055     fake_sclose(conn->sock[sockindex]);
1056     conn->sock[sockindex] = CURL_SOCKET_BAD;
1057
1058     if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
1059       /* A server might require different authentication based on the
1060        * particular path being requested by the client.  To support this
1061        * scenario, we must ensure that a connection will never reuse the
1062        * authentication data from a previous connection. */
1063       SSL_InvalidateSession(connssl->handle);
1064
1065     if(connssl->client_nickname != NULL) {
1066       free(connssl->client_nickname);
1067       connssl->client_nickname = NULL;
1068     }
1069     /* destroy all NSS objects in order to avoid failure of NSS shutdown */
1070     Curl_llist_destroy(connssl->obj_list, NULL);
1071     connssl->obj_list = NULL;
1072     connssl->obj_clicert = NULL;
1073
1074     PR_Close(connssl->handle);
1075     connssl->handle = NULL;
1076   }
1077 }
1078
1079 /*
1080  * This function is called when the 'data' struct is going away. Close
1081  * down everything and free all resources!
1082  */
1083 int Curl_nss_close_all(struct SessionHandle *data)
1084 {
1085   (void)data;
1086   return 0;
1087 }
1088
1089 /* return true if NSS can provide error code (and possibly msg) for the
1090    error */
1091 static bool is_nss_error(CURLcode err)
1092 {
1093   switch(err) {
1094   case CURLE_PEER_FAILED_VERIFICATION:
1095   case CURLE_SSL_CACERT:
1096   case CURLE_SSL_CERTPROBLEM:
1097   case CURLE_SSL_CONNECT_ERROR:
1098   case CURLE_SSL_ISSUER_ERROR:
1099     return true;
1100
1101   default:
1102     return false;
1103   }
1104 }
1105
1106 /* return true if the given error code is related to a client certificate */
1107 static bool is_cc_error(PRInt32 err)
1108 {
1109   switch(err) {
1110   case SSL_ERROR_BAD_CERT_ALERT:
1111   case SSL_ERROR_EXPIRED_CERT_ALERT:
1112   case SSL_ERROR_REVOKED_CERT_ALERT:
1113     return true;
1114
1115   default:
1116     return false;
1117   }
1118 }
1119
1120 static Curl_recv nss_recv;
1121 static Curl_send nss_send;
1122
1123 static CURLcode nss_load_ca_certificates(struct connectdata *conn,
1124                                          int sockindex)
1125 {
1126   struct SessionHandle *data = conn->data;
1127   const char *cafile = data->set.ssl.CAfile;
1128   const char *capath = data->set.ssl.CApath;
1129
1130   if(cafile) {
1131     CURLcode rv = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
1132     if(CURLE_OK != rv)
1133       return rv;
1134   }
1135
1136   if(capath) {
1137     struct_stat st;
1138     if(stat(capath, &st) == -1)
1139       return CURLE_SSL_CACERT_BADFILE;
1140
1141     if(S_ISDIR(st.st_mode)) {
1142       PRDirEntry *entry;
1143       PRDir *dir = PR_OpenDir(capath);
1144       if(!dir)
1145         return CURLE_SSL_CACERT_BADFILE;
1146
1147       while((entry = PR_ReadDir(dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN))) {
1148         char *fullpath = aprintf("%s/%s", capath, entry->name);
1149         if(!fullpath) {
1150           PR_CloseDir(dir);
1151           return CURLE_OUT_OF_MEMORY;
1152         }
1153
1154         if(CURLE_OK != nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE))
1155           /* This is purposefully tolerant of errors so non-PEM files can
1156            * be in the same directory */
1157           infof(data, "failed to load '%s' from CURLOPT_CAPATH\n", fullpath);
1158
1159         free(fullpath);
1160       }
1161
1162       PR_CloseDir(dir);
1163     }
1164     else
1165       infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
1166   }
1167
1168   infof(data, "  CAfile: %s\n  CApath: %s\n",
1169       cafile ? cafile : "none",
1170       capath ? capath : "none");
1171
1172   return CURLE_OK;
1173 }
1174
1175 CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
1176 {
1177   PRErrorCode err = 0;
1178   PRFileDesc *model = NULL;
1179   PRBool ssl2 = PR_FALSE;
1180   PRBool ssl3 = PR_FALSE;
1181   PRBool tlsv1 = PR_FALSE;
1182   PRBool ssl_no_cache;
1183   PRBool ssl_cbc_random_iv;
1184   struct SessionHandle *data = conn->data;
1185   curl_socket_t sockfd = conn->sock[sockindex];
1186   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1187   CURLcode curlerr;
1188   const int *cipher_to_enable;
1189   PRSocketOptionData sock_opt;
1190   long time_left;
1191   PRUint32 timeout;
1192
1193   if(connssl->state == ssl_connection_complete)
1194     return CURLE_OK;
1195
1196   connssl->data = data;
1197
1198   /* list of all NSS objects we need to destroy in Curl_nss_close() */
1199   connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
1200   if(!connssl->obj_list)
1201     return CURLE_OUT_OF_MEMORY;
1202
1203   /* FIXME. NSS doesn't support multiple databases open at the same time. */
1204   PR_Lock(nss_initlock);
1205   curlerr = nss_init(conn->data);
1206   if(CURLE_OK != curlerr) {
1207     PR_Unlock(nss_initlock);
1208     goto error;
1209   }
1210
1211   curlerr = CURLE_SSL_CONNECT_ERROR;
1212
1213   if(!mod) {
1214     char *configstring = aprintf("library=%s name=PEM", pem_library);
1215     if(!configstring) {
1216       PR_Unlock(nss_initlock);
1217       goto error;
1218     }
1219     mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
1220     free(configstring);
1221
1222     if(!mod || !mod->loaded) {
1223       if(mod) {
1224         SECMOD_DestroyModule(mod);
1225         mod = NULL;
1226       }
1227       infof(data, "WARNING: failed to load NSS PEM library %s. Using "
1228             "OpenSSL PEM certificates will not work.\n", pem_library);
1229     }
1230   }
1231
1232   PK11_SetPasswordFunc(nss_get_password);
1233   PR_Unlock(nss_initlock);
1234
1235   model = PR_NewTCPSocket();
1236   if(!model)
1237     goto error;
1238   model = SSL_ImportFD(NULL, model);
1239
1240   if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
1241     goto error;
1242   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
1243     goto error;
1244   if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
1245     goto error;
1246
1247   /* do not use SSL cache if we are not going to verify peer */
1248   ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE;
1249   if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
1250     goto error;
1251
1252   switch (data->set.ssl.version) {
1253   default:
1254   case CURL_SSLVERSION_DEFAULT:
1255     ssl3 = PR_TRUE;
1256     if(data->state.ssl_connect_retry)
1257       infof(data, "TLS disabled due to previous handshake failure\n");
1258     else
1259       tlsv1 = PR_TRUE;
1260     break;
1261   case CURL_SSLVERSION_TLSv1:
1262     tlsv1 = PR_TRUE;
1263     break;
1264   case CURL_SSLVERSION_SSLv2:
1265     ssl2 = PR_TRUE;
1266     break;
1267   case CURL_SSLVERSION_SSLv3:
1268     ssl3 = PR_TRUE;
1269     break;
1270   }
1271
1272   if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
1273     goto error;
1274   if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
1275     goto error;
1276   if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
1277     goto error;
1278
1279   if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
1280     goto error;
1281
1282   ssl_cbc_random_iv = !data->set.ssl_enable_beast;
1283 #ifdef SSL_CBC_RANDOM_IV
1284   /* unless the user explicitly asks to allow the protocol vulnerability, we
1285      use the work-around */
1286   if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
1287     infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
1288           ssl_cbc_random_iv);
1289 #else
1290   if(ssl_cbc_random_iv)
1291     infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
1292 #endif
1293
1294   /* reset the flag to avoid an infinite loop */
1295   data->state.ssl_connect_retry = FALSE;
1296
1297   /* enable all ciphers from enable_ciphers_by_default */
1298   cipher_to_enable = enable_ciphers_by_default;
1299   while(SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
1300     if(SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) {
1301       curlerr = CURLE_SSL_CIPHER;
1302       goto error;
1303     }
1304     cipher_to_enable++;
1305   }
1306
1307   if(data->set.ssl.cipher_list) {
1308     if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
1309       curlerr = CURLE_SSL_CIPHER;
1310       goto error;
1311     }
1312   }
1313
1314   if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
1315     infof(data, "warning: ignoring value of ssl.verifyhost\n");
1316
1317   /* bypass the default SSL_AuthCertificate() hook in case we do not want to
1318    * verify peer */
1319   if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
1320     goto error;
1321
1322   data->set.ssl.certverifyresult=0; /* not checked yet */
1323   if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
1324     goto error;
1325
1326   if(SSL_HandshakeCallback(model, HandshakeCallback, NULL) != SECSuccess)
1327     goto error;
1328
1329   if(data->set.ssl.verifypeer) {
1330     const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
1331     if(CURLE_OK != rv) {
1332       curlerr = rv;
1333       goto error;
1334     }
1335   }
1336
1337   if(data->set.ssl.CRLfile) {
1338     if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
1339       curlerr = CURLE_SSL_CRL_BADFILE;
1340       goto error;
1341     }
1342     infof(data,
1343           "  CRLfile: %s\n",
1344           data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
1345   }
1346
1347   if(data->set.str[STRING_CERT]) {
1348     char *nickname = dup_nickname(data, STRING_CERT);
1349     if(nickname) {
1350       /* we are not going to use libnsspem.so to read the client cert */
1351       connssl->obj_clicert = NULL;
1352     }
1353     else {
1354       CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
1355                                data->set.str[STRING_KEY]);
1356       if(CURLE_OK != rv) {
1357         /* failf() is already done in cert_stuff() */
1358         curlerr = rv;
1359         goto error;
1360       }
1361     }
1362
1363     /* store the nickname for SelectClientCert() called during handshake */
1364     connssl->client_nickname = nickname;
1365   }
1366   else
1367     connssl->client_nickname = NULL;
1368
1369   if(SSL_GetClientAuthDataHook(model, SelectClientCert,
1370                                (void *)connssl) != SECSuccess) {
1371     curlerr = CURLE_SSL_CERTPROBLEM;
1372     goto error;
1373   }
1374
1375   /* Import our model socket  onto the existing file descriptor */
1376   connssl->handle = PR_ImportTCPSocket(sockfd);
1377   connssl->handle = SSL_ImportFD(model, connssl->handle);
1378   if(!connssl->handle)
1379     goto error;
1380
1381   PR_Close(model); /* We don't need this any more */
1382   model = NULL;
1383
1384   /* This is the password associated with the cert that we're using */
1385   if(data->set.str[STRING_KEY_PASSWD]) {
1386     SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
1387   }
1388
1389   /* Force handshake on next I/O */
1390   SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
1391
1392   SSL_SetURL(connssl->handle, conn->host.name);
1393
1394   /* check timeout situation */
1395   time_left = Curl_timeleft(data, NULL, TRUE);
1396   if(time_left < 0L) {
1397     failf(data, "timed out before SSL handshake");
1398     curlerr = CURLE_OPERATION_TIMEDOUT;
1399     goto error;
1400   }
1401   timeout = PR_MillisecondsToInterval((PRUint32) time_left);
1402
1403   /* Force the handshake now */
1404   if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
1405     if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
1406       curlerr = CURLE_PEER_FAILED_VERIFICATION;
1407     else if(conn->data->set.ssl.certverifyresult!=0)
1408       curlerr = CURLE_SSL_CACERT;
1409     goto error;
1410   }
1411
1412   /* switch the SSL socket into non-blocking mode */
1413   sock_opt.option = PR_SockOpt_Nonblocking;
1414   sock_opt.value.non_blocking = PR_TRUE;
1415   if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
1416     goto error;
1417
1418   connssl->state = ssl_connection_complete;
1419   conn->recv[sockindex] = nss_recv;
1420   conn->send[sockindex] = nss_send;
1421
1422   display_conn_info(conn, connssl->handle);
1423
1424   if(data->set.str[STRING_SSL_ISSUERCERT]) {
1425     SECStatus ret = SECFailure;
1426     char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
1427     if(nickname) {
1428       /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
1429       ret = check_issuer_cert(connssl->handle, nickname);
1430       free(nickname);
1431     }
1432
1433     if(SECFailure == ret) {
1434       infof(data,"SSL certificate issuer check failed\n");
1435       curlerr = CURLE_SSL_ISSUER_ERROR;
1436       goto error;
1437     }
1438     else {
1439       infof(data, "SSL certificate issuer check ok\n");
1440     }
1441   }
1442
1443   return CURLE_OK;
1444
1445   error:
1446   /* reset the flag to avoid an infinite loop */
1447   data->state.ssl_connect_retry = FALSE;
1448
1449   if(is_nss_error(curlerr)) {
1450     /* read NSPR error code */
1451     err = PR_GetError();
1452     if(is_cc_error(err))
1453       curlerr = CURLE_SSL_CERTPROBLEM;
1454
1455     /* print the error number and error string */
1456     infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));
1457
1458     /* print a human-readable message describing the error if available */
1459     nss_print_error_message(data, err);
1460   }
1461
1462   if(model)
1463     PR_Close(model);
1464
1465     /* cleanup on connection failure */
1466     Curl_llist_destroy(connssl->obj_list, NULL);
1467     connssl->obj_list = NULL;
1468
1469   if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) {
1470     /* schedule reconnect through Curl_retry_request() */
1471     data->state.ssl_connect_retry = TRUE;
1472     infof(data, "Error in TLS handshake, trying SSLv3...\n");
1473     return CURLE_OK;
1474   }
1475
1476   return curlerr;
1477 }
1478
1479 static ssize_t nss_send(struct connectdata *conn,  /* connection data */
1480                         int sockindex,             /* socketindex */
1481                         const void *mem,           /* send this data */
1482                         size_t len,                /* amount to write */
1483                         CURLcode *curlcode)
1484 {
1485   ssize_t rc = PR_Send(conn->ssl[sockindex].handle, mem, (int)len, 0,
1486                        PR_INTERVAL_NO_WAIT);
1487   if(rc < 0) {
1488     PRInt32 err = PR_GetError();
1489     if(err == PR_WOULD_BLOCK_ERROR)
1490       *curlcode = CURLE_AGAIN;
1491     else {
1492       /* print the error number and error string */
1493       const char *err_name = nss_error_to_name(err);
1494       infof(conn->data, "SSL write: error %d (%s)\n", err, err_name);
1495
1496       /* print a human-readable message describing the error if available */
1497       nss_print_error_message(conn->data, err);
1498
1499       *curlcode = (is_cc_error(err))
1500         ? CURLE_SSL_CERTPROBLEM
1501         : CURLE_SEND_ERROR;
1502     }
1503     return -1;
1504   }
1505   return rc; /* number of bytes */
1506 }
1507
1508 static ssize_t nss_recv(struct connectdata * conn, /* connection data */
1509                         int num,                   /* socketindex */
1510                         char *buf,                 /* store read data here */
1511                         size_t buffersize,         /* max amount to read */
1512                         CURLcode *curlcode)
1513 {
1514   ssize_t nread = PR_Recv(conn->ssl[num].handle, buf, (int)buffersize, 0,
1515                           PR_INTERVAL_NO_WAIT);
1516   if(nread < 0) {
1517     /* failed SSL read */
1518     PRInt32 err = PR_GetError();
1519
1520     if(err == PR_WOULD_BLOCK_ERROR)
1521       *curlcode = CURLE_AGAIN;
1522     else {
1523       /* print the error number and error string */
1524       const char *err_name = nss_error_to_name(err);
1525       infof(conn->data, "SSL read: errno %d (%s)\n", err, err_name);
1526
1527       /* print a human-readable message describing the error if available */
1528       nss_print_error_message(conn->data, err);
1529
1530       *curlcode = (is_cc_error(err))
1531         ? CURLE_SSL_CERTPROBLEM
1532         : CURLE_RECV_ERROR;
1533     }
1534     return -1;
1535   }
1536   return nread;
1537 }
1538
1539 size_t Curl_nss_version(char *buffer, size_t size)
1540 {
1541   return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
1542 }
1543
1544 int Curl_nss_seed(struct SessionHandle *data)
1545 {
1546   /* TODO: implement? */
1547   (void) data;
1548   return 0;
1549 }
1550
1551 void Curl_nss_random(struct SessionHandle *data,
1552                      unsigned char *entropy,
1553                      size_t length)
1554 {
1555   Curl_nss_seed(data);  /* Initiate the seed if not already done */
1556   PK11_GenerateRandom(entropy, curlx_uztosi(length));
1557 }
1558
1559 void Curl_nss_md5sum(unsigned char *tmp, /* input */
1560                      size_t tmplen,
1561                      unsigned char *md5sum, /* output */
1562                      size_t md5len)
1563 {
1564   PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
1565   unsigned int MD5out;
1566   PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
1567   PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
1568   PK11_DestroyContext(MD5pw, PR_TRUE);
1569 }
1570
1571 #endif /* USE_NSS */