~ubuntu-branches/ubuntu/lucid/curl/lucid-201101212007

« back to all changes in this revision

Viewing changes to lib/nss.c

  • Committer: Bazaar Package Importer
  • Author(s): Domenico Andreoli
  • Date: 2009-11-05 10:11:57 UTC
  • mto: (3.3.3 squeeze)
  • mto: This revision was merged to the branch mainline in revision 41.
  • Revision ID: james.westby@ubuntu.com-20091105101157-bj4sosg9l00k9c08
Tags: upstream-7.19.7
ImportĀ upstreamĀ versionĀ 7.19.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.47 2009-05-11 09:13:49 bagder Exp $
 
21
 * $Id: nss.c,v 1.62 2009-10-28 20:30:24 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/*
63
63
#include <secitem.h>
64
64
#include <secport.h>
65
65
#include <certdb.h>
 
66
#include <base64.h>
66
67
 
67
68
#include "curl_memory.h"
68
69
#include "rawstr.h"
157
158
#endif
158
159
};
159
160
 
160
 
/* following ciphers are new in NSS 3.4 and not enabled by default, therefor
 
161
/* following ciphers are new in NSS 3.4 and not enabled by default, therefore
161
162
   they are enabled explicitly */
162
163
static const int enable_ciphers_by_default[] = {
163
164
  TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
265
266
 */
266
267
static int is_file(const char *filename)
267
268
{
268
 
  struct stat st;
 
269
  struct_stat st;
269
270
 
270
271
  if(filename == NULL)
271
272
    return 0;
277
278
  return 0;
278
279
}
279
280
 
 
281
static char *fmt_nickname(char *str, bool *nickname_alloc)
 
282
{
 
283
    char *nickname = NULL;
 
284
    *nickname_alloc = FALSE;
 
285
 
 
286
    if(is_file(str)) {
 
287
      char *n = strrchr(str, '/');
 
288
      if(n) {
 
289
        *nickname_alloc = TRUE;
 
290
        n++; /* skip last slash */
 
291
        nickname = aprintf("PEM Token #%d:%s", 1, n);
 
292
      }
 
293
      return nickname;
 
294
    }
 
295
 
 
296
    return str;
 
297
}
 
298
 
280
299
static int nss_load_cert(struct ssl_connect_data *ssl,
281
300
                         const char *filename, PRBool cacert)
282
301
{
585
604
    return (char *)PORT_Strdup((char *)arg);
586
605
}
587
606
 
588
 
static SECStatus nss_Init_Tokens(struct connectdata * conn)
589
 
{
590
 
  PK11SlotList *slotList;
591
 
  PK11SlotListElement *listEntry;
592
 
  SECStatus ret, status = SECSuccess;
593
 
 
594
 
  PK11_SetPasswordFunc(nss_get_password);
595
 
 
596
 
  slotList =
597
 
    PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);
598
 
 
599
 
  for(listEntry = PK11_GetFirstSafe(slotList);
600
 
      listEntry; listEntry = listEntry->next) {
601
 
    PK11SlotInfo *slot = listEntry->slot;
602
 
 
603
 
    if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
604
 
      if(slot == PK11_GetInternalKeySlot()) {
605
 
        failf(conn->data, "The NSS database has not been initialized");
606
 
      }
607
 
      else {
608
 
        failf(conn->data, "The token %s has not been initialized",
609
 
              PK11_GetTokenName(slot));
610
 
      }
611
 
      PK11_FreeSlot(slot);
612
 
      continue;
613
 
    }
614
 
 
615
 
    ret = PK11_Authenticate(slot, PR_TRUE,
616
 
                            conn->data->set.str[STRING_KEY_PASSWD]);
617
 
    if(SECSuccess != ret) {
618
 
      if(PR_GetError() == SEC_ERROR_BAD_PASSWORD)
619
 
        infof(conn->data, "The password for token '%s' is incorrect\n",
620
 
              PK11_GetTokenName(slot));
621
 
      status = SECFailure;
622
 
      break;
623
 
    }
624
 
    PK11_FreeSlot(slot);
625
 
  }
626
 
 
627
 
  return status;
628
 
}
629
 
 
630
607
static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
631
608
{
632
609
  SECStatus success = SECSuccess;
633
610
  struct connectdata *conn = (struct connectdata *)arg;
634
611
  PRErrorCode err = PR_GetError();
635
612
  CERTCertificate *cert = NULL;
636
 
  char *subject, *issuer;
 
613
  char *subject, *subject_cn, *issuer;
637
614
 
638
615
  if(conn->data->set.ssl.certverifyresult!=0)
639
616
    return success;
641
618
  conn->data->set.ssl.certverifyresult=err;
642
619
  cert = SSL_PeerCertificate(sock);
643
620
  subject = CERT_NameToAscii(&cert->subject);
 
621
  subject_cn = CERT_GetCommonName(&cert->subject);
644
622
  issuer = CERT_NameToAscii(&cert->issuer);
645
623
  CERT_DestroyCertificate(cert);
646
624
 
657
635
          issuer);
658
636
    break;
659
637
  case SSL_ERROR_BAD_CERT_DOMAIN:
660
 
    if(conn->data->set.ssl.verifypeer)
 
638
    if(conn->data->set.ssl.verifyhost) {
 
639
      failf(conn->data, "SSL: certificate subject name '%s' does not match "
 
640
            "target host name '%s'", subject_cn, conn->host.dispname);
661
641
      success = SECFailure;
662
 
    infof(conn->data, "common name: %s (does not match '%s')\n",
663
 
          subject, conn->host.dispname);
 
642
    } else {
 
643
      infof(conn->data, "warning: SSL: certificate subject name '%s' does not "
 
644
            "match target host name '%s'\n", subject_cn, conn->host.dispname);
 
645
    }
664
646
    break;
665
647
  case SEC_ERROR_EXPIRED_CERTIFICATE:
666
648
    if(conn->data->set.ssl.verifypeer)
667
649
      success = SECFailure;
668
650
    infof(conn->data, "Remote Certificate has expired.\n");
669
651
    break;
 
652
  case SEC_ERROR_UNKNOWN_ISSUER:
 
653
    if(conn->data->set.ssl.verifypeer)
 
654
      success = SECFailure;
 
655
    infof(conn->data, "Peer's certificate issuer is not recognized: '%s'\n",
 
656
          issuer);
 
657
    break;
670
658
  default:
671
659
    if(conn->data->set.ssl.verifypeer)
672
660
      success = SECFailure;
677
665
  if(success == SECSuccess)
678
666
    infof(conn->data, "SSL certificate verify ok.\n");
679
667
  PR_Free(subject);
 
668
  PR_Free(subject_cn);
680
669
  PR_Free(issuer);
681
670
 
682
671
  return success;
692
681
  return SECSuccess;
693
682
}
694
683
 
 
684
static void display_cert_info(struct SessionHandle *data, CERTCertificate *cert) {
 
685
    char *subject, *issuer, *common_name;
 
686
    PRExplodedTime printableTime;
 
687
    char timeString[256];
 
688
    PRTime notBefore, notAfter;
 
689
 
 
690
    subject = CERT_NameToAscii(&cert->subject);
 
691
    issuer = CERT_NameToAscii(&cert->issuer);
 
692
    common_name = CERT_GetCommonName(&cert->subject);
 
693
    infof(data, "\tsubject: %s\n", subject);
 
694
 
 
695
    CERT_GetCertTimes(cert, &notBefore, &notAfter);
 
696
    PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
 
697
    PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
 
698
    infof(data, "\tstart date: %s\n", timeString);
 
699
    PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
 
700
    PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
 
701
    infof(data, "\texpire date: %s\n", timeString);
 
702
    infof(data, "\tcommon name: %s\n", common_name);
 
703
    infof(data, "\tissuer: %s\n", issuer);
 
704
 
 
705
    PR_Free(subject);
 
706
    PR_Free(issuer);
 
707
    PR_Free(common_name);
 
708
}
 
709
 
695
710
static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
696
711
{
697
712
  SSLChannelInfo channel;
698
713
  SSLCipherSuiteInfo suite;
699
714
  CERTCertificate *cert;
700
 
  char *subject, *issuer, *common_name;
701
 
  PRExplodedTime printableTime;
702
 
  char timeString[256];
703
 
  PRTime notBefore, notAfter;
704
715
 
705
716
  if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
706
717
     SECSuccess && channel.length == sizeof channel &&
714
725
  infof(conn->data, "Server certificate:\n");
715
726
 
716
727
  cert = SSL_PeerCertificate(sock);
717
 
  subject = CERT_NameToAscii(&cert->subject);
718
 
  issuer = CERT_NameToAscii(&cert->issuer);
719
 
  common_name = CERT_GetCommonName(&cert->subject);
720
 
  infof(conn->data, "\tsubject: %s\n", subject);
721
 
 
722
 
  CERT_GetCertTimes(cert, &notBefore, &notAfter);
723
 
  PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
724
 
  PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
725
 
  infof(conn->data, "\tstart date: %s\n", timeString);
726
 
  PR_ExplodeTime(notAfter, PR_GMTParameters, &printableTime);
727
 
  PR_FormatTime(timeString, 256, "%b %d %H:%M:%S %Y GMT", &printableTime);
728
 
  infof(conn->data, "\texpire date: %s\n", timeString);
729
 
  infof(conn->data, "\tcommon name: %s\n", common_name);
730
 
  infof(conn->data, "\tissuer: %s\n", issuer);
731
 
 
732
 
  PR_Free(subject);
733
 
  PR_Free(issuer);
734
 
  PR_Free(common_name);
735
 
 
 
728
  display_cert_info(conn->data, cert);
736
729
  CERT_DestroyCertificate(cert);
737
730
 
738
731
  return;
786
779
                                  struct CERTCertificateStr **pRetCert,
787
780
                                  struct SECKEYPrivateKeyStr **pRetKey)
788
781
{
789
 
  SECKEYPrivateKey *privKey;
790
 
  struct ssl_connect_data *connssl = (struct ssl_connect_data *) arg;
791
 
  char *nickname = connssl->client_nickname;
792
 
  void *proto_win = NULL;
793
 
  SECStatus secStatus = SECFailure;
794
 
  PK11SlotInfo *slot;
795
 
  (void)caNames;
796
 
 
797
 
  proto_win = SSL_RevealPinArg(sock);
798
 
 
799
 
  if(!nickname)
800
 
    return secStatus;
801
 
 
802
 
  connssl->client_cert = PK11_FindCertFromNickname(nickname, proto_win);
803
 
  if(connssl->client_cert) {
804
 
 
805
 
    if(!strncmp(nickname, "PEM Token", 9)) {
806
 
      CK_SLOT_ID slotID = 1; /* hardcoded for now */
807
 
      char slotname[SLOTSIZE];
808
 
      snprintf(slotname, SLOTSIZE, "PEM Token #%ld", slotID);
809
 
      slot = PK11_FindSlotByName(slotname);
810
 
      privKey = PK11_FindPrivateKeyFromCert(slot, connssl->client_cert, NULL);
811
 
      PK11_FreeSlot(slot);
812
 
      if(privKey) {
813
 
        secStatus = SECSuccess;
814
 
      }
815
 
    }
816
 
    else {
817
 
      privKey = PK11_FindKeyByAnyCert(connssl->client_cert, proto_win);
818
 
      if(privKey)
819
 
        secStatus = SECSuccess;
820
 
    }
821
 
  }
822
 
 
823
 
  if(secStatus == SECSuccess) {
824
 
    *pRetCert = connssl->client_cert;
825
 
    *pRetKey = privKey;
826
 
  }
827
 
  else {
828
 
    if(connssl->client_cert)
829
 
      CERT_DestroyCertificate(connssl->client_cert);
830
 
    connssl->client_cert = NULL;
831
 
  }
832
 
 
833
 
  return secStatus;
 
782
  static const char pem_nickname[] = "PEM Token #1";
 
783
  const char *pem_slotname = pem_nickname;
 
784
 
 
785
  struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
 
786
  struct SessionHandle *data = connssl->data;
 
787
  const char *nickname = connssl->client_nickname;
 
788
 
 
789
  if (mod && nickname &&
 
790
      0 == strncmp(nickname, pem_nickname, /* length of "PEM Token" */ 9)) {
 
791
 
 
792
    /* use the cert/key provided by PEM reader */
 
793
    PK11SlotInfo *slot;
 
794
    void *proto_win = SSL_RevealPinArg(sock);
 
795
    *pRetKey = NULL;
 
796
 
 
797
    *pRetCert = PK11_FindCertFromNickname(nickname, proto_win);
 
798
    if (NULL == *pRetCert) {
 
799
      failf(data, "NSS: client certificate not found: %s", nickname);
 
800
      return SECFailure;
 
801
    }
 
802
 
 
803
    slot = PK11_FindSlotByName(pem_slotname);
 
804
    if (NULL == slot) {
 
805
      failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
 
806
      return SECFailure;
 
807
    }
 
808
 
 
809
    *pRetKey = PK11_FindPrivateKeyFromCert(slot, *pRetCert, NULL);
 
810
    PK11_FreeSlot(slot);
 
811
    if (NULL == *pRetKey) {
 
812
      failf(data, "NSS: private key not found for certificate: %s", nickname);
 
813
      return SECFailure;
 
814
    }
 
815
 
 
816
    infof(data, "NSS: client certificate: %s\n", nickname);
 
817
    display_cert_info(data, *pRetCert);
 
818
    return SECSuccess;
 
819
  }
 
820
 
 
821
  /* use the default NSS hook */
 
822
  if (SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
 
823
                                          pRetCert, pRetKey)
 
824
      || NULL == *pRetCert) {
 
825
 
 
826
    if (NULL == nickname)
 
827
      failf(data, "NSS: client certificate not found (nickname not specified)");
 
828
    else
 
829
      failf(data, "NSS: client certificate not found: %s", nickname);
 
830
 
 
831
    return SECFailure;
 
832
  }
 
833
 
 
834
  /* get certificate nickname if any */
 
835
  nickname = (*pRetCert)->nickname;
 
836
  if (NULL == nickname)
 
837
    nickname = "[unknown]";
 
838
 
 
839
  if (NULL == *pRetKey) {
 
840
    failf(data, "NSS: private key not found for certificate: %s", nickname);
 
841
    return SECFailure;
 
842
  }
 
843
 
 
844
  infof(data, "NSS: using client certificate: %s\n", nickname);
 
845
  display_cert_info(data, *pRetCert);
 
846
  return SECSuccess;
834
847
}
835
848
 
836
849
/**
860
873
   */
861
874
  PR_Lock(nss_initlock);
862
875
  if (initialized) {
863
 
    if(mod)
 
876
    /* Free references to client certificates held in the SSL session cache.
 
877
     * Omitting this hampers destruction of the security module owning
 
878
     * the certificates. */
 
879
    SSL_ClearSessionCache();
 
880
 
 
881
    if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
864
882
      SECMOD_DestroyModule(mod);
865
 
    mod = NULL;
 
883
      mod = NULL;
 
884
    }
866
885
    NSS_Shutdown();
867
886
  }
868
887
  PR_Unlock(nss_initlock);
908
927
 
909
928
  if(connssl->handle) {
910
929
    PR_Close(connssl->handle);
 
930
 
 
931
    /* NSS closes the socket we previously handed to it, so we must mark it
 
932
       as closed to avoid double close */
 
933
    fake_sclose(conn->sock[sockindex]);
 
934
    conn->sock[sockindex] = CURL_SOCKET_BAD;
911
935
    if(connssl->client_nickname != NULL) {
912
936
      free(connssl->client_nickname);
913
937
      connssl->client_nickname = NULL;
914
938
    }
915
 
    if(connssl->client_cert)
916
 
      CERT_DestroyCertificate(connssl->client_cert);
 
939
#ifdef HAVE_PK11_CREATEGENERICOBJECT
917
940
    if(connssl->key)
918
941
      (void)PK11_DestroyGenericObject(connssl->key);
919
942
    if(connssl->cacert[1])
920
943
      (void)PK11_DestroyGenericObject(connssl->cacert[1]);
921
944
    if(connssl->cacert[0])
922
945
      (void)PK11_DestroyGenericObject(connssl->cacert[0]);
 
946
#endif
923
947
    connssl->handle = NULL;
924
948
  }
925
949
}
943
967
  curl_socket_t sockfd = conn->sock[sockindex];
944
968
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
945
969
  SECStatus rv;
946
 
#ifdef HAVE_PK11_CREATEGENERICOBJECT
947
 
  char *configstring = NULL;
948
 
#endif
949
970
  char *certDir = NULL;
950
971
  int curlerr;
951
972
  const int *cipher_to_enable;
955
976
  if (connssl->state == ssl_connection_complete)
956
977
    return CURLE_OK;
957
978
 
958
 
  connssl->client_cert = NULL;
 
979
  connssl->data = data;
 
980
 
 
981
#ifdef HAVE_PK11_CREATEGENERICOBJECT
959
982
  connssl->cacert[0] = NULL;
960
983
  connssl->cacert[1] = NULL;
961
984
  connssl->key = NULL;
 
985
#endif
962
986
 
963
987
  /* FIXME. NSS doesn't support multiple databases open at the same time. */
964
988
  PR_Lock(nss_initlock);
965
989
  if(!initialized) {
966
 
 
967
 
    certDir = getenv("SSL_DIR"); /* Look in $SSL_DIR */
968
 
 
 
990
    struct_stat st;
 
991
 
 
992
    /* First we check if $SSL_DIR points to a valid dir */
 
993
    certDir = getenv("SSL_DIR");
 
994
    if(certDir) {
 
995
      if((stat(certDir, &st) != 0) ||
 
996
              (!S_ISDIR(st.st_mode))) {
 
997
        certDir = NULL;
 
998
      }
 
999
    }
 
1000
 
 
1001
    /* Now we check if the default location is a valid dir */
969
1002
    if(!certDir) {
970
 
      struct stat st;
971
 
 
972
 
      if(stat(SSL_DIR, &st) == 0)
973
 
        if(S_ISDIR(st.st_mode)) {
974
 
          certDir = (char *)SSL_DIR;
975
 
        }
 
1003
      if((stat(SSL_DIR, &st) == 0) &&
 
1004
              (S_ISDIR(st.st_mode))) {
 
1005
        certDir = (char *)SSL_DIR;
 
1006
      }
976
1007
    }
977
1008
 
978
1009
    if (!NSS_IsInitialized()) {
979
1010
      initialized = 1;
 
1011
      infof(conn->data, "Initializing NSS with certpath: %s\n",
 
1012
            certDir ? certDir : "none");
980
1013
      if(!certDir) {
981
1014
        rv = NSS_NoDB_Init(NULL);
982
1015
      }
983
1016
      else {
984
 
        rv = NSS_Initialize(certDir, NULL, NULL, "secmod.db",
985
 
                            NSS_INIT_READONLY);
 
1017
        char *certpath = PR_smprintf("%s%s",
 
1018
                         NSS_VersionCheck("3.12.0") ? "sql:" : "",
 
1019
                         certDir);
 
1020
        rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY);
 
1021
        PR_smprintf_free(certpath);
986
1022
      }
987
1023
      if(rv != SECSuccess) {
988
1024
        infof(conn->data, "Unable to initialize NSS database\n");
997
1033
      NSS_SetDomesticPolicy();
998
1034
 
999
1035
#ifdef HAVE_PK11_CREATEGENERICOBJECT
1000
 
    configstring = aprintf("library=%s name=PEM", pem_library);
1001
 
    if(!configstring) {
1002
 
      PR_Unlock(nss_initlock);
1003
 
      goto error;
1004
 
    }
1005
 
    mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
1006
 
    free(configstring);
 
1036
    if(!mod) {
 
1037
      char *configstring = aprintf("library=%s name=PEM", pem_library);
 
1038
      if(!configstring) {
 
1039
        PR_Unlock(nss_initlock);
 
1040
        goto error;
 
1041
      }
 
1042
      mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
 
1043
      free(configstring);
1007
1044
 
1008
 
    if(!mod || !mod->loaded) {
1009
 
      if(mod) {
1010
 
        SECMOD_DestroyModule(mod);
1011
 
        mod = NULL;
 
1045
      if(!mod || !mod->loaded) {
 
1046
        if(mod) {
 
1047
          SECMOD_DestroyModule(mod);
 
1048
          mod = NULL;
 
1049
        }
 
1050
        infof(data, "WARNING: failed to load NSS PEM library %s. Using OpenSSL "
 
1051
              "PEM certificates will not work.\n", pem_library);
1012
1052
      }
1013
 
      infof(data, "WARNING: failed to load NSS PEM library %s. Using OpenSSL "
1014
 
            "PEM certificates will not work.\n", pem_library);
1015
1053
    }
1016
1054
#endif
 
1055
 
 
1056
    PK11_SetPasswordFunc(nss_get_password);
 
1057
 
1017
1058
  }
1018
1059
  PR_Unlock(nss_initlock);
1019
1060
 
1074
1115
    }
1075
1116
  }
1076
1117
 
 
1118
  if(data->set.ssl.verifyhost == 1)
 
1119
    infof(data, "warning: ignoring unsupported value (1) of ssl.verifyhost\n");
 
1120
 
1077
1121
  data->set.ssl.certverifyresult=0; /* not checked yet */
1078
1122
  if(SSL_BadCertHook(model, (SSLBadCertHandler) BadCertHandler, conn)
1079
1123
     != SECSuccess) {
1095
1139
    }
1096
1140
  }
1097
1141
  else if(data->set.ssl.CApath) {
1098
 
    struct stat st;
 
1142
    struct_stat st;
1099
1143
    PRDir      *dir;
1100
1144
    PRDirEntry *entry;
1101
1145
 
1143
1187
  }
1144
1188
 
1145
1189
  if(data->set.str[STRING_CERT]) {
1146
 
    char *n;
1147
 
    char *nickname;
1148
1190
    bool nickname_alloc = FALSE;
1149
 
 
1150
 
    if(is_file(data->set.str[STRING_CERT])) {
1151
 
      n = strrchr(data->set.str[STRING_CERT], '/');
1152
 
      if(n) {
1153
 
        n++; /* skip last slash */
1154
 
        nickname = aprintf("PEM Token #%d:%s", 1, n);
1155
 
        if(!nickname)
1156
 
          return CURLE_OUT_OF_MEMORY;
1157
 
 
1158
 
        nickname_alloc = TRUE;
1159
 
      }
1160
 
    }
1161
 
    else {
1162
 
      nickname = data->set.str[STRING_CERT];
1163
 
    }
1164
 
    if(nss_Init_Tokens(conn) != SECSuccess) {
1165
 
      if(nickname_alloc)
1166
 
        free(nickname);
1167
 
      goto error;
1168
 
    }
 
1191
    char *nickname = fmt_nickname(data->set.str[STRING_CERT], &nickname_alloc);
 
1192
    if(!nickname)
 
1193
      return CURLE_OUT_OF_MEMORY;
 
1194
 
1169
1195
    if(!cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
1170
1196
                    data->set.str[STRING_KEY])) {
1171
1197
      /* failf() is already done in cert_stuff() */
1180
1206
    if(!connssl->client_nickname)
1181
1207
      return CURLE_OUT_OF_MEMORY;
1182
1208
 
1183
 
    if(SSL_GetClientAuthDataHook(model,
1184
 
                                 (SSLGetClientAuthData) SelectClientCert,
1185
 
                                 (void *)connssl) != SECSuccess) {
1186
 
      curlerr = CURLE_SSL_CERTPROBLEM;
1187
 
      goto error;
1188
 
    }
1189
1209
  }
1190
1210
  else
1191
1211
    connssl->client_nickname = NULL;
1192
1212
 
 
1213
  if(SSL_GetClientAuthDataHook(model, SelectClientCert,
 
1214
                               (void *)connssl) != SECSuccess) {
 
1215
    curlerr = CURLE_SSL_CERTPROBLEM;
 
1216
    goto error;
 
1217
  }
1193
1218
 
1194
1219
  /* Import our model socket  onto the existing file descriptor */
1195
1220
  connssl->handle = PR_ImportTCPSocket(sockfd);
1198
1223
    goto error;
1199
1224
  PR_Close(model); /* We don't need this any more */
1200
1225
 
 
1226
  /* This is the password associated with the cert that we're using */
 
1227
  if (data->set.str[STRING_KEY_PASSWD]) {
 
1228
      SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
 
1229
  }
 
1230
 
1201
1231
  /* Force handshake on next I/O */
1202
1232
  SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);
1203
1233
 
1207
1237
  if(SSL_ForceHandshakeWithTimeout(connssl->handle,
1208
1238
                                    PR_SecondsToInterval(HANDSHAKE_TIMEOUT))
1209
1239
      != SECSuccess) {
1210
 
    if(conn->data->set.ssl.certverifyresult!=0)
 
1240
    if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
 
1241
      curlerr = CURLE_PEER_FAILED_VERIFICATION;
 
1242
    else if(conn->data->set.ssl.certverifyresult!=0)
1211
1243
      curlerr = CURLE_SSL_CACERT;
1212
1244
    goto error;
1213
1245
  }
1217
1249
  display_conn_info(conn, connssl->handle);
1218
1250
 
1219
1251
  if (data->set.str[STRING_SSL_ISSUERCERT]) {
1220
 
    char *n;
1221
 
    char *nickname;
1222
 
    bool nickname_alloc = FALSE;
1223
1252
    SECStatus ret;
 
1253
    bool nickname_alloc = FALSE;
 
1254
    char *nickname = fmt_nickname(data->set.str[STRING_SSL_ISSUERCERT],
 
1255
                                  &nickname_alloc);
1224
1256
 
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];
 
1257
    if(!nickname)
 
1258
      return CURLE_OUT_OF_MEMORY;
1237
1259
 
1238
1260
    ret = check_issuer_cert(connssl->handle, nickname);
1239
1261
 
1272
1294
  int rc;
1273
1295
 
1274
1296
  if(data->set.timeout)
1275
 
    timeout = PR_MillisecondsToInterval(data->set.timeout);
 
1297
    timeout = PR_MillisecondsToInterval((PRUint32)data->set.timeout);
1276
1298
  else
1277
1299
    timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
1278
1300
 
1308
1330
  PRInt32 timeout;
1309
1331
 
1310
1332
  if(data->set.timeout)
1311
 
    timeout = PR_SecondsToInterval(data->set.timeout);
 
1333
    timeout = PR_SecondsToInterval((PRUint32)data->set.timeout);
1312
1334
  else
1313
1335
    timeout = PR_MillisecondsToInterval(DEFAULT_CONNECT_TIMEOUT);
1314
1336