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

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

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/pki/pki3hack.h ('k') | 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 /*
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 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 }
84
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 }
102
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;
112
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;
150
151 loser:
152 NSSTrustDomain_Destroy(td);
153 return PR_FAILURE;
154 }
155
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 }
173
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 }
201
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 }
222
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;
232
233 SECITEM_FROM_NSSITEM(&secDER, der);
234
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 PORT_FreeArena(arena, PR_FALSE);
243 return NULL;
244 }
245 rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
246 PORT_FreeArena(arena,PR_FALSE);
247 return rvKey;
248 }
249
250 NSS_IMPLEMENT PRStatus
251 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der,
252 NSSDER *issuer, NSSDER *serial)
253 {
254 SECItem derCert = { 0 };
255 SECItem derIssuer = { 0 };
256 SECItem derSerial = { 0 };
257 SECStatus secrv;
258 derCert.data = (unsigned char *)der->data;
259 derCert.len = der->size;
260 secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
261 if (secrv != SECSuccess) {
262 return PR_FAILURE;
263 }
264 secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
265 if (secrv != SECSuccess) {
266 PORT_Free(derSerial.data);
267 return PR_FAILURE;
268 }
269 issuer->data = derIssuer.data;
270 issuer->size = derIssuer.len;
271 serial->data = derSerial.data;
272 serial->size = derSerial.len;
273 return PR_SUCCESS;
274 }
275
276 static NSSItem *
277 nss3certificate_getIdentifier(nssDecodedCert *dc)
278 {
279 NSSItem *rvID;
280 CERTCertificate *c = (CERTCertificate *)dc->data;
281 rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
282 return rvID;
283 }
284
285 static void *
286 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
287 {
288 CERTCertificate *c = (CERTCertificate *)dc->data;
289 return (void *)c->authKeyID;
290 }
291
292 static nssCertIDMatch
293 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
294 {
295 CERTCertificate *c = (CERTCertificate *)dc->data;
296 CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
297 SECItem skid;
298 nssCertIDMatch match = nssCertIDMatch_Unknown;
299
300 /* keyIdentifier */
301 if (authKeyID->keyID.len > 0 &&
302 CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
303 PRBool skiEqual;
304 skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
305 PORT_Free(skid.data);
306 if (skiEqual) {
307 /* change the state to positive match, but keep going */
308 match = nssCertIDMatch_Yes;
309 } else {
310 /* exit immediately on failure */
311 return nssCertIDMatch_No;
312 }
313 }
314
315 /* issuer/serial (treated as pair) */
316 if (authKeyID->authCertIssuer) {
317 SECItem *caName = NULL;
318 SECItem *caSN = &authKeyID->authCertSerialNumber;
319
320 caName = (SECItem *)CERT_GetGeneralNameByType(
321 authKeyID->authCertIssuer,
322 certDirectoryName, PR_TRUE);
323 if (caName != NULL &&
324 SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
325 SECITEM_ItemsAreEqual(&c->serialNumber, caSN))
326 {
327 match = nssCertIDMatch_Yes;
328 } else {
329 match = nssCertIDMatch_Unknown;
330 }
331 }
332 return match;
333 }
334
335 static PRBool
336 nss3certificate_isValidIssuer(nssDecodedCert *dc)
337 {
338 CERTCertificate *c = (CERTCertificate *)dc->data;
339 unsigned int ignore;
340 return CERT_IsCACert(c, &ignore);
341 }
342
343 static NSSUsage *
344 nss3certificate_getUsage(nssDecodedCert *dc)
345 {
346 /* CERTCertificate *c = (CERTCertificate *)dc->data; */
347 return NULL;
348 }
349
350 static PRBool
351 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
352 {
353 SECCertTimeValidity validity;
354 CERTCertificate *c = (CERTCertificate *)dc->data;
355 validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
356 if (validity == secCertTimeValid) {
357 return PR_TRUE;
358 }
359 return PR_FALSE;
360 }
361
362 static PRBool
363 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
364 {
365 /* I know this isn't right, but this is glue code anyway */
366 if (cmpdc->type == dc->type) {
367 CERTCertificate *certa = (CERTCertificate *)dc->data;
368 CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
369 return CERT_IsNewer(certa, certb);
370 }
371 return PR_FALSE;
372 }
373
374 /* CERT_FilterCertListByUsage */
375 static PRBool
376 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
377 {
378 CERTCertificate *cc;
379 unsigned int requiredKeyUsage = 0;
380 unsigned int requiredCertType = 0;
381 SECStatus secrv;
382 PRBool match;
383 PRBool ca;
384
385 /* This is for NSS 3.3 functions that do not specify a usage */
386 if (usage->anyUsage) {
387 return PR_TRUE;
388 }
389 ca = usage->nss3lookingForCA;
390 secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
391 &requiredKeyUsage,
392 &requiredCertType);
393 if (secrv != SECSuccess) {
394 return PR_FALSE;
395 }
396 cc = (CERTCertificate *)dc->data;
397 secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
398 match = (PRBool)(secrv == SECSuccess);
399 if (match) {
400 unsigned int certType = 0;
401 if (ca) {
402 (void)CERT_IsCACert(cc, &certType);
403 } else {
404 certType = cc->nsCertType;
405 }
406 if (!(certType & requiredCertType)) {
407 match = PR_FALSE;
408 }
409 }
410 return match;
411 }
412
413 static PRBool
414 nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
415 {
416 CERTCertificate *cc;
417 PRBool ca;
418 SECStatus secrv;
419 unsigned int requiredFlags;
420 unsigned int trustFlags;
421 SECTrustType trustType;
422 CERTCertTrust trust;
423
424 /* This is for NSS 3.3 functions that do not specify a usage */
425 if (usage->anyUsage) {
426 return PR_FALSE; /* XXX is this right? */
427 }
428 cc = (CERTCertificate *)dc->data;
429 ca = usage->nss3lookingForCA;
430 if (!ca) {
431 PRBool trusted;
432 unsigned int failedFlags;
433 secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
434 &failedFlags, &trusted);
435 return secrv == SECSuccess && trusted;
436 }
437 secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
438 &trustType);
439 if (secrv != SECSuccess) {
440 return PR_FALSE;
441 }
442 secrv = CERT_GetCertTrust(cc, &trust);
443 if (secrv != SECSuccess) {
444 return PR_FALSE;
445 }
446 if (trustType == trustTypeNone) {
447 /* normally trustTypeNone usages accept any of the given trust bits
448 * being on as acceptable. */
449 trustFlags = trust.sslFlags | trust.emailFlags |
450 trust.objectSigningFlags;
451 } else {
452 trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
453 }
454 return (trustFlags & requiredFlags) == requiredFlags;
455 }
456
457 static NSSASCII7 *
458 nss3certificate_getEmailAddress(nssDecodedCert *dc)
459 {
460 CERTCertificate *cc = (CERTCertificate *)dc->data;
461 return (cc && cc->emailAddr && cc->emailAddr[0])
462 ? (NSSASCII7 *)cc->emailAddr : NULL;
463 }
464
465 static PRStatus
466 nss3certificate_getDERSerialNumber(nssDecodedCert *dc,
467 NSSDER *serial, NSSArena *arena)
468 {
469 CERTCertificate *cc = (CERTCertificate *)dc->data;
470 SECItem derSerial = { 0 };
471 SECStatus secrv;
472 secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
473 if (secrv == SECSuccess) {
474 (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
475 PORT_Free(derSerial.data);
476 return PR_SUCCESS;
477 }
478 return PR_FAILURE;
479 }
480
481 /* Returns NULL if "encoding" cannot be decoded. */
482 NSS_IMPLEMENT nssDecodedCert *
483 nssDecodedPKIXCertificate_Create (
484 NSSArena *arenaOpt,
485 NSSDER *encoding
486 )
487 {
488 nssDecodedCert *rvDC = NULL;
489 CERTCertificate *cert;
490 SECItem secDER;
491
492 SECITEM_FROM_NSSITEM(&secDER, encoding);
493 cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
494 if (cert) {
495 rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
496 if (rvDC) {
497 rvDC->type = NSSCertificateType_PKIX;
498 rvDC->data = (void *)cert;
499 rvDC->getIdentifier = nss3certificate_getIdentifier;
500 rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
501 rvDC->matchIdentifier = nss3certificate_matchIdentifier;
502 rvDC->isValidIssuer = nss3certificate_isValidIssuer;
503 rvDC->getUsage = nss3certificate_getUsage;
504 rvDC->isValidAtTime = nss3certificate_isValidAtTime;
505 rvDC->isNewerThan = nss3certificate_isNewerThan;
506 rvDC->matchUsage = nss3certificate_matchUsage;
507 rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
508 rvDC->getEmailAddress = nss3certificate_getEmailAddress;
509 rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
510 } else {
511 CERT_DestroyCertificate(cert);
512 }
513 }
514 return rvDC;
515 }
516
517 static nssDecodedCert *
518 create_decoded_pkix_cert_from_nss3cert (
519 NSSArena *arenaOpt,
520 CERTCertificate *cc
521 )
522 {
523 nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
524 if (rvDC) {
525 rvDC->type = NSSCertificateType_PKIX;
526 rvDC->data = (void *)cc;
527 rvDC->getIdentifier = nss3certificate_getIdentifier;
528 rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
529 rvDC->matchIdentifier = nss3certificate_matchIdentifier;
530 rvDC->isValidIssuer = nss3certificate_isValidIssuer;
531 rvDC->getUsage = nss3certificate_getUsage;
532 rvDC->isValidAtTime = nss3certificate_isValidAtTime;
533 rvDC->isNewerThan = nss3certificate_isNewerThan;
534 rvDC->matchUsage = nss3certificate_matchUsage;
535 rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
536 rvDC->getEmailAddress = nss3certificate_getEmailAddress;
537 rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
538 }
539 return rvDC;
540 }
541
542 NSS_IMPLEMENT PRStatus
543 nssDecodedPKIXCertificate_Destroy (
544 nssDecodedCert *dc
545 )
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;
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) return NULL;
599 rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
600 client = get_nss3trust_from_nss4trust(t->clientAuth);
601 if (client & (CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA)) {
602 client &= ~(CERTDB_TRUSTED_CA|CERTDB_NS_TRUSTED_CA);
603 rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
604 }
605 rvTrust->sslFlags |= client;
606 rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
607 rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
608 return rvTrust;
609 }
610
611 CERTCertTrust *
612 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
613 {
614 CERTCertTrust *rvTrust = NULL;
615 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
616 NSSTrust *t;
617 t = nssTrustDomain_FindTrustForCertificate(td, c);
618 if (t) {
619 rvTrust = cert_trust_from_stan_trust(t, cc->arena);
620 if (!rvTrust) {
621 nssTrust_Destroy(t);
622 return NULL;
623 }
624 nssTrust_Destroy(t);
625 } else {
626 rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
627 if (!rvTrust) {
628 return NULL;
629 }
630 memset(rvTrust, 0, sizeof(*rvTrust));
631 }
632 if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
633 rvTrust->sslFlags |= CERTDB_USER;
634 rvTrust->emailFlags |= CERTDB_USER;
635 rvTrust->objectSigningFlags |= CERTDB_USER;
636 }
637 return rvTrust;
638 }
639
640 static nssCryptokiInstance *
641 get_cert_instance(NSSCertificate *c)
642 {
643 nssCryptokiObject *instance, **ci;
644 nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
645 if (!instances) {
646 return NULL;
647 }
648 instance = NULL;
649 for (ci = instances; *ci; ci++) {
650 if (!instance) {
651 instance = nssCryptokiObject_Clone(*ci);
652 } else {
653 /* This only really works for two instances... But 3.4 can't
654 * handle more anyway. The logic is, if there are multiple
655 * instances, prefer the one that is not internal (e.g., on
656 * a hardware device.
657 */
658 if (PK11_IsInternal(instance->token->pk11slot)) {
659 nssCryptokiObject_Destroy(instance);
660 instance = nssCryptokiObject_Clone(*ci);
661 }
662 }
663 }
664 nssCryptokiObjectArray_Destroy(instances);
665 return instance;
666 }
667
668 char *
669 STAN_GetCERTCertificateNameForInstance (
670 PLArenaPool *arenaOpt,
671 NSSCertificate *c,
672 nssCryptokiInstance *instance
673 )
674 {
675 NSSCryptoContext *context = c->object.cryptoContext;
676 PRStatus nssrv;
677 int nicklen, tokenlen, len;
678 NSSUTF8 *tokenName = NULL;
679 NSSUTF8 *stanNick = NULL;
680 char *nickname = NULL;
681 char *nick;
682
683 if (instance) {
684 stanNick = instance->label;
685 } else if (context) {
686 stanNick = c->object.tempName;
687 }
688 if (stanNick) {
689 /* fill other fields needed by NSS3 functions using CERTCertificate */
690 if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
691 PORT_Strchr(stanNick, ':') != NULL) ) {
692 tokenName = nssToken_GetName(instance->token);
693 tokenlen = nssUTF8_Size(tokenName, &nssrv);
694 } else {
695 /* don't use token name for internal slot; 3.3 didn't */
696 tokenlen = 0;
697 }
698 nicklen = nssUTF8_Size(stanNick, &nssrv);
699 len = tokenlen + nicklen;
700 if (arenaOpt) {
701 nickname = PORT_ArenaAlloc(arenaOpt, len);
702 } else {
703 nickname = PORT_Alloc(len);
704 }
705 nick = nickname;
706 if (tokenName) {
707 memcpy(nick, tokenName, tokenlen-1);
708 nick += tokenlen-1;
709 *nick++ = ':';
710 }
711 memcpy(nick, stanNick, nicklen-1);
712 nickname[len-1] = '\0';
713 }
714 return nickname;
715 }
716
717 char *
718 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
719 {
720 char * result;
721 nssCryptokiInstance *instance = get_cert_instance(c);
722 /* It's OK to call this function, even if instance is NULL */
723 result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
724 if (instance)
725 nssCryptokiObject_Destroy(instance);
726 return result;
727 }
728
729 static void
730 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced )
731 {
732 CERTCertTrust* trust = NULL;
733 NSSTrust *nssTrust;
734 NSSCryptoContext *context = c->object.cryptoContext;
735 nssCryptokiInstance *instance;
736 NSSUTF8 *stanNick = NULL;
737
738 /* We are holding the base class object's lock on entry of this function
739 * This lock protects writes to fields of the CERTCertificate .
740 * It is also needed by some functions to compute values such as trust.
741 */
742 instance = get_cert_instance(c);
743
744 if (instance) {
745 stanNick = instance->label;
746 } else if (context) {
747 stanNick = c->object.tempName;
748 }
749 /* fill other fields needed by NSS3 functions using CERTCertificate */
750 if ((!cc->nickname && stanNick) || forced) {
751 PRStatus nssrv;
752 int nicklen, tokenlen, len;
753 NSSUTF8 *tokenName = NULL;
754 char *nick;
755 if (instance &&
756 (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
757 (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
758 tokenName = nssToken_GetName(instance->token);
759 tokenlen = nssUTF8_Size(tokenName, &nssrv);
760 } else {
761 /* don't use token name for internal slot; 3.3 didn't */
762 tokenlen = 0;
763 }
764 if (stanNick) {
765 nicklen = nssUTF8_Size(stanNick, &nssrv);
766 len = tokenlen + nicklen;
767 nick = PORT_ArenaAlloc(cc->arena, len);
768 if (tokenName) {
769 memcpy(nick, tokenName, tokenlen-1);
770 nick[tokenlen-1] = ':';
771 memcpy(nick+tokenlen, stanNick, nicklen-1);
772 } else {
773 memcpy(nick, stanNick, nicklen-1);
774 }
775 nick[len-1] = '\0';
776 cc->nickname = nick;
777 } else {
778 cc->nickname = NULL;
779 }
780 }
781 if (context) {
782 /* trust */
783 nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
784 if (!nssTrust) {
785 /* chicken and egg issue:
786 *
787 * c->issuer and c->serial are empty at this point, but
788 * nssTrustDomain_FindTrustForCertificate use them to look up
789 * up the trust object, so we point them to cc->derIssuer and
790 * cc->serialNumber.
791 *
792 * Our caller will fill these in with proper arena copies when we
793 * return. */
794 c->issuer.data = cc->derIssuer.data;
795 c->issuer.size = cc->derIssuer.len;
796 c->serial.data = cc->serialNumber.data;
797 c->serial.size = cc->serialNumber.len;
798 nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
799 }
800 if (nssTrust) {
801 trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
802 if (trust) {
803 /* we should destroy cc->trust before replacing it, but it's
804 allocated in cc->arena, so memory growth will occur on each
805 refresh */
806 CERT_LockCertTrust(cc);
807 cc->trust = trust;
808 CERT_UnlockCertTrust(cc);
809 }
810 nssTrust_Destroy(nssTrust);
811 }
812 } else if (instance) {
813 /* slot */
814 if (cc->slot != instance->token->pk11slot) {
815 if (cc->slot) {
816 PK11_FreeSlot(cc->slot);
817 }
818 cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
819 }
820 cc->ownSlot = PR_TRUE;
821 /* pkcs11ID */
822 cc->pkcs11ID = instance->handle;
823 /* trust */
824 trust = nssTrust_GetCERTCertTrustForCert(c, cc);
825 if (trust) {
826 /* we should destroy cc->trust before replacing it, but it's
827 allocated in cc->arena, so memory growth will occur on each
828 refresh */
829 CERT_LockCertTrust(cc);
830 cc->trust = trust;
831 CERT_UnlockCertTrust(cc);
832 }
833 }
834 if (instance) {
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 /* make sure object does not go away until we finish */
863 nssPKIObject_AddRef(&c->object);
864 nssPKIObject_Lock(&c->object);
865
866 dc = c->decoding;
867 if (!dc) {
868 dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
869 if (!dc) {
870 goto loser;
871 }
872 cc = (CERTCertificate *)dc->data;
873 PORT_Assert(cc); /* software error */
874 if (!cc) {
875 nssDecodedPKIXCertificate_Destroy(dc);
876 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
877 goto loser;
878 }
879 PORT_Assert(!c->decoding);
880 if (!c->decoding) {
881 c->decoding = dc;
882 } else {
883 /* this should never happen. Fail. */
884 nssDecodedPKIXCertificate_Destroy(dc);
885 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
886 goto loser;
887 }
888 }
889 cc = (CERTCertificate *)dc->data;
890 PORT_Assert(cc);
891 if (!cc) {
892 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
893 goto loser;
894 }
895 if (!cc->nssCertificate || forceUpdate) {
896 fill_CERTCertificateFields(c, cc, forceUpdate);
897 } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess &&
898 !c->object.cryptoContext) {
899 /* if it's a perm cert, it might have been stored before the
900 * trust, so look for the trust again. But a temp cert can be
901 * ignored.
902 */
903 CERTCertTrust* trust = NULL;
904 trust = nssTrust_GetCERTCertTrustForCert(c, cc);
905
906 CERT_LockCertTrust(cc);
907 cc->trust = trust;
908 CERT_UnlockCertTrust(cc);
909 }
910
911 loser:
912 nssPKIObject_Unlock(&c->object);
913 nssPKIObject_Destroy(&c->object);
914 return cc;
915 }
916
917 NSS_IMPLEMENT CERTCertificate *
918 STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
919 {
920 if (c->decoding) {
921 return stan_GetCERTCertificate(c, PR_TRUE);
922 }
923 return NULL;
924 }
925
926 NSS_IMPLEMENT CERTCertificate *
927 STAN_GetCERTCertificate(NSSCertificate *c)
928 {
929 return stan_GetCERTCertificate(c, PR_FALSE);
930 }
931 /*
932 * many callers of STAN_GetCERTCertificate() intend that
933 * the CERTCertificate returned inherits the reference to the
934 * NSSCertificate. For these callers it's convenient to have
935 * this function 'own' the reference and either return a valid
936 * CERTCertificate structure which inherits the reference or
937 * destroy the reference to NSSCertificate and returns NULL.
938 */
939 NSS_IMPLEMENT CERTCertificate *
940 STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
941 {
942 CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
943 if (!nss3cert) {
944 nssCertificate_Destroy(c);
945 }
946 return nss3cert;
947 }
948
949 static nssTrustLevel
950 get_stan_trust(unsigned int t, PRBool isClientAuth)
951 {
952 if (isClientAuth) {
953 if (t & CERTDB_TRUSTED_CLIENT_CA) {
954 return nssTrustLevel_TrustedDelegator;
955 }
956 } else {
957 if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
958 return nssTrustLevel_TrustedDelegator;
959 }
960 }
961 if (t & CERTDB_TRUSTED) {
962 return nssTrustLevel_Trusted;
963 }
964 if (t & CERTDB_TERMINAL_RECORD) {
965 return nssTrustLevel_NotTrusted;
966 }
967 if (t & CERTDB_VALID_CA) {
968 return nssTrustLevel_ValidDelegator;
969 }
970 return nssTrustLevel_MustVerify;
971 }
972
973 NSS_EXTERN NSSCertificate *
974 STAN_GetNSSCertificate(CERTCertificate *cc)
975 {
976 NSSCertificate *c;
977 nssCryptokiInstance *instance;
978 nssPKIObject *pkiob;
979 NSSArena *arena;
980 c = cc->nssCertificate;
981 if (c) {
982 return c;
983 }
984 /* i don't think this should happen. but if it can, need to create
985 * NSSCertificate from CERTCertificate values here. */
986 /* Yup, it can happen. */
987 arena = NSSArena_Create();
988 if (!arena) {
989 return NULL;
990 }
991 c = nss_ZNEW(arena, NSSCertificate);
992 if (!c) {
993 nssArena_Destroy(arena);
994 return NULL;
995 }
996 NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
997 c->type = NSSCertificateType_PKIX;
998 pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
999 if (!pkiob) {
1000 nssArena_Destroy(arena);
1001 return NULL;
1002 }
1003 c->object = *pkiob;
1004 nssItem_Create(arena,
1005 &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
1006 nssItem_Create(arena,
1007 &c->subject, cc->derSubject.len, cc->derSubject.data);
1008 if (PR_TRUE) {
1009 /* CERTCertificate stores serial numbers decoded. I need the DER
1010 * here. sigh.
1011 */
1012 SECItem derSerial;
1013 SECStatus secrv;
1014 secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
1015 if (secrv == SECFailure) {
1016 nssArena_Destroy(arena);
1017 return NULL;
1018 }
1019 nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
1020 PORT_Free(derSerial.data);
1021 }
1022 if (cc->emailAddr && cc->emailAddr[0]) {
1023 c->email = nssUTF8_Create(arena,
1024 nssStringType_PrintableString,
1025 (NSSUTF8 *)cc->emailAddr,
1026 PORT_Strlen(cc->emailAddr));
1027 }
1028 if (cc->slot) {
1029 instance = nss_ZNEW(arena, nssCryptokiInstance);
1030 if (!instance) {
1031 nssArena_Destroy(arena);
1032 return NULL;
1033 }
1034 instance->token = nssToken_AddRef(PK11Slot_GetNSSToken(cc->slot));
1035 instance->handle = cc->pkcs11ID;
1036 instance->isTokenObject = PR_TRUE;
1037 if (cc->nickname) {
1038 instance->label = nssUTF8_Create(arena,
1039 nssStringType_UTF8String,
1040 (NSSUTF8 *)cc->nickname,
1041 PORT_Strlen(cc->nickname));
1042 }
1043 nssPKIObject_AddInstance(&c->object, instance);
1044 }
1045 c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
1046 cc->nssCertificate = c;
1047 return c;
1048 }
1049
1050 static NSSToken*
1051 stan_GetTrustToken (
1052 NSSCertificate *c
1053 )
1054 {
1055 NSSToken *ttok = NULL;
1056 NSSToken *rtok = NULL;
1057 NSSToken *tok = NULL;
1058 nssCryptokiObject **ip;
1059 nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
1060 if (!instances) {
1061 return PR_FALSE;
1062 }
1063 for (ip = instances; *ip; ip++) {
1064 nssCryptokiObject *instance = *ip;
1065 nssCryptokiObject *to =
1066 nssToken_FindTrustForCertificate(instance->token, NULL,
1067 &c->encoding, &c->issuer, &c->serial,
1068 nssTokenSearchType_TokenOnly);
1069 NSSToken *ctok = instance->token;
1070 PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
1071
1072 if (to) {
1073 nssCryptokiObject_Destroy(to);
1074 ttok = ctok;
1075 if (!ro) {
1076 break;
1077 }
1078 } else {
1079 if (!rtok && ro) {
1080 rtok = ctok;
1081 }
1082 if (!tok && !ro) {
1083 tok = ctok;
1084 }
1085 }
1086 }
1087 nssCryptokiObjectArray_Destroy(instances);
1088 return ttok ? ttok : (tok ? tok : rtok);
1089 }
1090
1091 NSS_EXTERN PRStatus
1092 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
1093 {
1094 PRStatus nssrv;
1095 NSSCertificate *c = STAN_GetNSSCertificate(cc);
1096 NSSToken *tok;
1097 NSSTrustDomain *td;
1098 NSSTrust *nssTrust;
1099 NSSArena *arena;
1100 CERTCertTrust *oldTrust;
1101 CERTCertTrust *newTrust;
1102 nssListIterator *tokens;
1103 PRBool moving_object;
1104 nssCryptokiObject *newInstance;
1105 nssPKIObject *pkiob;
1106
1107 if (c == NULL) {
1108 return PR_FAILURE;
1109 }
1110 oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
1111 if (oldTrust) {
1112 if (memcmp(oldTrust, trust, sizeof (CERTCertTrust)) == 0) {
1113 /* ... and the new trust is no different, done) */
1114 return PR_SUCCESS;
1115 } else {
1116 /* take over memory already allocated in cc's arena */
1117 newTrust = oldTrust;
1118 }
1119 } else {
1120 newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
1121 }
1122 memcpy(newTrust, trust, sizeof(CERTCertTrust));
1123 CERT_LockCertTrust(cc);
1124 cc->trust = newTrust;
1125 CERT_UnlockCertTrust(cc);
1126 /* Set the NSSCerticate's trust */
1127 arena = nssArena_Create();
1128 if (!arena) return PR_FAILURE;
1129 nssTrust = nss_ZNEW(arena, NSSTrust);
1130 if (!nssTrust) {
1131 nssArena_Destroy(arena);
1132 return PR_FAILURE;
1133 }
1134 pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
1135 if (!pkiob) {
1136 nssArena_Destroy(arena);
1137 return PR_FAILURE;
1138 }
1139 nssTrust->object = *pkiob;
1140 nssTrust->certificate = c;
1141 nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
1142 nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
1143 nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
1144 nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
1145 nssTrust->stepUpApproved =
1146 (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
1147 if (c->object.cryptoContext != NULL) {
1148 /* The cert is in a context, set the trust there */
1149 NSSCryptoContext *cc = c->object.cryptoContext;
1150 nssrv = nssCryptoContext_ImportTrust(cc, nssTrust);
1151 if (nssrv != PR_SUCCESS) {
1152 goto done;
1153 }
1154 if (c->object.numInstances == 0) {
1155 /* The context is the only instance, finished */
1156 goto done;
1157 }
1158 }
1159 td = STAN_GetDefaultTrustDomain();
1160 tok = stan_GetTrustToken(c);
1161 moving_object = PR_FALSE;
1162 if (tok && PK11_IsReadOnly(tok->pk11slot)) {
1163 NSSRWLock_LockRead(td->tokensLock);
1164 tokens = nssList_CreateIterator(td->tokenList);
1165 if (!tokens) {
1166 nssrv = PR_FAILURE;
1167 NSSRWLock_UnlockRead(td->tokensLock);
1168 goto done;
1169 }
1170 for (tok = (NSSToken *)nssListIterator_Start(tokens);
1171 tok != (NSSToken *)NULL;
1172 tok = (NSSToken *)nssListIterator_Next(tokens))
1173 {
1174 if (!PK11_IsReadOnly(tok->pk11slot)) break;
1175 }
1176 nssListIterator_Finish(tokens);
1177 nssListIterator_Destroy(tokens);
1178 NSSRWLock_UnlockRead(td->tokensLock);
1179 moving_object = PR_TRUE;
1180 }
1181 if (tok) {
1182 if (moving_object) {
1183 /* this is kind of hacky. the softoken needs the cert
1184 * object in order to store trust. forcing it to be perm
1185 */
1186 NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1187 NSSASCII7 *email = NULL;
1188
1189 if (PK11_IsInternal(tok->pk11slot)) {
1190 email = c->email;
1191 }
1192 newInstance = nssToken_ImportCertificate(tok, NULL,
1193 NSSCertificateType_PKIX,
1194 &c->id,
1195 nickname,
1196 &c->encoding,
1197 &c->issuer,
1198 &c->subject,
1199 &c->serial,
1200 email,
1201 PR_TRUE);
1202 nss_ZFreeIf(nickname);
1203 nickname = NULL;
1204 if (!newInstance) {
1205 nssrv = PR_FAILURE;
1206 goto done;
1207 }
1208 nssPKIObject_AddInstance(&c->object, newInstance);
1209 }
1210 newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1211 &c->issuer, &c->serial,
1212 nssTrust->serverAuth,
1213 nssTrust->clientAuth,
1214 nssTrust->codeSigning,
1215 nssTrust->emailProtection,
1216 nssTrust->stepUpApproved, PR_TRUE);
1217 /* If the selected token can't handle trust, dump the trust on
1218 * the internal token */
1219 if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
1220 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
1221 NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
1222 NSSASCII7 *email = c->email;
1223 tok = PK11Slot_GetNSSToken(slot);
1224 PK11_FreeSlot(slot);
1225
1226 newInstance = nssToken_ImportCertificate(tok, NULL,
1227 NSSCertificateType_PKIX,
1228 &c->id,
1229 nickname,
1230 &c->encoding,
1231 &c->issuer,
1232 &c->subject,
1233 &c->serial,
1234 email,
1235 PR_TRUE);
1236 nss_ZFreeIf(nickname);
1237 nickname = NULL;
1238 if (!newInstance) {
1239 nssrv = PR_FAILURE;
1240 goto done;
1241 }
1242 nssPKIObject_AddInstance(&c->object, newInstance);
1243 newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
1244 &c->issuer, &c->serial,
1245 nssTrust->serverAuth,
1246 nssTrust->clientAuth,
1247 nssTrust->codeSigning,
1248 nssTrust->emailProtection,
1249 nssTrust->stepUpApproved, PR_TRUE);
1250 }
1251 if (newInstance) {
1252 nssCryptokiObject_Destroy(newInstance);
1253 nssrv = PR_SUCCESS;
1254 } else {
1255 nssrv = PR_FAILURE;
1256 }
1257 } else {
1258 nssrv = PR_FAILURE;
1259 }
1260 done:
1261 (void)nssTrust_Destroy(nssTrust);
1262 return nssrv;
1263 }
1264
1265 /*
1266 ** Delete trust objects matching the given slot.
1267 ** Returns error if a device fails to delete.
1268 **
1269 ** This function has the side effect of moving the
1270 ** surviving entries to the front of the object list
1271 ** and nullifying the rest.
1272 */
1273 static PRStatus
1274 DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
1275 {
1276 int numNotDestroyed = 0; /* the ones skipped plus the failures */
1277 int failureCount = 0; /* actual deletion failures by devices */
1278 unsigned int index;
1279
1280 nssPKIObject_AddRef(tObject);
1281 nssPKIObject_Lock(tObject);
1282 /* Keep going even if a module fails to delete. */
1283 for (index = 0; index < tObject->numInstances; index++) {
1284 nssCryptokiObject *instance = tObject->instances[index];
1285 if (!instance) {
1286 continue;
1287 }
1288
1289 /* ReadOnly and not matched treated the same */
1290 if (PK11_IsReadOnly(instance->token->pk11slot) ||
1291 pk11slot != instance->token->pk11slot) {
1292 tObject->instances[numNotDestroyed++] = instance;
1293 continue;
1294 }
1295
1296 /* Here we have found a matching one */
1297 tObject->instances[index] = NULL;
1298 if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
1299 nssCryptokiObject_Destroy(instance);
1300 } else {
1301 tObject->instances[numNotDestroyed++] = instance;
1302 failureCount++;
1303 }
1304
1305 }
1306 if (numNotDestroyed == 0) {
1307 nss_ZFreeIf(tObject->instances);
1308 tObject->numInstances = 0;
1309 } else {
1310 tObject->numInstances = numNotDestroyed;
1311 }
1312
1313 nssPKIObject_Unlock(tObject);
1314 nssPKIObject_Destroy(tObject);
1315
1316 return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
1317 }
1318
1319 /*
1320 ** Delete trust objects matching the slot of the given certificate.
1321 ** Returns an error if any device fails to delete.
1322 */
1323 NSS_EXTERN PRStatus
1324 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
1325 {
1326 PRStatus nssrv = PR_SUCCESS;
1327
1328 NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
1329 NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
1330 /* caller made sure nssTrust isn't NULL */
1331 nssPKIObject *tobject = &nssTrust->object;
1332 nssPKIObject *cobject = &c->object;
1333 unsigned int i;
1334
1335 /* Iterate through the cert and trust object instances looking for
1336 * those with matching pk11 slots to delete. Even if some device
1337 * can't delete we keep going. Keeping a status variable for the
1338 * loop so that once it's failed the other gets set.
1339 */
1340 NSSRWLock_LockRead(td->tokensLock);
1341 nssPKIObject_AddRef(cobject);
1342 nssPKIObject_Lock(cobject);
1343 for (i = 0; i < cobject->numInstances; i++) {
1344 nssCryptokiObject *cInstance = cobject->instances[i];
1345 if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
1346 PRStatus status;
1347 if (!tobject->numInstances || !tobject->instances) continue;
1348 status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tob ject);
1349 if (status == PR_FAILURE) {
1350 /* set the outer one but keep going */
1351 nssrv = PR_FAILURE;
1352 }
1353 }
1354 }
1355 nssPKIObject_Unlock(cobject);
1356 nssPKIObject_Destroy(cobject);
1357 NSSRWLock_UnlockRead(td->tokensLock);
1358 return nssrv;
1359 }
1360
1361 /* CERT_TraversePermCertsForSubject */
1362 NSS_IMPLEMENT PRStatus
1363 nssTrustDomain_TraverseCertificatesBySubject (
1364 NSSTrustDomain *td,
1365 NSSDER *subject,
1366 PRStatus (*callback)(NSSCertificate *c, void *arg),
1367 void *arg
1368 )
1369 {
1370 PRStatus nssrv = PR_SUCCESS;
1371 NSSArena *tmpArena;
1372 NSSCertificate **subjectCerts;
1373 NSSCertificate *c;
1374 PRIntn i;
1375 tmpArena = NSSArena_Create();
1376 if (!tmpArena) {
1377 return PR_FAILURE;
1378 }
1379 subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
1380 0, tmpArena);
1381 if (subjectCerts) {
1382 for (i=0, c = subjectCerts[i]; c; i++) {
1383 nssrv = callback(c, arg);
1384 if (nssrv != PR_SUCCESS) break;
1385 }
1386 }
1387 nssArena_Destroy(tmpArena);
1388 return nssrv;
1389 }
1390
1391 /* CERT_TraversePermCertsForNickname */
1392 NSS_IMPLEMENT PRStatus
1393 nssTrustDomain_TraverseCertificatesByNickname (
1394 NSSTrustDomain *td,
1395 NSSUTF8 *nickname,
1396 PRStatus (*callback)(NSSCertificate *c, void *arg),
1397 void *arg
1398 )
1399 {
1400 PRStatus nssrv = PR_SUCCESS;
1401 NSSArena *tmpArena;
1402 NSSCertificate **nickCerts;
1403 NSSCertificate *c;
1404 PRIntn i;
1405 tmpArena = NSSArena_Create();
1406 if (!tmpArena) {
1407 return PR_FAILURE;
1408 }
1409 nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
1410 0, tmpArena);
1411 if (nickCerts) {
1412 for (i=0, c = nickCerts[i]; c; i++) {
1413 nssrv = callback(c, arg);
1414 if (nssrv != PR_SUCCESS) break;
1415 }
1416 }
1417 nssArena_Destroy(tmpArena);
1418 return nssrv;
1419 }
1420
1421 static void cert_dump_iter(const void *k, void *v, void *a)
1422 {
1423 NSSCertificate *c = (NSSCertificate *)k;
1424 CERTCertificate *cert = STAN_GetCERTCertificate(c);
1425 printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
1426 }
1427
1428 void
1429 nss_DumpCertificateCacheInfo()
1430 {
1431 NSSTrustDomain *td;
1432 NSSCryptoContext *cc;
1433 td = STAN_GetDefaultTrustDomain();
1434 cc = STAN_GetDefaultCryptoContext();
1435 printf("\n\nCertificates in the cache:\n");
1436 nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
1437 printf("\n\nCertificates in the temporary store:\n");
1438 if (cc->certStore) {
1439 nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
1440 }
1441 }
1442
OLDNEW
« no previous file with comments | « nss/lib/pki/pki3hack.h ('k') | nss/lib/pki/pkibase.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698