NS_IMETHODIMP nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken, const nsAString &nickname, nsIX509Cert **_rvCert) { nsNSSShutDownPreventionLock locker; CERTCertificate *cert = NULL; char *asciiname = NULL; NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname); asciiname = const_cast<char*>(aUtf8Nickname.get()); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname)); #if 0 // what it should be, but for now... if (aToken) { cert = PK11_FindCertFromNickname(asciiname, NULL); } else { cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname); } #endif cert = PK11_FindCertFromNickname(asciiname, NULL); if (!cert) { cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname); } if (cert) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("got it\n")); nsCOMPtr<nsIX509Cert> pCert = new nsNSSCertificate(cert); CERT_DestroyCertificate(cert); *_rvCert = pCert; NS_ADDREF(*_rvCert); return NS_OK; } *_rvCert = nsnull; return NS_ERROR_FAILURE; }
static PRBool getCaAndSubjectCert(CERTCertDBHandle *certHandle, const char *caNick, const char *eeNick, CERTCertificate **outCA, CERTCertificate **outCert) { *outCA = CERT_FindCertByNickname(certHandle, caNick); *outCert = CERT_FindCertByNickname(certHandle, eeNick); return *outCA && *outCert; }
// nickname_collision // what to do when the nickname collides with one already in the db. // TODO: not handled, throw a dialog allowing the nick to be changed? SECItem * PR_CALLBACK nsPKCS12Blob::nickname_collision(SECItem *oldNick, PRBool *cancel, void *wincx) { nsNSSShutDownPreventionLock locker; *cancel = false; nsresult rv; nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv)) return nsnull; int count = 1; nsCString nickname; nsAutoString nickFromProp; nssComponent->GetPIPNSSBundleString("P12DefaultNickname", nickFromProp); NS_ConvertUTF16toUTF8 nickFromPropC(nickFromProp); // The user is trying to import a PKCS#12 file that doesn't have the // attribute we use to set the nickname. So in order to reduce the // number of interactions we require with the user, we'll build a nickname // for the user. The nickname isn't prominently displayed in the UI, // so it's OK if we generate one on our own here. // XXX If the NSS API were smarter and actually passed a pointer to // the CERTCertificate* we're importing we could actually just // call default_nickname (which is what the issuance code path // does) and come up with a reasonable nickname. Alas, the NSS // API limits our ability to produce a useful nickname without // bugging the user. :( while (1) { // If we've gotten this far, that means there isn't a certificate // in the database that has the same subject name as the cert we're // trying to import. So we need to come up with a "nickname" to // satisfy the NSS requirement or fail in trying to import. // Basically we use a default nickname from a properties file and // see if a certificate exists with that nickname. If there isn't, then // create update the count by one and append the string '#1' Or // whatever the count currently is, and look for a cert with // that nickname. Keep updating the count until we find a nickname // without a corresponding cert. // XXX If a user imports *many* certs without the 'friendly name' // attribute, then this may take a long time. :( if (count > 1) { nickname.Adopt(PR_smprintf("%s #%d", nickFromPropC.get(), count)); } else { nickname = nickFromPropC; } CERTCertificate *cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), const_cast<char*>(nickname.get())); if (!cert) { break; } CERT_DestroyCertificate(cert); count++; } SECItem *newNick = new SECItem; if (!newNick) return nsnull; newNick->type = siAsciiString; newNick->data = (unsigned char*) nsCRT::strdup(nickname.get()); newNick->len = strlen((char*)newNick->data); return newNick; }
static CERTCertificate * FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl, char *certNickName) { CERTCertificate *cert = NULL, *certTemp = NULL; SECStatus rv = SECFailure; CERTAuthKeyID *authorityKeyID = NULL; SECItem *subject = NULL; PORT_Assert(certHandle != NULL); if (!certHandle || (!signCrl && !certNickName)) { SECU_PrintError(progName, "invalid args for function " "FindSigningCert \n"); return NULL; } if (signCrl) { #if 0 authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl); #endif subject = &signCrl->crl.derName; } else { certTemp = CERT_FindCertByNickname(certHandle, certNickName); if (!certTemp) { SECU_PrintError(progName, "could not find certificate \"%s\" " "in database", certNickName); goto loser; } subject = &certTemp->derSubject; } cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now()); if (!cert) { SECU_PrintError(progName, "could not find signing certificate " "in database"); goto loser; } else { rv = SECSuccess; } loser: if (certTemp) CERT_DestroyCertificate(certTemp); if (cert && rv != SECSuccess) CERT_DestroyCertificate(cert); return cert; }
PRBool SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject, CERTCertDBHandle *handle) { CERTCertificate *cert; PRBool conflict = PR_FALSE; cert = CERT_FindCertByNickname(handle, nickname); if (!cert) { return conflict; } conflict = !SECITEM_ItemsAreEqual(derSubject, &cert->derSubject); CERT_DestroyCertificate(cert); return conflict; }
/* would not do name in pluto, but dn */ static CERTCertList *get_trust_certlist(CERTCertDBHandle *handle, const char *name) { CERTCertList *trustcl = NULL; CERTCertList *tmpcl = NULL; CERTCertificate *ca = NULL; CERTCertListNode *node = NULL; if ((ca = CERT_FindCertByNickname(handle, name)) == NULL) { printf("CERT_FindCertByNickname failed %d\n", PORT_GetError()); return NULL; } if (ca->isRoot) { printf("trust anchor: %s\n",ca->subjectName); trustcl = CERT_NewCertList(); CERT_AddCertToListTail(trustcl, ca); } else { tmpcl = CERT_GetCertChainFromCert(ca, PR_Now(), certUsageAnyCA); if (tmpcl == NULL) { printf("CERT_GetCertChainFromCert failed %d\n", PORT_GetError()); return NULL; } for (node = CERT_LIST_HEAD(tmpcl); !CERT_LIST_END(node, tmpcl); node = CERT_LIST_NEXT(node)) { printf("CERT list: %s\n", node->cert->subjectName); if (node->cert->isRoot) { trustcl = CERT_NewCertList(); CERT_AddCertToListTail(trustcl, node->cert); break; } } } if (trustcl == NULL || CERT_LIST_EMPTY(trustcl)) { printf("Trust chain empty!\n"); return NULL; } return trustcl; }
static CERTCertificate * get_signer_cert(char *addr) { CERTCertDBHandle *handle; CERTCertList *list; CERTCertListNode *node; CERTCertificate *cert = NULL; const char *cp; char *nick; char *vn; int vs, found = 0; addr = skin(addr); vn = ac_alloc(vs = strlen(addr) + 30); snprintf(vn, vs, "smime-sign-nickname-%s", addr); if ((nick = value(vn)) == NULL) nick = value("smime-sign-nickname"); ac_free(vn); handle = CERT_GetDefaultCertDB(); if (nick) { cert = CERT_FindCertByNickname(handle, nick); if (cert == NULL) fprintf(stderr, "No certificate \"%s\" found.\n", nick); return cert; } if ((list = CERT_FindUserCertsByUsage(handle, certUsageEmailSigner, PR_TRUE, PR_TRUE, NULL)) == NULL) { fprintf(stderr, "Cannot find any certificates for signing.\n"); return NULL; } for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node)) { if ((cp = CERT_GetCertEmailAddress(&node->cert->subject)) != NULL && asccasecmp(cp, addr) == 0) { cert = node->cert; found++; } } if (cert == NULL) { for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list) && cert == NULL; node = CERT_LIST_NEXT(node)) { cp = CERT_GetFirstEmailAddress(node->cert); while (cp) { if (asccasecmp(cp, addr) == 0) { cert = node->cert; found++; } cp = CERT_GetNextEmailAddress(node->cert, cp); } } } if (found > 1) { fprintf(stderr, "More than one signing certificate found for <%s>.\n" "Use the smime-sign-nickname variable.\n", addr); return NULL; } if (cert == NULL) fprintf(stderr, "Cannot find a signing certificate for <%s>.\n", addr); return cert; }
/* * Find all user certificates that match the given criteria. * * "handle" - database to search * "usage" - certificate usage to match * "oneCertPerName" - if set then only return the "best" cert per * name * "validOnly" - only return certs that are curently valid * "proto_win" - window handle passed to pkcs11 */ CERTCertList * CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, SECCertUsage usage, PRBool oneCertPerName, PRBool validOnly, void *proto_win) { CERTCertNicknames *nicknames = NULL; char **nnptr; int nn; CERTCertificate *cert = NULL; CERTCertList *certList = NULL; SECStatus rv; int64 time; CERTCertListNode *node = NULL; CERTCertListNode *freenode = NULL; int n; time = PR_Now(); nicknames = CERT_GetCertNicknames(handle, SEC_CERT_NICKNAMES_USER, proto_win); if ( ( nicknames == NULL ) || ( nicknames->numnicknames == 0 ) ) { goto loser; } nnptr = nicknames->nicknames; nn = nicknames->numnicknames; while ( nn > 0 ) { cert = NULL; /* use the pk11 call so that we pick up any certs on tokens, * which may require login */ if ( proto_win != NULL ) { cert = PK11_FindCertFromNickname(*nnptr,proto_win); } /* Sigh, It turns out if the cert is already in the temp db, because * it's in the perm db, then the nickname lookup doesn't work. * since we already have the cert here, though, than we can just call * CERT_CreateSubjectCertList directly. For those cases where we didn't * find the cert in pkcs #11 (because we didn't have a password arg, * or because the nickname is for a peer, server, or CA cert, then we * go look the cert up. */ if (cert == NULL) { cert = CERT_FindCertByNickname(handle,*nnptr); } if ( cert != NULL ) { /* collect certs for this nickname, sorting them into the list */ certList = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, time, validOnly); CERT_FilterCertListForUserCerts(certList); /* drop the extra reference */ CERT_DestroyCertificate(cert); } nnptr++; nn--; } /* remove certs with incorrect usage */ rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } /* remove any extra certs for each name */ if ( oneCertPerName ) { PRBool *flags; nn = nicknames->numnicknames; nnptr = nicknames->nicknames; flags = (PRBool *)PORT_ZAlloc(sizeof(PRBool) * nn); if ( flags == NULL ) { goto loser; } node = CERT_LIST_HEAD(certList); /* treverse all certs in the list */ while ( !CERT_LIST_END(node, certList) ) { /* find matching nickname index */ for ( n = 0; n < nn; n++ ) { if ( CERT_MatchNickname(nnptr[n], node->cert->nickname) ) { /* We found a match. If this is the first one, then * set the flag and move on to the next cert. If this * is not the first one then delete it from the list. */ if ( flags[n] ) { /* We have already seen a cert with this nickname, * so delete this one. */ freenode = node; node = CERT_LIST_NEXT(node); CERT_RemoveCertListNode(freenode); } else { /* keep the first cert for each nickname, but set the * flag so we know to delete any others with the same * nickname. */ flags[n] = PR_TRUE; node = CERT_LIST_NEXT(node); } break; } } if ( n == nn ) { /* if we get here it means that we didn't find a matching * nickname, which should not happen. */ PORT_Assert(0); node = CERT_LIST_NEXT(node); } } PORT_Free(flags); } goto done; loser: if ( certList != NULL ) { CERT_DestroyCertList(certList); certList = NULL; } done: if ( nicknames != NULL ) { CERT_FreeNicknames(nicknames); } return(certList); }
/* * Find a user certificate that matchs the given criteria. * * "handle" - database to search * "nickname" - nickname to match * "usage" - certificate usage to match * "validOnly" - only return certs that are curently valid * "proto_win" - window handle passed to pkcs11 */ CERTCertificate * CERT_FindUserCertByUsage(CERTCertDBHandle *handle, const char *nickname, SECCertUsage usage, PRBool validOnly, void *proto_win) { CERTCertificate *cert = NULL; CERTCertList *certList = NULL; SECStatus rv; int64 time; time = PR_Now(); /* use the pk11 call so that we pick up any certs on tokens, * which may require login */ /* XXX - why is this restricted? */ if ( proto_win != NULL ) { cert = PK11_FindCertFromNickname(nickname,proto_win); } /* sigh, There are still problems find smart cards from the temp * db. This will get smart cards working again. The real fix * is to make sure we can search the temp db by their token nickname. */ if (cert == NULL) { cert = CERT_FindCertByNickname(handle,nickname); } if ( cert != NULL ) { unsigned int requiredKeyUsage; unsigned int requiredCertType; rv = CERT_KeyUsageAndTypeForCertUsage(usage, PR_FALSE, &requiredKeyUsage, &requiredCertType); if ( rv != SECSuccess ) { /* drop the extra reference */ CERT_DestroyCertificate(cert); cert = NULL; goto loser; } /* If we already found the right cert, just return it */ if ( (!validOnly || CERT_CheckCertValidTimes(cert, time, PR_FALSE) == secCertTimeValid) && (CERT_CheckKeyUsage(cert, requiredKeyUsage) == SECSuccess) && (cert->nsCertType & requiredCertType) && CERT_IsUserCert(cert) ) { return(cert); } /* collect certs for this nickname, sorting them into the list */ certList = CERT_CreateSubjectCertList(certList, handle, &cert->derSubject, time, validOnly); CERT_FilterCertListForUserCerts(certList); /* drop the extra reference */ CERT_DestroyCertificate(cert); cert = NULL; } if ( certList == NULL ) { goto loser; } /* remove certs with incorrect usage */ rv = CERT_FilterCertListByUsage(certList, usage, PR_FALSE); if ( rv != SECSuccess ) { goto loser; } if ( ! CERT_LIST_END(CERT_LIST_HEAD(certList), certList) ) { cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert); } loser: if ( certList != NULL ) { CERT_DestroyCertList(certList); } return(cert); }
int main(int argc, char **argv) { char *progName; FILE *inFile, *outFile; char *certName; CERTCertDBHandle *certHandle; struct recipient *recipients, *rcpt; PLOptState *optstate; PLOptStatus status; SECStatus rv; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; inFile = NULL; outFile = NULL; certName = NULL; recipients = NULL; rcpt = NULL; /* * Parse command line arguments * XXX This needs to be enhanced to allow selection of algorithms * and key sizes (or to look up algorithms and key sizes for each * recipient in the magic database). */ optstate = PL_CreateOptState(argc, argv, "d:i:o:r:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': Usage(progName); break; case 'd': SECU_ConfigDirectory(optstate->value); break; case 'i': inFile = fopen(optstate->value, "r"); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); return -1; } break; case 'o': outFile = fopen(optstate->value, "wb"); if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); return -1; } break; case 'r': if (rcpt == NULL) { recipients = rcpt = PORT_Alloc (sizeof(struct recipient)); } else { rcpt->next = PORT_Alloc (sizeof(struct recipient)); rcpt = rcpt->next; } if (rcpt == NULL) { fprintf(stderr, "%s: unable to allocate recipient struct\n", progName); return -1; } rcpt->nickname = strdup(optstate->value); rcpt->cert = NULL; rcpt->next = NULL; break; } } if (!recipients) Usage(progName); if (!inFile) inFile = stdin; if (!outFile) outFile = stdout; /* Call the NSS initialization routines */ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); rv = NSS_Init(SECU_ConfigDirectory(NULL)); if (rv != SECSuccess) { SECU_PrintPRandOSError(progName); return -1; } /* open cert database */ certHandle = CERT_GetDefaultCertDB(); if (certHandle == NULL) { return -1; } /* find certs */ for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) { rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname); if (rcpt->cert == NULL) { SECU_PrintError(progName, "the cert for name \"%s\" not found in database", rcpt->nickname); return -1; } } if (EncryptFile(outFile, inFile, recipients, progName)) { SECU_PrintError(progName, "problem encrypting data"); return -1; } return 0; }
static xmlSecKeyPtr xmlSecNssKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) { xmlSecKeyStorePtr* ss; xmlSecKeyPtr key = NULL; xmlSecKeyPtr retval = NULL; xmlSecKeyReqPtr keyReq = NULL; CERTCertificate *cert = NULL; SECKEYPublicKey *pubkey = NULL; SECKEYPrivateKey *privkey = NULL; xmlSecKeyDataPtr data = NULL; xmlSecKeyDataPtr x509Data = NULL; int ret; xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); ss = xmlSecNssKeysStoreGetSS(store); xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL); key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx); if (key != NULL) { return (key); } /* Try to find the key in the NSS DB, and construct an xmlSecKey. * we must have a name to lookup keys in NSS DB. */ if (name == NULL) { goto done; } /* what type of key are we looking for? * TBD: For now, we'll look only for public/private keys using the * name as a cert nickname. Later on, we can attempt to find * symmetric keys using PK11_FindFixedKey */ keyReq = &(keyInfoCtx->keyReq); if (keyReq->keyType & (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) { cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB(), (char *)name); if (cert == NULL) { goto done; } if (keyReq->keyType & xmlSecKeyDataTypePublic) { pubkey = CERT_ExtractPublicKey(cert); if (pubkey == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "CERT_ExtractPublicKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } if (keyReq->keyType & xmlSecKeyDataTypePrivate) { privkey = PK11_FindKeyByAnyCert(cert, NULL); if (privkey == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_FindKeyByAnyCert", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } data = xmlSecNssPKIAdoptKey(privkey, pubkey); if(data == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "xmlSecNssPKIAdoptKey", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } privkey = NULL; pubkey = NULL; key = xmlSecKeyCreate(); if (key == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return (NULL); } x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id); if(x509Data == NULL) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyDataCreate", XMLSEC_ERRORS_R_XMLSEC_FAILED, "transform=%s", xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id))); goto done; } ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert); if (ret < 0) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "xmlSecNssKeyDataX509AdoptKeyCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "data=%s", xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); goto done; } cert = CERT_DupCertificate(cert); if (cert == NULL) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "CERT_DupCertificate", XMLSEC_ERRORS_R_CRYPTO_FAILED, "data=%s", xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); goto done; } ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert); if (ret < 0) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "xmlSecNssKeyDataX509AdoptCert", XMLSEC_ERRORS_R_XMLSEC_FAILED, "data=%s", xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); goto done; } cert = NULL; ret = xmlSecKeySetValue(key, data); if (ret < 0) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeySetValue", XMLSEC_ERRORS_R_XMLSEC_FAILED, "data=%s", xmlSecErrorsSafeString(xmlSecKeyDataGetName(data))); goto done; } data = NULL; ret = xmlSecKeyAdoptData(key, x509Data); if (ret < 0) { xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE, NULL, "xmlSecKeyAdoptData", XMLSEC_ERRORS_R_XMLSEC_FAILED, "data=%s", xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data))); goto done; } x509Data = NULL; retval = key; key = NULL; } done: if (cert != NULL) { CERT_DestroyCertificate(cert); } if (pubkey != NULL) { SECKEY_DestroyPublicKey(pubkey); } if (privkey != NULL) { SECKEY_DestroyPrivateKey(privkey); } if (data != NULL) { xmlSecKeyDataDestroy(data); } if (x509Data != NULL) { xmlSecKeyDataDestroy(x509Data); } if (key != NULL) { xmlSecKeyDestroy(key); } return (retval); }
int main(int argc, char **argv) { char *progName; FILE *outFile; PRFileDesc *inFile; char *keyName = NULL; CERTCertDBHandle *certHandle; CERTCertificate *cert; PLOptState *optstate; PLOptStatus status; SECStatus rv; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; inFile = NULL; outFile = NULL; keyName = NULL; /* * Parse command line arguments */ optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { switch (optstate->option) { case '?': Usage(progName); break; case 'd': SECU_ConfigDirectory(optstate->value); break; case 'i': inFile = PR_Open(optstate->value, PR_RDONLY, 0); if (!inFile) { fprintf(stderr, "%s: unable to open \"%s\" for reading\n", progName, optstate->value); return -1; } break; case 'k': keyName = strdup(optstate->value); break; case 'o': outFile = fopen(optstate->value, "wb"); if (!outFile) { fprintf(stderr, "%s: unable to open \"%s\" for writing\n", progName, optstate->value); return -1; } break; case 'p': pwdata.source = PW_PLAINTEXT; pwdata.data = strdup (optstate->value); break; case 'f': pwdata.source = PW_FROMFILE; pwdata.data = PORT_Strdup (optstate->value); break; } } if (!keyName) Usage(progName); if (!inFile) inFile = PR_STDIN; if (!outFile) outFile = stdout; /* Call the initialization routines */ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); rv = NSS_Init(SECU_ConfigDirectory(NULL)); if (rv != SECSuccess) { SECU_PrintPRandOSError(progName); goto loser; } PK11_SetPasswordFunc(SECU_GetModulePassword); /* open cert database */ certHandle = CERT_GetDefaultCertDB(); if (certHandle == NULL) { rv = SECFailure; goto loser; } /* find cert */ cert = CERT_FindCertByNickname(certHandle, keyName); if (cert == NULL) { SECU_PrintError(progName, "the corresponding cert for key \"%s\" does not exist", keyName); rv = SECFailure; goto loser; } if (SignFile(outFile, inFile, cert)) { SECU_PrintError(progName, "problem signing data"); rv = SECFailure; goto loser; } loser: if (pwdata.data) { PORT_Free(pwdata.data); } if (keyName) { PORT_Free(keyName); } if (cert) { CERT_DestroyCertificate(cert); } if (inFile && inFile != PR_STDIN) { PR_Close(inFile); } if (outFile && outFile != stdout) { fclose(outFile); } if (NSS_Shutdown() != SECSuccess) { SECU_PrintError(progName, "NSS shutdown:"); exit(1); } return (rv != SECSuccess); }
/* what to do when the nickname collides with one already in the db. * TODO: not handled, throw a dialog allowing the nick to be changed? */ static SECItem * PR_CALLBACK nickname_collision (SECItem *oldNick, PRBool *cancel, gpointer wincx) { /* nsNSSShutDownPreventionLock locker; */ gint count = 1; gchar *nickname = NULL; gchar *default_nickname = _("Imported Certificate"); SECItem *new_nick; *cancel = PR_FALSE; printf ("nickname_collision\n"); /* The user is trying to import a PKCS#12 file that doesn't have the * attribute we use to set the nickname. So in order to reduce the * number of interactions we require with the user, we'll build a nickname * for the user. The nickname isn't prominently displayed in the UI, * so it's OK if we generate one on our own here. * XXX If the NSS API were smarter and actually passed a pointer to * the CERTCertificate * we're importing we could actually just * call default_nickname (which is what the issuance code path * does) and come up with a reasonable nickname. Alas, the NSS * API limits our ability to produce a useful nickname without * bugging the user. :( */ while (1) { CERTCertificate *cert; /* If we've gotten this far, that means there isn't a certificate * in the database that has the same subject name as the cert we're * trying to import. So we need to come up with a "nickname" to * satisfy the NSS requirement or fail in trying to import. * Basically we use a default nickname from a properties file and * see if a certificate exists with that nickname. If there isn't, then * create update the count by one and append the string '#1' Or * whatever the count currently is, and look for a cert with * that nickname. Keep updating the count until we find a nickname * without a corresponding cert. * XXX If a user imports *many * certs without the 'friendly name' * attribute, then this may take a long time. :( */ if (count > 1) { g_free (nickname); nickname = g_strdup_printf ("%s #%d", default_nickname, count); } else { g_free (nickname); nickname = g_strdup (default_nickname); } cert = CERT_FindCertByNickname ( CERT_GetDefaultCertDB (), nickname); if (!cert) { break; } CERT_DestroyCertificate (cert); count++; } new_nick = PR_Malloc (sizeof (SECItem)); new_nick->type = siAsciiString; new_nick->data = (guchar *) nickname; new_nick->len = strlen ((gchar *) new_nick->data); return new_nick; }
void nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert, nsIInterfaceRequestor* ctx, nsCString &nickname) { nickname.Truncate(); nsNSSShutDownPreventionLock locker; nsresult rv; CK_OBJECT_HANDLE keyHandle; CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB(); nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); if (NS_FAILED(rv)) return; nsCAutoString username; char *temp_un = CERT_GetCommonName(&cert->subject); if (temp_un) { username = temp_un; PORT_Free(temp_un); temp_un = nsnull; } nsCAutoString caname; char *temp_ca = CERT_GetOrgName(&cert->issuer); if (temp_ca) { caname = temp_ca; PORT_Free(temp_ca); temp_ca = nsnull; } nsAutoString tmpNickFmt; nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt); NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt); nsCAutoString baseName; char *temp_nn = PR_smprintf(nickFmt.get(), username.get(), caname.get()); if (!temp_nn) { return; } else { baseName = temp_nn; PR_smprintf_free(temp_nn); temp_nn = nsnull; } nickname = baseName; /* * We need to see if the private key exists on a token, if it does * then we need to check for nicknames that already exist on the smart * card. */ PK11SlotInfo *slot = PK11_KeyForCertExists(cert, &keyHandle, ctx); PK11SlotInfoCleaner slotCleaner(slot); if (!slot) return; if (!PK11_IsInternal(slot)) { char *tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), baseName.get()); if (!tmp) { nickname.Truncate(); return; } baseName = tmp; PR_smprintf_free(tmp); nickname = baseName; } int count = 1; while (true) { if ( count > 1 ) { char *tmp = PR_smprintf("%s #%d", baseName.get(), count); if (!tmp) { nickname.Truncate(); return; } nickname = tmp; PR_smprintf_free(tmp); } CERTCertificate *dummycert = nsnull; CERTCertificateCleaner dummycertCleaner(dummycert); if (PK11_IsInternal(slot)) { /* look up the nickname to make sure it isn't in use already */ dummycert = CERT_FindCertByNickname(defaultcertdb, nickname.get()); } else { /* * Check the cert against others that already live on the smart * card. */ dummycert = PK11_FindCertFromNickname(nickname.get(), ctx); if (dummycert != NULL) { /* * Make sure the subject names are different. */ if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual) { /* * There is another certificate with the same nickname and * the same subject name on the smart card, so let's use this * nickname. */ CERT_DestroyCertificate(dummycert); dummycert = NULL; } } } if (!dummycert) break; count++; } }