Index: mozilla/security/nss/lib/certhigh/certhigh.c |
=================================================================== |
--- mozilla/security/nss/lib/certhigh/certhigh.c (revision 191424) |
+++ mozilla/security/nss/lib/certhigh/certhigh.c (working copy) |
@@ -1,1193 +0,0 @@ |
-/* 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 "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; |
- char *token = NULL; |
- int len; |
- |
- /* 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) { |
- token=name1; |
- nickname1=token1; |
- nickname2=name2; |
- } else { |
- token=name2; |
- nickname1=token2; |
- nickname2=name1; |
- } |
- len = nickname1-token; |
- nickname1++; |
- if (PORT_Strcmp(nickname1,nickname2) != 0) { |
- return PR_FALSE; |
- } |
- /* 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; |
- 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); |
-} |
- |
-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) |
-{ |
- PRArenaPool *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) |
-{ |
- PRArenaPool *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) |
-{ |
- PRArenaPool *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; |
- PRArenaPool * 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; |
- PRArenaPool *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; |
- PRArenaPool *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; |
- |
- 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 */ |
- if (cert->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; |
- } |
- |
- CERT_DestroyCertificate(cert); |
- cert = NULL; |
- |
- 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; |
- PRArenaPool *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; |
- SECITEM_CopyItem(arena, &chain->certs[i], &derCert); |
- 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; |
- PRArenaPool *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; |
- PRArenaPool *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); |
-} |
- |