~ubuntu-branches/ubuntu/natty/curl/natty-proposed

« back to all changes in this revision

Viewing changes to lib/nss.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Schuldei
  • Date: 2009-05-24 21:12:19 UTC
  • mfrom: (1.1.12 upstream)
  • mto: (3.3.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20090524211219-7jgcwuhl04ixuqsm
Tags: upstream-7.19.5
ImportĀ upstreamĀ versionĀ 7.19.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: nss.c,v 1.18 2008-05-26 01:59:00 yangtse Exp $
 
21
 * $Id: nss.c,v 1.47 2009-05-11 09:13:49 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/*
59
59
#include <sslproto.h>
60
60
#include <prtypes.h>
61
61
#include <pk11pub.h>
 
62
#include <prio.h>
 
63
#include <secitem.h>
 
64
#include <secport.h>
 
65
#include <certdb.h>
62
66
 
63
 
#include "memory.h"
 
67
#include "curl_memory.h"
 
68
#include "rawstr.h"
64
69
#include "easyif.h" /* for Curl_convert_from_utf8 prototype */
65
70
 
66
71
/* The last #include file should be: */
73
78
 
74
79
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
75
80
 
76
 
int initialized = 0;
 
81
PRLock * nss_initlock = NULL;
 
82
 
 
83
volatile int initialized = 0;
77
84
 
78
85
#define HANDSHAKE_TIMEOUT 30
79
86
 
80
87
typedef struct {
81
 
  PRInt32 retryCount;
82
 
  struct SessionHandle *data;
83
 
} pphrase_arg_t;
84
 
 
85
 
typedef struct {
86
88
  const char *name;
87
89
  int num;
88
90
  PRInt32 version; /* protocol version valid for this cipher */
89
91
} cipher_s;
90
92
 
91
 
#ifdef NSS_ENABLE_ECC
92
 
#define ciphernum 48
93
 
#else
94
 
#define ciphernum 23
95
 
#endif
96
 
 
97
93
#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
98
94
                     (x)->pValue=(v); (x)->ulValueLen = (l)
99
95
 
101
97
 
102
98
enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 };
103
99
 
104
 
static const cipher_s cipherlist[ciphernum] = {
 
100
#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
 
101
static const cipher_s cipherlist[] = {
105
102
  /* SSL2 cipher suites */
106
103
  {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2},
 
104
  {"rc4-md5", SSL_EN_RC4_128_WITH_MD5, SSL2},
107
105
  {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2},
108
106
  {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2},
109
107
  {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2},
159
157
#endif
160
158
};
161
159
 
 
160
/* following ciphers are new in NSS 3.4 and not enabled by default, therefor
 
161
   they are enabled explicitly */
 
162
static const int enable_ciphers_by_default[] = {
 
163
  TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
 
164
  TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
 
165
  TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
 
166
  TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
 
167
  TLS_RSA_WITH_AES_128_CBC_SHA,
 
168
  TLS_RSA_WITH_AES_256_CBC_SHA,
 
169
  SSL_NULL_WITH_NULL_NULL
 
170
};
 
171
 
162
172
#ifdef HAVE_PK11_CREATEGENERICOBJECT
163
173
static const char* pem_library = "libnsspem.so";
164
174
#endif
167
177
static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
168
178
                             char *cipher_list)
169
179
{
170
 
  int i;
171
 
  PRBool cipher_state[ciphernum];
 
180
  unsigned int i;
 
181
  PRBool cipher_state[NUM_OF_CIPHERS];
172
182
  PRBool found;
173
183
  char *cipher;
174
184
  SECStatus rv;
182
192
  }
183
193
 
184
194
  /* Set every entry in our list to false */
185
 
  for(i=0; i<ciphernum; i++) {
 
195
  for(i=0; i<NUM_OF_CIPHERS; i++) {
186
196
    cipher_state[i] = PR_FALSE;
187
197
  }
188
198
 
198
208
 
199
209
    found = PR_FALSE;
200
210
 
201
 
    for(i=0; i<ciphernum; i++) {
202
 
      if(!strcasecmp(cipher, cipherlist[i].name)) {
 
211
    for(i=0; i<NUM_OF_CIPHERS; i++) {
 
212
      if(Curl_raw_equal(cipher, cipherlist[i].name)) {
203
213
        cipher_state[i] = PR_TRUE;
204
214
        found = PR_TRUE;
205
215
        break;
217
227
  }
218
228
 
219
229
  /* Finally actually enable the selected ciphers */
220
 
  for(i=0; i<ciphernum; i++) {
 
230
  for(i=0; i<NUM_OF_CIPHERS; i++) {
221
231
    rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
222
232
    if(rv != SECSuccess) {
223
233
      failf(data, "Unknown cipher in cipher list");
229
239
}
230
240
 
231
241
/*
 
242
 * Get the number of ciphers that are enabled. We use this to determine
 
243
 * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
 
244
 */
 
245
static int num_enabled_ciphers(void)
 
246
{
 
247
  PRInt32 policy = 0;
 
248
  int count = 0;
 
249
  unsigned int i;
 
250
 
 
251
  for(i=0; i<NUM_OF_CIPHERS; i++) {
 
252
    SSL_CipherPolicyGet(cipherlist[i].num, &policy);
 
253
    if(policy)
 
254
      count++;
 
255
  }
 
256
  return count;
 
257
}
 
258
 
 
259
/*
232
260
 * Determine whether the nickname passed in is a filename that needs to
233
261
 * be loaded as a PEM or a regular NSS nickname.
234
262
 *
249
277
  return 0;
250
278
}
251
279
 
252
 
static int
253
 
nss_load_cert(const char *filename, PRBool cacert)
 
280
static int nss_load_cert(struct ssl_connect_data *ssl,
 
281
                         const char *filename, PRBool cacert)
254
282
{
255
283
#ifdef HAVE_PK11_CREATEGENERICOBJECT
256
284
  CK_SLOT_ID slotID;
257
285
  PK11SlotInfo * slot = NULL;
258
 
  PK11GenericObject *rv;
259
286
  CK_ATTRIBUTE *attrs;
260
287
  CK_ATTRIBUTE theTemplate[20];
261
288
  CK_BBOOL cktrue = CK_TRUE;
262
289
  CK_BBOOL ckfalse = CK_FALSE;
263
290
  CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
264
 
  char *slotname = NULL;
 
291
  char slotname[SLOTSIZE];
265
292
#endif
266
293
  CERTCertificate *cert;
267
294
  char *nickname = NULL;
282
309
    if(cacert)
283
310
      return 0; /* You can't specify an NSS CA nickname this way */
284
311
    nickname = strdup(filename);
 
312
    if(!nickname)
 
313
      return 0;
285
314
    goto done;
286
315
  }
287
316
 
297
326
  else
298
327
    slotID = 1;
299
328
 
300
 
  slotname = (char *)malloc(SLOTSIZE);
301
 
  nickname = (char *)malloc(PATH_MAX);
302
329
  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
303
 
  snprintf(nickname, PATH_MAX, "PEM Token #%ld:%s", slotID, n);
 
330
 
 
331
  nickname = aprintf("PEM Token #%ld:%s", slotID, n);
 
332
  if(!nickname)
 
333
    return 0;
304
334
 
305
335
  slot = PK11_FindSlotByName(slotname);
306
336
 
307
337
  if(!slot) {
308
 
    free(slotname);
309
338
    free(nickname);
310
339
    return 0;
311
340
  }
312
341
 
313
 
  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
314
 
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
 
342
  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) );
 
343
  attrs++;
 
344
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
 
345
  attrs++;
315
346
  PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)filename,
316
 
                strlen(filename)+1); attrs++;
 
347
                strlen(filename)+1);
 
348
  attrs++;
317
349
  if(cacert) {
318
 
    PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); attrs++;
 
350
    PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) );
319
351
  }
320
352
  else {
321
 
    PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); attrs++;
 
353
    PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) );
322
354
  }
 
355
  attrs++;
323
356
 
324
357
  /* This load the certificate in our PEM module into the appropriate
325
358
   * slot.
326
359
   */
327
 
  rv = PK11_CreateGenericObject(slot, theTemplate, 4, PR_FALSE /* isPerm */);
 
360
  ssl->cacert[slotID] = PK11_CreateGenericObject(slot, theTemplate, 4,
 
361
                                         PR_FALSE /* isPerm */);
328
362
 
329
363
  PK11_FreeSlot(slot);
330
364
 
331
 
  free(slotname);
332
 
  if(rv == NULL) {
 
365
  if(ssl->cacert[slotID] == NULL) {
333
366
    free(nickname);
334
367
    return 0;
335
368
  }
362
395
  return 1;
363
396
}
364
397
 
365
 
static int nss_load_key(struct connectdata *conn, char *key_file)
 
398
static int nss_load_crl(const char* crlfilename, PRBool ascii)
 
399
{
 
400
  PRFileDesc *infile;
 
401
  PRStatus    prstat;
 
402
  PRFileInfo  info;
 
403
  PRInt32     nb;
 
404
  int rv;
 
405
  SECItem crlDER;
 
406
  CERTSignedCrl *crl=NULL;
 
407
  PK11SlotInfo *slot=NULL;
 
408
 
 
409
  infile = PR_Open(crlfilename,PR_RDONLY,0);
 
410
  if (!infile) {
 
411
    return 0;
 
412
  }
 
413
  crlDER.data = NULL;
 
414
  prstat = PR_GetOpenFileInfo(infile,&info);
 
415
  if (prstat!=PR_SUCCESS)
 
416
    return 0;
 
417
  if (ascii) {
 
418
    SECItem filedata;
 
419
    char *asc,*body;
 
420
    filedata.data = NULL;
 
421
    if (!SECITEM_AllocItem(NULL,&filedata,info.size))
 
422
      return 0;
 
423
    nb = PR_Read(infile,filedata.data,info.size);
 
424
    if (nb!=info.size)
 
425
      return 0;
 
426
    asc = (char*)filedata.data;
 
427
    if (!asc)
 
428
      return 0;
 
429
 
 
430
    body=strstr(asc,"-----BEGIN");
 
431
    if (body != NULL) {
 
432
      char *trailer=NULL;
 
433
      asc = body;
 
434
      body = PORT_Strchr(asc,'\n');
 
435
      if (!body)
 
436
        body = PORT_Strchr(asc,'\r');
 
437
      if (body)
 
438
        trailer = strstr(++body,"-----END");
 
439
      if (trailer!=NULL)
 
440
        *trailer='\0';
 
441
      else
 
442
        return 0;
 
443
    }
 
444
    else {
 
445
      body = asc;
 
446
    }
 
447
    rv = ATOB_ConvertAsciiToItem(&crlDER,body);
 
448
    PORT_Free(filedata.data);
 
449
    if (rv)
 
450
      return 0;
 
451
  }
 
452
  else {
 
453
    if (!SECITEM_AllocItem(NULL,&crlDER,info.size))
 
454
      return 0;
 
455
    nb = PR_Read(infile,crlDER.data,info.size);
 
456
    if (nb!=info.size)
 
457
      return 0;
 
458
  }
 
459
 
 
460
  slot = PK11_GetInternalKeySlot();
 
461
  crl  = PK11_ImportCRL(slot,&crlDER,
 
462
                        NULL,SEC_CRL_TYPE,
 
463
                        NULL,CRL_IMPORT_DEFAULT_OPTIONS,
 
464
                        NULL,(CRL_DECODE_DEFAULT_OPTIONS|
 
465
                              CRL_DECODE_DONT_COPY_DER));
 
466
  if (slot) PK11_FreeSlot(slot);
 
467
  if (!crl) return 0;
 
468
  SEC_DestroyCrl(crl);
 
469
  return 1;
 
470
}
 
471
 
 
472
static int nss_load_key(struct connectdata *conn, int sockindex, char *key_file)
366
473
{
367
474
#ifdef HAVE_PK11_CREATEGENERICOBJECT
368
475
  PK11SlotInfo * slot = NULL;
369
 
  PK11GenericObject *rv;
370
476
  CK_ATTRIBUTE *attrs;
371
477
  CK_ATTRIBUTE theTemplate[20];
372
478
  CK_BBOOL cktrue = CK_TRUE;
373
479
  CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
374
480
  CK_SLOT_ID slotID;
375
 
  char *slotname = NULL;
376
 
  pphrase_arg_t *parg = NULL;
 
481
  char slotname[SLOTSIZE];
 
482
  struct ssl_connect_data *sslconn = &conn->ssl[sockindex];
377
483
 
378
484
  attrs = theTemplate;
379
485
 
381
487
 
382
488
  slotID = 1; /* hardcoded for now */
383
489
 
384
 
  slotname = (char *)malloc(SLOTSIZE);
385
 
  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
386
 
 
 
490
  snprintf(slotname, sizeof(slotname), "PEM Token #%ld", slotID);
387
491
  slot = PK11_FindSlotByName(slotname);
388
 
  free(slotname);
389
492
 
390
493
  if(!slot)
391
494
    return 0;
396
499
                strlen(key_file)+1); attrs++;
397
500
 
398
501
  /* When adding an encrypted key the PKCS#11 will be set as removed */
399
 
  rv = PK11_CreateGenericObject(slot, theTemplate, 3, PR_FALSE /* isPerm */);
400
 
  if(rv == NULL) {
 
502
  sslconn->key = PK11_CreateGenericObject(slot, theTemplate, 3,
 
503
                                          PR_FALSE /* isPerm */);
 
504
  if(sslconn->key == NULL) {
401
505
    PR_SetError(SEC_ERROR_BAD_KEY, 0);
402
506
    return 0;
403
507
  }
406
510
  SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
407
511
  PK11_IsPresent(slot);
408
512
 
409
 
  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
410
 
  parg->retryCount = 0;
411
 
  parg->data = conn->data;
412
513
  /* parg is initialized in nss_Init_Tokens() */
413
 
  if(PK11_Authenticate(slot, PR_TRUE, parg) != SECSuccess) {
414
 
    free(parg);
 
514
  if(PK11_Authenticate(slot, PR_TRUE,
 
515
                       conn->data->set.str[STRING_KEY_PASSWD]) != SECSuccess) {
 
516
 
 
517
    PK11_FreeSlot(slot);
415
518
    return 0;
416
519
  }
417
 
  free(parg);
 
520
  PK11_FreeSlot(slot);
418
521
 
419
522
  return 1;
420
523
#else
443
546
  return 0; /* The caller will print a generic error */
444
547
}
445
548
 
446
 
static int cert_stuff(struct connectdata *conn, char *cert_file, char *key_file)
 
549
static int cert_stuff(struct connectdata *conn,
 
550
                      int sockindex, char *cert_file, char *key_file)
447
551
{
448
552
  struct SessionHandle *data = conn->data;
449
553
  int rv = 0;
450
554
 
451
555
  if(cert_file) {
452
 
    rv = nss_load_cert(cert_file, PR_FALSE);
 
556
    rv = nss_load_cert(&conn->ssl[sockindex], cert_file, PR_FALSE);
453
557
    if(!rv) {
454
558
      if(!display_error(conn, PR_GetError(), cert_file))
455
559
        failf(data, "Unable to load client cert %d.", PR_GetError());
458
562
  }
459
563
  if(key_file || (is_file(cert_file))) {
460
564
    if(key_file)
461
 
      rv = nss_load_key(conn, key_file);
 
565
      rv = nss_load_key(conn, sockindex, key_file);
462
566
    else
463
567
      /* In case the cert file also has the key */
464
 
      rv = nss_load_key(conn, cert_file);
 
568
      rv = nss_load_key(conn, sockindex, cert_file);
465
569
    if(!rv) {
466
570
      if(!display_error(conn, PR_GetError(), key_file))
467
571
        failf(data, "Unable to load client key %d.", PR_GetError());
474
578
 
475
579
static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
476
580
{
477
 
  pphrase_arg_t *parg;
478
 
  parg = (pphrase_arg_t *) arg;
479
 
 
480
581
  (void)slot; /* unused */
481
 
  if(retry > 2)
 
582
  if(retry || NULL == arg)
482
583
    return NULL;
483
 
  if(parg->data->set.str[STRING_KEY_PASSWD])
484
 
    return (char *)PORT_Strdup((char *)parg->data->set.str[STRING_KEY_PASSWD]);
485
584
  else
486
 
    return NULL;
487
 
}
488
 
 
489
 
/* No longer ask for the password, parg has been freed */
490
 
static char * nss_no_password(PK11SlotInfo *slot, PRBool retry, void *arg)
491
 
{
492
 
  (void)slot; /* unused */
493
 
  (void)retry; /* unused */
494
 
  (void)arg; /* unused */
495
 
  return NULL;
 
585
    return (char *)PORT_Strdup((char *)arg);
496
586
}
497
587
 
498
588
static SECStatus nss_Init_Tokens(struct connectdata * conn)
500
590
  PK11SlotList *slotList;
501
591
  PK11SlotListElement *listEntry;
502
592
  SECStatus ret, status = SECSuccess;
503
 
  pphrase_arg_t *parg = NULL;
504
 
 
505
 
  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
506
 
  parg->retryCount = 0;
507
 
  parg->data = conn->data;
508
593
 
509
594
  PK11_SetPasswordFunc(nss_get_password);
510
595
 
527
612
      continue;
528
613
    }
529
614
 
530
 
    ret = PK11_Authenticate(slot, PR_TRUE, parg);
 
615
    ret = PK11_Authenticate(slot, PR_TRUE,
 
616
                            conn->data->set.str[STRING_KEY_PASSWD]);
531
617
    if(SECSuccess != ret) {
532
618
      if(PR_GetError() == SEC_ERROR_BAD_PASSWORD)
533
619
        infof(conn->data, "The password for token '%s' is incorrect\n",
535
621
      status = SECFailure;
536
622
      break;
537
623
    }
538
 
    parg->retryCount = 0; /* reset counter to 0 for the next token */
539
624
    PK11_FreeSlot(slot);
540
625
  }
541
626
 
542
 
  free(parg);
543
 
 
544
627
  return status;
545
628
}
546
629
 
620
703
  PRTime notBefore, notAfter;
621
704
 
622
705
  if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
623
 
    SECSuccess && channel.length == sizeof channel &&
624
 
    channel.cipherSuite) {
 
706
     SECSuccess && channel.length == sizeof channel &&
 
707
     channel.cipherSuite) {
625
708
    if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
626
 
      &suite, sizeof suite) == SECSuccess) {
 
709
                              &suite, sizeof suite) == SECSuccess) {
627
710
      infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
628
711
    }
629
712
  }
657
740
 
658
741
/**
659
742
 *
 
743
 * Check that the Peer certificate's issuer certificate matches the one found
 
744
 * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
 
745
 * issuer check, so we provide comments that mimic the OpenSSL
 
746
 * X509_check_issued function (in x509v3/v3_purp.c)
 
747
 */
 
748
static SECStatus check_issuer_cert(PRFileDesc *sock,
 
749
                                   char *issuer_nickname)
 
750
{
 
751
  CERTCertificate *cert,*cert_issuer,*issuer;
 
752
  SECStatus res=SECSuccess;
 
753
  void *proto_win = NULL;
 
754
 
 
755
  /*
 
756
  PRArenaPool   *tmpArena = NULL;
 
757
  CERTAuthKeyID *authorityKeyID = NULL;
 
758
  SECITEM       *caname = NULL;
 
759
  */
 
760
 
 
761
  cert = SSL_PeerCertificate(sock);
 
762
  cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
 
763
 
 
764
  proto_win = SSL_RevealPinArg(sock);
 
765
  issuer = NULL;
 
766
  issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
 
767
 
 
768
  if ((!cert_issuer) || (!issuer))
 
769
    res = SECFailure;
 
770
  else if (SECITEM_CompareItem(&cert_issuer->derCert,
 
771
                               &issuer->derCert)!=SECEqual)
 
772
    res = SECFailure;
 
773
 
 
774
  CERT_DestroyCertificate(cert);
 
775
  CERT_DestroyCertificate(issuer);
 
776
  CERT_DestroyCertificate(cert_issuer);
 
777
  return res;
 
778
}
 
779
 
 
780
/**
 
781
 *
660
782
 * Callback to pick the SSL client certificate.
661
783
 */
662
784
static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
664
786
                                  struct CERTCertificateStr **pRetCert,
665
787
                                  struct SECKEYPrivateKeyStr **pRetKey)
666
788
{
667
 
  CERTCertificate *cert;
668
789
  SECKEYPrivateKey *privKey;
669
 
  char *nickname = (char *)arg;
 
790
  struct ssl_connect_data *connssl = (struct ssl_connect_data *) arg;
 
791
  char *nickname = connssl->client_nickname;
670
792
  void *proto_win = NULL;
671
793
  SECStatus secStatus = SECFailure;
672
794
  PK11SlotInfo *slot;
677
799
  if(!nickname)
678
800
    return secStatus;
679
801
 
680
 
  cert = PK11_FindCertFromNickname(nickname, proto_win);
681
 
  if(cert) {
 
802
  connssl->client_cert = PK11_FindCertFromNickname(nickname, proto_win);
 
803
  if(connssl->client_cert) {
682
804
 
683
805
    if(!strncmp(nickname, "PEM Token", 9)) {
684
806
      CK_SLOT_ID slotID = 1; /* hardcoded for now */
685
 
      char * slotname = (char *)malloc(SLOTSIZE);
 
807
      char slotname[SLOTSIZE];
686
808
      snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
687
809
      slot = PK11_FindSlotByName(slotname);
688
 
      privKey = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
 
810
      privKey = PK11_FindPrivateKeyFromCert(slot, connssl->client_cert, NULL);
689
811
      PK11_FreeSlot(slot);
690
 
      free(slotname);
691
812
      if(privKey) {
692
813
        secStatus = SECSuccess;
693
814
      }
694
815
    }
695
816
    else {
696
 
      privKey = PK11_FindKeyByAnyCert(cert, proto_win);
 
817
      privKey = PK11_FindKeyByAnyCert(connssl->client_cert, proto_win);
697
818
      if(privKey)
698
819
        secStatus = SECSuccess;
699
820
    }
700
821
  }
701
822
 
702
823
  if(secStatus == SECSuccess) {
703
 
    *pRetCert = cert;
 
824
    *pRetCert = connssl->client_cert;
704
825
    *pRetKey = privKey;
705
826
  }
706
827
  else {
707
 
    if(cert)
708
 
      CERT_DestroyCertificate(cert);
 
828
    if(connssl->client_cert)
 
829
      CERT_DestroyCertificate(connssl->client_cert);
 
830
    connssl->client_cert = NULL;
709
831
  }
710
832
 
711
833
  return secStatus;
719
841
 */
720
842
int Curl_nss_init(void)
721
843
{
722
 
  if(!initialized)
 
844
  /* curl_global_init() is not thread-safe so this test is ok */
 
845
  if (nss_initlock == NULL) {
723
846
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
 
847
    nss_initlock = PR_NewLock();
 
848
  }
724
849
 
725
850
  /* We will actually initialize NSS later */
726
851
 
730
855
/* Global cleanup */
731
856
void Curl_nss_cleanup(void)
732
857
{
733
 
  NSS_Shutdown();
 
858
  /* This function isn't required to be threadsafe and this is only done
 
859
   * as a safety feature.
 
860
   */
 
861
  PR_Lock(nss_initlock);
 
862
  if (initialized) {
 
863
    if(mod)
 
864
      SECMOD_DestroyModule(mod);
 
865
    mod = NULL;
 
866
    NSS_Shutdown();
 
867
  }
 
868
  PR_Unlock(nss_initlock);
 
869
 
 
870
  PR_DestroyLock(nss_initlock);
 
871
  nss_initlock = NULL;
 
872
 
734
873
  initialized = 0;
735
874
}
736
875
 
773
912
      free(connssl->client_nickname);
774
913
      connssl->client_nickname = NULL;
775
914
    }
 
915
    if(connssl->client_cert)
 
916
      CERT_DestroyCertificate(connssl->client_cert);
 
917
    if(connssl->key)
 
918
      (void)PK11_DestroyGenericObject(connssl->key);
 
919
    if(connssl->cacert[1])
 
920
      (void)PK11_DestroyGenericObject(connssl->cacert[1]);
 
921
    if(connssl->cacert[0])
 
922
      (void)PK11_DestroyGenericObject(connssl->cacert[0]);
776
923
    connssl->handle = NULL;
777
924
  }
778
925
}
787
934
  return 0;
788
935
}
789
936
 
790
 
CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
 
937
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
791
938
{
792
939
  PRInt32 err;
793
940
  PRFileDesc *model = NULL;
801
948
#endif
802
949
  char *certDir = NULL;
803
950
  int curlerr;
 
951
  const int *cipher_to_enable;
804
952
 
805
953
  curlerr = CURLE_SSL_CONNECT_ERROR;
806
954
 
 
955
  if (connssl->state == ssl_connection_complete)
 
956
    return CURLE_OK;
 
957
 
 
958
  connssl->client_cert = NULL;
 
959
  connssl->cacert[0] = NULL;
 
960
  connssl->cacert[1] = NULL;
 
961
  connssl->key = NULL;
 
962
 
807
963
  /* FIXME. NSS doesn't support multiple databases open at the same time. */
 
964
  PR_Lock(nss_initlock);
808
965
  if(!initialized) {
809
 
    initialized = 1;
810
966
 
811
967
    certDir = getenv("SSL_DIR"); /* Look in $SSL_DIR */
812
968
 
819
975
        }
820
976
    }
821
977
 
822
 
    if(!certDir) {
823
 
      rv = NSS_NoDB_Init(NULL);
824
 
    }
825
 
    else {
826
 
      rv = NSS_Initialize(certDir, NULL, NULL, "secmod.db",
827
 
                          NSS_INIT_READONLY);
828
 
    }
829
 
    if(rv != SECSuccess) {
830
 
      infof(conn->data, "Unable to initialize NSS database\n");
831
 
      curlerr = CURLE_SSL_CACERT_BADFILE;
 
978
    if (!NSS_IsInitialized()) {
 
979
      initialized = 1;
 
980
      if(!certDir) {
 
981
        rv = NSS_NoDB_Init(NULL);
 
982
      }
 
983
      else {
 
984
        rv = NSS_Initialize(certDir, NULL, NULL, "secmod.db",
 
985
                            NSS_INIT_READONLY);
 
986
      }
 
987
      if(rv != SECSuccess) {
 
988
        infof(conn->data, "Unable to initialize NSS database\n");
 
989
        curlerr = CURLE_SSL_CACERT_BADFILE;
 
990
        initialized = 0;
 
991
        PR_Unlock(nss_initlock);
 
992
        goto error;
 
993
      }
 
994
    }
 
995
 
 
996
    if(num_enabled_ciphers() == 0)
 
997
      NSS_SetDomesticPolicy();
 
998
 
 
999
#ifdef HAVE_PK11_CREATEGENERICOBJECT
 
1000
    configstring = aprintf("library=%s name=PEM", pem_library);
 
1001
    if(!configstring) {
 
1002
      PR_Unlock(nss_initlock);
832
1003
      goto error;
833
1004
    }
834
 
 
835
 
    NSS_SetDomesticPolicy();
836
 
 
837
 
#ifdef HAVE_PK11_CREATEGENERICOBJECT
838
 
    configstring = (char *)malloc(PATH_MAX);
839
 
 
840
 
    PR_snprintf(configstring, PATH_MAX, "library=%s name=PEM", pem_library);
841
 
 
842
1005
    mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
843
1006
    free(configstring);
 
1007
 
844
1008
    if(!mod || !mod->loaded) {
845
1009
      if(mod) {
846
1010
        SECMOD_DestroyModule(mod);
851
1015
    }
852
1016
#endif
853
1017
  }
 
1018
  PR_Unlock(nss_initlock);
854
1019
 
855
1020
  model = PR_NewTCPSocket();
856
1021
  if(!model)
892
1057
  if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
893
1058
    goto error;
894
1059
 
 
1060
  /* enable all ciphers from enable_ciphers_by_default */
 
1061
  cipher_to_enable = enable_ciphers_by_default;
 
1062
  while (SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
 
1063
    if (SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) {
 
1064
      curlerr = CURLE_SSL_CIPHER;
 
1065
      goto error;
 
1066
    }
 
1067
    cipher_to_enable++;
 
1068
  }
 
1069
 
895
1070
  if(data->set.ssl.cipher_list) {
896
1071
    if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
897
1072
      curlerr = CURLE_SSL_CIPHER;
912
1087
    /* skip the verifying of the peer */
913
1088
    ;
914
1089
  else if(data->set.ssl.CAfile) {
915
 
    int rc = nss_load_cert(data->set.ssl.CAfile, PR_TRUE);
 
1090
    int rc = nss_load_cert(&conn->ssl[sockindex], data->set.ssl.CAfile,
 
1091
                           PR_TRUE);
916
1092
    if(!rc) {
917
1093
      curlerr = CURLE_SSL_CACERT_BADFILE;
918
1094
      goto error;
940
1116
 
941
1117
          snprintf(fullpath, sizeof(fullpath), "%s/%s", data->set.ssl.CApath,
942
1118
                   entry->name);
943
 
          rc = nss_load_cert(fullpath, PR_TRUE);
 
1119
          rc = nss_load_cert(&conn->ssl[sockindex], fullpath, PR_TRUE);
944
1120
          /* FIXME: check this return value! */
945
1121
        }
946
 
      /* This is purposefully tolerant of errors so non-PEM files
947
 
       * can be in the same directory */
 
1122
        /* This is purposefully tolerant of errors so non-PEM files
 
1123
         * can be in the same directory */
948
1124
      } while(entry != NULL);
949
1125
      PR_CloseDir(dir);
950
1126
    }
955
1131
        data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
956
1132
        data->set.ssl.CApath ? data->set.ssl.CApath : "none");
957
1133
 
 
1134
  if (data->set.ssl.CRLfile) {
 
1135
    int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE);
 
1136
    if (!rc) {
 
1137
      curlerr = CURLE_SSL_CRL_BADFILE;
 
1138
      goto error;
 
1139
    }
 
1140
    infof(data,
 
1141
          "  CRLfile: %s\n",
 
1142
          data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
 
1143
  }
 
1144
 
958
1145
  if(data->set.str[STRING_CERT]) {
959
1146
    char *n;
960
1147
    char *nickname;
 
1148
    bool nickname_alloc = FALSE;
961
1149
 
962
 
    nickname = (char *)malloc(PATH_MAX);
963
1150
    if(is_file(data->set.str[STRING_CERT])) {
964
1151
      n = strrchr(data->set.str[STRING_CERT], '/');
965
1152
      if(n) {
966
1153
        n++; /* skip last slash */
967
 
        snprintf(nickname, PATH_MAX, "PEM Token #%ld:%s", 1, n);
 
1154
        nickname = aprintf("PEM Token #%d:%s", 1, n);
 
1155
        if(!nickname)
 
1156
          return CURLE_OUT_OF_MEMORY;
 
1157
 
 
1158
        nickname_alloc = TRUE;
968
1159
      }
969
1160
    }
970
1161
    else {
971
 
      strncpy(nickname, data->set.str[STRING_CERT], PATH_MAX);
 
1162
      nickname = data->set.str[STRING_CERT];
972
1163
    }
973
1164
    if(nss_Init_Tokens(conn) != SECSuccess) {
974
 
      free(nickname);
 
1165
      if(nickname_alloc)
 
1166
        free(nickname);
975
1167
      goto error;
976
1168
    }
977
 
    if(!cert_stuff(conn, data->set.str[STRING_CERT],
 
1169
    if(!cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
978
1170
                    data->set.str[STRING_KEY])) {
979
1171
      /* failf() is already done in cert_stuff() */
980
 
      free(nickname);
 
1172
      if(nickname_alloc)
 
1173
        free(nickname);
981
1174
      return CURLE_SSL_CERTPROBLEM;
982
1175
    }
983
1176
 
984
 
    connssl->client_nickname = strdup(nickname);
 
1177
    /* this "takes over" the pointer to the allocated name or makes a
 
1178
       dup of it */
 
1179
    connssl->client_nickname = nickname_alloc?nickname:strdup(nickname);
 
1180
    if(!connssl->client_nickname)
 
1181
      return CURLE_OUT_OF_MEMORY;
 
1182
 
985
1183
    if(SSL_GetClientAuthDataHook(model,
986
1184
                                 (SSLGetClientAuthData) SelectClientCert,
987
 
                                 (void *)connssl->client_nickname) !=
988
 
       SECSuccess) {
 
1185
                                 (void *)connssl) != SECSuccess) {
989
1186
      curlerr = CURLE_SSL_CERTPROBLEM;
990
1187
      goto error;
991
1188
    }
992
 
 
993
 
    free(nickname);
994
 
 
995
 
    PK11_SetPasswordFunc(nss_no_password);
996
1189
  }
997
1190
  else
998
1191
    connssl->client_nickname = NULL;
999
1192
 
 
1193
 
1000
1194
  /* Import our model socket  onto the existing file descriptor */
1001
1195
  connssl->handle = PR_ImportTCPSocket(sockfd);
1002
1196
  connssl->handle = SSL_ImportFD(model, connssl->handle);
1022
1216
 
1023
1217
  display_conn_info(conn, connssl->handle);
1024
1218
 
 
1219
  if (data->set.str[STRING_SSL_ISSUERCERT]) {
 
1220
    char *n;
 
1221
    char *nickname;
 
1222
    bool nickname_alloc = FALSE;
 
1223
    SECStatus ret;
 
1224
 
 
1225
    if(is_file(data->set.str[STRING_SSL_ISSUERCERT])) {
 
1226
      n = strrchr(data->set.str[STRING_SSL_ISSUERCERT], '/');
 
1227
      if (n) {
 
1228
        n++; /* skip last slash */
 
1229
        nickname = aprintf("PEM Token #%d:%s", 1, n);
 
1230
        if(!nickname)
 
1231
          return CURLE_OUT_OF_MEMORY;
 
1232
        nickname_alloc = TRUE;
 
1233
      }
 
1234
    }
 
1235
    else
 
1236
      nickname = data->set.str[STRING_SSL_ISSUERCERT];
 
1237
 
 
1238
    ret = check_issuer_cert(connssl->handle, nickname);
 
1239
 
 
1240
    if(nickname_alloc)
 
1241
      free(nickname);
 
1242
 
 
1243
    if(SECFailure == ret) {
 
1244
      infof(data,"SSL certificate issuer check failed\n");
 
1245
      curlerr = CURLE_SSL_ISSUER_ERROR;
 
1246
      goto error;
 
1247
    }
 
1248
    else {
 
1249
      infof(data, "SSL certificate issuer check ok\n");
 
1250
    }
 
1251
  }
 
1252
 
1025
1253
  return CURLE_OK;
1026
1254
 
1027
1255
error:
1035
1263
/* return number of sent (non-SSL) bytes */
1036
1264
int Curl_nss_send(struct connectdata *conn,  /* connection data */
1037
1265
                  int sockindex,             /* socketindex */
1038
 
                  void *mem,                 /* send this data */
 
1266
                  const void *mem,           /* send this data */
1039
1267
                  size_t len)                /* amount to write */
1040
1268
{
1041
1269
  PRInt32 err;