Blame nss/lib/pki/pki3hack.c

Packit 40b132
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit 40b132
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit 40b132
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
Packit 40b132
 */
Packit 40b132
Packit 40b132
#ifndef NSSPKI_H
Packit 40b132
#include "nsspki.h"
Packit 40b132
#endif /* NSSPKI_H */
Packit 40b132
Packit 40b132
#ifndef PKI_H
Packit 40b132
#include "pki.h"
Packit 40b132
#endif /* PKI_H */
Packit 40b132
Packit 40b132
#ifndef PKIM_H
Packit 40b132
#include "pkim.h"
Packit 40b132
#endif /* PKIM_H */
Packit 40b132
Packit 40b132
#ifndef DEV_H
Packit 40b132
#include "dev.h"
Packit 40b132
#endif /* DEV_H */
Packit 40b132
Packit 40b132
#ifndef DEVNSS3HACK_H
Packit 40b132
#include "dev3hack.h"
Packit 40b132
#endif /* DEVNSS3HACK_H */
Packit 40b132
Packit 40b132
#ifndef PKINSS3HACK_H
Packit 40b132
#include "pki3hack.h"
Packit 40b132
#endif /* PKINSS3HACK_H */
Packit 40b132
Packit 40b132
#include "secitem.h"
Packit 40b132
#include "certdb.h"
Packit 40b132
#include "certt.h"
Packit 40b132
#include "cert.h"
Packit 40b132
#include "certi.h"
Packit 40b132
#include "pk11func.h"
Packit 40b132
#include "pkistore.h"
Packit 40b132
#include "secmod.h"
Packit 40b132
#include "nssrwlk.h"
Packit 40b132
Packit 40b132
NSSTrustDomain *g_default_trust_domain = NULL;
Packit 40b132
Packit 40b132
NSSCryptoContext *g_default_crypto_context = NULL;
Packit 40b132
Packit 40b132
NSSTrustDomain *
Packit 40b132
STAN_GetDefaultTrustDomain()
Packit 40b132
{
Packit 40b132
    return g_default_trust_domain;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSSCryptoContext *
Packit 40b132
STAN_GetDefaultCryptoContext()
Packit 40b132
{
Packit 40b132
    return g_default_crypto_context;
Packit 40b132
}
Packit 40b132
Packit 40b132
extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
Packit 40b132
extern const NSSError NSS_ERROR_INTERNAL_ERROR;
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
Packit 40b132
{
Packit 40b132
    NSSToken *token;
Packit 40b132
    if (!td) {
Packit 40b132
	td = g_default_trust_domain;
Packit 40b132
	if (!td) {
Packit 40b132
	    /* we're called while still initting. slot will get added
Packit 40b132
	     * appropriately through normal init processes */
Packit 40b132
	    return PR_SUCCESS;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    token = nssToken_CreateFromPK11SlotInfo(td, slot);
Packit 40b132
    PK11Slot_SetNSSToken(slot, token);
Packit 40b132
    /* Don't add nonexistent token to TD's token list */
Packit 40b132
    if (token) {
Packit 40b132
	NSSRWLock_LockWrite(td->tokensLock);
Packit 40b132
	nssList_Add(td->tokenList, token);
Packit 40b132
	NSSRWLock_UnlockWrite(td->tokensLock);
Packit 40b132
    }
Packit 40b132
    return PR_SUCCESS;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
STAN_ResetTokenInterator(NSSTrustDomain *td)
Packit 40b132
{
Packit 40b132
    if (!td) {
Packit 40b132
	td = g_default_trust_domain;
Packit 40b132
	if (!td) {
Packit 40b132
	    /* we're called while still initting. slot will get added
Packit 40b132
	     * appropriately through normal init processes */
Packit 40b132
	    return PR_SUCCESS;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    NSSRWLock_LockWrite(td->tokensLock);
Packit 40b132
    nssListIterator_Destroy(td->tokens);
Packit 40b132
    td->tokens = nssList_CreateIterator(td->tokenList);
Packit 40b132
    NSSRWLock_UnlockWrite(td->tokensLock);
Packit 40b132
    return PR_SUCCESS;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
STAN_LoadDefaultNSS3TrustDomain (
Packit 40b132
  void
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    NSSTrustDomain *td;
Packit 40b132
    SECMODModuleList *mlp;
Packit 40b132
    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
Packit 40b132
    int i;
Packit 40b132
Packit 40b132
    if (g_default_trust_domain || g_default_crypto_context) {
Packit 40b132
	/* Stan is already initialized or a previous shutdown failed. */
Packit 40b132
	nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
Packit 40b132
    if (!td) {
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    /*
Packit 40b132
     * Deadlock warning: we should never acquire the moduleLock while
Packit 40b132
     * we hold the tokensLock. We can use the NSSRWLock Rank feature to
Packit 40b132
     * guarrentee this. tokensLock have a higher rank than module lock.
Packit 40b132
     */
Packit 40b132
    td->tokenList = nssList_Create(td->arena, PR_TRUE);
Packit 40b132
    if (!td->tokenList) {
Packit 40b132
	goto loser;
Packit 40b132
    }
Packit 40b132
    SECMOD_GetReadLock(moduleLock);
Packit 40b132
    NSSRWLock_LockWrite(td->tokensLock);
Packit 40b132
    for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
Packit 40b132
	for (i=0; i < mlp->module->slotCount; i++) {
Packit 40b132
	    STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    td->tokens = nssList_CreateIterator(td->tokenList);
Packit 40b132
    NSSRWLock_UnlockWrite(td->tokensLock);
Packit 40b132
    SECMOD_ReleaseReadLock(moduleLock);
Packit 40b132
    if (!td->tokens) {
Packit 40b132
	goto loser;
Packit 40b132
    }
Packit 40b132
    g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
Packit 40b132
    if (!g_default_crypto_context) {
Packit 40b132
	goto loser;
Packit 40b132
    }
Packit 40b132
    g_default_trust_domain = td;
Packit 40b132
    return PR_SUCCESS;
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    NSSTrustDomain_Destroy(td);
Packit 40b132
    return PR_FAILURE;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * must be called holding the ModuleListLock (either read or write).
Packit 40b132
 */
Packit 40b132
NSS_IMPLEMENT SECStatus
Packit 40b132
STAN_AddModuleToDefaultTrustDomain (
Packit 40b132
  SECMODModule *module
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    NSSTrustDomain *td;
Packit 40b132
    int i;
Packit 40b132
    td = STAN_GetDefaultTrustDomain();
Packit 40b132
    for (i=0; i<module->slotCount; i++) {
Packit 40b132
	STAN_InitTokenForSlotInfo(td, module->slots[i]);
Packit 40b132
    }
Packit 40b132
    STAN_ResetTokenInterator(td);
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
 * must be called holding the ModuleListLock (either read or write).
Packit 40b132
 */
Packit 40b132
NSS_IMPLEMENT SECStatus
Packit 40b132
STAN_RemoveModuleFromDefaultTrustDomain (
Packit 40b132
  SECMODModule *module
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    NSSToken *token;
Packit 40b132
    NSSTrustDomain *td;
Packit 40b132
    int i;
Packit 40b132
    td = STAN_GetDefaultTrustDomain();
Packit 40b132
    NSSRWLock_LockWrite(td->tokensLock);
Packit 40b132
    for (i=0; i<module->slotCount; i++) {
Packit 40b132
	token = PK11Slot_GetNSSToken(module->slots[i]);
Packit 40b132
	if (token) {
Packit 40b132
	    nssToken_NotifyCertsNotVisible(token);
Packit 40b132
	    nssList_Remove(td->tokenList, token);
Packit 40b132
	    PK11Slot_SetNSSToken(module->slots[i], NULL);
Packit 40b132
	    nssToken_Destroy(token);
Packit 40b132
 	}
Packit 40b132
    }
Packit 40b132
    nssListIterator_Destroy(td->tokens);
Packit 40b132
    td->tokens = nssList_CreateIterator(td->tokenList);
Packit 40b132
    NSSRWLock_UnlockWrite(td->tokensLock);
Packit 40b132
    return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
STAN_Shutdown()
Packit 40b132
{
Packit 40b132
    PRStatus status = PR_SUCCESS;
Packit 40b132
    if (g_default_trust_domain) {
Packit 40b132
	if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
Packit 40b132
	    g_default_trust_domain = NULL;
Packit 40b132
	} else {
Packit 40b132
	    status = PR_FAILURE;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    if (g_default_crypto_context) {
Packit 40b132
	if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
Packit 40b132
	    g_default_crypto_context = NULL;
Packit 40b132
	} else {
Packit 40b132
	    status = PR_FAILURE;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    return status;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* this function should not be a hack; it will be needed in 4.0 (rename) */
Packit 40b132
NSS_IMPLEMENT NSSItem *
Packit 40b132
STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
Packit 40b132
{
Packit 40b132
    NSSItem *rvKey;
Packit 40b132
    SECItem secDER;
Packit 40b132
    SECItem secKey = { 0 };
Packit 40b132
    SECStatus secrv;
Packit 40b132
    PLArenaPool *arena;
Packit 40b132
Packit 40b132
    SECITEM_FROM_NSSITEM(&secDER, der);
Packit 40b132
Packit 40b132
    /* nss3 call uses nss3 arena's */
Packit 40b132
    arena = PORT_NewArena(256);
Packit 40b132
    if (!arena) {
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
Packit 40b132
    PORT_FreeArena(arena,PR_FALSE);
Packit 40b132
    return rvKey;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der,
Packit 40b132
                                     NSSDER *issuer, NSSDER *serial)
Packit 40b132
{
Packit 40b132
    SECItem derCert   = { 0 };
Packit 40b132
    SECItem derIssuer = { 0 };
Packit 40b132
    SECItem derSerial = { 0 };
Packit 40b132
    SECStatus secrv;
Packit 40b132
    derCert.data = (unsigned char *)der->data;
Packit 40b132
    derCert.len = der->size;
Packit 40b132
    secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	PORT_Free(derSerial.data);
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    issuer->data = derIssuer.data;
Packit 40b132
    issuer->size = derIssuer.len;
Packit 40b132
    serial->data = derSerial.data;
Packit 40b132
    serial->size = derSerial.len;
Packit 40b132
    return PR_SUCCESS;
Packit 40b132
}
Packit 40b132
Packit 40b132
static NSSItem *
Packit 40b132
nss3certificate_getIdentifier(nssDecodedCert *dc)
Packit 40b132
{
Packit 40b132
    NSSItem *rvID;
Packit 40b132
    CERTCertificate *c = (CERTCertificate *)dc->data;
Packit 40b132
    rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
Packit 40b132
    return rvID;
Packit 40b132
}
Packit 40b132
Packit 40b132
static void *
Packit 40b132
nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
Packit 40b132
{
Packit 40b132
    CERTCertificate *c = (CERTCertificate *)dc->data;
Packit 40b132
    return (void *)c->authKeyID;
Packit 40b132
}
Packit 40b132
Packit 40b132
static nssCertIDMatch
Packit 40b132
nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
Packit 40b132
{
Packit 40b132
    CERTCertificate *c = (CERTCertificate *)dc->data;
Packit 40b132
    CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
Packit 40b132
    SECItem skid;
Packit 40b132
    nssCertIDMatch match = nssCertIDMatch_Unknown;
Packit 40b132
Packit 40b132
    /* keyIdentifier */
Packit 40b132
    if (authKeyID->keyID.len > 0 &&
Packit 40b132
	CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
Packit 40b132
	PRBool skiEqual;
Packit 40b132
	skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
Packit 40b132
	PORT_Free(skid.data);
Packit 40b132
	if (skiEqual) {
Packit 40b132
	    /* change the state to positive match, but keep going */
Packit 40b132
	    match = nssCertIDMatch_Yes;
Packit 40b132
	} else {
Packit 40b132
	    /* exit immediately on failure */
Packit 40b132
	    return nssCertIDMatch_No;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
Packit 40b132
    /* issuer/serial (treated as pair) */
Packit 40b132
    if (authKeyID->authCertIssuer) {
Packit 40b132
	SECItem *caName = NULL;
Packit 40b132
	SECItem *caSN = &authKeyID->authCertSerialNumber;
Packit 40b132
Packit 40b132
	caName = (SECItem *)CERT_GetGeneralNameByType(
Packit 40b132
	                                        authKeyID->authCertIssuer,
Packit 40b132
						certDirectoryName, PR_TRUE);
Packit 40b132
	if (caName != NULL &&
Packit 40b132
	    SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
Packit 40b132
	    SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) 
Packit 40b132
	{
Packit 40b132
	    match = nssCertIDMatch_Yes;
Packit 40b132
	} else {
Packit 40b132
	    match = nssCertIDMatch_Unknown;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    return match;
Packit 40b132
}
Packit 40b132
Packit 40b132
static PRBool
Packit 40b132
nss3certificate_isValidIssuer(nssDecodedCert *dc)
Packit 40b132
{
Packit 40b132
    CERTCertificate *c = (CERTCertificate *)dc->data;
Packit 40b132
    unsigned int ignore;
Packit 40b132
    return CERT_IsCACert(c, &ignore);
Packit 40b132
}
Packit 40b132
Packit 40b132
static NSSUsage *
Packit 40b132
nss3certificate_getUsage(nssDecodedCert *dc)
Packit 40b132
{
Packit 40b132
    /* CERTCertificate *c = (CERTCertificate *)dc->data; */
Packit 40b132
    return NULL;
Packit 40b132
}
Packit 40b132
Packit 40b132
static PRBool 
Packit 40b132
nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
Packit 40b132
{
Packit 40b132
    SECCertTimeValidity validity;
Packit 40b132
    CERTCertificate *c = (CERTCertificate *)dc->data;
Packit 40b132
    validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
Packit 40b132
    if (validity == secCertTimeValid) {
Packit 40b132
	return PR_TRUE;
Packit 40b132
    }
Packit 40b132
    return PR_FALSE;
Packit 40b132
}
Packit 40b132
Packit 40b132
static PRBool 
Packit 40b132
nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
Packit 40b132
{
Packit 40b132
    /* I know this isn't right, but this is glue code anyway */
Packit 40b132
    if (cmpdc->type == dc->type) {
Packit 40b132
	CERTCertificate *certa = (CERTCertificate *)dc->data;
Packit 40b132
	CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
Packit 40b132
	return CERT_IsNewer(certa, certb);
Packit 40b132
    }
Packit 40b132
    return PR_FALSE;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* CERT_FilterCertListByUsage */
Packit 40b132
static PRBool
Packit 40b132
nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
Packit 40b132
{
Packit 40b132
    CERTCertificate *cc;
Packit 40b132
    unsigned int requiredKeyUsage = 0;
Packit 40b132
    unsigned int requiredCertType = 0;
Packit 40b132
    SECStatus secrv;
Packit 40b132
    PRBool match;
Packit 40b132
    PRBool ca;
Packit 40b132
Packit 40b132
    /* This is for NSS 3.3 functions that do not specify a usage */
Packit 40b132
    if (usage->anyUsage) {
Packit 40b132
	return PR_TRUE;
Packit 40b132
    }
Packit 40b132
    ca = usage->nss3lookingForCA;
Packit 40b132
    secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
Packit 40b132
                                             &requiredKeyUsage,
Packit 40b132
                                             &requiredCertType);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	return PR_FALSE;
Packit 40b132
    }
Packit 40b132
    cc = (CERTCertificate *)dc->data;
Packit 40b132
    secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
Packit 40b132
    match = (PRBool)(secrv == SECSuccess);
Packit 40b132
    if (match) {
Packit 40b132
	unsigned int certType = 0;
Packit 40b132
	if (ca) {
Packit 40b132
	    (void)CERT_IsCACert(cc, &certType);
Packit 40b132
	} else {
Packit 40b132
	    certType = cc->nsCertType;
Packit 40b132
	}
Packit 40b132
	if (!(certType & requiredCertType)) {
Packit 40b132
	    match = PR_FALSE;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    return match;
Packit 40b132
}
Packit 40b132
Packit 40b132
static PRBool
Packit 40b132
nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
Packit 40b132
{
Packit 40b132
    CERTCertificate *cc;
Packit 40b132
    PRBool ca;
Packit 40b132
    SECStatus secrv;
Packit 40b132
    unsigned int requiredFlags;
Packit 40b132
    unsigned int trustFlags;
Packit 40b132
    SECTrustType trustType;
Packit 40b132
    CERTCertTrust trust;
Packit 40b132
Packit 40b132
    /* This is for NSS 3.3 functions that do not specify a usage */
Packit 40b132
    if (usage->anyUsage) {
Packit 40b132
	return PR_FALSE;  /* XXX is this right? */
Packit 40b132
    }
Packit 40b132
    cc = (CERTCertificate *)dc->data;
Packit 40b132
    ca = usage->nss3lookingForCA;
Packit 40b132
    if (!ca) {
Packit 40b132
	PRBool trusted;
Packit 40b132
	unsigned int failedFlags;
Packit 40b132
	secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
Packit 40b132
				    &failedFlags, &trusted);
Packit 40b132
	return secrv == SECSuccess && trusted;
Packit 40b132
    }
Packit 40b132
    secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
Packit 40b132
					  &trustType);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	return PR_FALSE;
Packit 40b132
    }
Packit 40b132
    secrv = CERT_GetCertTrust(cc, &trust);
Packit 40b132
    if (secrv != SECSuccess) {
Packit 40b132
	return PR_FALSE;
Packit 40b132
    }
Packit 40b132
    if (trustType == trustTypeNone) {
Packit 40b132
	/* normally trustTypeNone usages accept any of the given trust bits
Packit 40b132
	 * being on as acceptable. */
Packit 40b132
	trustFlags = trust.sslFlags | trust.emailFlags |
Packit 40b132
		     trust.objectSigningFlags;
Packit 40b132
    } else {
Packit 40b132
	trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
Packit 40b132
    }
Packit 40b132
    return (trustFlags & requiredFlags) == requiredFlags;
Packit 40b132
}
Packit 40b132
Packit 40b132
static NSSASCII7 *
Packit 40b132
nss3certificate_getEmailAddress(nssDecodedCert *dc)
Packit 40b132
{
Packit 40b132
    CERTCertificate *cc = (CERTCertificate *)dc->data;
Packit 40b132
    return (cc && cc->emailAddr && cc->emailAddr[0])
Packit 40b132
	    ? (NSSASCII7 *)cc->emailAddr : NULL;
Packit 40b132
}
Packit 40b132
Packit 40b132
static PRStatus
Packit 40b132
nss3certificate_getDERSerialNumber(nssDecodedCert *dc, 
Packit 40b132
                                   NSSDER *serial, NSSArena *arena)
Packit 40b132
{
Packit 40b132
    CERTCertificate *cc = (CERTCertificate *)dc->data;
Packit 40b132
    SECItem derSerial = { 0 };
Packit 40b132
    SECStatus secrv;
Packit 40b132
    secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
Packit 40b132
    if (secrv == SECSuccess) {
Packit 40b132
	(void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
Packit 40b132
	PORT_Free(derSerial.data);
Packit 40b132
	return PR_SUCCESS;
Packit 40b132
    }
Packit 40b132
    return PR_FAILURE;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* Returns NULL if "encoding" cannot be decoded. */
Packit 40b132
NSS_IMPLEMENT nssDecodedCert *
Packit 40b132
nssDecodedPKIXCertificate_Create (
Packit 40b132
  NSSArena *arenaOpt,
Packit 40b132
  NSSDER *encoding
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    nssDecodedCert  *rvDC = NULL;
Packit 40b132
    CERTCertificate *cert;
Packit 40b132
    SECItem          secDER;
Packit 40b132
Packit 40b132
    SECITEM_FROM_NSSITEM(&secDER, encoding);
Packit 40b132
    cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
Packit 40b132
    if (cert) {
Packit 40b132
	rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
Packit 40b132
	if (rvDC) {
Packit 40b132
	    rvDC->type                = NSSCertificateType_PKIX;
Packit 40b132
	    rvDC->data                = (void *)cert;
Packit 40b132
	    rvDC->getIdentifier       = nss3certificate_getIdentifier;
Packit 40b132
	    rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
Packit 40b132
	    rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
Packit 40b132
	    rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
Packit 40b132
	    rvDC->getUsage            = nss3certificate_getUsage;
Packit 40b132
	    rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
Packit 40b132
	    rvDC->isNewerThan         = nss3certificate_isNewerThan;
Packit 40b132
	    rvDC->matchUsage          = nss3certificate_matchUsage;
Packit 40b132
	    rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage;
Packit 40b132
	    rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
Packit 40b132
	    rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber;
Packit 40b132
	} else {
Packit 40b132
	    CERT_DestroyCertificate(cert);
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    return rvDC;
Packit 40b132
}
Packit 40b132
Packit 40b132
static nssDecodedCert *
Packit 40b132
create_decoded_pkix_cert_from_nss3cert (
Packit 40b132
  NSSArena *arenaOpt,
Packit 40b132
  CERTCertificate *cc
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
Packit 40b132
    if (rvDC) {
Packit 40b132
	rvDC->type                = NSSCertificateType_PKIX;
Packit 40b132
	rvDC->data                = (void *)cc;
Packit 40b132
	rvDC->getIdentifier       = nss3certificate_getIdentifier;
Packit 40b132
	rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
Packit 40b132
	rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
Packit 40b132
	rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
Packit 40b132
	rvDC->getUsage            = nss3certificate_getUsage;
Packit 40b132
	rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
Packit 40b132
	rvDC->isNewerThan         = nss3certificate_isNewerThan;
Packit 40b132
	rvDC->matchUsage          = nss3certificate_matchUsage;
Packit 40b132
	rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage;
Packit 40b132
	rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
Packit 40b132
	rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber;
Packit 40b132
    }
Packit 40b132
    return rvDC;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
nssDecodedPKIXCertificate_Destroy (
Packit 40b132
  nssDecodedCert *dc
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    CERTCertificate *cert = (CERTCertificate *)dc->data;
Packit 40b132
Packit 40b132
    /* The decoder may only be half initialized (the case where we find we 
Packit 40b132
     * could not decode the certificate). In this case, there is not cert to
Packit 40b132
     * free, just free the dc structure. */
Packit 40b132
    if (cert) {
Packit 40b132
	PRBool freeSlot = cert->ownSlot;
Packit 40b132
	PK11SlotInfo *slot = cert->slot;
Packit 40b132
	PLArenaPool *arena  = cert->arena;
Packit 40b132
	/* zero cert before freeing. Any stale references to this cert
Packit 40b132
	 * after this point will probably cause an exception.  */
Packit 40b132
	PORT_Memset(cert, 0, sizeof *cert);
Packit 40b132
	/* free the arena that contains the cert. */
Packit 40b132
	PORT_FreeArena(arena, PR_FALSE);
Packit 40b132
	if (slot && freeSlot) {
Packit 40b132
	    PK11_FreeSlot(slot);
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nss_ZFreeIf(dc);
Packit 40b132
    return PR_SUCCESS;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* see pk11cert.c:pk11_HandleTrustObject */
Packit 40b132
static unsigned int
Packit 40b132
get_nss3trust_from_nss4trust(nssTrustLevel t)
Packit 40b132
{
Packit 40b132
    unsigned int rt = 0;
Packit 40b132
    if (t == nssTrustLevel_Trusted) {
Packit 40b132
	rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
Packit 40b132
    }
Packit 40b132
    if (t == nssTrustLevel_TrustedDelegator) {
Packit 40b132
	rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
Packit 40b132
    }
Packit 40b132
    if (t == nssTrustLevel_NotTrusted) {
Packit 40b132
	rt |= CERTDB_TERMINAL_RECORD;
Packit 40b132
    }
Packit 40b132
    if (t == nssTrustLevel_ValidDelegator) {
Packit 40b132
	rt |= CERTDB_VALID_CA;
Packit 40b132
    }
Packit 40b132
    return rt;
Packit 40b132
}
Packit 40b132
Packit 40b132
static CERTCertTrust *
Packit 40b132
cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena)
Packit 40b132
{
Packit 40b132
    CERTCertTrust *rvTrust;
Packit 40b132
    unsigned int client;
Packit 40b132
    if (!t) {
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
Packit 40b132
    if (!rvTrust) return NULL;
Packit 40b132
    rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
Packit 40b132
    client = get_nss3trust_from_nss4trust(t->clientAuth);
Packit 40b132
    if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
Packit 40b132
	client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA);
Packit 40b132
	rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
Packit 40b132
    }
Packit 40b132
    rvTrust->sslFlags |= client;
Packit 40b132
    rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
Packit 40b132
    rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
Packit 40b132
    return rvTrust;
Packit 40b132
}
Packit 40b132
Packit 40b132
CERTCertTrust * 
Packit 40b132
nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
Packit 40b132
{
Packit 40b132
    CERTCertTrust *rvTrust = NULL;
Packit 40b132
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
Packit 40b132
    NSSTrust *t;
Packit 40b132
    t = nssTrustDomain_FindTrustForCertificate(td, c);
Packit 40b132
    if (t) {
Packit 40b132
	rvTrust = cert_trust_from_stan_trust(t, cc->arena);
Packit 40b132
	if (!rvTrust) {
Packit 40b132
	    nssTrust_Destroy(t);
Packit 40b132
	    return NULL;
Packit 40b132
	}
Packit 40b132
	nssTrust_Destroy(t);
Packit 40b132
    } else {
Packit 40b132
	rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
Packit 40b132
	if (!rvTrust) {
Packit 40b132
	    return NULL;
Packit 40b132
	}
Packit 40b132
	memset(rvTrust, 0, sizeof(*rvTrust));
Packit 40b132
    }
Packit 40b132
    if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
Packit 40b132
	rvTrust->sslFlags |= CERTDB_USER;
Packit 40b132
	rvTrust->emailFlags |= CERTDB_USER;
Packit 40b132
	rvTrust->objectSigningFlags |= CERTDB_USER;
Packit 40b132
    }
Packit 40b132
    return rvTrust;
Packit 40b132
}
Packit 40b132
Packit 40b132
static nssCryptokiInstance *
Packit 40b132
get_cert_instance(NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    nssCryptokiObject *instance, **ci;
Packit 40b132
    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
Packit 40b132
    if (!instances) {
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    instance = NULL;
Packit 40b132
    for (ci = instances; *ci; ci++) {
Packit 40b132
	if (!instance) {
Packit 40b132
	    instance = nssCryptokiObject_Clone(*ci);
Packit 40b132
	} else {
Packit 40b132
	    /* This only really works for two instances...  But 3.4 can't
Packit 40b132
	     * handle more anyway.  The logic is, if there are multiple
Packit 40b132
	     * instances, prefer the one that is not internal (e.g., on
Packit 40b132
	     * a hardware device.
Packit 40b132
	     */
Packit 40b132
	    if (PK11_IsInternal(instance->token->pk11slot)) {
Packit 40b132
		nssCryptokiObject_Destroy(instance);
Packit 40b132
		instance = nssCryptokiObject_Clone(*ci);
Packit 40b132
	    }
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nssCryptokiObjectArray_Destroy(instances);
Packit 40b132
    return instance;
Packit 40b132
}
Packit 40b132
Packit 40b132
char * 
Packit 40b132
STAN_GetCERTCertificateNameForInstance (
Packit 40b132
  PLArenaPool *arenaOpt,
Packit 40b132
  NSSCertificate *c,
Packit 40b132
  nssCryptokiInstance *instance
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    NSSCryptoContext *context = c->object.cryptoContext;
Packit 40b132
    PRStatus nssrv;
Packit 40b132
    int nicklen, tokenlen, len;
Packit 40b132
    NSSUTF8 *tokenName = NULL;
Packit 40b132
    NSSUTF8 *stanNick = NULL;
Packit 40b132
    char *nickname = NULL;
Packit 40b132
    char *nick;
Packit 40b132
Packit 40b132
    if (instance) {
Packit 40b132
	stanNick = instance->label;
Packit 40b132
    } else if (context) {
Packit 40b132
	stanNick = c->object.tempName;
Packit 40b132
    }
Packit 40b132
    if (stanNick) {
Packit 40b132
	/* fill other fields needed by NSS3 functions using CERTCertificate */
Packit 40b132
	if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 
Packit 40b132
	                 PORT_Strchr(stanNick, ':') != NULL) ) {
Packit 40b132
	    tokenName = nssToken_GetName(instance->token);
Packit 40b132
	    tokenlen = nssUTF8_Size(tokenName, &nssrv);
Packit 40b132
	} else {
Packit 40b132
	/* don't use token name for internal slot; 3.3 didn't */
Packit 40b132
	    tokenlen = 0;
Packit 40b132
	}
Packit 40b132
	nicklen = nssUTF8_Size(stanNick, &nssrv);
Packit 40b132
	len = tokenlen + nicklen;
Packit 40b132
	if (arenaOpt) {
Packit 40b132
	    nickname = PORT_ArenaAlloc(arenaOpt, len);
Packit 40b132
	} else {
Packit 40b132
	    nickname = PORT_Alloc(len);
Packit 40b132
	}
Packit 40b132
	nick = nickname;
Packit 40b132
	if (tokenName) {
Packit 40b132
	    memcpy(nick, tokenName, tokenlen-1);
Packit 40b132
	    nick += tokenlen-1;
Packit 40b132
	    *nick++ = ':';
Packit 40b132
	}
Packit 40b132
	memcpy(nick, stanNick, nicklen-1);
Packit 40b132
	nickname[len-1] = '\0';
Packit 40b132
    }
Packit 40b132
    return nickname;
Packit 40b132
}
Packit 40b132
Packit 40b132
char * 
Packit 40b132
STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    char * result;
Packit 40b132
    nssCryptokiInstance *instance = get_cert_instance(c);
Packit 40b132
    /* It's OK to call this function, even if instance is NULL */
Packit 40b132
    result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
Packit 40b132
    if (instance)
Packit 40b132
	nssCryptokiObject_Destroy(instance);
Packit 40b132
    return result;
Packit 40b132
}
Packit 40b132
Packit 40b132
static void
Packit 40b132
fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
Packit 40b132
{
Packit 40b132
    CERTCertTrust* trust = NULL;
Packit 40b132
    NSSTrust *nssTrust;
Packit 40b132
    NSSCryptoContext *context = c->object.cryptoContext;
Packit 40b132
    nssCryptokiInstance *instance;
Packit 40b132
    NSSUTF8 *stanNick = NULL;
Packit 40b132
Packit 40b132
    /* We are holding the base class object's lock on entry of this function
Packit 40b132
     * This lock protects writes to fields of the CERTCertificate .
Packit 40b132
     * It is also needed by some functions to compute values such as trust.
Packit 40b132
     */
Packit 40b132
    instance = get_cert_instance(c);
Packit 40b132
Packit 40b132
    if (instance) {
Packit 40b132
	stanNick = instance->label;
Packit 40b132
    } else if (context) {
Packit 40b132
	stanNick = c->object.tempName;
Packit 40b132
    }
Packit 40b132
    /* fill other fields needed by NSS3 functions using CERTCertificate */
Packit 40b132
    if ((!cc->nickname && stanNick) || forced) {
Packit 40b132
	PRStatus nssrv;
Packit 40b132
	int nicklen, tokenlen, len;
Packit 40b132
	NSSUTF8 *tokenName = NULL;
Packit 40b132
	char *nick;
Packit 40b132
	if (instance && 
Packit 40b132
	     (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 
Packit 40b132
	      (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
Packit 40b132
	    tokenName = nssToken_GetName(instance->token);
Packit 40b132
	    tokenlen = nssUTF8_Size(tokenName, &nssrv);
Packit 40b132
	} else {
Packit 40b132
	    /* don't use token name for internal slot; 3.3 didn't */
Packit 40b132
	    tokenlen = 0;
Packit 40b132
	}
Packit 40b132
	if (stanNick) {
Packit 40b132
	    nicklen = nssUTF8_Size(stanNick, &nssrv);
Packit 40b132
	    len = tokenlen + nicklen;
Packit 40b132
	    nick = PORT_ArenaAlloc(cc->arena, len);
Packit 40b132
	    if (tokenName) {
Packit 40b132
		memcpy(nick, tokenName, tokenlen-1);
Packit 40b132
		nick[tokenlen-1] = ':';
Packit 40b132
		memcpy(nick+tokenlen, stanNick, nicklen-1);
Packit 40b132
	    } else {
Packit 40b132
		memcpy(nick, stanNick, nicklen-1);
Packit 40b132
	    }
Packit 40b132
	    nick[len-1] = '\0';
Packit 40b132
            cc->nickname = nick;
Packit 40b132
	} else {
Packit 40b132
	    cc->nickname = NULL;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    if (context) {
Packit 40b132
	/* trust */
Packit 40b132
	nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
Packit 40b132
	if (!nssTrust) {
Packit 40b132
	    /* chicken and egg issue:
Packit 40b132
	     *
Packit 40b132
	     * c->issuer and c->serial are empty at this point, but
Packit 40b132
	     * nssTrustDomain_FindTrustForCertificate use them to look up
Packit 40b132
	     * up the trust object, so we point them to cc->derIssuer and
Packit 40b132
	     * cc->serialNumber.
Packit 40b132
	     *
Packit 40b132
	     * Our caller will fill these in with proper arena copies when we
Packit 40b132
	     * return. */
Packit 40b132
	    c->issuer.data = cc->derIssuer.data;
Packit 40b132
	    c->issuer.size = cc->derIssuer.len;
Packit 40b132
	    c->serial.data = cc->serialNumber.data;
Packit 40b132
	    c->serial.size = cc->serialNumber.len;
Packit 40b132
	    nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
Packit 40b132
	}
Packit 40b132
	if (nssTrust) {
Packit 40b132
            trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
Packit 40b132
            if (trust) {
Packit 40b132
                /* we should destroy cc->trust before replacing it, but it's
Packit 40b132
                   allocated in cc->arena, so memory growth will occur on each
Packit 40b132
                   refresh */
Packit 40b132
                CERT_LockCertTrust(cc);
Packit 40b132
                cc->trust = trust;
Packit 40b132
                CERT_UnlockCertTrust(cc);
Packit 40b132
            }
Packit 40b132
	    nssTrust_Destroy(nssTrust);
Packit 40b132
	}
Packit 40b132
    } else if (instance) {
Packit 40b132
	/* slot */
Packit 40b132
	if (cc->slot != instance->token->pk11slot) {
Packit 40b132
	    if (cc->slot) {
Packit 40b132
		PK11_FreeSlot(cc->slot);
Packit 40b132
	    }
Packit 40b132
	    cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
Packit 40b132
	}
Packit 40b132
	cc->ownSlot = PR_TRUE;
Packit 40b132
	/* pkcs11ID */
Packit 40b132
	cc->pkcs11ID = instance->handle;
Packit 40b132
	/* trust */
Packit 40b132
	trust = nssTrust_GetCERTCertTrustForCert(c, cc);
Packit 40b132
        if (trust) {
Packit 40b132
            /* we should destroy cc->trust before replacing it, but it's
Packit 40b132
               allocated in cc->arena, so memory growth will occur on each
Packit 40b132
               refresh */
Packit 40b132
            CERT_LockCertTrust(cc);
Packit 40b132
            cc->trust = trust;
Packit 40b132
            CERT_UnlockCertTrust(cc);
Packit 40b132
        }
Packit 40b132
	nssCryptokiObject_Destroy(instance);
Packit 40b132
    } 
Packit 40b132
    /* database handle is now the trust domain */
Packit 40b132
    cc->dbhandle = c->object.trustDomain;
Packit 40b132
    /* subjectList ? */
Packit 40b132
    /* istemp and isperm are supported in NSS 3.4 */
Packit 40b132
    cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
Packit 40b132
    cc->isperm = PR_TRUE;  /* by default */
Packit 40b132
    /* pointer back */
Packit 40b132
    cc->nssCertificate = c;
Packit 40b132
    if (trust) {
Packit 40b132
	/* force the cert type to be recomputed to include trust info */
Packit 40b132
	PRUint32 nsCertType = cert_ComputeCertType(cc);
Packit 40b132
Packit 40b132
	/* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
Packit 40b132
	PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32));
Packit 40b132
	PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType);
Packit 40b132
    }
Packit 40b132
}
Packit 40b132
Packit 40b132
static CERTCertificate *
Packit 40b132
stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
Packit 40b132
{
Packit 40b132
    nssDecodedCert *dc = NULL;
Packit 40b132
    CERTCertificate *cc = NULL;
Packit 40b132
    CERTCertTrust certTrust;
Packit 40b132
Packit 40b132
    /* make sure object does not go away until we finish */
Packit 40b132
    nssPKIObject_AddRef(&c->object);
Packit 40b132
    nssPKIObject_Lock(&c->object);
Packit 40b132
Packit 40b132
    dc = c->decoding;
Packit 40b132
    if (!dc) {
Packit 40b132
	dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
Packit 40b132
	if (!dc) {
Packit 40b132
            goto loser;
Packit 40b132
        }
Packit 40b132
	cc = (CERTCertificate *)dc->data;
Packit 40b132
	PORT_Assert(cc); /* software error */
Packit 40b132
	if (!cc) {
Packit 40b132
	    nssDecodedPKIXCertificate_Destroy(dc);
Packit 40b132
	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
Packit 40b132
	    goto loser;
Packit 40b132
	}
Packit 40b132
    	PORT_Assert(!c->decoding); 
Packit 40b132
	if (!c->decoding) {
Packit 40b132
	    c->decoding = dc;
Packit 40b132
	} else { 
Packit 40b132
            /* this should never happen. Fail. */
Packit 40b132
	    nssDecodedPKIXCertificate_Destroy(dc);
Packit 40b132
	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
Packit 40b132
            goto loser;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    cc = (CERTCertificate *)dc->data;
Packit 40b132
    PORT_Assert(cc);
Packit 40b132
    if (!cc) {
Packit 40b132
        nss_SetError(NSS_ERROR_INTERNAL_ERROR);
Packit 40b132
        goto loser;
Packit 40b132
    }
Packit 40b132
    if (!cc->nssCertificate || forceUpdate) {
Packit 40b132
        fill_CERTCertificateFields(c, cc, forceUpdate);
Packit 40b132
    } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess &&
Packit 40b132
               !c->object.cryptoContext) {
Packit 40b132
        /* if it's a perm cert, it might have been stored before the
Packit 40b132
         * trust, so look for the trust again.  But a temp cert can be
Packit 40b132
         * ignored.
Packit 40b132
         */
Packit 40b132
        CERTCertTrust* trust = NULL;
Packit 40b132
        trust = nssTrust_GetCERTCertTrustForCert(c, cc);
Packit 40b132
Packit 40b132
        CERT_LockCertTrust(cc);
Packit 40b132
        cc->trust = trust;
Packit 40b132
        CERT_UnlockCertTrust(cc);
Packit 40b132
    }
Packit 40b132
Packit 40b132
  loser:
Packit 40b132
    nssPKIObject_Unlock(&c->object);
Packit 40b132
    nssPKIObject_Destroy(&c->object);
Packit 40b132
    return cc;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT CERTCertificate *
Packit 40b132
STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    if (c->decoding) {
Packit 40b132
	return stan_GetCERTCertificate(c, PR_TRUE);
Packit 40b132
    }
Packit 40b132
    return NULL;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_IMPLEMENT CERTCertificate *
Packit 40b132
STAN_GetCERTCertificate(NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    return stan_GetCERTCertificate(c, PR_FALSE);
Packit 40b132
}
Packit 40b132
/*
Packit 40b132
 * many callers of STAN_GetCERTCertificate() intend that
Packit 40b132
 * the CERTCertificate returned inherits the reference to the 
Packit 40b132
 * NSSCertificate. For these callers it's convenient to have 
Packit 40b132
 * this function 'own' the reference and either return a valid 
Packit 40b132
 * CERTCertificate structure which inherits the reference or 
Packit 40b132
 * destroy the reference to NSSCertificate and returns NULL.
Packit 40b132
 */
Packit 40b132
NSS_IMPLEMENT CERTCertificate *
Packit 40b132
STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
Packit 40b132
    if (!nss3cert) {
Packit 40b132
	nssCertificate_Destroy(c);
Packit 40b132
    }
Packit 40b132
    return nss3cert;
Packit 40b132
}
Packit 40b132
Packit 40b132
static nssTrustLevel
Packit 40b132
get_stan_trust(unsigned int t, PRBool isClientAuth) 
Packit 40b132
{
Packit 40b132
    if (isClientAuth) {
Packit 40b132
	if (t & CERTDB_TRUSTED_CLIENT_CA) {
Packit 40b132
	    return nssTrustLevel_TrustedDelegator;
Packit 40b132
	}
Packit 40b132
    } else {
Packit 40b132
	if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
Packit 40b132
	    return nssTrustLevel_TrustedDelegator;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    if (t & CERTDB_TRUSTED) {
Packit 40b132
	return nssTrustLevel_Trusted;
Packit 40b132
    }
Packit 40b132
    if (t & CERTDB_TERMINAL_RECORD) {
Packit 40b132
	return nssTrustLevel_NotTrusted;
Packit 40b132
    }
Packit 40b132
    if (t & CERTDB_VALID_CA) {
Packit 40b132
	return nssTrustLevel_ValidDelegator;
Packit 40b132
    }
Packit 40b132
    return nssTrustLevel_MustVerify;
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_EXTERN NSSCertificate *
Packit 40b132
STAN_GetNSSCertificate(CERTCertificate *cc)
Packit 40b132
{
Packit 40b132
    NSSCertificate *c;
Packit 40b132
    nssCryptokiInstance *instance;
Packit 40b132
    nssPKIObject *pkiob;
Packit 40b132
    NSSArena *arena;
Packit 40b132
    c = cc->nssCertificate;
Packit 40b132
    if (c) {
Packit 40b132
    	return c;
Packit 40b132
    }
Packit 40b132
    /* i don't think this should happen.  but if it can, need to create
Packit 40b132
     * NSSCertificate from CERTCertificate values here.  */
Packit 40b132
    /* Yup, it can happen. */
Packit 40b132
    arena = NSSArena_Create();
Packit 40b132
    if (!arena) {
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    c = nss_ZNEW(arena, NSSCertificate);
Packit 40b132
    if (!c) {
Packit 40b132
	nssArena_Destroy(arena);
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
Packit 40b132
    c->type = NSSCertificateType_PKIX;
Packit 40b132
    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
Packit 40b132
    if (!pkiob) {
Packit 40b132
	nssArena_Destroy(arena);
Packit 40b132
	return NULL;
Packit 40b132
    }
Packit 40b132
    c->object = *pkiob;
Packit 40b132
    nssItem_Create(arena,
Packit 40b132
                   &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
Packit 40b132
    nssItem_Create(arena,
Packit 40b132
                   &c->subject, cc->derSubject.len, cc->derSubject.data);
Packit 40b132
    if (PR_TRUE) {
Packit 40b132
	/* CERTCertificate stores serial numbers decoded.  I need the DER
Packit 40b132
	* here.  sigh.
Packit 40b132
	*/
Packit 40b132
	SECItem derSerial;
Packit 40b132
	SECStatus secrv;
Packit 40b132
	secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
Packit 40b132
	if (secrv == SECFailure) {
Packit 40b132
	    nssArena_Destroy(arena);
Packit 40b132
	    return NULL;
Packit 40b132
	}
Packit 40b132
	nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
Packit 40b132
	PORT_Free(derSerial.data);
Packit 40b132
    }
Packit 40b132
    if (cc->emailAddr && cc->emailAddr[0]) {
Packit 40b132
        c->email = nssUTF8_Create(arena,
Packit 40b132
                                  nssStringType_PrintableString,
Packit 40b132
                                  (NSSUTF8 *)cc->emailAddr,
Packit 40b132
                                  PORT_Strlen(cc->emailAddr));
Packit 40b132
    }
Packit 40b132
    if (cc->slot) {
Packit 40b132
	instance = nss_ZNEW(arena, nssCryptokiInstance);
Packit 40b132
	if (!instance) {
Packit 40b132
	    nssArena_Destroy(arena);
Packit 40b132
	    return NULL;
Packit 40b132
	}
Packit 40b132
	instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot));
Packit 40b132
	instance->handle = cc->pkcs11ID;
Packit 40b132
	instance->isTokenObject = PR_TRUE;
Packit 40b132
	if (cc->nickname) {
Packit 40b132
	    instance->label = nssUTF8_Create(arena,
Packit 40b132
	                                     nssStringType_UTF8String,
Packit 40b132
	                                     (NSSUTF8 *)cc->nickname,
Packit 40b132
	                                     PORT_Strlen(cc->nickname));
Packit 40b132
	}
Packit 40b132
	nssPKIObject_AddInstance(&c->object, instance);
Packit 40b132
    }
Packit 40b132
    c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
Packit 40b132
    cc->nssCertificate = c;
Packit 40b132
    return c;
Packit 40b132
}
Packit 40b132
Packit 40b132
static NSSToken*
Packit 40b132
stan_GetTrustToken (
Packit 40b132
  NSSCertificate *c
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    NSSToken *ttok = NULL;
Packit 40b132
    NSSToken *rtok = NULL;
Packit 40b132
    NSSToken *tok = NULL;
Packit 40b132
    nssCryptokiObject **ip;
Packit 40b132
    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
Packit 40b132
    if (!instances) {
Packit 40b132
	return PR_FALSE;
Packit 40b132
    }
Packit 40b132
    for (ip = instances; *ip; ip++) {
Packit 40b132
	nssCryptokiObject *instance = *ip;
Packit 40b132
        nssCryptokiObject *to = 
Packit 40b132
		nssToken_FindTrustForCertificate(instance->token, NULL,
Packit 40b132
		&c->encoding, &c->issuer, &c->serial, 
Packit 40b132
		nssTokenSearchType_TokenOnly);
Packit 40b132
	NSSToken *ctok = instance->token;
Packit 40b132
	PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
Packit 40b132
Packit 40b132
	if (to) {
Packit 40b132
	    nssCryptokiObject_Destroy(to);
Packit 40b132
	    ttok = ctok;
Packit 40b132
 	    if (!ro) {
Packit 40b132
		break;
Packit 40b132
	    }
Packit 40b132
	} else {
Packit 40b132
	    if (!rtok && ro) {
Packit 40b132
		rtok = ctok;
Packit 40b132
	    } 
Packit 40b132
	    if (!tok && !ro) {
Packit 40b132
		tok = ctok;
Packit 40b132
	    }
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nssCryptokiObjectArray_Destroy(instances);
Packit 40b132
    return ttok ? ttok : (tok ? tok : rtok);
Packit 40b132
}
Packit 40b132
Packit 40b132
NSS_EXTERN PRStatus
Packit 40b132
STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
Packit 40b132
{
Packit 40b132
    PRStatus nssrv;
Packit 40b132
    NSSCertificate *c = STAN_GetNSSCertificate(cc);
Packit 40b132
    NSSToken *tok;
Packit 40b132
    NSSTrustDomain *td;
Packit 40b132
    NSSTrust *nssTrust;
Packit 40b132
    NSSArena *arena;
Packit 40b132
    CERTCertTrust *oldTrust;
Packit 40b132
    CERTCertTrust *newTrust;
Packit 40b132
    nssListIterator *tokens;
Packit 40b132
    PRBool moving_object;
Packit 40b132
    nssCryptokiObject *newInstance;
Packit 40b132
    nssPKIObject *pkiob;
Packit 40b132
Packit 40b132
    if (c == NULL) {
Packit 40b132
        return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
Packit 40b132
    if (oldTrust) {
Packit 40b132
	if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) {
Packit 40b132
	    /* ... and the new trust is no different, done) */
Packit 40b132
	    return PR_SUCCESS;
Packit 40b132
	} else {
Packit 40b132
	    /* take over memory already allocated in cc's arena */
Packit 40b132
	    newTrust = oldTrust;
Packit 40b132
	}
Packit 40b132
    } else {
Packit 40b132
	newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
Packit 40b132
    }
Packit 40b132
    memcpy(newTrust, trust, sizeof(CERTCertTrust));
Packit 40b132
    CERT_LockCertTrust(cc);
Packit 40b132
    cc->trust = newTrust;
Packit 40b132
    CERT_UnlockCertTrust(cc);
Packit 40b132
    /* Set the NSSCerticate's trust */
Packit 40b132
    arena = nssArena_Create();
Packit 40b132
    if (!arena) return PR_FAILURE;
Packit 40b132
    nssTrust = nss_ZNEW(arena, NSSTrust);
Packit 40b132
    if (!nssTrust) {
Packit 40b132
	nssArena_Destroy(arena);
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
Packit 40b132
    if (!pkiob) {
Packit 40b132
	nssArena_Destroy(arena);
Packit 40b132
	return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    nssTrust->object = *pkiob;
Packit 40b132
    nssTrust->certificate = c;
Packit 40b132
    nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
Packit 40b132
    nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
Packit 40b132
    nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
Packit 40b132
    nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
Packit 40b132
    nssTrust->stepUpApproved = 
Packit 40b132
                    (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
Packit 40b132
    if (c->object.cryptoContext != NULL) {
Packit 40b132
	/* The cert is in a context, set the trust there */
Packit 40b132
	NSSCryptoContext *cc = c->object.cryptoContext;
Packit 40b132
	nssrv = nssCryptoContext_ImportTrust(cc, nssTrust);
Packit 40b132
	if (nssrv != PR_SUCCESS) {
Packit 40b132
	    goto done;
Packit 40b132
	}
Packit 40b132
	if (c->object.numInstances == 0) {
Packit 40b132
	    /* The context is the only instance, finished */
Packit 40b132
	    goto done;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    td = STAN_GetDefaultTrustDomain();
Packit 40b132
    tok = stan_GetTrustToken(c);
Packit 40b132
    moving_object = PR_FALSE;
Packit 40b132
    if (tok && PK11_IsReadOnly(tok->pk11slot))  {
Packit 40b132
	NSSRWLock_LockRead(td->tokensLock);
Packit 40b132
	tokens = nssList_CreateIterator(td->tokenList);
Packit 40b132
	if (!tokens) {
Packit 40b132
	    nssrv = PR_FAILURE;
Packit 40b132
	    NSSRWLock_UnlockRead(td->tokensLock);
Packit 40b132
	    goto done;
Packit 40b132
	}
Packit 40b132
	for (tok  = (NSSToken *)nssListIterator_Start(tokens);
Packit 40b132
	     tok != (NSSToken *)NULL;
Packit 40b132
	     tok  = (NSSToken *)nssListIterator_Next(tokens))
Packit 40b132
	{
Packit 40b132
	    if (!PK11_IsReadOnly(tok->pk11slot)) break;
Packit 40b132
	}
Packit 40b132
	nssListIterator_Finish(tokens);
Packit 40b132
	nssListIterator_Destroy(tokens);
Packit 40b132
	NSSRWLock_UnlockRead(td->tokensLock);
Packit 40b132
	moving_object = PR_TRUE;
Packit 40b132
    } 
Packit 40b132
    if (tok) {
Packit 40b132
	if (moving_object) {
Packit 40b132
	    /* this is kind of hacky.  the softoken needs the cert
Packit 40b132
	     * object in order to store trust.  forcing it to be perm
Packit 40b132
	     */
Packit 40b132
	    NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
Packit 40b132
	    NSSASCII7 *email = NULL;
Packit 40b132
Packit 40b132
	    if (PK11_IsInternal(tok->pk11slot)) {
Packit 40b132
		email = c->email;
Packit 40b132
	    }
Packit 40b132
	    newInstance = nssToken_ImportCertificate(tok, NULL,
Packit 40b132
	                                             NSSCertificateType_PKIX,
Packit 40b132
	                                             &c->id,
Packit 40b132
	                                             nickname,
Packit 40b132
	                                             &c->encoding,
Packit 40b132
	                                             &c->issuer,
Packit 40b132
	                                             &c->subject,
Packit 40b132
	                                             &c->serial,
Packit 40b132
						     email,
Packit 40b132
	                                             PR_TRUE);
Packit 40b132
            nss_ZFreeIf(nickname);
Packit 40b132
            nickname = NULL;
Packit 40b132
	    if (!newInstance) {
Packit 40b132
		nssrv = PR_FAILURE;
Packit 40b132
		goto done;
Packit 40b132
	    }
Packit 40b132
	    nssPKIObject_AddInstance(&c->object, newInstance);
Packit 40b132
	}
Packit 40b132
	newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
Packit 40b132
	                                   &c->issuer, &c->serial,
Packit 40b132
	                                   nssTrust->serverAuth,
Packit 40b132
	                                   nssTrust->clientAuth,
Packit 40b132
	                                   nssTrust->codeSigning,
Packit 40b132
	                                   nssTrust->emailProtection,
Packit 40b132
	                                   nssTrust->stepUpApproved, PR_TRUE);
Packit 40b132
	/* If the selected token can't handle trust, dump the trust on 
Packit 40b132
	 * the internal token */
Packit 40b132
	if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
Packit 40b132
	    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
Packit 40b132
	    NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
Packit 40b132
	    NSSASCII7 *email = c->email;
Packit 40b132
	    tok = PK11Slot_GetNSSToken(slot);
Packit 40b132
	    PK11_FreeSlot(slot);
Packit 40b132
	
Packit 40b132
	    newInstance = nssToken_ImportCertificate(tok, NULL,
Packit 40b132
	                                             NSSCertificateType_PKIX,
Packit 40b132
	                                             &c->id,
Packit 40b132
	                                             nickname,
Packit 40b132
	                                             &c->encoding,
Packit 40b132
	                                             &c->issuer,
Packit 40b132
	                                             &c->subject,
Packit 40b132
	                                             &c->serial,
Packit 40b132
						     email,
Packit 40b132
	                                             PR_TRUE);
Packit 40b132
            nss_ZFreeIf(nickname);
Packit 40b132
            nickname = NULL;
Packit 40b132
	    if (!newInstance) {
Packit 40b132
		nssrv = PR_FAILURE;
Packit 40b132
		goto done;
Packit 40b132
	    }
Packit 40b132
	    nssPKIObject_AddInstance(&c->object, newInstance);
Packit 40b132
	    newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
Packit 40b132
	                                   &c->issuer, &c->serial,
Packit 40b132
	                                   nssTrust->serverAuth,
Packit 40b132
	                                   nssTrust->clientAuth,
Packit 40b132
	                                   nssTrust->codeSigning,
Packit 40b132
	                                   nssTrust->emailProtection,
Packit 40b132
	                                   nssTrust->stepUpApproved, PR_TRUE);
Packit 40b132
	}
Packit 40b132
	if (newInstance) {
Packit 40b132
	    nssCryptokiObject_Destroy(newInstance);
Packit 40b132
	    nssrv = PR_SUCCESS;
Packit 40b132
	} else {
Packit 40b132
	    nssrv = PR_FAILURE;
Packit 40b132
	}
Packit 40b132
    } else {
Packit 40b132
	nssrv = PR_FAILURE;
Packit 40b132
    }
Packit 40b132
done:
Packit 40b132
    (void)nssTrust_Destroy(nssTrust);
Packit 40b132
    return nssrv;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
** Delete trust objects matching the given slot.
Packit 40b132
** Returns error if a device fails to delete.
Packit 40b132
**
Packit 40b132
** This function has the side effect of moving the
Packit 40b132
** surviving entries to the front of the object list
Packit 40b132
** and nullifying the rest.
Packit 40b132
*/
Packit 40b132
static PRStatus
Packit 40b132
DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
Packit 40b132
{
Packit 40b132
    int numNotDestroyed = 0;     /* the ones skipped plus the failures */
Packit 40b132
    int failureCount = 0;        /* actual deletion failures by devices */
Packit 40b132
    int index;
Packit 40b132
Packit 40b132
    nssPKIObject_AddRef(tObject);
Packit 40b132
    nssPKIObject_Lock(tObject);
Packit 40b132
    /* Keep going even if a module fails to delete. */
Packit 40b132
    for (index = 0; index < tObject->numInstances; index++) {
Packit 40b132
	nssCryptokiObject *instance = tObject->instances[index];
Packit 40b132
	if (!instance) {
Packit 40b132
	    continue;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* ReadOnly and not matched treated the same */
Packit 40b132
	if (PK11_IsReadOnly(instance->token->pk11slot) ||
Packit 40b132
	    pk11slot != instance->token->pk11slot) {
Packit 40b132
	    tObject->instances[numNotDestroyed++] = instance;
Packit 40b132
	    continue;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* Here we have found a matching one */
Packit 40b132
	tObject->instances[index] = NULL;
Packit 40b132
	if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
Packit 40b132
	    nssCryptokiObject_Destroy(instance);
Packit 40b132
	} else {
Packit 40b132
	    tObject->instances[numNotDestroyed++] = instance;
Packit 40b132
	    failureCount++;
Packit 40b132
	}
Packit 40b132
Packit 40b132
    }
Packit 40b132
    if (numNotDestroyed == 0) {
Packit 40b132
    	nss_ZFreeIf(tObject->instances);
Packit 40b132
    	tObject->numInstances = 0;
Packit 40b132
    } else {
Packit 40b132
    	tObject->numInstances = numNotDestroyed;
Packit 40b132
    }
Packit 40b132
Packit 40b132
    nssPKIObject_Unlock(tObject);
Packit 40b132
    nssPKIObject_Destroy(tObject);
Packit 40b132
Packit 40b132
    return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
Packit 40b132
}
Packit 40b132
Packit 40b132
/*
Packit 40b132
** Delete trust objects matching the slot of the given certificate.
Packit 40b132
** Returns an error if any device fails to delete. 
Packit 40b132
*/
Packit 40b132
NSS_EXTERN PRStatus
Packit 40b132
STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
Packit 40b132
{
Packit 40b132
    PRStatus nssrv = PR_SUCCESS;
Packit 40b132
Packit 40b132
    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
Packit 40b132
    NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
Packit 40b132
    /* caller made sure nssTrust isn't NULL */
Packit 40b132
    nssPKIObject *tobject = &nssTrust->object;
Packit 40b132
    nssPKIObject *cobject = &c->object;
Packit 40b132
    int i;
Packit 40b132
Packit 40b132
    /* Iterate through the cert and trust object instances looking for
Packit 40b132
     * those with matching pk11 slots to delete. Even if some device
Packit 40b132
     * can't delete we keep going. Keeping a status variable for the
Packit 40b132
     * loop so that once it's failed the other gets set.
Packit 40b132
     */
Packit 40b132
    NSSRWLock_LockRead(td->tokensLock);
Packit 40b132
    nssPKIObject_AddRef(cobject);
Packit 40b132
    nssPKIObject_Lock(cobject);
Packit 40b132
    for (i = 0; i < cobject->numInstances; i++) {
Packit 40b132
	nssCryptokiObject *cInstance = cobject->instances[i];
Packit 40b132
	if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
Packit 40b132
		PRStatus status;
Packit 40b132
	    if (!tobject->numInstances || !tobject->instances) continue;
Packit 40b132
	    status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject);
Packit 40b132
	    if (status == PR_FAILURE) {
Packit 40b132
	    	/* set the outer one but keep going */
Packit 40b132
	    	nssrv = PR_FAILURE;
Packit 40b132
	    }
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nssPKIObject_Unlock(cobject);
Packit 40b132
    nssPKIObject_Destroy(cobject);
Packit 40b132
    NSSRWLock_UnlockRead(td->tokensLock);
Packit 40b132
    return nssrv;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* CERT_TraversePermCertsForSubject */
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
nssTrustDomain_TraverseCertificatesBySubject (
Packit 40b132
  NSSTrustDomain *td,
Packit 40b132
  NSSDER *subject,
Packit 40b132
  PRStatus (*callback)(NSSCertificate *c, void *arg),
Packit 40b132
  void *arg
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    PRStatus nssrv = PR_SUCCESS;
Packit 40b132
    NSSArena *tmpArena;
Packit 40b132
    NSSCertificate **subjectCerts;
Packit 40b132
    NSSCertificate *c;
Packit 40b132
    PRIntn i;
Packit 40b132
    tmpArena = NSSArena_Create();
Packit 40b132
    if (!tmpArena) {
Packit 40b132
        return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
Packit 40b132
                                                            0, tmpArena);
Packit 40b132
    if (subjectCerts) {
Packit 40b132
	for (i=0, c = subjectCerts[i]; c; i++) {
Packit 40b132
	    nssrv = callback(c, arg);
Packit 40b132
	    if (nssrv != PR_SUCCESS) break;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nssArena_Destroy(tmpArena);
Packit 40b132
    return nssrv;
Packit 40b132
}
Packit 40b132
Packit 40b132
/* CERT_TraversePermCertsForNickname */
Packit 40b132
NSS_IMPLEMENT PRStatus
Packit 40b132
nssTrustDomain_TraverseCertificatesByNickname (
Packit 40b132
  NSSTrustDomain *td,
Packit 40b132
  NSSUTF8 *nickname,
Packit 40b132
  PRStatus (*callback)(NSSCertificate *c, void *arg),
Packit 40b132
  void *arg
Packit 40b132
)
Packit 40b132
{
Packit 40b132
    PRStatus nssrv = PR_SUCCESS;
Packit 40b132
    NSSArena *tmpArena;
Packit 40b132
    NSSCertificate **nickCerts;
Packit 40b132
    NSSCertificate *c;
Packit 40b132
    PRIntn i;
Packit 40b132
    tmpArena = NSSArena_Create();
Packit 40b132
    if (!tmpArena) {
Packit 40b132
        return PR_FAILURE;
Packit 40b132
    }
Packit 40b132
    nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
Packit 40b132
                                                          0, tmpArena);
Packit 40b132
    if (nickCerts) {
Packit 40b132
	for (i=0, c = nickCerts[i]; c; i++) {
Packit 40b132
	    nssrv = callback(c, arg);
Packit 40b132
	    if (nssrv != PR_SUCCESS) break;
Packit 40b132
	}
Packit 40b132
    }
Packit 40b132
    nssArena_Destroy(tmpArena);
Packit 40b132
    return nssrv;
Packit 40b132
}
Packit 40b132
Packit 40b132
static void cert_dump_iter(const void *k, void *v, void *a)
Packit 40b132
{
Packit 40b132
    NSSCertificate *c = (NSSCertificate *)k;
Packit 40b132
    CERTCertificate *cert = STAN_GetCERTCertificate(c);
Packit 40b132
    printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
Packit 40b132
}
Packit 40b132
Packit 40b132
void
Packit 40b132
nss_DumpCertificateCacheInfo()
Packit 40b132
{
Packit 40b132
    NSSTrustDomain *td;
Packit 40b132
    NSSCryptoContext *cc;
Packit 40b132
    td = STAN_GetDefaultTrustDomain();
Packit 40b132
    cc = STAN_GetDefaultCryptoContext();
Packit 40b132
    printf("\n\nCertificates in the cache:\n");
Packit 40b132
    nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
Packit 40b132
    printf("\n\nCertificates in the temporary store:\n");
Packit 40b132
    if (cc->certStore) {
Packit 40b132
	nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
Packit 40b132
    }
Packit 40b132
}
Packit 40b132