Back to index

lightning-sunbird  0.9+nobinonly
pki3hack.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #ifdef DEBUG
00038 static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.86.28.5 $ $Date: 2006/10/01 05:43:02 $";
00039 #endif /* DEBUG */
00040 
00041 /*
00042  * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
00043  */
00044 
00045 #ifndef NSSPKI_H
00046 #include "nsspki.h"
00047 #endif /* NSSPKI_H */
00048 
00049 #ifndef PKI_H
00050 #include "pki.h"
00051 #endif /* PKI_H */
00052 
00053 #ifndef PKIM_H
00054 #include "pkim.h"
00055 #endif /* PKIM_H */
00056 
00057 #ifndef DEV_H
00058 #include "dev.h"
00059 #endif /* DEV_H */
00060 
00061 #ifndef DEVNSS3HACK_H
00062 #include "dev3hack.h"
00063 #endif /* DEVNSS3HACK_H */
00064 
00065 #ifndef PKINSS3HACK_H
00066 #include "pki3hack.h"
00067 #endif /* PKINSS3HACK_H */
00068 
00069 #include "secitem.h"
00070 #include "certdb.h"
00071 #include "certt.h"
00072 #include "cert.h"
00073 #include "pk11func.h"
00074 #include "pkistore.h"
00075 #include "secmod.h"
00076 #include "nssrwlk.h"
00077 
00078 NSSTrustDomain *g_default_trust_domain = NULL;
00079 
00080 NSSCryptoContext *g_default_crypto_context = NULL;
00081 
00082 NSSTrustDomain *
00083 STAN_GetDefaultTrustDomain()
00084 {
00085     return g_default_trust_domain;
00086 }
00087 
00088 NSSCryptoContext *
00089 STAN_GetDefaultCryptoContext()
00090 {
00091     return g_default_crypto_context;
00092 }
00093 
00094 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
00095 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
00096 
00097 NSS_IMPLEMENT PRStatus
00098 STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
00099 {
00100     NSSToken *token;
00101     if (!td) {
00102        td = g_default_trust_domain;
00103     }
00104     token = nssToken_CreateFromPK11SlotInfo(td, slot);
00105     PK11Slot_SetNSSToken(slot, token);
00106     NSSRWLock_LockWrite(td->tokensLock);
00107     nssList_Add(td->tokenList, token);
00108     NSSRWLock_UnlockWrite(td->tokensLock);
00109     return PR_SUCCESS;
00110 }
00111 
00112 NSS_IMPLEMENT PRStatus
00113 STAN_ResetTokenInterator(NSSTrustDomain *td)
00114 {
00115     if (!td) {
00116        td = g_default_trust_domain;
00117     }
00118     NSSRWLock_LockWrite(td->tokensLock);
00119     nssListIterator_Destroy(td->tokens);
00120     td->tokens = nssList_CreateIterator(td->tokenList);
00121     NSSRWLock_UnlockWrite(td->tokensLock);
00122     return PR_SUCCESS;
00123 }
00124 
00125 NSS_IMPLEMENT PRStatus
00126 STAN_LoadDefaultNSS3TrustDomain (
00127   void
00128 )
00129 {
00130     NSSTrustDomain *td;
00131     SECMODModuleList *mlp;
00132     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
00133     int i;
00134 
00135     if (g_default_trust_domain || g_default_crypto_context) {
00136        /* Stan is already initialized or a previous shutdown failed. */
00137        nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
00138        return PR_FAILURE;
00139     }
00140     td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
00141     if (!td) {
00142        return PR_FAILURE;
00143     }
00144     /*
00145      * Deadlock warning: we should never acquire the moduleLock while
00146      * we hold the tokensLock. We can use the NSSRWLock Rank feature to
00147      * guarrentee this. tokensLock have a higher rank than module lock.
00148      */
00149     td->tokenList = nssList_Create(td->arena, PR_TRUE);
00150     if (!td->tokenList) {
00151        goto loser;
00152     }
00153     SECMOD_GetReadLock(moduleLock);
00154     NSSRWLock_LockWrite(td->tokensLock);
00155     for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
00156        for (i=0; i < mlp->module->slotCount; i++) {
00157            STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
00158        }
00159     }
00160     td->tokens = nssList_CreateIterator(td->tokenList);
00161     NSSRWLock_UnlockWrite(td->tokensLock);
00162     SECMOD_ReleaseReadLock(moduleLock);
00163     if (!td->tokens) {
00164        goto loser;
00165     }
00166     g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
00167     if (!g_default_crypto_context) {
00168        goto loser;
00169     }
00170     g_default_trust_domain = td;
00171     return PR_SUCCESS;
00172 
00173   loser:
00174     NSSTrustDomain_Destroy(td);
00175     return PR_FAILURE;
00176 }
00177 
00178 /*
00179  * must be called holding the ModuleListLock (either read or write).
00180  */
00181 NSS_IMPLEMENT SECStatus
00182 STAN_AddModuleToDefaultTrustDomain (
00183   SECMODModule *module
00184 )
00185 {
00186     NSSTrustDomain *td;
00187     int i;
00188     td = STAN_GetDefaultTrustDomain();
00189     for (i=0; i<module->slotCount; i++) {
00190        STAN_InitTokenForSlotInfo(td, module->slots[i]);
00191     }
00192     STAN_ResetTokenInterator(td);
00193     return SECSuccess;
00194 }
00195 
00196 /*
00197  * must be called holding the ModuleListLock (either read or write).
00198  */
00199 NSS_IMPLEMENT SECStatus
00200 STAN_RemoveModuleFromDefaultTrustDomain (
00201   SECMODModule *module
00202 )
00203 {
00204     NSSToken *token;
00205     NSSTrustDomain *td;
00206     int i;
00207     td = STAN_GetDefaultTrustDomain();
00208     NSSRWLock_LockWrite(td->tokensLock);
00209     for (i=0; i<module->slotCount; i++) {
00210        token = PK11Slot_GetNSSToken(module->slots[i]);
00211        if (token) {
00212            nssToken_NotifyCertsNotVisible(token);
00213            nssList_Remove(td->tokenList, token);
00214            PK11Slot_SetNSSToken(module->slots[i], NULL);
00215            nssToken_Destroy(token);
00216        }
00217     }
00218     nssListIterator_Destroy(td->tokens);
00219     td->tokens = nssList_CreateIterator(td->tokenList);
00220     NSSRWLock_UnlockWrite(td->tokensLock);
00221     return SECSuccess;
00222 }
00223 
00224 NSS_IMPLEMENT PRStatus
00225 STAN_Shutdown()
00226 {
00227     PRStatus status = PR_SUCCESS;
00228     if (g_default_trust_domain) {
00229        if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
00230            g_default_trust_domain = NULL;
00231        } else {
00232            status = PR_FAILURE;
00233        }
00234     }
00235     if (g_default_crypto_context) {
00236        if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
00237            g_default_crypto_context = NULL;
00238        } else {
00239            status = PR_FAILURE;
00240        }
00241     }
00242     return status;
00243 }
00244 
00245 /* this function should not be a hack; it will be needed in 4.0 (rename) */
00246 NSS_IMPLEMENT NSSItem *
00247 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
00248 {
00249     NSSItem *rvKey;
00250     SECItem secDER;
00251     SECItem secKey = { 0 };
00252     SECStatus secrv;
00253     PRArenaPool *arena;
00254 
00255     SECITEM_FROM_NSSITEM(&secDER, der);
00256 
00257     /* nss3 call uses nss3 arena's */
00258     arena = PORT_NewArena(256);
00259     if (!arena) {
00260        return NULL;
00261     }
00262     secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
00263     if (secrv != SECSuccess) {
00264        return NULL;
00265     }
00266     rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
00267     PORT_FreeArena(arena,PR_FALSE);
00268     return rvKey;
00269 }
00270 
00271 NSS_IMPLEMENT PRStatus
00272 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena, 
00273                                      NSSDER *issuer, NSSDER *serial)
00274 {
00275     SECStatus secrv;
00276     SECItem derCert;
00277     SECItem derIssuer = { 0 };
00278     SECItem derSerial = { 0 };
00279     SECITEM_FROM_NSSITEM(&derCert, der);
00280     secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
00281     if (secrv != SECSuccess) {
00282        return PR_FAILURE;
00283     }
00284     (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
00285     secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
00286     if (secrv != SECSuccess) {
00287        PORT_Free(derSerial.data);
00288        return PR_FAILURE;
00289     }
00290     (void)nssItem_Create(arena, issuer, derIssuer.len, derIssuer.data);
00291     PORT_Free(derSerial.data);
00292     PORT_Free(derIssuer.data);
00293     return PR_SUCCESS;
00294 }
00295 
00296 static NSSItem *
00297 nss3certificate_getIdentifier(nssDecodedCert *dc)
00298 {
00299     NSSItem *rvID;
00300     CERTCertificate *c = (CERTCertificate *)dc->data;
00301     rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
00302     return rvID;
00303 }
00304 
00305 static void *
00306 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
00307 {
00308     CERTCertificate *c = (CERTCertificate *)dc->data;
00309     return (void *)c->authKeyID;
00310 }
00311 
00312 static nssCertIDMatch
00313 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
00314 {
00315     CERTCertificate *c = (CERTCertificate *)dc->data;
00316     CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
00317     SECItem skid;
00318     nssCertIDMatch match = nssCertIDMatch_Unknown;
00319 
00320     /* keyIdentifier */
00321     if (authKeyID->keyID.len > 0) {
00322        if (CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
00323            PRBool skiEqual;
00324            skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
00325            PORT_Free(skid.data);
00326            if (skiEqual) {
00327               /* change the state to positive match, but keep going */
00328               match = nssCertIDMatch_Yes;
00329            } else {
00330               /* exit immediately on failure */
00331               return nssCertIDMatch_No;
00332            }
00333        } /* else fall through */
00334     }
00335 
00336     /* issuer/serial (treated as pair) */
00337     if (authKeyID->authCertIssuer) {
00338        SECItem *caName = NULL;
00339        SECItem *caSN = &authKeyID->authCertSerialNumber;
00340 
00341        caName = (SECItem *)CERT_GetGeneralNameByType(
00342                                                authKeyID->authCertIssuer,
00343                                           certDirectoryName, PR_TRUE);
00344        if (caName == NULL) {
00345            /* this is some kind of error, so treat it as unknown */
00346            return nssCertIDMatch_Unknown;
00347        }
00348        if (SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
00349            SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) 
00350        {
00351            /* change the state to positive match, but keep going */
00352            match = nssCertIDMatch_Yes;
00353        } else {
00354            /* exit immediately on failure */
00355            return nssCertIDMatch_No;
00356        }
00357     }
00358 
00359     /* If the issued cert has a keyIdentifier field with a value, but
00360      * this issuer cert does not have a subjectKeyID extension, and
00361      * the issuer/serial number fields of the authKeyID extension
00362      * are empty, the state will be Unknown.  Otherwise it should have
00363      * been set to Yes.
00364      */
00365     return match;
00366 }
00367 
00368 static PRBool
00369 nss3certificate_isValidIssuer(nssDecodedCert *dc)
00370 {
00371     CERTCertificate *c = (CERTCertificate *)dc->data;
00372     unsigned int ignore;
00373     return CERT_IsCACert(c, &ignore);
00374 }
00375 
00376 static NSSUsage *
00377 nss3certificate_getUsage(nssDecodedCert *dc)
00378 {
00379     /* CERTCertificate *c = (CERTCertificate *)dc->data; */
00380     return NULL;
00381 }
00382 
00383 static PRBool 
00384 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
00385 {
00386     SECCertTimeValidity validity;
00387     CERTCertificate *c = (CERTCertificate *)dc->data;
00388     validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
00389     if (validity == secCertTimeValid) {
00390        return PR_TRUE;
00391     }
00392     return PR_FALSE;
00393 }
00394 
00395 static PRBool 
00396 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
00397 {
00398     /* I know this isn't right, but this is glue code anyway */
00399     if (cmpdc->type == dc->type) {
00400        CERTCertificate *certa = (CERTCertificate *)dc->data;
00401        CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
00402        return CERT_IsNewer(certa, certb);
00403     }
00404     return PR_FALSE;
00405 }
00406 
00407 /* CERT_FilterCertListByUsage */
00408 static PRBool
00409 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
00410 {
00411     CERTCertificate *cc;
00412     unsigned int requiredKeyUsage = 0;
00413     unsigned int requiredCertType = 0;
00414     SECStatus secrv;
00415     PRBool match;
00416     PRBool ca;
00417 
00418     /* This is for NSS 3.3 functions that do not specify a usage */
00419     if (usage->anyUsage) {
00420        return PR_TRUE;
00421     }
00422     ca = usage->nss3lookingForCA;
00423     secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
00424                                              &requiredKeyUsage,
00425                                              &requiredCertType);
00426     if (secrv != SECSuccess) {
00427        return PR_FALSE;
00428     }
00429     cc = (CERTCertificate *)dc->data;
00430     secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
00431     match = (PRBool)(secrv == SECSuccess);
00432     if (match) {
00433        unsigned int certType = 0;
00434        if (ca) {
00435            (void)CERT_IsCACert(cc, &certType);
00436        } else {
00437            certType = cc->nsCertType;
00438        }
00439        if (!(certType & requiredCertType)) {
00440            match = PR_FALSE;
00441        }
00442     }
00443     return match;
00444 }
00445 
00446 static NSSASCII7 *
00447 nss3certificate_getEmailAddress(nssDecodedCert *dc)
00448 {
00449     CERTCertificate *cc = (CERTCertificate *)dc->data;
00450     return (cc && cc->emailAddr && cc->emailAddr[0])
00451            ? (NSSASCII7 *)cc->emailAddr : NULL;
00452 }
00453 
00454 static PRStatus
00455 nss3certificate_getDERSerialNumber(nssDecodedCert *dc, 
00456                                    NSSDER *serial, NSSArena *arena)
00457 {
00458     CERTCertificate *cc = (CERTCertificate *)dc->data;
00459     SECItem derSerial = { 0 };
00460     SECStatus secrv;
00461     secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
00462     if (secrv == SECSuccess) {
00463        (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
00464        PORT_Free(derSerial.data);
00465        return PR_SUCCESS;
00466     }
00467     return PR_FAILURE;
00468 }
00469 
00470 /* Returns NULL if "encoding" cannot be decoded. */
00471 NSS_IMPLEMENT nssDecodedCert *
00472 nssDecodedPKIXCertificate_Create (
00473   NSSArena *arenaOpt,
00474   NSSDER *encoding
00475 )
00476 {
00477     nssDecodedCert  *rvDC = NULL;
00478     CERTCertificate *cert;
00479     SECItem          secDER;
00480 
00481     SECITEM_FROM_NSSITEM(&secDER, encoding);
00482     cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
00483     if (cert) {
00484        rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
00485        if (rvDC) {
00486            rvDC->type                = NSSCertificateType_PKIX;
00487            rvDC->data                = (void *)cert;
00488            rvDC->getIdentifier       = nss3certificate_getIdentifier;
00489            rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
00490            rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
00491            rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
00492            rvDC->getUsage            = nss3certificate_getUsage;
00493            rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
00494            rvDC->isNewerThan         = nss3certificate_isNewerThan;
00495            rvDC->matchUsage          = nss3certificate_matchUsage;
00496            rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
00497            rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber;
00498        } else {
00499            CERT_DestroyCertificate(cert);
00500        }
00501     }
00502     return rvDC;
00503 }
00504 
00505 static nssDecodedCert *
00506 create_decoded_pkix_cert_from_nss3cert (
00507   NSSArena *arenaOpt,
00508   CERTCertificate *cc
00509 )
00510 {
00511     nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
00512     if (rvDC) {
00513        rvDC->type                = NSSCertificateType_PKIX;
00514        rvDC->data                = (void *)cc;
00515        rvDC->getIdentifier       = nss3certificate_getIdentifier;
00516        rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
00517        rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
00518        rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
00519        rvDC->getUsage            = nss3certificate_getUsage;
00520        rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
00521        rvDC->isNewerThan         = nss3certificate_isNewerThan;
00522        rvDC->matchUsage          = nss3certificate_matchUsage;
00523        rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
00524     }
00525     return rvDC;
00526 }
00527 
00528 NSS_IMPLEMENT PRStatus
00529 nssDecodedPKIXCertificate_Destroy (
00530   nssDecodedCert *dc
00531 )
00532 {
00533     CERTCertificate *cert = (CERTCertificate *)dc->data;
00534 
00535     /* The decoder may only be half initialized (the case where we find we 
00536      * could not decode the certificate). In this case, there is not cert to
00537      * free, just free the dc structure. */
00538     if (cert) {
00539        PRBool freeSlot = cert->ownSlot;
00540        PK11SlotInfo *slot = cert->slot;
00541        PRArenaPool *arena  = cert->arena;
00542        /* zero cert before freeing. Any stale references to this cert
00543         * after this point will probably cause an exception.  */
00544        PORT_Memset(cert, 0, sizeof *cert);
00545        /* free the arena that contains the cert. */
00546        PORT_FreeArena(arena, PR_FALSE);
00547        if (slot && freeSlot) {
00548            PK11_FreeSlot(slot);
00549        }
00550     }
00551     nss_ZFreeIf(dc);
00552     return PR_SUCCESS;
00553 }
00554 
00555 /* see pk11cert.c:pk11_HandleTrustObject */
00556 static unsigned int
00557 get_nss3trust_from_nss4trust(CK_TRUST t)
00558 {
00559     unsigned int rt = 0;
00560     if (t == nssTrustLevel_Trusted) {
00561        rt |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
00562     }
00563     if (t == nssTrustLevel_TrustedDelegator) {
00564        rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA /*| CERTDB_NS_TRUSTED_CA*/;
00565     }
00566     if (t == nssTrustLevel_Valid) {
00567        rt |= CERTDB_VALID_PEER;
00568     }
00569     if (t == nssTrustLevel_ValidDelegator) {
00570        rt |= CERTDB_VALID_CA;
00571     }
00572     return rt;
00573 }
00574 
00575 static CERTCertTrust *
00576 cert_trust_from_stan_trust(NSSTrust *t, PRArenaPool *arena)
00577 {
00578     CERTCertTrust *rvTrust;
00579     unsigned int client;
00580     if (!t) {
00581        return NULL;
00582     }
00583     rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
00584     if (!rvTrust) return NULL;
00585     rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
00586     client = get_nss3trust_from_nss4trust(t->clientAuth);
00587     if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
00588        client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA);
00589        rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
00590     }
00591     rvTrust->sslFlags |= client;
00592     rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
00593     rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
00594     /* The cert is a valid step-up cert (in addition to/lieu of trust above */
00595     if (t->stepUpApproved) {
00596        rvTrust->sslFlags |= CERTDB_GOVT_APPROVED_CA;
00597     }
00598     return rvTrust;
00599 }
00600 
00601 CERTCertTrust * 
00602 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
00603 {
00604     CERTCertTrust *rvTrust = NULL;
00605     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
00606     NSSTrust *t;
00607     t = nssTrustDomain_FindTrustForCertificate(td, c);
00608     if (t) {
00609        rvTrust = cert_trust_from_stan_trust(t, cc->arena);
00610        if (!rvTrust) {
00611            nssTrust_Destroy(t);
00612            return NULL;
00613        }
00614        nssTrust_Destroy(t);
00615     } else {
00616        rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
00617        if (!rvTrust) {
00618            return NULL;
00619        }
00620        memset(rvTrust, 0, sizeof(*rvTrust));
00621     }
00622     if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
00623        rvTrust->sslFlags |= CERTDB_USER;
00624        rvTrust->emailFlags |= CERTDB_USER;
00625        rvTrust->objectSigningFlags |= CERTDB_USER;
00626     }
00627     return rvTrust;
00628 }
00629 
00630 static nssCryptokiInstance *
00631 get_cert_instance(NSSCertificate *c)
00632 {
00633     nssCryptokiObject *instance, **ci;
00634     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
00635     if (!instances) {
00636        return NULL;
00637     }
00638     instance = NULL;
00639     for (ci = instances; *ci; ci++) {
00640        if (!instance) {
00641            instance = nssCryptokiObject_Clone(*ci);
00642        } else {
00643            /* This only really works for two instances...  But 3.4 can't
00644             * handle more anyway.  The logic is, if there are multiple
00645             * instances, prefer the one that is not internal (e.g., on
00646             * a hardware device.
00647             */
00648            if (PK11_IsInternal(instance->token->pk11slot)) {
00649               nssCryptokiObject_Destroy(instance);
00650               instance = nssCryptokiObject_Clone(*ci);
00651            }
00652        }
00653     }
00654     nssCryptokiObjectArray_Destroy(instances);
00655     return instance;
00656 }
00657 
00658 char * 
00659 STAN_GetCERTCertificateNameForInstance (
00660   PLArenaPool *arenaOpt,
00661   NSSCertificate *c,
00662   nssCryptokiInstance *instance
00663 )
00664 {
00665     NSSCryptoContext *context = c->object.cryptoContext;
00666     PRStatus nssrv;
00667     int nicklen, tokenlen, len;
00668     NSSUTF8 *tokenName = NULL;
00669     NSSUTF8 *stanNick = NULL;
00670     char *nickname = NULL;
00671     char *nick;
00672 
00673     if (instance) {
00674        stanNick = instance->label;
00675     } else if (context) {
00676        stanNick = c->object.tempName;
00677     }
00678     if (stanNick) {
00679        /* fill other fields needed by NSS3 functions using CERTCertificate */
00680        if (instance && !PK11_IsInternal(instance->token->pk11slot)) {
00681            tokenName = nssToken_GetName(instance->token);
00682            tokenlen = nssUTF8_Size(tokenName, &nssrv);
00683        } else {
00684        /* don't use token name for internal slot; 3.3 didn't */
00685            tokenlen = 0;
00686        }
00687        nicklen = nssUTF8_Size(stanNick, &nssrv);
00688        len = tokenlen + nicklen;
00689        if (arenaOpt) {
00690            nickname = PORT_ArenaAlloc(arenaOpt, len);
00691        } else {
00692            nickname = PORT_Alloc(len);
00693        }
00694        nick = nickname;
00695        if (tokenName) {
00696            memcpy(nick, tokenName, tokenlen-1);
00697            nick += tokenlen-1;
00698            *nick++ = ':';
00699        }
00700        memcpy(nick, stanNick, nicklen-1);
00701        nickname[len-1] = '\0';
00702     }
00703     return nickname;
00704 }
00705 
00706 char * 
00707 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
00708 {
00709     char * result;
00710     nssCryptokiInstance *instance = get_cert_instance(c);
00711     /* It's OK to call this function, even if instance is NULL */
00712     result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
00713     if (instance)
00714        nssCryptokiObject_Destroy(instance);
00715     return result;
00716 }
00717 
00718 static void
00719 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
00720 {
00721     CERTCertTrust* trust = NULL;
00722     NSSTrust *nssTrust;
00723     NSSCryptoContext *context = c->object.cryptoContext;
00724     nssCryptokiInstance *instance;
00725     NSSUTF8 *stanNick = NULL;
00726 
00727     /* We are holding the base class object's lock on entry of this function
00728      * This lock protects writes to fields of the CERTCertificate .
00729      * It is also needed by some functions to compute values such as trust.
00730      */
00731     instance = get_cert_instance(c);
00732 
00733     if (instance) {
00734        stanNick = instance->label;
00735     } else if (context) {
00736        stanNick = c->object.tempName;
00737     }
00738     /* fill other fields needed by NSS3 functions using CERTCertificate */
00739     if ((!cc->nickname && stanNick) || forced) {
00740        PRStatus nssrv;
00741        int nicklen, tokenlen, len;
00742        NSSUTF8 *tokenName = NULL;
00743        char *nick;
00744        if (instance && !PK11_IsInternal(instance->token->pk11slot)) {
00745            tokenName = nssToken_GetName(instance->token);
00746            tokenlen = nssUTF8_Size(tokenName, &nssrv);
00747        } else {
00748            /* don't use token name for internal slot; 3.3 didn't */
00749            tokenlen = 0;
00750        }
00751        if (stanNick) {
00752            nicklen = nssUTF8_Size(stanNick, &nssrv);
00753            len = tokenlen + nicklen;
00754            nick = PORT_ArenaAlloc(cc->arena, len);
00755            if (tokenName) {
00756               memcpy(nick, tokenName, tokenlen-1);
00757               nick[tokenlen-1] = ':';
00758               memcpy(nick+tokenlen, stanNick, nicklen-1);
00759            } else {
00760               memcpy(nick, stanNick, nicklen-1);
00761            }
00762            nick[len-1] = '\0';
00763             cc->nickname = nick;
00764        } else {
00765            cc->nickname = NULL;
00766        }
00767     }
00768     if (context) {
00769        /* trust */
00770        nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
00771        if (nssTrust) {
00772             trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
00773             if (trust) {
00774                 /* we should destroy cc->trust before replacing it, but it's
00775                    allocated in cc->arena, so memory growth will occur on each
00776                    refresh */
00777                 cc->trust = trust;
00778             }
00779            nssTrust_Destroy(nssTrust);
00780        }
00781     } else if (instance) {
00782        /* slot */
00783        if (cc->slot != instance->token->pk11slot) {
00784            if (cc->slot) {
00785               PK11_FreeSlot(cc->slot);
00786            }
00787            cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
00788        }
00789        cc->ownSlot = PR_TRUE;
00790        /* pkcs11ID */
00791        cc->pkcs11ID = instance->handle;
00792        /* trust */
00793        trust = nssTrust_GetCERTCertTrustForCert(c, cc);
00794         if (trust) {
00795             /* we should destroy cc->trust before replacing it, but it's
00796                allocated in cc->arena, so memory growth will occur on each
00797                refresh */
00798             cc->trust = trust;
00799         }
00800        nssCryptokiObject_Destroy(instance);
00801     } 
00802     /* database handle is now the trust domain */
00803     cc->dbhandle = c->object.trustDomain;
00804     /* subjectList ? */
00805     /* istemp and isperm are supported in NSS 3.4 */
00806     cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
00807     cc->isperm = PR_TRUE;  /* by default */
00808     /* pointer back */
00809     cc->nssCertificate = c;
00810 }
00811 
00812 static CERTCertificate *
00813 stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
00814 {
00815     nssDecodedCert *dc = NULL;
00816     CERTCertificate *cc = NULL;
00817 
00818     nssPKIObject_Lock(&c->object);
00819 
00820     dc = c->decoding;
00821     if (!dc) {
00822        dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
00823        if (!dc) {
00824             goto loser;
00825         }
00826        cc = (CERTCertificate *)dc->data;
00827        PORT_Assert(cc); /* software error */
00828        if (!cc) {
00829            nssDecodedPKIXCertificate_Destroy(dc);
00830            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00831            goto loser;
00832        }
00833        PORT_Assert(!c->decoding); 
00834        if (!c->decoding) {
00835            c->decoding = dc;
00836        } else { 
00837             /* this should never happen. Fail. */
00838            nssDecodedPKIXCertificate_Destroy(dc);
00839            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00840             goto loser;
00841        }
00842     }
00843     cc = (CERTCertificate *)dc->data;
00844     PORT_Assert(cc);
00845     if (!cc) {
00846         nss_SetError(NSS_ERROR_INTERNAL_ERROR);
00847         goto loser;
00848     }
00849     if (!cc->nssCertificate || forceUpdate) {
00850         fill_CERTCertificateFields(c, cc, forceUpdate);
00851     } else if (!cc->trust && !c->object.cryptoContext) {
00852         /* if it's a perm cert, it might have been stored before the
00853          * trust, so look for the trust again.  But a temp cert can be
00854          * ignored.
00855          */
00856         CERTCertTrust* trust = NULL;
00857         trust = nssTrust_GetCERTCertTrustForCert(c, cc);
00858         cc->trust = trust;
00859     }
00860 
00861   loser:
00862     nssPKIObject_Unlock(&c->object);
00863     return cc;
00864 }
00865 
00866 NSS_IMPLEMENT CERTCertificate *
00867 STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
00868 {
00869     if (c->decoding) {
00870        return stan_GetCERTCertificate(c, PR_TRUE);
00871     }
00872     return NULL;
00873 }
00874 
00875 NSS_IMPLEMENT CERTCertificate *
00876 STAN_GetCERTCertificate(NSSCertificate *c)
00877 {
00878     return stan_GetCERTCertificate(c, PR_FALSE);
00879 }
00880 /*
00881  * many callers of STAN_GetCERTCertificate() intend that
00882  * the CERTCertificate returned inherits the reference to the 
00883  * NSSCertificate. For these callers it's convenient to have 
00884  * this function 'own' the reference and either return a valid 
00885  * CERTCertificate structure which inherits the reference or 
00886  * destroy the reference to NSSCertificate and returns NULL.
00887  */
00888 NSS_IMPLEMENT CERTCertificate *
00889 STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
00890 {
00891     CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
00892     if (!nss3cert) {
00893        nssCertificate_Destroy(c);
00894     }
00895     return nss3cert;
00896 }
00897 
00898 static nssTrustLevel
00899 get_stan_trust(unsigned int t, PRBool isClientAuth) 
00900 {
00901     if (isClientAuth) {
00902        if (t & CERTDB_TRUSTED_CLIENT_CA) {
00903            return nssTrustLevel_TrustedDelegator;
00904        }
00905     } else {
00906        if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
00907            return nssTrustLevel_TrustedDelegator;
00908        }
00909     }
00910     if (t & CERTDB_TRUSTED) {
00911        return nssTrustLevel_Trusted;
00912     }
00913     if (t & CERTDB_VALID_CA) {
00914        return nssTrustLevel_ValidDelegator;
00915     }
00916     if (t & CERTDB_VALID_PEER) {
00917        return nssTrustLevel_Valid;
00918     }
00919     return nssTrustLevel_NotTrusted;
00920 }
00921 
00922 NSS_EXTERN NSSCertificate *
00923 STAN_GetNSSCertificate(CERTCertificate *cc)
00924 {
00925     NSSCertificate *c;
00926     nssCryptokiInstance *instance;
00927     nssPKIObject *pkiob;
00928     NSSArena *arena;
00929     c = cc->nssCertificate;
00930     if (c) {
00931        return c;
00932     }
00933     /* i don't think this should happen.  but if it can, need to create
00934      * NSSCertificate from CERTCertificate values here.  */
00935     /* Yup, it can happen. */
00936     arena = NSSArena_Create();
00937     if (!arena) {
00938        return NULL;
00939     }
00940     c = nss_ZNEW(arena, NSSCertificate);
00941     if (!c) {
00942        nssArena_Destroy(arena);
00943        return NULL;
00944     }
00945     NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
00946     c->type = NSSCertificateType_PKIX;
00947     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
00948     if (!pkiob) {
00949        nssArena_Destroy(arena);
00950        return NULL;
00951     }
00952     c->object = *pkiob;
00953     nssItem_Create(arena,
00954                    &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
00955     nssItem_Create(arena,
00956                    &c->subject, cc->derSubject.len, cc->derSubject.data);
00957     if (PR_TRUE) {
00958        /* CERTCertificate stores serial numbers decoded.  I need the DER
00959        * here.  sigh.
00960        */
00961        SECItem derSerial;
00962        SECStatus secrv;
00963        secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
00964        if (secrv == SECFailure) {
00965            nssArena_Destroy(arena);
00966            return NULL;
00967        }
00968        nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
00969        PORT_Free(derSerial.data);
00970     }
00971     if (cc->emailAddr && cc->emailAddr[0]) {
00972         c->email = nssUTF8_Create(arena,
00973                                   nssStringType_PrintableString,
00974                                   (NSSUTF8 *)cc->emailAddr,
00975                                   PORT_Strlen(cc->emailAddr));
00976     }
00977     if (cc->slot) {
00978        instance = nss_ZNEW(arena, nssCryptokiInstance);
00979        instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot));
00980        instance->handle = cc->pkcs11ID;
00981        instance->isTokenObject = PR_TRUE;
00982        if (cc->nickname) {
00983            instance->label = nssUTF8_Create(arena,
00984                                             nssStringType_UTF8String,
00985                                             (NSSUTF8 *)cc->nickname,
00986                                             PORT_Strlen(cc->nickname));
00987        }
00988        nssPKIObject_AddInstance(&c->object, instance);
00989     }
00990     c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
00991     cc->nssCertificate = c;
00992     return c;
00993 }
00994 
00995 static NSSToken*
00996 stan_GetTrustToken (
00997   NSSCertificate *c
00998 )
00999 {
01000     NSSToken *ttok = NULL;
01001     NSSToken *rtok = NULL;
01002     NSSToken *tok = NULL;
01003     nssCryptokiObject **ip;
01004     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
01005     if (!instances) {
01006        return PR_FALSE;
01007     }
01008     for (ip = instances; *ip; ip++) {
01009        nssCryptokiObject *instance = *ip;
01010         nssCryptokiObject *to = 
01011               nssToken_FindTrustForCertificate(instance->token, NULL,
01012               &c->encoding, &c->issuer, &c->serial, 
01013               nssTokenSearchType_TokenOnly);
01014        NSSToken *ctok = instance->token;
01015        PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
01016 
01017        if (to) {
01018            nssCryptokiObject_Destroy(to);
01019            ttok = ctok;
01020            if (!ro) {
01021               break;
01022            }
01023        } else {
01024            if (!rtok && ro) {
01025               rtok = ctok;
01026            } 
01027            if (!tok && !ro) {
01028               tok = ctok;
01029            }
01030        }
01031     }
01032     nssCryptokiObjectArray_Destroy(instances);
01033     return ttok ? ttok : (tok ? tok : rtok);
01034 }
01035 
01036 NSS_EXTERN PRStatus
01037 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
01038 {
01039     PRStatus nssrv;
01040     NSSCertificate *c = STAN_GetNSSCertificate(cc);
01041     NSSToken *tok;
01042     NSSTrustDomain *td;
01043     NSSTrust *nssTrust;
01044     NSSArena *arena;
01045     CERTCertTrust *oldTrust;
01046     nssListIterator *tokens;
01047     PRBool moving_object;
01048     nssCryptokiObject *newInstance;
01049     nssPKIObject *pkiob;
01050     oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
01051     if (oldTrust) {
01052        if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) {
01053            /* ... and the new trust is no different, done) */
01054            return PR_SUCCESS;
01055        } else {
01056            /* take over memory already allocated in cc's arena */
01057            cc->trust = oldTrust;
01058        }
01059     } else {
01060        cc->trust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
01061     }
01062     memcpy(cc->trust, trust, sizeof(CERTCertTrust));
01063     /* Set the NSSCerticate's trust */
01064     arena = nssArena_Create();
01065     if (!arena) return PR_FAILURE;
01066     nssTrust = nss_ZNEW(arena, NSSTrust);
01067     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
01068     if (!pkiob) {
01069        nssArena_Destroy(arena);
01070        return PR_FAILURE;
01071     }
01072     nssTrust->object = *pkiob;
01073     nssTrust->certificate = c;
01074     nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
01075     nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
01076     nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
01077     nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
01078     nssTrust->stepUpApproved = 
01079                     (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
01080     if (c->object.cryptoContext != NULL) {
01081        /* The cert is in a context, set the trust there */
01082        NSSCryptoContext *cc = c->object.cryptoContext;
01083        nssrv = nssCryptoContext_ImportTrust(cc, nssTrust);
01084        if (nssrv != PR_SUCCESS) {
01085            goto done;
01086        }
01087        if (c->object.numInstances == 0) {
01088            /* The context is the only instance, finished */
01089            goto done;
01090        }
01091     }
01092     td = STAN_GetDefaultTrustDomain();
01093     tok = stan_GetTrustToken(c);
01094     moving_object = PR_FALSE;
01095     if (tok && PK11_IsReadOnly(tok->pk11slot))  {
01096        NSSRWLock_LockRead(td->tokensLock);
01097        tokens = nssList_CreateIterator(td->tokenList);
01098        if (!tokens) {
01099            nssrv = PR_FAILURE;
01100            NSSRWLock_UnlockRead(td->tokensLock);
01101            goto done;
01102        }
01103        for (tok  = (NSSToken *)nssListIterator_Start(tokens);
01104             tok != (NSSToken *)NULL;
01105             tok  = (NSSToken *)nssListIterator_Next(tokens))
01106        {
01107            if (!PK11_IsReadOnly(tok->pk11slot)) break;
01108        }
01109        nssListIterator_Finish(tokens);
01110        nssListIterator_Destroy(tokens);
01111        NSSRWLock_UnlockRead(td->tokensLock);
01112        moving_object = PR_TRUE;
01113     } 
01114     if (tok) {
01115        if (moving_object) {
01116            /* this is kind of hacky.  the softoken needs the cert
01117             * object in order to store trust.  forcing it to be perm
01118             */
01119            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
01120            NSSASCII7 *email = NULL;
01121 
01122            if (PK11_IsInternal(tok->pk11slot)) {
01123               email = c->email;
01124            }
01125            newInstance = nssToken_ImportCertificate(tok, NULL,
01126                                                     NSSCertificateType_PKIX,
01127                                                     &c->id,
01128                                                     nickname,
01129                                                     &c->encoding,
01130                                                     &c->issuer,
01131                                                     &c->subject,
01132                                                     &c->serial,
01133                                                email,
01134                                                     PR_TRUE);
01135            if (!newInstance) {
01136               nssrv = PR_FAILURE;
01137               goto done;
01138            }
01139            nssPKIObject_AddInstance(&c->object, newInstance);
01140        }
01141        newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
01142                                           &c->issuer, &c->serial,
01143                                           nssTrust->serverAuth,
01144                                           nssTrust->clientAuth,
01145                                           nssTrust->codeSigning,
01146                                           nssTrust->emailProtection,
01147                                           nssTrust->stepUpApproved, PR_TRUE);
01148        /* If the selected token can't handle trust, dump the trust on 
01149         * the internal token */
01150        if (!newInstance && !PK11_IsInternal(tok->pk11slot)) {
01151            PK11SlotInfo *slot = PK11_GetInternalKeySlot();
01152            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
01153            NSSASCII7 *email = c->email;
01154            tok = PK11Slot_GetNSSToken(slot);
01155            PK11_FreeSlot(slot);
01156        
01157            newInstance = nssToken_ImportCertificate(tok, NULL,
01158                                                     NSSCertificateType_PKIX,
01159                                                     &c->id,
01160                                                     nickname,
01161                                                     &c->encoding,
01162                                                     &c->issuer,
01163                                                     &c->subject,
01164                                                     &c->serial,
01165                                                email,
01166                                                     PR_TRUE);
01167            if (!newInstance) {
01168               nssrv = PR_FAILURE;
01169               goto done;
01170            }
01171            nssPKIObject_AddInstance(&c->object, newInstance);
01172            newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
01173                                           &c->issuer, &c->serial,
01174                                           nssTrust->serverAuth,
01175                                           nssTrust->clientAuth,
01176                                           nssTrust->codeSigning,
01177                                           nssTrust->emailProtection,
01178                                           nssTrust->stepUpApproved, PR_TRUE);
01179        }
01180        if (newInstance) {
01181            nssCryptokiObject_Destroy(newInstance);
01182            nssrv = PR_SUCCESS;
01183        } else {
01184            nssrv = PR_FAILURE;
01185        }
01186     } else {
01187        nssrv = PR_FAILURE;
01188     }
01189 done:
01190     (void)nssTrust_Destroy(nssTrust);
01191     return nssrv;
01192 }
01193 
01194 /* CERT_TraversePermCertsForSubject */
01195 NSS_IMPLEMENT PRStatus
01196 nssTrustDomain_TraverseCertificatesBySubject (
01197   NSSTrustDomain *td,
01198   NSSDER *subject,
01199   PRStatus (*callback)(NSSCertificate *c, void *arg),
01200   void *arg
01201 )
01202 {
01203     PRStatus nssrv = PR_SUCCESS;
01204     NSSArena *tmpArena;
01205     NSSCertificate **subjectCerts;
01206     NSSCertificate *c;
01207     PRIntn i;
01208     tmpArena = NSSArena_Create();
01209     if (!tmpArena) {
01210         return PR_FAILURE;
01211     }
01212     subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
01213                                                             0, tmpArena);
01214     if (subjectCerts) {
01215        for (i=0, c = subjectCerts[i]; c; i++) {
01216            nssrv = callback(c, arg);
01217            if (nssrv != PR_SUCCESS) break;
01218        }
01219     }
01220     nssArena_Destroy(tmpArena);
01221     return nssrv;
01222 }
01223 
01224 /* CERT_TraversePermCertsForNickname */
01225 NSS_IMPLEMENT PRStatus
01226 nssTrustDomain_TraverseCertificatesByNickname (
01227   NSSTrustDomain *td,
01228   NSSUTF8 *nickname,
01229   PRStatus (*callback)(NSSCertificate *c, void *arg),
01230   void *arg
01231 )
01232 {
01233     PRStatus nssrv = PR_SUCCESS;
01234     NSSArena *tmpArena;
01235     NSSCertificate **nickCerts;
01236     NSSCertificate *c;
01237     PRIntn i;
01238     tmpArena = NSSArena_Create();
01239     if (!tmpArena) {
01240         return PR_FAILURE;
01241     }
01242     nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
01243                                                           0, tmpArena);
01244     if (nickCerts) {
01245        for (i=0, c = nickCerts[i]; c; i++) {
01246            nssrv = callback(c, arg);
01247            if (nssrv != PR_SUCCESS) break;
01248        }
01249     }
01250     nssArena_Destroy(tmpArena);
01251     return nssrv;
01252 }
01253 
01254 static void cert_dump_iter(const void *k, void *v, void *a)
01255 {
01256     NSSCertificate *c = (NSSCertificate *)k;
01257     CERTCertificate *cert = STAN_GetCERTCertificate(c);
01258     printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
01259 }
01260 
01261 void
01262 nss_DumpCertificateCacheInfo()
01263 {
01264     NSSTrustDomain *td;
01265     NSSCryptoContext *cc;
01266     td = STAN_GetDefaultTrustDomain();
01267     cc = STAN_GetDefaultCryptoContext();
01268     printf("\n\nCertificates in the cache:\n");
01269     nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
01270     printf("\n\nCertificates in the temporary store:\n");
01271     if (cc->certStore) {
01272        nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
01273     }
01274 }
01275