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

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

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/pki/symmkey.c ('k') | nss/lib/pki/trustdomain.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #ifndef PKIM_H
6 #include "pkim.h"
7 #endif /* PKIM_H */
8
9 #ifndef PKIT_H
10 #include "pkit.h"
11 #endif /* PKIT_H */
12
13 #ifndef NSSPKI_H
14 #include "nsspki.h"
15 #endif /* NSSPKI_H */
16
17 #ifndef PKI_H
18 #include "pki.h"
19 #endif /* PKI_H */
20
21 #ifndef NSSBASE_H
22 #include "nssbase.h"
23 #endif /* NSSBASE_H */
24
25 #ifndef BASE_H
26 #include "base.h"
27 #endif /* BASE_H */
28
29 #include "cert.h"
30 #include "dev.h"
31 #include "pki3hack.h"
32
33 #ifdef DEBUG_CACHE
34 static PRLogModuleInfo *s_log = NULL;
35 #endif
36
37 #ifdef DEBUG_CACHE
38 static void log_item_dump(const char *msg, NSSItem *it)
39 {
40 char buf[33];
41 int i, j;
42 for (i=0; i<10 && i<it->size; i++) {
43 sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[i]);
44 }
45 if (it->size>10) {
46 sprintf(&buf[2*i], "..");
47 i += 1;
48 for (j=it->size-1; i<=16 && j>10; i++, j--) {
49 sprintf(&buf[2*i], "%02X", ((PRUint8 *)it->data)[j]);
50 }
51 }
52 PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg, buf));
53 }
54 #endif
55
56 #ifdef DEBUG_CACHE
57 static void log_cert_ref(const char *msg, NSSCertificate *c)
58 {
59 PR_LOG(s_log, PR_LOG_DEBUG, ("%s: %s", msg,
60 (c->nickname) ? c->nickname : c->email));
61 log_item_dump("\tserial", &c->serial);
62 log_item_dump("\tsubject", &c->subject);
63 }
64 #endif
65
66 /* Certificate cache routines */
67
68 /* XXX
69 * Locking is not handled well at all. A single, global lock with sub-locks
70 * in the collection types. Cleanup needed.
71 */
72
73 /* should it live in its own arena? */
74 struct nssTDCertificateCacheStr
75 {
76 PZLock *lock;
77 NSSArena *arena;
78 nssHash *issuerAndSN;
79 nssHash *subject;
80 nssHash *nickname;
81 nssHash *email;
82 };
83
84 struct cache_entry_str
85 {
86 union {
87 NSSCertificate *cert;
88 nssList *list;
89 void *value;
90 } entry;
91 PRUint32 hits;
92 PRTime lastHit;
93 NSSArena *arena;
94 NSSUTF8 *nickname;
95 };
96
97 typedef struct cache_entry_str cache_entry;
98
99 static cache_entry *
100 new_cache_entry(NSSArena *arena, void *value, PRBool ownArena)
101 {
102 cache_entry *ce = nss_ZNEW(arena, cache_entry);
103 if (ce) {
104 ce->entry.value = value;
105 ce->hits = 1;
106 ce->lastHit = PR_Now();
107 if (ownArena) {
108 ce->arena = arena;
109 }
110 ce->nickname = NULL;
111 }
112 return ce;
113 }
114
115 /* this should not be exposed in a header, but is here to keep the above
116 * types/functions static
117 */
118 NSS_IMPLEMENT PRStatus
119 nssTrustDomain_InitializeCache (
120 NSSTrustDomain *td,
121 PRUint32 cacheSize
122 )
123 {
124 NSSArena *arena;
125 nssTDCertificateCache *cache = td->cache;
126 #ifdef DEBUG_CACHE
127 s_log = PR_NewLogModule("nss_cache");
128 PR_ASSERT(s_log);
129 #endif
130 PR_ASSERT(!cache);
131 arena = nssArena_Create();
132 if (!arena) {
133 return PR_FAILURE;
134 }
135 cache = nss_ZNEW(arena, nssTDCertificateCache);
136 if (!cache) {
137 nssArena_Destroy(arena);
138 return PR_FAILURE;
139 }
140 cache->lock = PZ_NewLock(nssILockCache);
141 if (!cache->lock) {
142 nssArena_Destroy(arena);
143 return PR_FAILURE;
144 }
145 /* Create the issuer and serial DER --> certificate hash */
146 cache->issuerAndSN = nssHash_CreateCertificate(arena, cacheSize);
147 if (!cache->issuerAndSN) {
148 goto loser;
149 }
150 /* Create the subject DER --> subject list hash */
151 cache->subject = nssHash_CreateItem(arena, cacheSize);
152 if (!cache->subject) {
153 goto loser;
154 }
155 /* Create the nickname --> subject list hash */
156 cache->nickname = nssHash_CreateString(arena, cacheSize);
157 if (!cache->nickname) {
158 goto loser;
159 }
160 /* Create the email --> list of subject lists hash */
161 cache->email = nssHash_CreateString(arena, cacheSize);
162 if (!cache->email) {
163 goto loser;
164 }
165 cache->arena = arena;
166 td->cache = cache;
167 #ifdef DEBUG_CACHE
168 PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialized."));
169 #endif
170 return PR_SUCCESS;
171 loser:
172 PZ_DestroyLock(cache->lock);
173 nssArena_Destroy(arena);
174 td->cache = NULL;
175 #ifdef DEBUG_CACHE
176 PR_LOG(s_log, PR_LOG_DEBUG, ("Cache initialization failed."));
177 #endif
178 return PR_FAILURE;
179 }
180
181 /* The entries of the hashtable are currently dependent on the certificate(s)
182 * that produced them. That is, the entries will be freed when the cert is
183 * released from the cache. If there are certs in the cache at any time,
184 * including shutdown, the hash table entries will hold memory. In order for
185 * clean shutdown, it is necessary for there to be no certs in the cache.
186 */
187
188 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
189 extern const NSSError NSS_ERROR_BUSY;
190
191 NSS_IMPLEMENT PRStatus
192 nssTrustDomain_DestroyCache (
193 NSSTrustDomain *td
194 )
195 {
196 if (!td->cache) {
197 nss_SetError(NSS_ERROR_INTERNAL_ERROR);
198 return PR_FAILURE;
199 }
200 if (nssHash_Count(td->cache->issuerAndSN) > 0) {
201 nss_SetError(NSS_ERROR_BUSY);
202 return PR_FAILURE;
203 }
204 PZ_DestroyLock(td->cache->lock);
205 nssHash_Destroy(td->cache->issuerAndSN);
206 nssHash_Destroy(td->cache->subject);
207 nssHash_Destroy(td->cache->nickname);
208 nssHash_Destroy(td->cache->email);
209 nssArena_Destroy(td->cache->arena);
210 td->cache = NULL;
211 #ifdef DEBUG_CACHE
212 PR_LOG(s_log, PR_LOG_DEBUG, ("Cache destroyed."));
213 #endif
214 return PR_SUCCESS;
215 }
216
217 static PRStatus
218 remove_issuer_and_serial_entry (
219 nssTDCertificateCache *cache,
220 NSSCertificate *cert
221 )
222 {
223 /* Remove the cert from the issuer/serial hash */
224 nssHash_Remove(cache->issuerAndSN, cert);
225 #ifdef DEBUG_CACHE
226 log_cert_ref("removed issuer/sn", cert);
227 #endif
228 return PR_SUCCESS;
229 }
230
231 static PRStatus
232 remove_subject_entry (
233 nssTDCertificateCache *cache,
234 NSSCertificate *cert,
235 nssList **subjectList,
236 NSSUTF8 **nickname,
237 NSSArena **arena
238 )
239 {
240 PRStatus nssrv;
241 cache_entry *ce;
242 *subjectList = NULL;
243 *arena = NULL;
244 /* Get the subject list for the cert's subject */
245 ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject);
246 if (ce) {
247 /* Remove the cert from the subject hash */
248 nssList_Remove(ce->entry.list, cert);
249 *subjectList = ce->entry.list;
250 *nickname = ce->nickname;
251 *arena = ce->arena;
252 nssrv = PR_SUCCESS;
253 #ifdef DEBUG_CACHE
254 log_cert_ref("removed cert", cert);
255 log_item_dump("from subject list", &cert->subject);
256 #endif
257 } else {
258 nssrv = PR_FAILURE;
259 }
260 return nssrv;
261 }
262
263 static PRStatus
264 remove_nickname_entry (
265 nssTDCertificateCache *cache,
266 NSSUTF8 *nickname,
267 nssList *subjectList
268 )
269 {
270 PRStatus nssrv;
271 if (nickname) {
272 nssHash_Remove(cache->nickname, nickname);
273 nssrv = PR_SUCCESS;
274 #ifdef DEBUG_CACHE
275 PR_LOG(s_log, PR_LOG_DEBUG, ("removed nickname %s", nickname));
276 #endif
277 } else {
278 nssrv = PR_FAILURE;
279 }
280 return nssrv;
281 }
282
283 static PRStatus
284 remove_email_entry (
285 nssTDCertificateCache *cache,
286 NSSCertificate *cert,
287 nssList *subjectList
288 )
289 {
290 PRStatus nssrv = PR_FAILURE;
291 cache_entry *ce;
292 /* Find the subject list in the email hash */
293 if (cert->email) {
294 ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email);
295 if (ce) {
296 nssList *subjects = ce->entry.list;
297 /* Remove the subject list from the email hash */
298 nssList_Remove(subjects, subjectList);
299 #ifdef DEBUG_CACHE
300 log_item_dump("removed subject list", &cert->subject);
301 PR_LOG(s_log, PR_LOG_DEBUG, ("for email %s", cert->email));
302 #endif
303 if (nssList_Count(subjects) == 0) {
304 /* No more subject lists for email, delete list and
305 * remove hash entry
306 */
307 (void)nssList_Destroy(subjects);
308 nssHash_Remove(cache->email, cert->email);
309 /* there are no entries left for this address, free space
310 * used for email entries
311 */
312 nssArena_Destroy(ce->arena);
313 #ifdef DEBUG_CACHE
314 PR_LOG(s_log, PR_LOG_DEBUG, ("removed email %s", cert->email));
315 #endif
316 }
317 nssrv = PR_SUCCESS;
318 }
319 }
320 return nssrv;
321 }
322
323 NSS_IMPLEMENT void
324 nssTrustDomain_RemoveCertFromCacheLOCKED (
325 NSSTrustDomain *td,
326 NSSCertificate *cert
327 )
328 {
329 nssList *subjectList;
330 cache_entry *ce;
331 NSSArena *arena;
332 NSSUTF8 *nickname = NULL;
333
334 #ifdef DEBUG_CACHE
335 log_cert_ref("attempt to remove cert", cert);
336 #endif
337 ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert);
338 if (!ce || ce->entry.cert != cert) {
339 /* If it's not in the cache, or a different cert is (this is really
340 * for safety reasons, though it shouldn't happen), do nothing
341 */
342 #ifdef DEBUG_CACHE
343 PR_LOG(s_log, PR_LOG_DEBUG, ("but it wasn't in the cache"));
344 #endif
345 return;
346 }
347 (void)remove_issuer_and_serial_entry(td->cache, cert);
348 (void)remove_subject_entry(td->cache, cert, &subjectList,
349 &nickname, &arena);
350 if (nssList_Count(subjectList) == 0) {
351 (void)remove_nickname_entry(td->cache, nickname, subjectList);
352 (void)remove_email_entry(td->cache, cert, subjectList);
353 (void)nssList_Destroy(subjectList);
354 nssHash_Remove(td->cache->subject, &cert->subject);
355 /* there are no entries left for this subject, free the space used
356 * for both the nickname and subject entries
357 */
358 if (arena) {
359 nssArena_Destroy(arena);
360 }
361 }
362 }
363
364 NSS_IMPLEMENT void
365 nssTrustDomain_LockCertCache (
366 NSSTrustDomain *td
367 )
368 {
369 PZ_Lock(td->cache->lock);
370 }
371
372 NSS_IMPLEMENT void
373 nssTrustDomain_UnlockCertCache (
374 NSSTrustDomain *td
375 )
376 {
377 PZ_Unlock(td->cache->lock);
378 }
379
380 struct token_cert_dtor {
381 NSSToken *token;
382 nssTDCertificateCache *cache;
383 NSSCertificate **certs;
384 PRUint32 numCerts, arrSize;
385 };
386
387 static void
388 remove_token_certs(const void *k, void *v, void *a)
389 {
390 NSSCertificate *c = (NSSCertificate *)k;
391 nssPKIObject *object = &c->object;
392 struct token_cert_dtor *dtor = a;
393 PRUint32 i;
394 nssPKIObject_AddRef(object);
395 nssPKIObject_Lock(object);
396 for (i=0; i<object->numInstances; i++) {
397 if (object->instances[i]->token == dtor->token) {
398 nssCryptokiObject_Destroy(object->instances[i]);
399 object->instances[i] = object->instances[object->numInstances-1];
400 object->instances[object->numInstances-1] = NULL;
401 object->numInstances--;
402 dtor->certs[dtor->numCerts++] = c;
403 if (dtor->numCerts == dtor->arrSize) {
404 dtor->arrSize *= 2;
405 dtor->certs = nss_ZREALLOCARRAY(dtor->certs,
406 NSSCertificate *,
407 dtor->arrSize);
408 }
409 break;
410 }
411 }
412 nssPKIObject_Unlock(object);
413 nssPKIObject_Destroy(object);
414 return;
415 }
416
417 /*
418 * Remove all certs for the given token from the cache. This is
419 * needed if the token is removed.
420 */
421 NSS_IMPLEMENT PRStatus
422 nssTrustDomain_RemoveTokenCertsFromCache (
423 NSSTrustDomain *td,
424 NSSToken *token
425 )
426 {
427 NSSCertificate **certs;
428 PRUint32 i, arrSize = 10;
429 struct token_cert_dtor dtor;
430 certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize);
431 if (!certs) {
432 return PR_FAILURE;
433 }
434 dtor.cache = td->cache;
435 dtor.token = token;
436 dtor.certs = certs;
437 dtor.numCerts = 0;
438 dtor.arrSize = arrSize;
439 PZ_Lock(td->cache->lock);
440 nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, &dtor);
441 for (i=0; i<dtor.numCerts; i++) {
442 if (dtor.certs[i]->object.numInstances == 0) {
443 nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]);
444 dtor.certs[i] = NULL; /* skip this cert in the second for loop */
445 } else {
446 /* make sure it doesn't disappear on us before we finish */
447 nssCertificate_AddRef(dtor.certs[i]);
448 }
449 }
450 PZ_Unlock(td->cache->lock);
451 for (i=0; i<dtor.numCerts; i++) {
452 if (dtor.certs[i]) {
453 STAN_ForceCERTCertificateUpdate(dtor.certs[i]);
454 nssCertificate_Destroy(dtor.certs[i]);
455 }
456 }
457 nss_ZFreeIf(dtor.certs);
458 return PR_SUCCESS;
459 }
460
461 NSS_IMPLEMENT PRStatus
462 nssTrustDomain_UpdateCachedTokenCerts (
463 NSSTrustDomain *td,
464 NSSToken *token
465 )
466 {
467 NSSCertificate **cp, **cached = NULL;
468 nssList *certList;
469 PRUint32 count;
470 certList = nssList_Create(NULL, PR_FALSE);
471 if (!certList) return PR_FAILURE;
472 (void)nssTrustDomain_GetCertsFromCache(td, certList);
473 count = nssList_Count(certList);
474 if (count > 0) {
475 cached = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
476 if (!cached) {
477 nssList_Destroy(certList);
478 return PR_FAILURE;
479 }
480 nssList_GetArray(certList, (void **)cached, count);
481 for (cp = cached; *cp; cp++) {
482 nssCryptokiObject *instance;
483 NSSCertificate *c = *cp;
484 nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
485 instance = nssToken_FindCertificateByIssuerAndSerialNumber(
486 token,
487 NULL,
488 &c->issuer,
489 &c->serial,
490 tokenOnly,
491 NULL);
492 if (instance) {
493 nssPKIObject_AddInstance(&c->object, instance);
494 STAN_ForceCERTCertificateUpdate(c);
495 }
496 }
497 nssCertificateArray_Destroy(cached);
498 }
499 nssList_Destroy(certList);
500 return PR_SUCCESS;
501 }
502
503 static PRStatus
504 add_issuer_and_serial_entry (
505 NSSArena *arena,
506 nssTDCertificateCache *cache,
507 NSSCertificate *cert
508 )
509 {
510 cache_entry *ce;
511 ce = new_cache_entry(arena, (void *)cert, PR_FALSE);
512 #ifdef DEBUG_CACHE
513 log_cert_ref("added to issuer/sn", cert);
514 #endif
515 return nssHash_Add(cache->issuerAndSN, cert, (void *)ce);
516 }
517
518 static PRStatus
519 add_subject_entry (
520 NSSArena *arena,
521 nssTDCertificateCache *cache,
522 NSSCertificate *cert,
523 NSSUTF8 *nickname,
524 nssList **subjectList
525 )
526 {
527 PRStatus nssrv;
528 nssList *list;
529 cache_entry *ce;
530 *subjectList = NULL; /* this is only set if a new one is created */
531 ce = (cache_entry *)nssHash_Lookup(cache->subject, &cert->subject);
532 if (ce) {
533 ce->hits++;
534 ce->lastHit = PR_Now();
535 /* The subject is already in, add this cert to the list */
536 nssrv = nssList_AddUnique(ce->entry.list, cert);
537 #ifdef DEBUG_CACHE
538 log_cert_ref("added to existing subject list", cert);
539 #endif
540 } else {
541 NSSDER *subject;
542 /* Create a new subject list for the subject */
543 list = nssList_Create(arena, PR_FALSE);
544 if (!list) {
545 return PR_FAILURE;
546 }
547 ce = new_cache_entry(arena, (void *)list, PR_TRUE);
548 if (!ce) {
549 return PR_FAILURE;
550 }
551 if (nickname) {
552 ce->nickname = nssUTF8_Duplicate(nickname, arena);
553 }
554 nssList_SetSortFunction(list, nssCertificate_SubjectListSort);
555 /* Add the cert entry to this list of subjects */
556 nssrv = nssList_AddUnique(list, cert);
557 if (nssrv != PR_SUCCESS) {
558 return nssrv;
559 }
560 /* Add the subject list to the cache */
561 subject = nssItem_Duplicate(&cert->subject, arena, NULL);
562 if (!subject) {
563 return PR_FAILURE;
564 }
565 nssrv = nssHash_Add(cache->subject, subject, ce);
566 if (nssrv != PR_SUCCESS) {
567 return nssrv;
568 }
569 *subjectList = list;
570 #ifdef DEBUG_CACHE
571 log_cert_ref("created subject list", cert);
572 #endif
573 }
574 return nssrv;
575 }
576
577 static PRStatus
578 add_nickname_entry (
579 NSSArena *arena,
580 nssTDCertificateCache *cache,
581 NSSUTF8 *certNickname,
582 nssList *subjectList
583 )
584 {
585 PRStatus nssrv = PR_SUCCESS;
586 cache_entry *ce;
587 ce = (cache_entry *)nssHash_Lookup(cache->nickname, certNickname);
588 if (ce) {
589 /* This is a collision. A nickname entry already exists for this
590 * subject, but a subject entry didn't. This would imply there are
591 * two subjects using the same nickname, which is not allowed.
592 */
593 return PR_FAILURE;
594 } else {
595 NSSUTF8 *nickname;
596 ce = new_cache_entry(arena, subjectList, PR_FALSE);
597 if (!ce) {
598 return PR_FAILURE;
599 }
600 nickname = nssUTF8_Duplicate(certNickname, arena);
601 if (!nickname) {
602 return PR_FAILURE;
603 }
604 nssrv = nssHash_Add(cache->nickname, nickname, ce);
605 #ifdef DEBUG_CACHE
606 log_cert_ref("created nickname for", cert);
607 #endif
608 }
609 return nssrv;
610 }
611
612 static PRStatus
613 add_email_entry (
614 nssTDCertificateCache *cache,
615 NSSCertificate *cert,
616 nssList *subjectList
617 )
618 {
619 PRStatus nssrv = PR_SUCCESS;
620 nssList *subjects;
621 cache_entry *ce;
622 ce = (cache_entry *)nssHash_Lookup(cache->email, cert->email);
623 if (ce) {
624 /* Already have an entry for this email address, but not subject */
625 subjects = ce->entry.list;
626 nssrv = nssList_AddUnique(subjects, subjectList);
627 ce->hits++;
628 ce->lastHit = PR_Now();
629 #ifdef DEBUG_CACHE
630 log_cert_ref("added subject to email for", cert);
631 #endif
632 } else {
633 NSSASCII7 *email;
634 NSSArena *arena;
635 arena = nssArena_Create();
636 if (!arena) {
637 return PR_FAILURE;
638 }
639 /* Create a new list of subject lists, add this subject */
640 subjects = nssList_Create(arena, PR_TRUE);
641 if (!subjects) {
642 nssArena_Destroy(arena);
643 return PR_FAILURE;
644 }
645 /* Add the new subject to the list */
646 nssrv = nssList_AddUnique(subjects, subjectList);
647 if (nssrv != PR_SUCCESS) {
648 nssArena_Destroy(arena);
649 return nssrv;
650 }
651 /* Add the new entry to the cache */
652 ce = new_cache_entry(arena, (void *)subjects, PR_TRUE);
653 if (!ce) {
654 nssArena_Destroy(arena);
655 return PR_FAILURE;
656 }
657 email = nssUTF8_Duplicate(cert->email, arena);
658 if (!email) {
659 nssArena_Destroy(arena);
660 return PR_FAILURE;
661 }
662 nssrv = nssHash_Add(cache->email, email, ce);
663 if (nssrv != PR_SUCCESS) {
664 nssArena_Destroy(arena);
665 return nssrv;
666 }
667 #ifdef DEBUG_CACHE
668 log_cert_ref("created email for", cert);
669 #endif
670 }
671 return nssrv;
672 }
673
674 extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE;
675
676 static void
677 remove_object_instances (
678 nssPKIObject *object,
679 nssCryptokiObject **instances,
680 int numInstances
681 )
682 {
683 int i;
684
685 for (i = 0; i < numInstances; i++) {
686 nssPKIObject_RemoveInstanceForToken(object, instances[i]->token);
687 }
688 }
689
690 static SECStatus
691 merge_object_instances (
692 nssPKIObject *to,
693 nssPKIObject *from
694 )
695 {
696 nssCryptokiObject **instances, **ci;
697 int i;
698 SECStatus rv = SECSuccess;
699
700 instances = nssPKIObject_GetInstances(from);
701 if (instances == NULL) {
702 return SECFailure;
703 }
704 for (ci = instances, i = 0; *ci; ci++, i++) {
705 nssCryptokiObject *instance = nssCryptokiObject_Clone(*ci);
706 if (instance) {
707 if (nssPKIObject_AddInstance(to, instance) == PR_SUCCESS) {
708 continue;
709 }
710 nssCryptokiObject_Destroy(instance);
711 }
712 remove_object_instances(to, instances, i);
713 rv = SECFailure;
714 break;
715 }
716 nssCryptokiObjectArray_Destroy(instances);
717 return rv;
718 }
719
720 static NSSCertificate *
721 add_cert_to_cache (
722 NSSTrustDomain *td,
723 NSSCertificate *cert
724 )
725 {
726 NSSArena *arena = NULL;
727 nssList *subjectList = NULL;
728 PRStatus nssrv;
729 PRUint32 added = 0;
730 cache_entry *ce;
731 NSSCertificate *rvCert = NULL;
732 NSSUTF8 *certNickname = nssCertificate_GetNickname(cert, NULL);
733
734 PZ_Lock(td->cache->lock);
735 /* If it exists in the issuer/serial hash, it's already in all */
736 ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, cert);
737 if (ce) {
738 ce->hits++;
739 ce->lastHit = PR_Now();
740 rvCert = nssCertificate_AddRef(ce->entry.cert);
741 #ifdef DEBUG_CACHE
742 log_cert_ref("attempted to add cert already in cache", cert);
743 #endif
744 PZ_Unlock(td->cache->lock);
745 nss_ZFreeIf(certNickname);
746 /* collision - somebody else already added the cert
747 * to the cache before this thread got around to it.
748 */
749 /* merge the instances of the cert */
750 if (merge_object_instances(&rvCert->object, &cert->object)
751 != SECSuccess) {
752 nssCertificate_Destroy(rvCert);
753 return NULL;
754 }
755 STAN_ForceCERTCertificateUpdate(rvCert);
756 nssCertificate_Destroy(cert);
757 return rvCert;
758 }
759 /* create a new cache entry for this cert within the cert's arena*/
760 nssrv = add_issuer_and_serial_entry(cert->object.arena, td->cache, cert);
761 if (nssrv != PR_SUCCESS) {
762 goto loser;
763 }
764 added++;
765 /* create an arena for the nickname and subject entries */
766 arena = nssArena_Create();
767 if (!arena) {
768 goto loser;
769 }
770 /* create a new subject list for this cert, or add to existing */
771 nssrv = add_subject_entry(arena, td->cache, cert,
772 certNickname, &subjectList);
773 if (nssrv != PR_SUCCESS) {
774 goto loser;
775 }
776 added++;
777 /* If a new subject entry was created, also need nickname and/or email */
778 if (subjectList != NULL) {
779 #ifdef nodef
780 PRBool handle = PR_FALSE;
781 #endif
782 if (certNickname) {
783 nssrv = add_nickname_entry(arena, td->cache,
784 certNickname, subjectList);
785 if (nssrv != PR_SUCCESS) {
786 goto loser;
787 }
788 #ifdef nodef
789 handle = PR_TRUE;
790 #endif
791 added++;
792 }
793 if (cert->email) {
794 nssrv = add_email_entry(td->cache, cert, subjectList);
795 if (nssrv != PR_SUCCESS) {
796 goto loser;
797 }
798 #ifdef nodef
799 handle = PR_TRUE;
800 #endif
801 added += 2;
802 }
803 #ifdef nodef
804 /* I think either a nickname or email address must be associated
805 * with the cert. However, certs are passed to NewTemp without
806 * either. This worked in the old code, so it must work now.
807 */
808 if (!handle) {
809 /* Require either nickname or email handle */
810 nssrv = PR_FAILURE;
811 goto loser;
812 }
813 #endif
814 } else {
815 /* A new subject entry was not created. arena is unused. */
816 nssArena_Destroy(arena);
817 }
818 rvCert = cert;
819 PZ_Unlock(td->cache->lock);
820 nss_ZFreeIf(certNickname);
821 return rvCert;
822 loser:
823 nss_ZFreeIf(certNickname);
824 certNickname = NULL;
825 /* Remove any handles that have been created */
826 subjectList = NULL;
827 if (added >= 1) {
828 (void)remove_issuer_and_serial_entry(td->cache, cert);
829 }
830 if (added >= 2) {
831 (void)remove_subject_entry(td->cache, cert, &subjectList,
832 &certNickname, &arena);
833 }
834 if (added == 3 || added == 5) {
835 (void)remove_nickname_entry(td->cache, certNickname, subjectList);
836 }
837 if (added >= 4) {
838 (void)remove_email_entry(td->cache, cert, subjectList);
839 }
840 if (subjectList) {
841 nssHash_Remove(td->cache->subject, &cert->subject);
842 nssList_Destroy(subjectList);
843 }
844 if (arena) {
845 nssArena_Destroy(arena);
846 }
847 PZ_Unlock(td->cache->lock);
848 return NULL;
849 }
850
851 NSS_IMPLEMENT PRStatus
852 nssTrustDomain_AddCertsToCache (
853 NSSTrustDomain *td,
854 NSSCertificate **certs,
855 PRUint32 numCerts
856 )
857 {
858 PRUint32 i;
859 NSSCertificate *c;
860 for (i=0; i<numCerts && certs[i]; i++) {
861 c = add_cert_to_cache(td, certs[i]);
862 if (c == NULL) {
863 return PR_FAILURE;
864 } else {
865 certs[i] = c;
866 }
867 }
868 return PR_SUCCESS;
869 }
870
871 static NSSCertificate **
872 collect_subject_certs (
873 nssList *subjectList,
874 nssList *rvCertListOpt
875 )
876 {
877 NSSCertificate *c;
878 NSSCertificate **rvArray = NULL;
879 PRUint32 count;
880 nssCertificateList_AddReferences(subjectList);
881 if (rvCertListOpt) {
882 nssListIterator *iter = nssList_CreateIterator(subjectList);
883 if (!iter) {
884 return (NSSCertificate **)NULL;
885 }
886 for (c = (NSSCertificate *)nssListIterator_Start(iter);
887 c != (NSSCertificate *)NULL;
888 c = (NSSCertificate *)nssListIterator_Next(iter)) {
889 nssList_Add(rvCertListOpt, c);
890 }
891 nssListIterator_Finish(iter);
892 nssListIterator_Destroy(iter);
893 } else {
894 count = nssList_Count(subjectList);
895 rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
896 if (!rvArray) {
897 return (NSSCertificate **)NULL;
898 }
899 nssList_GetArray(subjectList, (void **)rvArray, count);
900 }
901 return rvArray;
902 }
903
904 /*
905 * Find all cached certs with this subject.
906 */
907 NSS_IMPLEMENT NSSCertificate **
908 nssTrustDomain_GetCertsForSubjectFromCache (
909 NSSTrustDomain *td,
910 NSSDER *subject,
911 nssList *certListOpt
912 )
913 {
914 NSSCertificate **rvArray = NULL;
915 cache_entry *ce;
916 #ifdef DEBUG_CACHE
917 log_item_dump("looking for cert by subject", subject);
918 #endif
919 PZ_Lock(td->cache->lock);
920 ce = (cache_entry *)nssHash_Lookup(td->cache->subject, subject);
921 if (ce) {
922 ce->hits++;
923 ce->lastHit = PR_Now();
924 #ifdef DEBUG_CACHE
925 PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
926 #endif
927 rvArray = collect_subject_certs(ce->entry.list, certListOpt);
928 }
929 PZ_Unlock(td->cache->lock);
930 return rvArray;
931 }
932
933 /*
934 * Find all cached certs with this label.
935 */
936 NSS_IMPLEMENT NSSCertificate **
937 nssTrustDomain_GetCertsForNicknameFromCache (
938 NSSTrustDomain *td,
939 const NSSUTF8 *nickname,
940 nssList *certListOpt
941 )
942 {
943 NSSCertificate **rvArray = NULL;
944 cache_entry *ce;
945 #ifdef DEBUG_CACHE
946 PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by nick %s", nickname));
947 #endif
948 PZ_Lock(td->cache->lock);
949 ce = (cache_entry *)nssHash_Lookup(td->cache->nickname, nickname);
950 if (ce) {
951 ce->hits++;
952 ce->lastHit = PR_Now();
953 #ifdef DEBUG_CACHE
954 PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
955 #endif
956 rvArray = collect_subject_certs(ce->entry.list, certListOpt);
957 }
958 PZ_Unlock(td->cache->lock);
959 return rvArray;
960 }
961
962 /*
963 * Find all cached certs with this email address.
964 */
965 NSS_IMPLEMENT NSSCertificate **
966 nssTrustDomain_GetCertsForEmailAddressFromCache (
967 NSSTrustDomain *td,
968 NSSASCII7 *email,
969 nssList *certListOpt
970 )
971 {
972 NSSCertificate **rvArray = NULL;
973 cache_entry *ce;
974 nssList *collectList = NULL;
975 nssListIterator *iter = NULL;
976 nssList *subjectList;
977 #ifdef DEBUG_CACHE
978 PR_LOG(s_log, PR_LOG_DEBUG, ("looking for cert by email %s", email));
979 #endif
980 PZ_Lock(td->cache->lock);
981 ce = (cache_entry *)nssHash_Lookup(td->cache->email, email);
982 if (ce) {
983 ce->hits++;
984 ce->lastHit = PR_Now();
985 #ifdef DEBUG_CACHE
986 PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
987 #endif
988 /* loop over subject lists and get refs for certs */
989 if (certListOpt) {
990 collectList = certListOpt;
991 } else {
992 collectList = nssList_Create(NULL, PR_FALSE);
993 if (!collectList) {
994 PZ_Unlock(td->cache->lock);
995 return NULL;
996 }
997 }
998 iter = nssList_CreateIterator(ce->entry.list);
999 if (!iter) {
1000 PZ_Unlock(td->cache->lock);
1001 if (!certListOpt) {
1002 nssList_Destroy(collectList);
1003 }
1004 return NULL;
1005 }
1006 for (subjectList = (nssList *)nssListIterator_Start(iter);
1007 subjectList != (nssList *)NULL;
1008 subjectList = (nssList *)nssListIterator_Next(iter)) {
1009 (void)collect_subject_certs(subjectList, collectList);
1010 }
1011 nssListIterator_Finish(iter);
1012 nssListIterator_Destroy(iter);
1013 }
1014 PZ_Unlock(td->cache->lock);
1015 if (!certListOpt && collectList) {
1016 PRUint32 count = nssList_Count(collectList);
1017 rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count);
1018 if (rvArray) {
1019 nssList_GetArray(collectList, (void **)rvArray, count);
1020 }
1021 nssList_Destroy(collectList);
1022 }
1023 return rvArray;
1024 }
1025
1026 /*
1027 * Look for a specific cert in the cache
1028 */
1029 NSS_IMPLEMENT NSSCertificate *
1030 nssTrustDomain_GetCertForIssuerAndSNFromCache (
1031 NSSTrustDomain *td,
1032 NSSDER *issuer,
1033 NSSDER *serial
1034 )
1035 {
1036 NSSCertificate certkey;
1037 NSSCertificate *rvCert = NULL;
1038 cache_entry *ce;
1039 certkey.issuer.data = issuer->data;
1040 certkey.issuer.size = issuer->size;
1041 certkey.serial.data = serial->data;
1042 certkey.serial.size = serial->size;
1043 #ifdef DEBUG_CACHE
1044 log_item_dump("looking for cert by issuer/sn, issuer", issuer);
1045 log_item_dump(" serial", serial);
1046 #endif
1047 PZ_Lock(td->cache->lock);
1048 ce = (cache_entry *)nssHash_Lookup(td->cache->issuerAndSN, &certkey);
1049 if (ce) {
1050 ce->hits++;
1051 ce->lastHit = PR_Now();
1052 rvCert = nssCertificate_AddRef(ce->entry.cert);
1053 #ifdef DEBUG_CACHE
1054 PR_LOG(s_log, PR_LOG_DEBUG, ("... found, %d hits", ce->hits));
1055 #endif
1056 }
1057 PZ_Unlock(td->cache->lock);
1058 return rvCert;
1059 }
1060
1061 /*
1062 * Look for a specific cert in the cache
1063 */
1064 NSS_IMPLEMENT NSSCertificate *
1065 nssTrustDomain_GetCertByDERFromCache (
1066 NSSTrustDomain *td,
1067 NSSDER *der
1068 )
1069 {
1070 PRStatus nssrv = PR_FAILURE;
1071 NSSDER issuer, serial;
1072 NSSCertificate *rvCert;
1073 nssrv = nssPKIX509_GetIssuerAndSerialFromDER(der, &issuer, &serial);
1074 if (nssrv != PR_SUCCESS) {
1075 return NULL;
1076 }
1077 #ifdef DEBUG_CACHE
1078 log_item_dump("looking for cert by DER", der);
1079 #endif
1080 rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td,
1081 &issuer, &serial);
1082 PORT_Free(issuer.data);
1083 PORT_Free(serial.data);
1084 return rvCert;
1085 }
1086
1087 static void cert_iter(const void *k, void *v, void *a)
1088 {
1089 nssList *certList = (nssList *)a;
1090 NSSCertificate *c = (NSSCertificate *)k;
1091 nssList_Add(certList, nssCertificate_AddRef(c));
1092 }
1093
1094 NSS_EXTERN NSSCertificate **
1095 nssTrustDomain_GetCertsFromCache (
1096 NSSTrustDomain *td,
1097 nssList *certListOpt
1098 )
1099 {
1100 NSSCertificate **rvArray = NULL;
1101 nssList *certList;
1102 if (certListOpt) {
1103 certList = certListOpt;
1104 } else {
1105 certList = nssList_Create(NULL, PR_FALSE);
1106 if (!certList) {
1107 return NULL;
1108 }
1109 }
1110 PZ_Lock(td->cache->lock);
1111 nssHash_Iterate(td->cache->issuerAndSN, cert_iter, (void *)certList);
1112 PZ_Unlock(td->cache->lock);
1113 if (!certListOpt) {
1114 PRUint32 count = nssList_Count(certList);
1115 rvArray = nss_ZNEWARRAY(NULL, NSSCertificate *, count);
1116 nssList_GetArray(certList, (void **)rvArray, count);
1117 /* array takes the references */
1118 nssList_Destroy(certList);
1119 }
1120 return rvArray;
1121 }
1122
1123 NSS_IMPLEMENT void
1124 nssTrustDomain_DumpCacheInfo (
1125 NSSTrustDomain *td,
1126 void (* cert_dump_iter)(const void *, void *, void *),
1127 void *arg
1128 )
1129 {
1130 PZ_Lock(td->cache->lock);
1131 nssHash_Iterate(td->cache->issuerAndSN, cert_dump_iter, arg);
1132 PZ_Unlock(td->cache->lock);
1133 }
OLDNEW
« no previous file with comments | « nss/lib/pki/symmkey.c ('k') | nss/lib/pki/trustdomain.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698