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