12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211 |
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nspr.h"
- #include "secerr.h"
- #include "secasn1.h"
- #include "seccomon.h"
- #include "pk11func.h"
- #include "certdb.h"
- #include "certt.h"
- #include "cert.h"
- #include "certxutl.h"
- #include "certi.h"
- #include "nsspki.h"
- #include "pki.h"
- #include "pkit.h"
- #include "pkitm.h"
- #include "pki3hack.h"
- PRBool
- CERT_MatchNickname(char *name1, char *name2)
- {
- char *nickname1 = NULL;
- char *nickname2 = NULL;
- char *token1;
- char *token2;
- /* first deal with the straight comparison */
- if (PORT_Strcmp(name1, name2) == 0) {
- return PR_TRUE;
- }
- /* we need to handle the case where one name has an explicit token and the other
- * doesn't */
- token1 = PORT_Strchr(name1, ':');
- token2 = PORT_Strchr(name2, ':');
- if ((token1 && token2) || (!token1 && !token2)) {
- /* either both token names are specified or neither are, not match */
- return PR_FALSE;
- }
- if (token1) {
- nickname1 = token1;
- nickname2 = name2;
- } else {
- nickname1 = token2;
- nickname2 = name1;
- }
- nickname1++;
- if (PORT_Strcmp(nickname1, nickname2) != 0) {
- return PR_FALSE;
- }
- /* Bug 1192443 - compare the other token with the internal slot here */
- return PR_TRUE;
- }
- /*
- * 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;
- PRTime 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;
- if (!certList) {
- goto loser;
- }
- 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;
- PRTime 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_EMPTY(certList)) {
- cert = CERT_DupCertificate(CERT_LIST_HEAD(certList)->cert);
- }
- loser:
- if (certList != NULL) {
- CERT_DestroyCertList(certList);
- }
- return (cert);
- }
- CERTCertList *
- CERT_MatchUserCert(CERTCertDBHandle *handle,
- SECCertUsage usage,
- int nCANames, char **caNames,
- void *proto_win)
- {
- CERTCertList *certList = NULL;
- SECStatus rv;
- certList = CERT_FindUserCertsByUsage(handle, usage, PR_TRUE, PR_TRUE,
- proto_win);
- if (certList == NULL) {
- goto loser;
- }
- rv = CERT_FilterCertListByCANames(certList, nCANames, caNames, usage);
- if (rv != SECSuccess) {
- goto loser;
- }
- goto done;
- loser:
- if (certList != NULL) {
- CERT_DestroyCertList(certList);
- certList = NULL;
- }
- done:
- return (certList);
- }
- typedef struct stringNode {
- struct stringNode *next;
- char *string;
- } stringNode;
- static PRStatus
- CollectNicknames(NSSCertificate *c, void *data)
- {
- CERTCertNicknames *names;
- PRBool saveit = PR_FALSE;
- stringNode *node;
- int len;
- #ifdef notdef
- NSSTrustDomain *td;
- NSSTrust *trust;
- #endif
- char *stanNickname;
- char *nickname = NULL;
- names = (CERTCertNicknames *)data;
- stanNickname = nssCertificate_GetNickname(c, NULL);
- if (stanNickname) {
- nss_ZFreeIf(stanNickname);
- stanNickname = NULL;
- if (names->what == SEC_CERT_NICKNAMES_USER) {
- saveit = NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL);
- }
- #ifdef notdef
- else {
- td = NSSCertificate_GetTrustDomain(c);
- if (!td) {
- return PR_SUCCESS;
- }
- trust = nssTrustDomain_FindTrustForCertificate(td, c);
- switch (names->what) {
- case SEC_CERT_NICKNAMES_ALL:
- if ((trust->sslFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
- (trust->emailFlags & (CERTDB_VALID_CA | CERTDB_VALID_PEER)) ||
- (trust->objectSigningFlags &
- (CERTDB_VALID_CA | CERTDB_VALID_PEER))) {
- saveit = PR_TRUE;
- }
- break;
- case SEC_CERT_NICKNAMES_SERVER:
- if (trust->sslFlags & CERTDB_VALID_PEER) {
- saveit = PR_TRUE;
- }
- break;
- case SEC_CERT_NICKNAMES_CA:
- if (((trust->sslFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
- ((trust->emailFlags & CERTDB_VALID_CA) == CERTDB_VALID_CA) ||
- ((trust->objectSigningFlags & CERTDB_VALID_CA) ==
- CERTDB_VALID_CA)) {
- saveit = PR_TRUE;
- }
- break;
- }
- }
- #endif
- }
- /* traverse the list of collected nicknames and make sure we don't make
- * a duplicate
- */
- if (saveit) {
- nickname = STAN_GetCERTCertificateName(NULL, c);
- /* nickname can only be NULL here if we are having memory
- * alloc problems */
- if (nickname == NULL) {
- return PR_FAILURE;
- }
- node = (stringNode *)names->head;
- while (node != NULL) {
- if (PORT_Strcmp(nickname, node->string) == 0) {
- /* if the string matches, then don't save this one */
- saveit = PR_FALSE;
- break;
- }
- node = node->next;
- }
- }
- if (saveit) {
- /* allocate the node */
- node = (stringNode *)PORT_ArenaAlloc(names->arena, sizeof(stringNode));
- if (node == NULL) {
- PORT_Free(nickname);
- return PR_FAILURE;
- }
- /* copy the string */
- len = PORT_Strlen(nickname) + 1;
- node->string = (char *)PORT_ArenaAlloc(names->arena, len);
- if (node->string == NULL) {
- PORT_Free(nickname);
- return PR_FAILURE;
- }
- PORT_Memcpy(node->string, nickname, len);
- /* link it into the list */
- node->next = (stringNode *)names->head;
- names->head = (void *)node;
- /* bump the count */
- names->numnicknames++;
- }
- if (nickname)
- PORT_Free(nickname);
- return (PR_SUCCESS);
- }
- CERTCertNicknames *
- CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
- {
- PLArenaPool *arena;
- CERTCertNicknames *names;
- int i;
- stringNode *node;
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return (NULL);
- }
- names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
- if (names == NULL) {
- goto loser;
- }
- names->arena = arena;
- names->head = NULL;
- names->numnicknames = 0;
- names->nicknames = NULL;
- names->what = what;
- names->totallen = 0;
- /* make sure we are logged in */
- (void)pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx);
- NSSTrustDomain_TraverseCertificates(handle,
- CollectNicknames, (void *)names);
- if (names->numnicknames) {
- names->nicknames = (char **)PORT_ArenaAlloc(arena,
- names->numnicknames *
- sizeof(char *));
- if (names->nicknames == NULL) {
- goto loser;
- }
- node = (stringNode *)names->head;
- for (i = 0; i < names->numnicknames; i++) {
- PORT_Assert(node != NULL);
- names->nicknames[i] = node->string;
- names->totallen += PORT_Strlen(node->string);
- node = node->next;
- }
- PORT_Assert(node == NULL);
- }
- return (names);
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return (NULL);
- }
- void
- CERT_FreeNicknames(CERTCertNicknames *nicknames)
- {
- PORT_FreeArena(nicknames->arena, PR_FALSE);
- return;
- }
- /* [ FROM pcertdb.c ] */
- typedef struct dnameNode {
- struct dnameNode *next;
- SECItem name;
- } dnameNode;
- void
- CERT_FreeDistNames(CERTDistNames *names)
- {
- PORT_FreeArena(names->arena, PR_FALSE);
- return;
- }
- static SECStatus
- CollectDistNames(CERTCertificate *cert, SECItem *k, void *data)
- {
- CERTDistNames *names;
- PRBool saveit = PR_FALSE;
- CERTCertTrust trust;
- dnameNode *node;
- int len;
- names = (CERTDistNames *)data;
- if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
- /* only collect names of CAs trusted for issuing SSL clients */
- if (trust.sslFlags & CERTDB_TRUSTED_CLIENT_CA) {
- saveit = PR_TRUE;
- }
- }
- if (saveit) {
- /* allocate the node */
- node = (dnameNode *)PORT_ArenaAlloc(names->arena, sizeof(dnameNode));
- if (node == NULL) {
- return (SECFailure);
- }
- /* copy the name */
- node->name.len = len = cert->derSubject.len;
- node->name.type = siBuffer;
- node->name.data = (unsigned char *)PORT_ArenaAlloc(names->arena, len);
- if (node->name.data == NULL) {
- return (SECFailure);
- }
- PORT_Memcpy(node->name.data, cert->derSubject.data, len);
- /* link it into the list */
- node->next = (dnameNode *)names->head;
- names->head = (void *)node;
- /* bump the count */
- names->nnames++;
- }
- return (SECSuccess);
- }
- /*
- * Return all of the CAs that are "trusted" for SSL.
- */
- CERTDistNames *
- CERT_DupDistNames(CERTDistNames *orig)
- {
- PLArenaPool *arena;
- CERTDistNames *names;
- int i;
- SECStatus rv;
- /* allocate an arena to use */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return (NULL);
- }
- /* allocate the header structure */
- names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
- if (names == NULL) {
- goto loser;
- }
- /* initialize the header struct */
- names->arena = arena;
- names->head = NULL;
- names->nnames = orig->nnames;
- names->names = NULL;
- /* construct the array from the list */
- if (orig->nnames) {
- names->names = (SECItem *)PORT_ArenaNewArray(arena, SECItem,
- orig->nnames);
- if (names->names == NULL) {
- goto loser;
- }
- for (i = 0; i < orig->nnames; i++) {
- rv = SECITEM_CopyItem(arena, &names->names[i], &orig->names[i]);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
- }
- return (names);
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return (NULL);
- }
- CERTDistNames *
- CERT_GetSSLCACerts(CERTCertDBHandle *handle)
- {
- PLArenaPool *arena;
- CERTDistNames *names;
- int i;
- SECStatus rv;
- dnameNode *node;
- /* allocate an arena to use */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return (NULL);
- }
- /* allocate the header structure */
- names = (CERTDistNames *)PORT_ArenaAlloc(arena, sizeof(CERTDistNames));
- if (names == NULL) {
- goto loser;
- }
- /* initialize the header struct */
- names->arena = arena;
- names->head = NULL;
- names->nnames = 0;
- names->names = NULL;
- /* collect the names from the database */
- rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL);
- if (rv) {
- goto loser;
- }
- /* construct the array from the list */
- if (names->nnames) {
- names->names = (SECItem *)PORT_ArenaAlloc(arena, names->nnames * sizeof(SECItem));
- if (names->names == NULL) {
- goto loser;
- }
- node = (dnameNode *)names->head;
- for (i = 0; i < names->nnames; i++) {
- PORT_Assert(node != NULL);
- names->names[i] = node->name;
- node = node->next;
- }
- PORT_Assert(node == NULL);
- }
- return (names);
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return (NULL);
- }
- CERTDistNames *
- CERT_DistNamesFromCertList(CERTCertList *certList)
- {
- CERTDistNames *dnames = NULL;
- PLArenaPool *arena;
- CERTCertListNode *node = NULL;
- SECItem *names = NULL;
- int listLen = 0, i = 0;
- if (certList == NULL) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return NULL;
- }
- node = CERT_LIST_HEAD(certList);
- while (!CERT_LIST_END(node, certList)) {
- listLen += 1;
- node = CERT_LIST_NEXT(node);
- }
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL)
- goto loser;
- dnames = PORT_ArenaZNew(arena, CERTDistNames);
- if (dnames == NULL)
- goto loser;
- dnames->arena = arena;
- dnames->nnames = listLen;
- dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, listLen);
- if (names == NULL)
- goto loser;
- node = CERT_LIST_HEAD(certList);
- while (!CERT_LIST_END(node, certList)) {
- CERTCertificate *cert = node->cert;
- SECStatus rv = SECITEM_CopyItem(arena, &names[i++], &cert->derSubject);
- if (rv == SECFailure) {
- goto loser;
- }
- node = CERT_LIST_NEXT(node);
- }
- return dnames;
- loser:
- if (arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return NULL;
- }
- CERTDistNames *
- CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, char **nicknames,
- int nnames)
- {
- CERTDistNames *dnames = NULL;
- PLArenaPool *arena;
- int i, rv;
- SECItem *names = NULL;
- CERTCertificate *cert = NULL;
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL)
- goto loser;
- dnames = PORT_ArenaZNew(arena, CERTDistNames);
- if (dnames == NULL)
- goto loser;
- dnames->arena = arena;
- dnames->nnames = nnames;
- dnames->names = names = PORT_ArenaZNewArray(arena, SECItem, nnames);
- if (names == NULL)
- goto loser;
- for (i = 0; i < nnames; i++) {
- cert = CERT_FindCertByNicknameOrEmailAddr(handle, nicknames[i]);
- if (cert == NULL)
- goto loser;
- rv = SECITEM_CopyItem(arena, &names[i], &cert->derSubject);
- if (rv == SECFailure)
- goto loser;
- CERT_DestroyCertificate(cert);
- }
- return dnames;
- loser:
- if (cert != NULL)
- CERT_DestroyCertificate(cert);
- if (arena != NULL)
- PORT_FreeArena(arena, PR_FALSE);
- return NULL;
- }
- /* [ from pcertdb.c - calls Ascii to Name ] */
- /*
- * Lookup a certificate in the database by name
- */
- CERTCertificate *
- CERT_FindCertByNameString(CERTCertDBHandle *handle, char *nameStr)
- {
- CERTName *name;
- SECItem *nameItem;
- CERTCertificate *cert = NULL;
- PLArenaPool *arena = NULL;
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- goto loser;
- }
- name = CERT_AsciiToName(nameStr);
- if (name) {
- nameItem = SEC_ASN1EncodeItem(arena, NULL, (void *)name,
- CERT_NameTemplate);
- if (nameItem != NULL) {
- cert = CERT_FindCertByName(handle, nameItem);
- }
- CERT_DestroyName(name);
- }
- loser:
- if (arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return (cert);
- }
- /* From certv3.c */
- CERTCrlDistributionPoints *
- CERT_FindCRLDistributionPoints(CERTCertificate *cert)
- {
- SECItem encodedExtenValue;
- SECStatus rv;
- CERTCrlDistributionPoints *dps;
- encodedExtenValue.data = NULL;
- encodedExtenValue.len = 0;
- rv = cert_FindExtension(cert->extensions, SEC_OID_X509_CRL_DIST_POINTS,
- &encodedExtenValue);
- if (rv != SECSuccess) {
- return (NULL);
- }
- dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue);
- PORT_Free(encodedExtenValue.data);
- return dps;
- }
- /* From crl.c */
- CERTSignedCrl *
- CERT_ImportCRL(CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
- {
- CERTSignedCrl *retCrl = NULL;
- PK11SlotInfo *slot = PK11_GetInternalKeySlot();
- retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
- CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
- PK11_FreeSlot(slot);
- return retCrl;
- }
- /* From certdb.c */
- static SECStatus
- cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
- {
- SECStatus rv;
- SECItem *derCert;
- CERTCertificate *cert = NULL;
- CERTCertificate *newcert = NULL;
- CERTCertDBHandle *handle;
- CERTCertTrust trust;
- PRBool isca;
- char *nickname;
- unsigned int certtype;
- PRBool istemp = PR_FALSE;
- handle = CERT_GetDefaultCertDB();
- while (numcerts--) {
- derCert = certs;
- certs++;
- /* decode my certificate */
- /* This use is ok -- only looks at decoded parts, calls NewTemp later */
- newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
- if (newcert == NULL) {
- goto loser;
- }
- if (!trusted) {
- /* make sure that cert is valid */
- rv = CERT_CertTimesValid(newcert);
- if (rv == SECFailure) {
- goto endloop;
- }
- }
- /* does it have the CA extension */
- /*
- * Make sure that if this is an intermediate CA in the chain that
- * it was given permission by its signer to be a CA.
- */
- isca = CERT_IsCACert(newcert, &certtype);
- if (!isca) {
- if (!trusted) {
- goto endloop;
- }
- trust.sslFlags = CERTDB_VALID_CA;
- trust.emailFlags = CERTDB_VALID_CA;
- trust.objectSigningFlags = CERTDB_VALID_CA;
- } else {
- /* SSL ca's must have the ssl bit set */
- if ((certUsage == certUsageSSLCA) &&
- ((certtype & NS_CERT_TYPE_SSL_CA) != NS_CERT_TYPE_SSL_CA)) {
- goto endloop;
- }
- /* it passed all of the tests, so lets add it to the database */
- /* mark it as a CA */
- PORT_Memset((void *)&trust, 0, sizeof(trust));
- switch (certUsage) {
- case certUsageSSLCA:
- trust.sslFlags = CERTDB_VALID_CA;
- break;
- case certUsageUserCertImport:
- if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
- trust.sslFlags = CERTDB_VALID_CA;
- }
- if ((certtype & NS_CERT_TYPE_EMAIL_CA) ==
- NS_CERT_TYPE_EMAIL_CA) {
- trust.emailFlags = CERTDB_VALID_CA;
- }
- if ((certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA) ==
- NS_CERT_TYPE_OBJECT_SIGNING_CA) {
- trust.objectSigningFlags = CERTDB_VALID_CA;
- }
- break;
- default:
- PORT_Assert(0);
- break;
- }
- }
- cert = CERT_NewTempCertificate(handle, derCert, NULL,
- PR_FALSE, PR_FALSE);
- if (cert == NULL) {
- goto loser;
- }
- /* if the cert is temp, make it perm; otherwise we're done */
- rv = CERT_GetCertIsTemp(cert, &istemp);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (istemp) {
- /* get a default nickname for it */
- nickname = CERT_MakeCANickname(cert);
- rv = CERT_AddTempCertToPerm(cert, nickname, &trust);
- /* free the nickname */
- if (nickname) {
- PORT_Free(nickname);
- }
- } else {
- rv = SECSuccess;
- }
- if (rv != SECSuccess) {
- goto loser;
- }
- endloop:
- if (newcert) {
- CERT_DestroyCertificate(newcert);
- newcert = NULL;
- }
- }
- rv = SECSuccess;
- goto done;
- loser:
- rv = SECFailure;
- done:
- if (newcert) {
- CERT_DestroyCertificate(newcert);
- newcert = NULL;
- }
- if (cert) {
- CERT_DestroyCertificate(cert);
- cert = NULL;
- }
- return (rv);
- }
- SECStatus
- CERT_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage)
- {
- return cert_ImportCAChain(certs, numcerts, certUsage, PR_FALSE);
- }
- SECStatus
- CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage)
- {
- return cert_ImportCAChain(certs, numcerts, certUsage, PR_TRUE);
- }
- /* Moved from certdb.c */
- /*
- ** CERT_CertChainFromCert
- **
- ** Construct a CERTCertificateList consisting of the given certificate and all
- ** of the issuer certs until we either get to a self-signed cert or can't find
- ** an issuer. Since we don't know how many certs are in the chain we have to
- ** build a linked list first as we count them.
- */
- typedef struct certNode {
- struct certNode *next;
- CERTCertificate *cert;
- } certNode;
- CERTCertificateList *
- CERT_CertChainFromCert(CERTCertificate *cert, SECCertUsage usage,
- PRBool includeRoot)
- {
- CERTCertificateList *chain = NULL;
- NSSCertificate **stanChain;
- NSSCertificate *stanCert;
- PLArenaPool *arena;
- NSSUsage nssUsage;
- int i, len;
- NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
- NSSCryptoContext *cc = STAN_GetDefaultCryptoContext();
- stanCert = STAN_GetNSSCertificate(cert);
- if (!stanCert) {
- /* error code is set */
- return NULL;
- }
- nssUsage.anyUsage = PR_FALSE;
- nssUsage.nss3usage = usage;
- nssUsage.nss3lookingForCA = PR_FALSE;
- stanChain = NSSCertificate_BuildChain(stanCert, NULL, &nssUsage, NULL, NULL,
- CERT_MAX_CERT_CHAIN, NULL, NULL, td, cc);
- if (!stanChain) {
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- return NULL;
- }
- len = 0;
- stanCert = stanChain[0];
- while (stanCert) {
- stanCert = stanChain[++len];
- }
- arena = PORT_NewArena(4096);
- if (arena == NULL) {
- goto loser;
- }
- chain = (CERTCertificateList *)PORT_ArenaAlloc(arena,
- sizeof(CERTCertificateList));
- if (!chain)
- goto loser;
- chain->certs = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
- if (!chain->certs)
- goto loser;
- i = 0;
- stanCert = stanChain[i];
- while (stanCert) {
- SECItem derCert;
- CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
- if (!cCert) {
- goto loser;
- }
- derCert.len = (unsigned int)stanCert->encoding.size;
- derCert.data = (unsigned char *)stanCert->encoding.data;
- derCert.type = siBuffer;
- if (SECITEM_CopyItem(arena, &chain->certs[i], &derCert) != SECSuccess) {
- CERT_DestroyCertificate(cCert);
- goto loser;
- }
- stanCert = stanChain[++i];
- if (!stanCert && !cCert->isRoot) {
- /* reached the end of the chain, but the final cert is
- * not a root. Don't discard it.
- */
- includeRoot = PR_TRUE;
- }
- CERT_DestroyCertificate(cCert);
- }
- if (!includeRoot && len > 1) {
- chain->len = len - 1;
- } else {
- chain->len = len;
- }
- chain->arena = arena;
- nss_ZFreeIf(stanChain);
- return chain;
- loser:
- i = 0;
- stanCert = stanChain[i];
- while (stanCert) {
- CERTCertificate *cCert = STAN_GetCERTCertificate(stanCert);
- if (cCert) {
- CERT_DestroyCertificate(cCert);
- }
- stanCert = stanChain[++i];
- }
- nss_ZFreeIf(stanChain);
- if (arena) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return NULL;
- }
- /* Builds a CERTCertificateList holding just one DER-encoded cert, namely
- ** the one for the cert passed as an argument.
- */
- CERTCertificateList *
- CERT_CertListFromCert(CERTCertificate *cert)
- {
- CERTCertificateList *chain = NULL;
- int rv;
- PLArenaPool *arena;
- /* arena for SecCertificateList */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL)
- goto no_memory;
- /* build the CERTCertificateList */
- chain = (CERTCertificateList *)PORT_ArenaAlloc(arena, sizeof(CERTCertificateList));
- if (chain == NULL)
- goto no_memory;
- chain->certs = (SECItem *)PORT_ArenaAlloc(arena, 1 * sizeof(SECItem));
- if (chain->certs == NULL)
- goto no_memory;
- rv = SECITEM_CopyItem(arena, chain->certs, &(cert->derCert));
- if (rv < 0)
- goto loser;
- chain->len = 1;
- chain->arena = arena;
- return chain;
- no_memory:
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- loser:
- if (arena != NULL) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return NULL;
- }
- CERTCertificateList *
- CERT_DupCertList(const CERTCertificateList *oldList)
- {
- CERTCertificateList *newList = NULL;
- PLArenaPool *arena = NULL;
- SECItem *newItem;
- SECItem *oldItem;
- int len = oldList->len;
- int rv;
- /* arena for SecCertificateList */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL)
- goto no_memory;
- /* now build the CERTCertificateList */
- newList = PORT_ArenaNew(arena, CERTCertificateList);
- if (newList == NULL)
- goto no_memory;
- newList->arena = arena;
- newItem = (SECItem *)PORT_ArenaAlloc(arena, len * sizeof(SECItem));
- if (newItem == NULL)
- goto no_memory;
- newList->certs = newItem;
- newList->len = len;
- for (oldItem = oldList->certs; len > 0; --len, ++newItem, ++oldItem) {
- rv = SECITEM_CopyItem(arena, newItem, oldItem);
- if (rv < 0)
- goto loser;
- }
- return newList;
- no_memory:
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- loser:
- if (arena != NULL) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return NULL;
- }
- void
- CERT_DestroyCertificateList(CERTCertificateList *list)
- {
- PORT_FreeArena(list->arena, PR_FALSE);
- }
|