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