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