Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(459)

Side by Side Diff: mozilla/security/nss/lib/pki/pki3hack.c

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

Powered by Google App Engine
This is Rietveld 408576698