security/nss/lib/pki/pki3hack.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
     7  */
     9 #ifndef NSSPKI_H
    10 #include "nsspki.h"
    11 #endif /* NSSPKI_H */
    13 #ifndef PKI_H
    14 #include "pki.h"
    15 #endif /* PKI_H */
    17 #ifndef PKIM_H
    18 #include "pkim.h"
    19 #endif /* PKIM_H */
    21 #ifndef DEV_H
    22 #include "dev.h"
    23 #endif /* DEV_H */
    25 #ifndef DEVNSS3HACK_H
    26 #include "dev3hack.h"
    27 #endif /* DEVNSS3HACK_H */
    29 #ifndef PKINSS3HACK_H
    30 #include "pki3hack.h"
    31 #endif /* PKINSS3HACK_H */
    33 #include "secitem.h"
    34 #include "certdb.h"
    35 #include "certt.h"
    36 #include "cert.h"
    37 #include "certi.h"
    38 #include "pk11func.h"
    39 #include "pkistore.h"
    40 #include "secmod.h"
    41 #include "nssrwlk.h"
    43 NSSTrustDomain *g_default_trust_domain = NULL;
    45 NSSCryptoContext *g_default_crypto_context = NULL;
    47 NSSTrustDomain *
    48 STAN_GetDefaultTrustDomain()
    49 {
    50     return g_default_trust_domain;
    51 }
    53 NSSCryptoContext *
    54 STAN_GetDefaultCryptoContext()
    55 {
    56     return g_default_crypto_context;
    57 }
    59 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
    60 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
    62 NSS_IMPLEMENT PRStatus
    63 STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
    64 {
    65     NSSToken *token;
    66     if (!td) {
    67 	td = g_default_trust_domain;
    68 	if (!td) {
    69 	    /* we're called while still initting. slot will get added
    70 	     * appropriately through normal init processes */
    71 	    return PR_SUCCESS;
    72 	}
    73     }
    74     token = nssToken_CreateFromPK11SlotInfo(td, slot);
    75     PK11Slot_SetNSSToken(slot, token);
    76     /* Don't add nonexistent token to TD's token list */
    77     if (token) {
    78 	NSSRWLock_LockWrite(td->tokensLock);
    79 	nssList_Add(td->tokenList, token);
    80 	NSSRWLock_UnlockWrite(td->tokensLock);
    81     }
    82     return PR_SUCCESS;
    83 }
    85 NSS_IMPLEMENT PRStatus
    86 STAN_ResetTokenInterator(NSSTrustDomain *td)
    87 {
    88     if (!td) {
    89 	td = g_default_trust_domain;
    90 	if (!td) {
    91 	    /* we're called while still initting. slot will get added
    92 	     * appropriately through normal init processes */
    93 	    return PR_SUCCESS;
    94 	}
    95     }
    96     NSSRWLock_LockWrite(td->tokensLock);
    97     nssListIterator_Destroy(td->tokens);
    98     td->tokens = nssList_CreateIterator(td->tokenList);
    99     NSSRWLock_UnlockWrite(td->tokensLock);
   100     return PR_SUCCESS;
   101 }
   103 NSS_IMPLEMENT PRStatus
   104 STAN_LoadDefaultNSS3TrustDomain (
   105   void
   106 )
   107 {
   108     NSSTrustDomain *td;
   109     SECMODModuleList *mlp;
   110     SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
   111     int i;
   113     if (g_default_trust_domain || g_default_crypto_context) {
   114 	/* Stan is already initialized or a previous shutdown failed. */
   115 	nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
   116 	return PR_FAILURE;
   117     }
   118     td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
   119     if (!td) {
   120 	return PR_FAILURE;
   121     }
   122     /*
   123      * Deadlock warning: we should never acquire the moduleLock while
   124      * we hold the tokensLock. We can use the NSSRWLock Rank feature to
   125      * guarrentee this. tokensLock have a higher rank than module lock.
   126      */
   127     td->tokenList = nssList_Create(td->arena, PR_TRUE);
   128     if (!td->tokenList) {
   129 	goto loser;
   130     }
   131     SECMOD_GetReadLock(moduleLock);
   132     NSSRWLock_LockWrite(td->tokensLock);
   133     for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp=mlp->next) {
   134 	for (i=0; i < mlp->module->slotCount; i++) {
   135 	    STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
   136 	}
   137     }
   138     td->tokens = nssList_CreateIterator(td->tokenList);
   139     NSSRWLock_UnlockWrite(td->tokensLock);
   140     SECMOD_ReleaseReadLock(moduleLock);
   141     if (!td->tokens) {
   142 	goto loser;
   143     }
   144     g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
   145     if (!g_default_crypto_context) {
   146 	goto loser;
   147     }
   148     g_default_trust_domain = td;
   149     return PR_SUCCESS;
   151   loser:
   152     NSSTrustDomain_Destroy(td);
   153     return PR_FAILURE;
   154 }
   156 /*
   157  * must be called holding the ModuleListLock (either read or write).
   158  */
   159 NSS_IMPLEMENT SECStatus
   160 STAN_AddModuleToDefaultTrustDomain (
   161   SECMODModule *module
   162 )
   163 {
   164     NSSTrustDomain *td;
   165     int i;
   166     td = STAN_GetDefaultTrustDomain();
   167     for (i=0; i<module->slotCount; i++) {
   168 	STAN_InitTokenForSlotInfo(td, module->slots[i]);
   169     }
   170     STAN_ResetTokenInterator(td);
   171     return SECSuccess;
   172 }
   174 /*
   175  * must be called holding the ModuleListLock (either read or write).
   176  */
   177 NSS_IMPLEMENT SECStatus
   178 STAN_RemoveModuleFromDefaultTrustDomain (
   179   SECMODModule *module
   180 )
   181 {
   182     NSSToken *token;
   183     NSSTrustDomain *td;
   184     int i;
   185     td = STAN_GetDefaultTrustDomain();
   186     NSSRWLock_LockWrite(td->tokensLock);
   187     for (i=0; i<module->slotCount; i++) {
   188 	token = PK11Slot_GetNSSToken(module->slots[i]);
   189 	if (token) {
   190 	    nssToken_NotifyCertsNotVisible(token);
   191 	    nssList_Remove(td->tokenList, token);
   192 	    PK11Slot_SetNSSToken(module->slots[i], NULL);
   193 	    nssToken_Destroy(token);
   194  	}
   195     }
   196     nssListIterator_Destroy(td->tokens);
   197     td->tokens = nssList_CreateIterator(td->tokenList);
   198     NSSRWLock_UnlockWrite(td->tokensLock);
   199     return SECSuccess;
   200 }
   202 NSS_IMPLEMENT PRStatus
   203 STAN_Shutdown()
   204 {
   205     PRStatus status = PR_SUCCESS;
   206     if (g_default_trust_domain) {
   207 	if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
   208 	    g_default_trust_domain = NULL;
   209 	} else {
   210 	    status = PR_FAILURE;
   211 	}
   212     }
   213     if (g_default_crypto_context) {
   214 	if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
   215 	    g_default_crypto_context = NULL;
   216 	} else {
   217 	    status = PR_FAILURE;
   218 	}
   219     }
   220     return status;
   221 }
   223 /* this function should not be a hack; it will be needed in 4.0 (rename) */
   224 NSS_IMPLEMENT NSSItem *
   225 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
   226 {
   227     NSSItem *rvKey;
   228     SECItem secDER;
   229     SECItem secKey = { 0 };
   230     SECStatus secrv;
   231     PLArenaPool *arena;
   233     SECITEM_FROM_NSSITEM(&secDER, der);
   235     /* nss3 call uses nss3 arena's */
   236     arena = PORT_NewArena(256);
   237     if (!arena) {
   238 	return NULL;
   239     }
   240     secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
   241     if (secrv != SECSuccess) {
   242 	return NULL;
   243     }
   244     rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
   245     PORT_FreeArena(arena,PR_FALSE);
   246     return rvKey;
   247 }
   249 NSS_IMPLEMENT PRStatus
   250 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der, NSSArena *arena, 
   251                                      NSSDER *issuer, NSSDER *serial)
   252 {
   253     SECStatus secrv;
   254     SECItem derCert;
   255     SECItem derIssuer = { 0 };
   256     SECItem derSerial = { 0 };
   257     SECITEM_FROM_NSSITEM(&derCert, der);
   258     secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
   259     if (secrv != SECSuccess) {
   260 	return PR_FAILURE;
   261     }
   262     (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
   263     secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
   264     if (secrv != SECSuccess) {
   265 	PORT_Free(derSerial.data);
   266 	return PR_FAILURE;
   267     }
   268     (void)nssItem_Create(arena, issuer, derIssuer.len, derIssuer.data);
   269     PORT_Free(derSerial.data);
   270     PORT_Free(derIssuer.data);
   271     return PR_SUCCESS;
   272 }
   274 static NSSItem *
   275 nss3certificate_getIdentifier(nssDecodedCert *dc)
   276 {
   277     NSSItem *rvID;
   278     CERTCertificate *c = (CERTCertificate *)dc->data;
   279     rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
   280     return rvID;
   281 }
   283 static void *
   284 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
   285 {
   286     CERTCertificate *c = (CERTCertificate *)dc->data;
   287     return (void *)c->authKeyID;
   288 }
   290 static nssCertIDMatch
   291 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
   292 {
   293     CERTCertificate *c = (CERTCertificate *)dc->data;
   294     CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
   295     SECItem skid;
   296     nssCertIDMatch match = nssCertIDMatch_Unknown;
   298     /* keyIdentifier */
   299     if (authKeyID->keyID.len > 0 &&
   300 	CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
   301 	PRBool skiEqual;
   302 	skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
   303 	PORT_Free(skid.data);
   304 	if (skiEqual) {
   305 	    /* change the state to positive match, but keep going */
   306 	    match = nssCertIDMatch_Yes;
   307 	} else {
   308 	    /* exit immediately on failure */
   309 	    return nssCertIDMatch_No;
   310 	}
   311     }
   313     /* issuer/serial (treated as pair) */
   314     if (authKeyID->authCertIssuer) {
   315 	SECItem *caName = NULL;
   316 	SECItem *caSN = &authKeyID->authCertSerialNumber;
   318 	caName = (SECItem *)CERT_GetGeneralNameByType(
   319 	                                        authKeyID->authCertIssuer,
   320 						certDirectoryName, PR_TRUE);
   321 	if (caName != NULL &&
   322 	    SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
   323 	    SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) 
   324 	{
   325 	    match = nssCertIDMatch_Yes;
   326 	} else {
   327 	    match = nssCertIDMatch_Unknown;
   328 	}
   329     }
   330     return match;
   331 }
   333 static PRBool
   334 nss3certificate_isValidIssuer(nssDecodedCert *dc)
   335 {
   336     CERTCertificate *c = (CERTCertificate *)dc->data;
   337     unsigned int ignore;
   338     return CERT_IsCACert(c, &ignore);
   339 }
   341 static NSSUsage *
   342 nss3certificate_getUsage(nssDecodedCert *dc)
   343 {
   344     /* CERTCertificate *c = (CERTCertificate *)dc->data; */
   345     return NULL;
   346 }
   348 static PRBool 
   349 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
   350 {
   351     SECCertTimeValidity validity;
   352     CERTCertificate *c = (CERTCertificate *)dc->data;
   353     validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
   354     if (validity == secCertTimeValid) {
   355 	return PR_TRUE;
   356     }
   357     return PR_FALSE;
   358 }
   360 static PRBool 
   361 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
   362 {
   363     /* I know this isn't right, but this is glue code anyway */
   364     if (cmpdc->type == dc->type) {
   365 	CERTCertificate *certa = (CERTCertificate *)dc->data;
   366 	CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
   367 	return CERT_IsNewer(certa, certb);
   368     }
   369     return PR_FALSE;
   370 }
   372 /* CERT_FilterCertListByUsage */
   373 static PRBool
   374 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
   375 {
   376     CERTCertificate *cc;
   377     unsigned int requiredKeyUsage = 0;
   378     unsigned int requiredCertType = 0;
   379     SECStatus secrv;
   380     PRBool match;
   381     PRBool ca;
   383     /* This is for NSS 3.3 functions that do not specify a usage */
   384     if (usage->anyUsage) {
   385 	return PR_TRUE;
   386     }
   387     ca = usage->nss3lookingForCA;
   388     secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
   389                                              &requiredKeyUsage,
   390                                              &requiredCertType);
   391     if (secrv != SECSuccess) {
   392 	return PR_FALSE;
   393     }
   394     cc = (CERTCertificate *)dc->data;
   395     secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
   396     match = (PRBool)(secrv == SECSuccess);
   397     if (match) {
   398 	unsigned int certType = 0;
   399 	if (ca) {
   400 	    (void)CERT_IsCACert(cc, &certType);
   401 	} else {
   402 	    certType = cc->nsCertType;
   403 	}
   404 	if (!(certType & requiredCertType)) {
   405 	    match = PR_FALSE;
   406 	}
   407     }
   408     return match;
   409 }
   411 static PRBool
   412 nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
   413 {
   414     CERTCertificate *cc;
   415     PRBool ca;
   416     SECStatus secrv;
   417     unsigned int requiredFlags;
   418     unsigned int trustFlags;
   419     SECTrustType trustType;
   420     CERTCertTrust trust;
   422     /* This is for NSS 3.3 functions that do not specify a usage */
   423     if (usage->anyUsage) {
   424 	return PR_FALSE;  /* XXX is this right? */
   425     }
   426     cc = (CERTCertificate *)dc->data;
   427     ca = usage->nss3lookingForCA;
   428     if (!ca) {
   429 	PRBool trusted;
   430 	unsigned int failedFlags;
   431 	secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
   432 				    &failedFlags, &trusted);
   433 	return secrv == SECSuccess && trusted;
   434     }
   435     secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
   436 					  &trustType);
   437     if (secrv != SECSuccess) {
   438 	return PR_FALSE;
   439     }
   440     secrv = CERT_GetCertTrust(cc, &trust);
   441     if (secrv != SECSuccess) {
   442 	return PR_FALSE;
   443     }
   444     if (trustType == trustTypeNone) {
   445 	/* normally trustTypeNone usages accept any of the given trust bits
   446 	 * being on as acceptable. */
   447 	trustFlags = trust.sslFlags | trust.emailFlags |
   448 		     trust.objectSigningFlags;
   449     } else {
   450 	trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
   451     }
   452     return (trustFlags & requiredFlags) == requiredFlags;
   453 }
   455 static NSSASCII7 *
   456 nss3certificate_getEmailAddress(nssDecodedCert *dc)
   457 {
   458     CERTCertificate *cc = (CERTCertificate *)dc->data;
   459     return (cc && cc->emailAddr && cc->emailAddr[0])
   460 	    ? (NSSASCII7 *)cc->emailAddr : NULL;
   461 }
   463 static PRStatus
   464 nss3certificate_getDERSerialNumber(nssDecodedCert *dc, 
   465                                    NSSDER *serial, NSSArena *arena)
   466 {
   467     CERTCertificate *cc = (CERTCertificate *)dc->data;
   468     SECItem derSerial = { 0 };
   469     SECStatus secrv;
   470     secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
   471     if (secrv == SECSuccess) {
   472 	(void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
   473 	PORT_Free(derSerial.data);
   474 	return PR_SUCCESS;
   475     }
   476     return PR_FAILURE;
   477 }
   479 /* Returns NULL if "encoding" cannot be decoded. */
   480 NSS_IMPLEMENT nssDecodedCert *
   481 nssDecodedPKIXCertificate_Create (
   482   NSSArena *arenaOpt,
   483   NSSDER *encoding
   484 )
   485 {
   486     nssDecodedCert  *rvDC = NULL;
   487     CERTCertificate *cert;
   488     SECItem          secDER;
   490     SECITEM_FROM_NSSITEM(&secDER, encoding);
   491     cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
   492     if (cert) {
   493 	rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
   494 	if (rvDC) {
   495 	    rvDC->type                = NSSCertificateType_PKIX;
   496 	    rvDC->data                = (void *)cert;
   497 	    rvDC->getIdentifier       = nss3certificate_getIdentifier;
   498 	    rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
   499 	    rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
   500 	    rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
   501 	    rvDC->getUsage            = nss3certificate_getUsage;
   502 	    rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
   503 	    rvDC->isNewerThan         = nss3certificate_isNewerThan;
   504 	    rvDC->matchUsage          = nss3certificate_matchUsage;
   505 	    rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage;
   506 	    rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
   507 	    rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber;
   508 	} else {
   509 	    CERT_DestroyCertificate(cert);
   510 	}
   511     }
   512     return rvDC;
   513 }
   515 static nssDecodedCert *
   516 create_decoded_pkix_cert_from_nss3cert (
   517   NSSArena *arenaOpt,
   518   CERTCertificate *cc
   519 )
   520 {
   521     nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
   522     if (rvDC) {
   523 	rvDC->type                = NSSCertificateType_PKIX;
   524 	rvDC->data                = (void *)cc;
   525 	rvDC->getIdentifier       = nss3certificate_getIdentifier;
   526 	rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
   527 	rvDC->matchIdentifier     = nss3certificate_matchIdentifier;
   528 	rvDC->isValidIssuer       = nss3certificate_isValidIssuer;
   529 	rvDC->getUsage            = nss3certificate_getUsage;
   530 	rvDC->isValidAtTime       = nss3certificate_isValidAtTime;
   531 	rvDC->isNewerThan         = nss3certificate_isNewerThan;
   532 	rvDC->matchUsage          = nss3certificate_matchUsage;
   533 	rvDC->isTrustedForUsage   = nss3certificate_isTrustedForUsage;
   534 	rvDC->getEmailAddress     = nss3certificate_getEmailAddress;
   535 	rvDC->getDERSerialNumber  = nss3certificate_getDERSerialNumber;
   536     }
   537     return rvDC;
   538 }
   540 NSS_IMPLEMENT PRStatus
   541 nssDecodedPKIXCertificate_Destroy (
   542   nssDecodedCert *dc
   543 )
   544 {
   545     CERTCertificate *cert = (CERTCertificate *)dc->data;
   547     /* The decoder may only be half initialized (the case where we find we 
   548      * could not decode the certificate). In this case, there is not cert to
   549      * free, just free the dc structure. */
   550     if (cert) {
   551 	PRBool freeSlot = cert->ownSlot;
   552 	PK11SlotInfo *slot = cert->slot;
   553 	PLArenaPool *arena  = cert->arena;
   554 	/* zero cert before freeing. Any stale references to this cert
   555 	 * after this point will probably cause an exception.  */
   556 	PORT_Memset(cert, 0, sizeof *cert);
   557 	/* free the arena that contains the cert. */
   558 	PORT_FreeArena(arena, PR_FALSE);
   559 	if (slot && freeSlot) {
   560 	    PK11_FreeSlot(slot);
   561 	}
   562     }
   563     nss_ZFreeIf(dc);
   564     return PR_SUCCESS;
   565 }
   567 /* see pk11cert.c:pk11_HandleTrustObject */
   568 static unsigned int
   569 get_nss3trust_from_nss4trust(nssTrustLevel t)
   570 {
   571     unsigned int rt = 0;
   572     if (t == nssTrustLevel_Trusted) {
   573 	rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
   574     }
   575     if (t == nssTrustLevel_TrustedDelegator) {
   576 	rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA;
   577     }
   578     if (t == nssTrustLevel_NotTrusted) {
   579 	rt |= CERTDB_TERMINAL_RECORD;
   580     }
   581     if (t == nssTrustLevel_ValidDelegator) {
   582 	rt |= CERTDB_VALID_CA;
   583     }
   584     return rt;
   585 }
   587 static CERTCertTrust *
   588 cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena)
   589 {
   590     CERTCertTrust *rvTrust;
   591     unsigned int client;
   592     if (!t) {
   593 	return NULL;
   594     }
   595     rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
   596     if (!rvTrust) return NULL;
   597     rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
   598     client = get_nss3trust_from_nss4trust(t->clientAuth);
   599     if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
   600 	client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA);
   601 	rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
   602     }
   603     rvTrust->sslFlags |= client;
   604     rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
   605     rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
   606     return rvTrust;
   607 }
   609 CERTCertTrust * 
   610 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
   611 {
   612     CERTCertTrust *rvTrust = NULL;
   613     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
   614     NSSTrust *t;
   615     t = nssTrustDomain_FindTrustForCertificate(td, c);
   616     if (t) {
   617 	rvTrust = cert_trust_from_stan_trust(t, cc->arena);
   618 	if (!rvTrust) {
   619 	    nssTrust_Destroy(t);
   620 	    return NULL;
   621 	}
   622 	nssTrust_Destroy(t);
   623     } else {
   624 	rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
   625 	if (!rvTrust) {
   626 	    return NULL;
   627 	}
   628 	memset(rvTrust, 0, sizeof(*rvTrust));
   629     }
   630     if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
   631 	rvTrust->sslFlags |= CERTDB_USER;
   632 	rvTrust->emailFlags |= CERTDB_USER;
   633 	rvTrust->objectSigningFlags |= CERTDB_USER;
   634     }
   635     return rvTrust;
   636 }
   638 static nssCryptokiInstance *
   639 get_cert_instance(NSSCertificate *c)
   640 {
   641     nssCryptokiObject *instance, **ci;
   642     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
   643     if (!instances) {
   644 	return NULL;
   645     }
   646     instance = NULL;
   647     for (ci = instances; *ci; ci++) {
   648 	if (!instance) {
   649 	    instance = nssCryptokiObject_Clone(*ci);
   650 	} else {
   651 	    /* This only really works for two instances...  But 3.4 can't
   652 	     * handle more anyway.  The logic is, if there are multiple
   653 	     * instances, prefer the one that is not internal (e.g., on
   654 	     * a hardware device.
   655 	     */
   656 	    if (PK11_IsInternal(instance->token->pk11slot)) {
   657 		nssCryptokiObject_Destroy(instance);
   658 		instance = nssCryptokiObject_Clone(*ci);
   659 	    }
   660 	}
   661     }
   662     nssCryptokiObjectArray_Destroy(instances);
   663     return instance;
   664 }
   666 char * 
   667 STAN_GetCERTCertificateNameForInstance (
   668   PLArenaPool *arenaOpt,
   669   NSSCertificate *c,
   670   nssCryptokiInstance *instance
   671 )
   672 {
   673     NSSCryptoContext *context = c->object.cryptoContext;
   674     PRStatus nssrv;
   675     int nicklen, tokenlen, len;
   676     NSSUTF8 *tokenName = NULL;
   677     NSSUTF8 *stanNick = NULL;
   678     char *nickname = NULL;
   679     char *nick;
   681     if (instance) {
   682 	stanNick = instance->label;
   683     } else if (context) {
   684 	stanNick = c->object.tempName;
   685     }
   686     if (stanNick) {
   687 	/* fill other fields needed by NSS3 functions using CERTCertificate */
   688 	if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 
   689 	                 PORT_Strchr(stanNick, ':') != NULL) ) {
   690 	    tokenName = nssToken_GetName(instance->token);
   691 	    tokenlen = nssUTF8_Size(tokenName, &nssrv);
   692 	} else {
   693 	/* don't use token name for internal slot; 3.3 didn't */
   694 	    tokenlen = 0;
   695 	}
   696 	nicklen = nssUTF8_Size(stanNick, &nssrv);
   697 	len = tokenlen + nicklen;
   698 	if (arenaOpt) {
   699 	    nickname = PORT_ArenaAlloc(arenaOpt, len);
   700 	} else {
   701 	    nickname = PORT_Alloc(len);
   702 	}
   703 	nick = nickname;
   704 	if (tokenName) {
   705 	    memcpy(nick, tokenName, tokenlen-1);
   706 	    nick += tokenlen-1;
   707 	    *nick++ = ':';
   708 	}
   709 	memcpy(nick, stanNick, nicklen-1);
   710 	nickname[len-1] = '\0';
   711     }
   712     return nickname;
   713 }
   715 char * 
   716 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
   717 {
   718     char * result;
   719     nssCryptokiInstance *instance = get_cert_instance(c);
   720     /* It's OK to call this function, even if instance is NULL */
   721     result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
   722     if (instance)
   723 	nssCryptokiObject_Destroy(instance);
   724     return result;
   725 }
   727 static void
   728 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
   729 {
   730     CERTCertTrust* trust = NULL;
   731     NSSTrust *nssTrust;
   732     NSSCryptoContext *context = c->object.cryptoContext;
   733     nssCryptokiInstance *instance;
   734     NSSUTF8 *stanNick = NULL;
   736     /* We are holding the base class object's lock on entry of this function
   737      * This lock protects writes to fields of the CERTCertificate .
   738      * It is also needed by some functions to compute values such as trust.
   739      */
   740     instance = get_cert_instance(c);
   742     if (instance) {
   743 	stanNick = instance->label;
   744     } else if (context) {
   745 	stanNick = c->object.tempName;
   746     }
   747     /* fill other fields needed by NSS3 functions using CERTCertificate */
   748     if ((!cc->nickname && stanNick) || forced) {
   749 	PRStatus nssrv;
   750 	int nicklen, tokenlen, len;
   751 	NSSUTF8 *tokenName = NULL;
   752 	char *nick;
   753 	if (instance && 
   754 	     (!PK11_IsInternalKeySlot(instance->token->pk11slot) || 
   755 	      (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
   756 	    tokenName = nssToken_GetName(instance->token);
   757 	    tokenlen = nssUTF8_Size(tokenName, &nssrv);
   758 	} else {
   759 	    /* don't use token name for internal slot; 3.3 didn't */
   760 	    tokenlen = 0;
   761 	}
   762 	if (stanNick) {
   763 	    nicklen = nssUTF8_Size(stanNick, &nssrv);
   764 	    len = tokenlen + nicklen;
   765 	    nick = PORT_ArenaAlloc(cc->arena, len);
   766 	    if (tokenName) {
   767 		memcpy(nick, tokenName, tokenlen-1);
   768 		nick[tokenlen-1] = ':';
   769 		memcpy(nick+tokenlen, stanNick, nicklen-1);
   770 	    } else {
   771 		memcpy(nick, stanNick, nicklen-1);
   772 	    }
   773 	    nick[len-1] = '\0';
   774             cc->nickname = nick;
   775 	} else {
   776 	    cc->nickname = NULL;
   777 	}
   778     }
   779     if (context) {
   780 	/* trust */
   781 	nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
   782 	if (!nssTrust) {
   783 	    /* chicken and egg issue:
   784 	     *
   785 	     * c->issuer and c->serial are empty at this point, but
   786 	     * nssTrustDomain_FindTrustForCertificate use them to look up
   787 	     * up the trust object, so we point them to cc->derIssuer and
   788 	     * cc->serialNumber.
   789 	     *
   790 	     * Our caller will fill these in with proper arena copies when we
   791 	     * return. */
   792 	    c->issuer.data = cc->derIssuer.data;
   793 	    c->issuer.size = cc->derIssuer.len;
   794 	    c->serial.data = cc->serialNumber.data;
   795 	    c->serial.size = cc->serialNumber.len;
   796 	    nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
   797 	}
   798 	if (nssTrust) {
   799             trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
   800             if (trust) {
   801                 /* we should destroy cc->trust before replacing it, but it's
   802                    allocated in cc->arena, so memory growth will occur on each
   803                    refresh */
   804                 CERT_LockCertTrust(cc);
   805                 cc->trust = trust;
   806                 CERT_UnlockCertTrust(cc);
   807             }
   808 	    nssTrust_Destroy(nssTrust);
   809 	}
   810     } else if (instance) {
   811 	/* slot */
   812 	if (cc->slot != instance->token->pk11slot) {
   813 	    if (cc->slot) {
   814 		PK11_FreeSlot(cc->slot);
   815 	    }
   816 	    cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
   817 	}
   818 	cc->ownSlot = PR_TRUE;
   819 	/* pkcs11ID */
   820 	cc->pkcs11ID = instance->handle;
   821 	/* trust */
   822 	trust = nssTrust_GetCERTCertTrustForCert(c, cc);
   823         if (trust) {
   824             /* we should destroy cc->trust before replacing it, but it's
   825                allocated in cc->arena, so memory growth will occur on each
   826                refresh */
   827             CERT_LockCertTrust(cc);
   828             cc->trust = trust;
   829             CERT_UnlockCertTrust(cc);
   830         }
   831 	nssCryptokiObject_Destroy(instance);
   832     } 
   833     /* database handle is now the trust domain */
   834     cc->dbhandle = c->object.trustDomain;
   835     /* subjectList ? */
   836     /* istemp and isperm are supported in NSS 3.4 */
   837     cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
   838     cc->isperm = PR_TRUE;  /* by default */
   839     /* pointer back */
   840     cc->nssCertificate = c;
   841     if (trust) {
   842 	/* force the cert type to be recomputed to include trust info */
   843 	PRUint32 nsCertType = cert_ComputeCertType(cc);
   845 	/* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
   846 	PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32));
   847 	PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType);
   848     }
   849 }
   851 static CERTCertificate *
   852 stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
   853 {
   854     nssDecodedCert *dc = NULL;
   855     CERTCertificate *cc = NULL;
   856     CERTCertTrust certTrust;
   858     nssPKIObject_Lock(&c->object);
   860     dc = c->decoding;
   861     if (!dc) {
   862 	dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
   863 	if (!dc) {
   864             goto loser;
   865         }
   866 	cc = (CERTCertificate *)dc->data;
   867 	PORT_Assert(cc); /* software error */
   868 	if (!cc) {
   869 	    nssDecodedPKIXCertificate_Destroy(dc);
   870 	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
   871 	    goto loser;
   872 	}
   873     	PORT_Assert(!c->decoding); 
   874 	if (!c->decoding) {
   875 	    c->decoding = dc;
   876 	} else { 
   877             /* this should never happen. Fail. */
   878 	    nssDecodedPKIXCertificate_Destroy(dc);
   879 	    nss_SetError(NSS_ERROR_INTERNAL_ERROR);
   880             goto loser;
   881 	}
   882     }
   883     cc = (CERTCertificate *)dc->data;
   884     PORT_Assert(cc);
   885     if (!cc) {
   886         nss_SetError(NSS_ERROR_INTERNAL_ERROR);
   887         goto loser;
   888     }
   889     if (!cc->nssCertificate || forceUpdate) {
   890         fill_CERTCertificateFields(c, cc, forceUpdate);
   891     } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess &&
   892                !c->object.cryptoContext) {
   893         /* if it's a perm cert, it might have been stored before the
   894          * trust, so look for the trust again.  But a temp cert can be
   895          * ignored.
   896          */
   897         CERTCertTrust* trust = NULL;
   898         trust = nssTrust_GetCERTCertTrustForCert(c, cc);
   900         CERT_LockCertTrust(cc);
   901         cc->trust = trust;
   902         CERT_UnlockCertTrust(cc);
   903     }
   905   loser:
   906     nssPKIObject_Unlock(&c->object);
   907     return cc;
   908 }
   910 NSS_IMPLEMENT CERTCertificate *
   911 STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
   912 {
   913     if (c->decoding) {
   914 	return stan_GetCERTCertificate(c, PR_TRUE);
   915     }
   916     return NULL;
   917 }
   919 NSS_IMPLEMENT CERTCertificate *
   920 STAN_GetCERTCertificate(NSSCertificate *c)
   921 {
   922     return stan_GetCERTCertificate(c, PR_FALSE);
   923 }
   924 /*
   925  * many callers of STAN_GetCERTCertificate() intend that
   926  * the CERTCertificate returned inherits the reference to the 
   927  * NSSCertificate. For these callers it's convenient to have 
   928  * this function 'own' the reference and either return a valid 
   929  * CERTCertificate structure which inherits the reference or 
   930  * destroy the reference to NSSCertificate and returns NULL.
   931  */
   932 NSS_IMPLEMENT CERTCertificate *
   933 STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
   934 {
   935     CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
   936     if (!nss3cert) {
   937 	nssCertificate_Destroy(c);
   938     }
   939     return nss3cert;
   940 }
   942 static nssTrustLevel
   943 get_stan_trust(unsigned int t, PRBool isClientAuth) 
   944 {
   945     if (isClientAuth) {
   946 	if (t & CERTDB_TRUSTED_CLIENT_CA) {
   947 	    return nssTrustLevel_TrustedDelegator;
   948 	}
   949     } else {
   950 	if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
   951 	    return nssTrustLevel_TrustedDelegator;
   952 	}
   953     }
   954     if (t & CERTDB_TRUSTED) {
   955 	return nssTrustLevel_Trusted;
   956     }
   957     if (t & CERTDB_TERMINAL_RECORD) {
   958 	return nssTrustLevel_NotTrusted;
   959     }
   960     if (t & CERTDB_VALID_CA) {
   961 	return nssTrustLevel_ValidDelegator;
   962     }
   963     return nssTrustLevel_MustVerify;
   964 }
   966 NSS_EXTERN NSSCertificate *
   967 STAN_GetNSSCertificate(CERTCertificate *cc)
   968 {
   969     NSSCertificate *c;
   970     nssCryptokiInstance *instance;
   971     nssPKIObject *pkiob;
   972     NSSArena *arena;
   973     c = cc->nssCertificate;
   974     if (c) {
   975     	return c;
   976     }
   977     /* i don't think this should happen.  but if it can, need to create
   978      * NSSCertificate from CERTCertificate values here.  */
   979     /* Yup, it can happen. */
   980     arena = NSSArena_Create();
   981     if (!arena) {
   982 	return NULL;
   983     }
   984     c = nss_ZNEW(arena, NSSCertificate);
   985     if (!c) {
   986 	nssArena_Destroy(arena);
   987 	return NULL;
   988     }
   989     NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
   990     c->type = NSSCertificateType_PKIX;
   991     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
   992     if (!pkiob) {
   993 	nssArena_Destroy(arena);
   994 	return NULL;
   995     }
   996     c->object = *pkiob;
   997     nssItem_Create(arena,
   998                    &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
   999     nssItem_Create(arena,
  1000                    &c->subject, cc->derSubject.len, cc->derSubject.data);
  1001     if (PR_TRUE) {
  1002 	/* CERTCertificate stores serial numbers decoded.  I need the DER
  1003 	* here.  sigh.
  1004 	*/
  1005 	SECItem derSerial;
  1006 	SECStatus secrv;
  1007 	secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
  1008 	if (secrv == SECFailure) {
  1009 	    nssArena_Destroy(arena);
  1010 	    return NULL;
  1012 	nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
  1013 	PORT_Free(derSerial.data);
  1015     if (cc->emailAddr && cc->emailAddr[0]) {
  1016         c->email = nssUTF8_Create(arena,
  1017                                   nssStringType_PrintableString,
  1018                                   (NSSUTF8 *)cc->emailAddr,
  1019                                   PORT_Strlen(cc->emailAddr));
  1021     if (cc->slot) {
  1022 	instance = nss_ZNEW(arena, nssCryptokiInstance);
  1023 	if (!instance) {
  1024 	    nssArena_Destroy(arena);
  1025 	    return NULL;
  1027 	instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot));
  1028 	instance->handle = cc->pkcs11ID;
  1029 	instance->isTokenObject = PR_TRUE;
  1030 	if (cc->nickname) {
  1031 	    instance->label = nssUTF8_Create(arena,
  1032 	                                     nssStringType_UTF8String,
  1033 	                                     (NSSUTF8 *)cc->nickname,
  1034 	                                     PORT_Strlen(cc->nickname));
  1036 	nssPKIObject_AddInstance(&c->object, instance);
  1038     c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
  1039     cc->nssCertificate = c;
  1040     return c;
  1043 static NSSToken*
  1044 stan_GetTrustToken (
  1045   NSSCertificate *c
  1048     NSSToken *ttok = NULL;
  1049     NSSToken *rtok = NULL;
  1050     NSSToken *tok = NULL;
  1051     nssCryptokiObject **ip;
  1052     nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
  1053     if (!instances) {
  1054 	return PR_FALSE;
  1056     for (ip = instances; *ip; ip++) {
  1057 	nssCryptokiObject *instance = *ip;
  1058         nssCryptokiObject *to = 
  1059 		nssToken_FindTrustForCertificate(instance->token, NULL,
  1060 		&c->encoding, &c->issuer, &c->serial, 
  1061 		nssTokenSearchType_TokenOnly);
  1062 	NSSToken *ctok = instance->token;
  1063 	PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
  1065 	if (to) {
  1066 	    nssCryptokiObject_Destroy(to);
  1067 	    ttok = ctok;
  1068  	    if (!ro) {
  1069 		break;
  1071 	} else {
  1072 	    if (!rtok && ro) {
  1073 		rtok = ctok;
  1075 	    if (!tok && !ro) {
  1076 		tok = ctok;
  1080     nssCryptokiObjectArray_Destroy(instances);
  1081     return ttok ? ttok : (tok ? tok : rtok);
  1084 NSS_EXTERN PRStatus
  1085 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
  1087     PRStatus nssrv;
  1088     NSSCertificate *c = STAN_GetNSSCertificate(cc);
  1089     NSSToken *tok;
  1090     NSSTrustDomain *td;
  1091     NSSTrust *nssTrust;
  1092     NSSArena *arena;
  1093     CERTCertTrust *oldTrust;
  1094     CERTCertTrust *newTrust;
  1095     nssListIterator *tokens;
  1096     PRBool moving_object;
  1097     nssCryptokiObject *newInstance;
  1098     nssPKIObject *pkiob;
  1100     if (c == NULL) {
  1101         return PR_FAILURE;
  1103     oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
  1104     if (oldTrust) {
  1105 	if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) {
  1106 	    /* ... and the new trust is no different, done) */
  1107 	    return PR_SUCCESS;
  1108 	} else {
  1109 	    /* take over memory already allocated in cc's arena */
  1110 	    newTrust = oldTrust;
  1112     } else {
  1113 	newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
  1115     memcpy(newTrust, trust, sizeof(CERTCertTrust));
  1116     CERT_LockCertTrust(cc);
  1117     cc->trust = newTrust;
  1118     CERT_UnlockCertTrust(cc);
  1119     /* Set the NSSCerticate's trust */
  1120     arena = nssArena_Create();
  1121     if (!arena) return PR_FAILURE;
  1122     nssTrust = nss_ZNEW(arena, NSSTrust);
  1123     if (!nssTrust) {
  1124 	nssArena_Destroy(arena);
  1125 	return PR_FAILURE;
  1127     pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
  1128     if (!pkiob) {
  1129 	nssArena_Destroy(arena);
  1130 	return PR_FAILURE;
  1132     nssTrust->object = *pkiob;
  1133     nssTrust->certificate = c;
  1134     nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
  1135     nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
  1136     nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
  1137     nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
  1138     nssTrust->stepUpApproved = 
  1139                     (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
  1140     if (c->object.cryptoContext != NULL) {
  1141 	/* The cert is in a context, set the trust there */
  1142 	NSSCryptoContext *cc = c->object.cryptoContext;
  1143 	nssrv = nssCryptoContext_ImportTrust(cc, nssTrust);
  1144 	if (nssrv != PR_SUCCESS) {
  1145 	    goto done;
  1147 	if (c->object.numInstances == 0) {
  1148 	    /* The context is the only instance, finished */
  1149 	    goto done;
  1152     td = STAN_GetDefaultTrustDomain();
  1153     tok = stan_GetTrustToken(c);
  1154     moving_object = PR_FALSE;
  1155     if (tok && PK11_IsReadOnly(tok->pk11slot))  {
  1156 	NSSRWLock_LockRead(td->tokensLock);
  1157 	tokens = nssList_CreateIterator(td->tokenList);
  1158 	if (!tokens) {
  1159 	    nssrv = PR_FAILURE;
  1160 	    NSSRWLock_UnlockRead(td->tokensLock);
  1161 	    goto done;
  1163 	for (tok  = (NSSToken *)nssListIterator_Start(tokens);
  1164 	     tok != (NSSToken *)NULL;
  1165 	     tok  = (NSSToken *)nssListIterator_Next(tokens))
  1167 	    if (!PK11_IsReadOnly(tok->pk11slot)) break;
  1169 	nssListIterator_Finish(tokens);
  1170 	nssListIterator_Destroy(tokens);
  1171 	NSSRWLock_UnlockRead(td->tokensLock);
  1172 	moving_object = PR_TRUE;
  1174     if (tok) {
  1175 	if (moving_object) {
  1176 	    /* this is kind of hacky.  the softoken needs the cert
  1177 	     * object in order to store trust.  forcing it to be perm
  1178 	     */
  1179 	    NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
  1180 	    NSSASCII7 *email = NULL;
  1182 	    if (PK11_IsInternal(tok->pk11slot)) {
  1183 		email = c->email;
  1185 	    newInstance = nssToken_ImportCertificate(tok, NULL,
  1186 	                                             NSSCertificateType_PKIX,
  1187 	                                             &c->id,
  1188 	                                             nickname,
  1189 	                                             &c->encoding,
  1190 	                                             &c->issuer,
  1191 	                                             &c->subject,
  1192 	                                             &c->serial,
  1193 						     email,
  1194 	                                             PR_TRUE);
  1195             nss_ZFreeIf(nickname);
  1196             nickname = NULL;
  1197 	    if (!newInstance) {
  1198 		nssrv = PR_FAILURE;
  1199 		goto done;
  1201 	    nssPKIObject_AddInstance(&c->object, newInstance);
  1203 	newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
  1204 	                                   &c->issuer, &c->serial,
  1205 	                                   nssTrust->serverAuth,
  1206 	                                   nssTrust->clientAuth,
  1207 	                                   nssTrust->codeSigning,
  1208 	                                   nssTrust->emailProtection,
  1209 	                                   nssTrust->stepUpApproved, PR_TRUE);
  1210 	/* If the selected token can't handle trust, dump the trust on 
  1211 	 * the internal token */
  1212 	if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
  1213 	    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
  1214 	    NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
  1215 	    NSSASCII7 *email = c->email;
  1216 	    tok = PK11Slot_GetNSSToken(slot);
  1217 	    PK11_FreeSlot(slot);
  1219 	    newInstance = nssToken_ImportCertificate(tok, NULL,
  1220 	                                             NSSCertificateType_PKIX,
  1221 	                                             &c->id,
  1222 	                                             nickname,
  1223 	                                             &c->encoding,
  1224 	                                             &c->issuer,
  1225 	                                             &c->subject,
  1226 	                                             &c->serial,
  1227 						     email,
  1228 	                                             PR_TRUE);
  1229             nss_ZFreeIf(nickname);
  1230             nickname = NULL;
  1231 	    if (!newInstance) {
  1232 		nssrv = PR_FAILURE;
  1233 		goto done;
  1235 	    nssPKIObject_AddInstance(&c->object, newInstance);
  1236 	    newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
  1237 	                                   &c->issuer, &c->serial,
  1238 	                                   nssTrust->serverAuth,
  1239 	                                   nssTrust->clientAuth,
  1240 	                                   nssTrust->codeSigning,
  1241 	                                   nssTrust->emailProtection,
  1242 	                                   nssTrust->stepUpApproved, PR_TRUE);
  1244 	if (newInstance) {
  1245 	    nssCryptokiObject_Destroy(newInstance);
  1246 	    nssrv = PR_SUCCESS;
  1247 	} else {
  1248 	    nssrv = PR_FAILURE;
  1250     } else {
  1251 	nssrv = PR_FAILURE;
  1253 done:
  1254     (void)nssTrust_Destroy(nssTrust);
  1255     return nssrv;
  1258 /*
  1259 ** Delete trust objects matching the given slot.
  1260 ** Returns error if a device fails to delete.
  1261 **
  1262 ** This function has the side effect of moving the
  1263 ** surviving entries to the front of the object list
  1264 ** and nullifying the rest.
  1265 */
  1266 static PRStatus
  1267 DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
  1269     int numNotDestroyed = 0;     /* the ones skipped plus the failures */
  1270     int failureCount = 0;        /* actual deletion failures by devices */
  1271     int index;
  1273     nssPKIObject_Lock(tObject);
  1274     /* Keep going even if a module fails to delete. */
  1275     for (index = 0; index < tObject->numInstances; index++) {
  1276 	nssCryptokiObject *instance = tObject->instances[index];
  1277 	if (!instance) {
  1278 	    continue;
  1281 	/* ReadOnly and not matched treated the same */
  1282 	if (PK11_IsReadOnly(instance->token->pk11slot) ||
  1283 	    pk11slot != instance->token->pk11slot) {
  1284 	    tObject->instances[numNotDestroyed++] = instance;
  1285 	    continue;
  1288 	/* Here we have found a matching one */
  1289 	tObject->instances[index] = NULL;
  1290 	if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
  1291 	    nssCryptokiObject_Destroy(instance);
  1292 	} else {
  1293 	    tObject->instances[numNotDestroyed++] = instance;
  1294 	    failureCount++;
  1298     if (numNotDestroyed == 0) {
  1299     	nss_ZFreeIf(tObject->instances);
  1300     	tObject->numInstances = 0;
  1301     } else {
  1302     	tObject->numInstances = numNotDestroyed;
  1305     nssPKIObject_Unlock(tObject);
  1307     return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
  1310 /*
  1311 ** Delete trust objects matching the slot of the given certificate.
  1312 ** Returns an error if any device fails to delete. 
  1313 */
  1314 NSS_EXTERN PRStatus
  1315 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
  1317     PRStatus nssrv = PR_SUCCESS;
  1319     NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
  1320     NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
  1321     /* caller made sure nssTrust isn't NULL */
  1322     nssPKIObject *tobject = &nssTrust->object;
  1323     nssPKIObject *cobject = &c->object;
  1324     int i;
  1326     /* Iterate through the cert and trust object instances looking for
  1327      * those with matching pk11 slots to delete. Even if some device
  1328      * can't delete we keep going. Keeping a status variable for the
  1329      * loop so that once it's failed the other gets set.
  1330      */
  1331     NSSRWLock_LockRead(td->tokensLock);
  1332     nssPKIObject_Lock(cobject);
  1333     for (i = 0; i < cobject->numInstances; i++) {
  1334 	nssCryptokiObject *cInstance = cobject->instances[i];
  1335 	if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
  1336 		PRStatus status;
  1337 	    if (!tobject->numInstances || !tobject->instances) continue;
  1338 	    status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject);
  1339 	    if (status == PR_FAILURE) {
  1340 	    	/* set the outer one but keep going */
  1341 	    	nssrv = PR_FAILURE;
  1345     nssPKIObject_Unlock(cobject);
  1346     NSSRWLock_UnlockRead(td->tokensLock);
  1347     return nssrv;
  1350 /* CERT_TraversePermCertsForSubject */
  1351 NSS_IMPLEMENT PRStatus
  1352 nssTrustDomain_TraverseCertificatesBySubject (
  1353   NSSTrustDomain *td,
  1354   NSSDER *subject,
  1355   PRStatus (*callback)(NSSCertificate *c, void *arg),
  1356   void *arg
  1359     PRStatus nssrv = PR_SUCCESS;
  1360     NSSArena *tmpArena;
  1361     NSSCertificate **subjectCerts;
  1362     NSSCertificate *c;
  1363     PRIntn i;
  1364     tmpArena = NSSArena_Create();
  1365     if (!tmpArena) {
  1366         return PR_FAILURE;
  1368     subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
  1369                                                             0, tmpArena);
  1370     if (subjectCerts) {
  1371 	for (i=0, c = subjectCerts[i]; c; i++) {
  1372 	    nssrv = callback(c, arg);
  1373 	    if (nssrv != PR_SUCCESS) break;
  1376     nssArena_Destroy(tmpArena);
  1377     return nssrv;
  1380 /* CERT_TraversePermCertsForNickname */
  1381 NSS_IMPLEMENT PRStatus
  1382 nssTrustDomain_TraverseCertificatesByNickname (
  1383   NSSTrustDomain *td,
  1384   NSSUTF8 *nickname,
  1385   PRStatus (*callback)(NSSCertificate *c, void *arg),
  1386   void *arg
  1389     PRStatus nssrv = PR_SUCCESS;
  1390     NSSArena *tmpArena;
  1391     NSSCertificate **nickCerts;
  1392     NSSCertificate *c;
  1393     PRIntn i;
  1394     tmpArena = NSSArena_Create();
  1395     if (!tmpArena) {
  1396         return PR_FAILURE;
  1398     nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
  1399                                                           0, tmpArena);
  1400     if (nickCerts) {
  1401 	for (i=0, c = nickCerts[i]; c; i++) {
  1402 	    nssrv = callback(c, arg);
  1403 	    if (nssrv != PR_SUCCESS) break;
  1406     nssArena_Destroy(tmpArena);
  1407     return nssrv;
  1410 static void cert_dump_iter(const void *k, void *v, void *a)
  1412     NSSCertificate *c = (NSSCertificate *)k;
  1413     CERTCertificate *cert = STAN_GetCERTCertificate(c);
  1414     printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
  1417 void
  1418 nss_DumpCertificateCacheInfo()
  1420     NSSTrustDomain *td;
  1421     NSSCryptoContext *cc;
  1422     td = STAN_GetDefaultTrustDomain();
  1423     cc = STAN_GetDefaultCryptoContext();
  1424     printf("\n\nCertificates in the cache:\n");
  1425     nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
  1426     printf("\n\nCertificates in the temporary store:\n");
  1427     if (cc->certStore) {
  1428 	nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);

mercurial