~ubuntu-branches/ubuntu/vivid/curl/vivid

« back to all changes in this revision

Viewing changes to lib/nss.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Schuldei
  • Date: 2009-04-02 23:35:45 UTC
  • mto: (1.2.1 upstream) (3.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 38.
  • Revision ID: james.westby@ubuntu.com-20090402233545-geixkwhe3izccjt7
Tags: upstream-7.19.4
ImportĀ upstreamĀ versionĀ 7.19.4

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.41 2009-02-27 08:53:10 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
67
#include "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
 
88
95
  PRInt32 version; /* protocol version valid for this cipher */
89
96
} cipher_s;
90
97
 
91
 
#ifdef NSS_ENABLE_ECC
92
 
#define ciphernum 48
93
 
#else
94
 
#define ciphernum 23
95
 
#endif
96
 
 
97
98
#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
98
99
                     (x)->pValue=(v); (x)->ulValueLen = (l)
99
100
 
101
102
 
102
103
enum sslversion { SSL2 = 1, SSL3 = 2, TLS = 4 };
103
104
 
104
 
static const cipher_s cipherlist[ciphernum] = {
 
105
#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
 
106
static const cipher_s cipherlist[] = {
105
107
  /* SSL2 cipher suites */
106
108
  {"rc4", SSL_EN_RC4_128_WITH_MD5, SSL2},
 
109
  {"rc4-md5", SSL_EN_RC4_128_WITH_MD5, SSL2},
107
110
  {"rc4export", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL2},
108
111
  {"rc2", SSL_EN_RC2_128_CBC_WITH_MD5, SSL2},
109
112
  {"rc2export", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2},
167
170
static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model,
168
171
                             char *cipher_list)
169
172
{
170
 
  int i;
171
 
  PRBool cipher_state[ciphernum];
 
173
  unsigned int i;
 
174
  PRBool cipher_state[NUM_OF_CIPHERS];
172
175
  PRBool found;
173
176
  char *cipher;
174
177
  SECStatus rv;
182
185
  }
183
186
 
184
187
  /* Set every entry in our list to false */
185
 
  for(i=0; i<ciphernum; i++) {
 
188
  for(i=0; i<NUM_OF_CIPHERS; i++) {
186
189
    cipher_state[i] = PR_FALSE;
187
190
  }
188
191
 
198
201
 
199
202
    found = PR_FALSE;
200
203
 
201
 
    for(i=0; i<ciphernum; i++) {
202
 
      if(!strcasecmp(cipher, cipherlist[i].name)) {
 
204
    for(i=0; i<NUM_OF_CIPHERS; i++) {
 
205
      if(Curl_raw_equal(cipher, cipherlist[i].name)) {
203
206
        cipher_state[i] = PR_TRUE;
204
207
        found = PR_TRUE;
205
208
        break;
217
220
  }
218
221
 
219
222
  /* Finally actually enable the selected ciphers */
220
 
  for(i=0; i<ciphernum; i++) {
 
223
  for(i=0; i<NUM_OF_CIPHERS; i++) {
221
224
    rv = SSL_CipherPrefSet(model, cipherlist[i].num, cipher_state[i]);
222
225
    if(rv != SECSuccess) {
223
226
      failf(data, "Unknown cipher in cipher list");
229
232
}
230
233
 
231
234
/*
 
235
 * Get the number of ciphers that are enabled. We use this to determine
 
236
 * if we need to call NSS_SetDomesticPolicy() to enable the default ciphers.
 
237
 */
 
238
static int num_enabled_ciphers(void)
 
239
{
 
240
  PRInt32 policy = 0;
 
241
  int count = 0;
 
242
  unsigned int i;
 
243
 
 
244
  for(i=0; i<NUM_OF_CIPHERS; i++) {
 
245
    SSL_CipherPolicyGet(cipherlist[i].num, &policy);
 
246
    if(policy)
 
247
      count++;
 
248
  }
 
249
  return count;
 
250
}
 
251
 
 
252
/*
232
253
 * Determine whether the nickname passed in is a filename that needs to
233
254
 * be loaded as a PEM or a regular NSS nickname.
234
255
 *
261
282
  CK_BBOOL cktrue = CK_TRUE;
262
283
  CK_BBOOL ckfalse = CK_FALSE;
263
284
  CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
264
 
  char *slotname = NULL;
 
285
  char slotname[SLOTSIZE];
265
286
#endif
266
287
  CERTCertificate *cert;
267
288
  char *nickname = NULL;
282
303
    if(cacert)
283
304
      return 0; /* You can't specify an NSS CA nickname this way */
284
305
    nickname = strdup(filename);
 
306
    if(!nickname)
 
307
      return 0;
285
308
    goto done;
286
309
  }
287
310
 
297
320
  else
298
321
    slotID = 1;
299
322
 
300
 
  slotname = (char *)malloc(SLOTSIZE);
301
 
  nickname = (char *)malloc(PATH_MAX);
302
323
  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
303
 
  snprintf(nickname, PATH_MAX, "PEM Token #%ld:%s", slotID, n);
 
324
 
 
325
  nickname = aprintf("PEM Token #%ld:%s", slotID, n);
 
326
  if(!nickname)
 
327
    return 0;
304
328
 
305
329
  slot = PK11_FindSlotByName(slotname);
306
330
 
307
331
  if(!slot) {
308
 
    free(slotname);
309
332
    free(nickname);
310
333
    return 0;
311
334
  }
312
335
 
313
 
  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
314
 
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
 
336
  PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass) );
 
337
  attrs++;
 
338
  PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) );
 
339
  attrs++;
315
340
  PK11_SETATTRS(attrs, CKA_LABEL, (unsigned char *)filename,
316
 
                strlen(filename)+1); attrs++;
 
341
                strlen(filename)+1);
 
342
  attrs++;
317
343
  if(cacert) {
318
 
    PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); attrs++;
 
344
    PK11_SETATTRS(attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) );
319
345
  }
320
346
  else {
321
 
    PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); attrs++;
 
347
    PK11_SETATTRS(attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) );
322
348
  }
 
349
  attrs++;
323
350
 
324
351
  /* This load the certificate in our PEM module into the appropriate
325
352
   * slot.
328
355
 
329
356
  PK11_FreeSlot(slot);
330
357
 
331
 
  free(slotname);
332
358
  if(rv == NULL) {
333
359
    free(nickname);
334
360
    return 0;
362
388
  return 1;
363
389
}
364
390
 
 
391
static int nss_load_crl(const char* crlfilename, PRBool ascii)
 
392
{
 
393
  PRFileDesc *infile;
 
394
  PRStatus    prstat;
 
395
  PRFileInfo  info;
 
396
  PRInt32     nb;
 
397
  int rv;
 
398
  SECItem crlDER;
 
399
  CERTSignedCrl *crl=NULL;
 
400
  PK11SlotInfo *slot=NULL;
 
401
 
 
402
  infile = PR_Open(crlfilename,PR_RDONLY,0);
 
403
  if (!infile) {
 
404
    return 0;
 
405
  }
 
406
  crlDER.data = NULL;
 
407
  prstat = PR_GetOpenFileInfo(infile,&info);
 
408
  if (prstat!=PR_SUCCESS)
 
409
    return 0;
 
410
  if (ascii) {
 
411
    SECItem filedata;
 
412
    char *asc,*body;
 
413
    filedata.data = NULL;
 
414
    if (!SECITEM_AllocItem(NULL,&filedata,info.size))
 
415
      return 0;
 
416
    nb = PR_Read(infile,filedata.data,info.size);
 
417
    if (nb!=info.size)
 
418
      return 0;
 
419
    asc = (char*)filedata.data;
 
420
    if (!asc)
 
421
      return 0;
 
422
 
 
423
    body=strstr(asc,"-----BEGIN");
 
424
    if (body != NULL) {
 
425
      char *trailer=NULL;
 
426
      asc = body;
 
427
      body = PORT_Strchr(asc,'\n');
 
428
      if (!body)
 
429
        body = PORT_Strchr(asc,'\r');
 
430
      if (body)
 
431
        trailer = strstr(++body,"-----END");
 
432
      if (trailer!=NULL)
 
433
        *trailer='\0';
 
434
      else
 
435
        return 0;
 
436
    }
 
437
    else {
 
438
      body = asc;
 
439
    }
 
440
    rv = ATOB_ConvertAsciiToItem(&crlDER,body);
 
441
    PORT_Free(filedata.data);
 
442
    if (rv)
 
443
      return 0;
 
444
  }
 
445
  else {
 
446
    if (!SECITEM_AllocItem(NULL,&crlDER,info.size))
 
447
      return 0;
 
448
    nb = PR_Read(infile,crlDER.data,info.size);
 
449
    if (nb!=info.size)
 
450
      return 0;
 
451
  }
 
452
 
 
453
  slot = PK11_GetInternalKeySlot();
 
454
  crl  = PK11_ImportCRL(slot,&crlDER,
 
455
                        NULL,SEC_CRL_TYPE,
 
456
                        NULL,CRL_IMPORT_DEFAULT_OPTIONS,
 
457
                        NULL,(CRL_DECODE_DEFAULT_OPTIONS|
 
458
                              CRL_DECODE_DONT_COPY_DER));
 
459
  if (slot) PK11_FreeSlot(slot);
 
460
  if (!crl) return 0;
 
461
  SEC_DestroyCrl(crl);
 
462
  return 1;
 
463
}
 
464
 
365
465
static int nss_load_key(struct connectdata *conn, char *key_file)
366
466
{
367
467
#ifdef HAVE_PK11_CREATEGENERICOBJECT
372
472
  CK_BBOOL cktrue = CK_TRUE;
373
473
  CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
374
474
  CK_SLOT_ID slotID;
375
 
  char *slotname = NULL;
376
475
  pphrase_arg_t *parg = NULL;
 
476
  char slotname[SLOTSIZE];
377
477
 
378
478
  attrs = theTemplate;
379
479
 
381
481
 
382
482
  slotID = 1; /* hardcoded for now */
383
483
 
384
 
  slotname = (char *)malloc(SLOTSIZE);
385
 
  snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
386
 
 
 
484
  snprintf(slotname, sizeof(slotname), "PEM Token #%ld", slotID);
387
485
  slot = PK11_FindSlotByName(slotname);
388
 
  free(slotname);
389
486
 
390
487
  if(!slot)
391
488
    return 0;
406
503
  SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
407
504
  PK11_IsPresent(slot);
408
505
 
409
 
  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
 
506
  parg = malloc(sizeof(pphrase_arg_t));
 
507
  if(!parg)
 
508
    return 0;
410
509
  parg->retryCount = 0;
411
510
  parg->data = conn->data;
412
511
  /* parg is initialized in nss_Init_Tokens() */
502
601
  SECStatus ret, status = SECSuccess;
503
602
  pphrase_arg_t *parg = NULL;
504
603
 
505
 
  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
 
604
  parg = malloc(sizeof(pphrase_arg_t));
 
605
  if(!parg)
 
606
    return SECFailure;
 
607
 
506
608
  parg->retryCount = 0;
507
609
  parg->data = conn->data;
508
610
 
620
722
  PRTime notBefore, notAfter;
621
723
 
622
724
  if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
623
 
    SECSuccess && channel.length == sizeof channel &&
624
 
    channel.cipherSuite) {
 
725
     SECSuccess && channel.length == sizeof channel &&
 
726
     channel.cipherSuite) {
625
727
    if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
626
 
      &suite, sizeof suite) == SECSuccess) {
 
728
                              &suite, sizeof suite) == SECSuccess) {
627
729
      infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
628
730
    }
629
731
  }
657
759
 
658
760
/**
659
761
 *
 
762
 * Check that the Peer certificate's issuer certificate matches the one found
 
763
 * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
 
764
 * issuer check, so we provide comments that mimic the OpenSSL
 
765
 * X509_check_issued function (in x509v3/v3_purp.c)
 
766
 */
 
767
static SECStatus check_issuer_cert(PRFileDesc *sock,
 
768
                                   char *issuer_nickname)
 
769
{
 
770
  CERTCertificate *cert,*cert_issuer,*issuer;
 
771
  SECStatus res=SECSuccess;
 
772
  void *proto_win = NULL;
 
773
 
 
774
  /*
 
775
  PRArenaPool   *tmpArena = NULL;
 
776
  CERTAuthKeyID *authorityKeyID = NULL;
 
777
  SECITEM       *caname = NULL;
 
778
  */
 
779
 
 
780
  cert = SSL_PeerCertificate(sock);
 
781
  cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);
 
782
 
 
783
  proto_win = SSL_RevealPinArg(sock);
 
784
  issuer = NULL;
 
785
  issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);
 
786
 
 
787
  if ((!cert_issuer) || (!issuer))
 
788
    res = SECFailure;
 
789
  else if (SECITEM_CompareItem(&cert_issuer->derCert,
 
790
                               &issuer->derCert)!=SECEqual)
 
791
    res = SECFailure;
 
792
 
 
793
  CERT_DestroyCertificate(cert);
 
794
  CERT_DestroyCertificate(issuer);
 
795
  CERT_DestroyCertificate(cert_issuer);
 
796
  return res;
 
797
}
 
798
 
 
799
/**
 
800
 *
660
801
 * Callback to pick the SSL client certificate.
661
802
 */
662
803
static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
682
823
 
683
824
    if(!strncmp(nickname, "PEM Token", 9)) {
684
825
      CK_SLOT_ID slotID = 1; /* hardcoded for now */
685
 
      char * slotname = (char *)malloc(SLOTSIZE);
 
826
      char slotname[SLOTSIZE];
686
827
      snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
687
828
      slot = PK11_FindSlotByName(slotname);
688
829
      privKey = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
689
830
      PK11_FreeSlot(slot);
690
 
      free(slotname);
691
831
      if(privKey) {
692
832
        secStatus = SECSuccess;
693
833
      }
719
859
 */
720
860
int Curl_nss_init(void)
721
861
{
722
 
  if(!initialized)
 
862
  /* curl_global_init() is not thread-safe so this test is ok */
 
863
  if (nss_initlock == NULL) {
723
864
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
 
865
    nss_initlock = PR_NewLock();
 
866
  }
724
867
 
725
868
  /* We will actually initialize NSS later */
726
869
 
730
873
/* Global cleanup */
731
874
void Curl_nss_cleanup(void)
732
875
{
733
 
  NSS_Shutdown();
 
876
  /* This function isn't required to be threadsafe and this is only done
 
877
   * as a safety feature.
 
878
   */
 
879
  PR_Lock(nss_initlock);
 
880
  if (initialized)
 
881
    NSS_Shutdown();
 
882
  PR_Unlock(nss_initlock);
 
883
 
 
884
  PR_DestroyLock(nss_initlock);
 
885
  nss_initlock = NULL;
 
886
 
734
887
  initialized = 0;
735
888
}
736
889
 
787
940
  return 0;
788
941
}
789
942
 
790
 
CURLcode Curl_nss_connect(struct connectdata * conn, int sockindex)
 
943
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
791
944
{
792
945
  PRInt32 err;
793
946
  PRFileDesc *model = NULL;
804
957
 
805
958
  curlerr = CURLE_SSL_CONNECT_ERROR;
806
959
 
 
960
  if (connssl->state == ssl_connection_complete)
 
961
    return CURLE_OK;
 
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)
943
1108
          rc = nss_load_cert(fullpath, PR_TRUE);
944
1109
          /* FIXME: check this return value! */
945
1110
        }
946
 
      /* This is purposefully tolerant of errors so non-PEM files
947
 
       * can be in the same directory */
 
1111
        /* This is purposefully tolerant of errors so non-PEM files
 
1112
         * can be in the same directory */
948
1113
      } while(entry != NULL);
949
1114
      PR_CloseDir(dir);
950
1115
    }
955
1120
        data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
956
1121
        data->set.ssl.CApath ? data->set.ssl.CApath : "none");
957
1122
 
 
1123
  if (data->set.ssl.CRLfile) {
 
1124
    int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE);
 
1125
    if (!rc) {
 
1126
      curlerr = CURLE_SSL_CRL_BADFILE;
 
1127
      goto error;
 
1128
    }
 
1129
    infof(data,
 
1130
          "  CRLfile: %s\n",
 
1131
          data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
 
1132
  }
 
1133
 
958
1134
  if(data->set.str[STRING_CERT]) {
959
1135
    char *n;
960
1136
    char *nickname;
 
1137
    bool nickname_alloc = FALSE;
961
1138
 
962
 
    nickname = (char *)malloc(PATH_MAX);
963
1139
    if(is_file(data->set.str[STRING_CERT])) {
964
1140
      n = strrchr(data->set.str[STRING_CERT], '/');
965
1141
      if(n) {
966
1142
        n++; /* skip last slash */
967
 
        snprintf(nickname, PATH_MAX, "PEM Token #%ld:%s", 1, n);
 
1143
        nickname = aprintf("PEM Token #%d:%s", 1, n);
 
1144
        if(!nickname)
 
1145
          return CURLE_OUT_OF_MEMORY;
 
1146
 
 
1147
        nickname_alloc = TRUE;
968
1148
      }
969
1149
    }
970
1150
    else {
971
 
      strncpy(nickname, data->set.str[STRING_CERT], PATH_MAX);
 
1151
      nickname = data->set.str[STRING_CERT];
972
1152
    }
973
1153
    if(nss_Init_Tokens(conn) != SECSuccess) {
974
 
      free(nickname);
 
1154
      if(nickname_alloc)
 
1155
        free(nickname);
975
1156
      goto error;
976
1157
    }
977
1158
    if(!cert_stuff(conn, data->set.str[STRING_CERT],
978
1159
                    data->set.str[STRING_KEY])) {
979
1160
      /* failf() is already done in cert_stuff() */
980
 
      free(nickname);
 
1161
      if(nickname_alloc)
 
1162
        free(nickname);
981
1163
      return CURLE_SSL_CERTPROBLEM;
982
1164
    }
983
1165
 
984
 
    connssl->client_nickname = strdup(nickname);
 
1166
    /* this "takes over" the pointer to the allocated name or makes a
 
1167
       dup of it */
 
1168
    connssl->client_nickname = nickname_alloc?nickname:strdup(nickname);
 
1169
    if(!connssl->client_nickname)
 
1170
      return CURLE_OUT_OF_MEMORY;
 
1171
 
985
1172
    if(SSL_GetClientAuthDataHook(model,
986
1173
                                 (SSLGetClientAuthData) SelectClientCert,
987
1174
                                 (void *)connssl->client_nickname) !=
990
1177
      goto error;
991
1178
    }
992
1179
 
993
 
    free(nickname);
994
 
 
995
1180
    PK11_SetPasswordFunc(nss_no_password);
996
1181
  }
997
1182
  else
998
1183
    connssl->client_nickname = NULL;
999
1184
 
 
1185
 
1000
1186
  /* Import our model socket  onto the existing file descriptor */
1001
1187
  connssl->handle = PR_ImportTCPSocket(sockfd);
1002
1188
  connssl->handle = SSL_ImportFD(model, connssl->handle);
1022
1208
 
1023
1209
  display_conn_info(conn, connssl->handle);
1024
1210
 
 
1211
  if (data->set.str[STRING_SSL_ISSUERCERT]) {
 
1212
    char *n;
 
1213
    char *nickname;
 
1214
    bool nickname_alloc = FALSE;
 
1215
    SECStatus ret;
 
1216
 
 
1217
    if(is_file(data->set.str[STRING_SSL_ISSUERCERT])) {
 
1218
      n = strrchr(data->set.str[STRING_SSL_ISSUERCERT], '/');
 
1219
      if (n) {
 
1220
        n++; /* skip last slash */
 
1221
        nickname = aprintf("PEM Token #%d:%s", 1, n);
 
1222
        if(!nickname)
 
1223
          return CURLE_OUT_OF_MEMORY;
 
1224
        nickname_alloc = TRUE;
 
1225
      }
 
1226
    }
 
1227
    else
 
1228
      nickname = data->set.str[STRING_SSL_ISSUERCERT];
 
1229
 
 
1230
    ret = check_issuer_cert(connssl->handle, nickname);
 
1231
 
 
1232
    if(nickname_alloc)
 
1233
      free(nickname);
 
1234
 
 
1235
    if(SECFailure == ret) {
 
1236
      infof(data,"SSL certificate issuer check failed\n");
 
1237
      curlerr = CURLE_SSL_ISSUER_ERROR;
 
1238
      goto error;
 
1239
    }
 
1240
    else {
 
1241
      infof(data, "SSL certificate issuer check ok\n");
 
1242
    }
 
1243
  }
 
1244
 
1025
1245
  return CURLE_OK;
1026
1246
 
1027
1247
error:
1035
1255
/* return number of sent (non-SSL) bytes */
1036
1256
int Curl_nss_send(struct connectdata *conn,  /* connection data */
1037
1257
                  int sockindex,             /* socketindex */
1038
 
                  void *mem,                 /* send this data */
 
1258
                  const void *mem,           /* send this data */
1039
1259
                  size_t len)                /* amount to write */
1040
1260
{
1041
1261
  PRInt32 err;