comparison nss/lib/pki/pki3hack.c @ 0:1e5118fa0cb1

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