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

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #ifndef DEV_H
6 #include "dev.h"
7 #endif /* DEV_H */
8
9 #ifndef PKIM_H
10 #include "pkim.h"
11 #endif /* PKIM_H */
12
13 #include "pki3hack.h"
14
15 extern const NSSError NSS_ERROR_NOT_FOUND;
16
17 NSS_IMPLEMENT void
18 nssPKIObject_Lock(nssPKIObject * object)
19 {
20 switch (object->lockType) {
21 case nssPKIMonitor:
22 PZ_EnterMonitor(object->sync.mlock);
23 break;
24 case nssPKILock:
25 PZ_Lock(object->sync.lock);
26 break;
27 default:
28 PORT_Assert(0);
29 }
30 }
31
32 NSS_IMPLEMENT void
33 nssPKIObject_Unlock(nssPKIObject * object)
34 {
35 switch (object->lockType) {
36 case nssPKIMonitor:
37 PZ_ExitMonitor(object->sync.mlock);
38 break;
39 case nssPKILock:
40 PZ_Unlock(object->sync.lock);
41 break;
42 default:
43 PORT_Assert(0);
44 }
45 }
46
47 NSS_IMPLEMENT PRStatus
48 nssPKIObject_NewLock(nssPKIObject * object, nssPKILockType lockType)
49 {
50 object->lockType = lockType;
51 switch (lockType) {
52 case nssPKIMonitor:
53 object->sync.mlock = PZ_NewMonitor(nssILockSSL);
54 return (object->sync.mlock ? PR_SUCCESS : PR_FAILURE);
55 case nssPKILock:
56 object->sync.lock = PZ_NewLock(nssILockSSL);
57 return (object->sync.lock ? PR_SUCCESS : PR_FAILURE);
58 default:
59 PORT_Assert(0);
60 return PR_FAILURE;
61 }
62 }
63
64 NSS_IMPLEMENT void
65 nssPKIObject_DestroyLock(nssPKIObject * object)
66 {
67 switch (object->lockType) {
68 case nssPKIMonitor:
69 PZ_DestroyMonitor(object->sync.mlock);
70 object->sync.mlock = NULL;
71 break;
72 case nssPKILock:
73 PZ_DestroyLock(object->sync.lock);
74 object->sync.lock = NULL;
75 break;
76 default:
77 PORT_Assert(0);
78 }
79 }
80
81
82
83 NSS_IMPLEMENT nssPKIObject *
84 nssPKIObject_Create (
85 NSSArena *arenaOpt,
86 nssCryptokiObject *instanceOpt,
87 NSSTrustDomain *td,
88 NSSCryptoContext *cc,
89 nssPKILockType lockType
90 )
91 {
92 NSSArena *arena;
93 nssArenaMark *mark = NULL;
94 nssPKIObject *object;
95 if (arenaOpt) {
96 arena = arenaOpt;
97 mark = nssArena_Mark(arena);
98 } else {
99 arena = nssArena_Create();
100 if (!arena) {
101 return (nssPKIObject *)NULL;
102 }
103 }
104 object = nss_ZNEW(arena, nssPKIObject);
105 if (!object) {
106 goto loser;
107 }
108 object->arena = arena;
109 object->trustDomain = td; /* XXX */
110 object->cryptoContext = cc;
111 if (PR_SUCCESS != nssPKIObject_NewLock(object, lockType)) {
112 goto loser;
113 }
114 if (instanceOpt) {
115 if (nssPKIObject_AddInstance(object, instanceOpt) != PR_SUCCESS) {
116 goto loser;
117 }
118 }
119 PR_ATOMIC_INCREMENT(&object->refCount);
120 if (mark) {
121 nssArena_Unmark(arena, mark);
122 }
123 return object;
124 loser:
125 if (mark) {
126 nssArena_Release(arena, mark);
127 } else {
128 nssArena_Destroy(arena);
129 }
130 return (nssPKIObject *)NULL;
131 }
132
133 NSS_IMPLEMENT PRBool
134 nssPKIObject_Destroy (
135 nssPKIObject *object
136 )
137 {
138 PRUint32 i;
139 PR_ASSERT(object->refCount > 0);
140 if (PR_ATOMIC_DECREMENT(&object->refCount) == 0) {
141 for (i=0; i<object->numInstances; i++) {
142 nssCryptokiObject_Destroy(object->instances[i]);
143 }
144 nssPKIObject_DestroyLock(object);
145 nssArena_Destroy(object->arena);
146 return PR_TRUE;
147 }
148 return PR_FALSE;
149 }
150
151 NSS_IMPLEMENT nssPKIObject *
152 nssPKIObject_AddRef (
153 nssPKIObject *object
154 )
155 {
156 PR_ATOMIC_INCREMENT(&object->refCount);
157 return object;
158 }
159
160 NSS_IMPLEMENT PRStatus
161 nssPKIObject_AddInstance (
162 nssPKIObject *object,
163 nssCryptokiObject *instance
164 )
165 {
166 nssCryptokiObject **newInstances = NULL;
167
168 nssPKIObject_Lock(object);
169 if (object->numInstances == 0) {
170 newInstances = nss_ZNEWARRAY(object->arena,
171 nssCryptokiObject *,
172 object->numInstances + 1);
173 } else {
174 PRBool found = PR_FALSE;
175 PRUint32 i;
176 for (i=0; i<object->numInstances; i++) {
177 if (nssCryptokiObject_Equal(object->instances[i], instance)) {
178 found = PR_TRUE;
179 break;
180 }
181 }
182 if (found) {
183 /* The new instance is identical to one in the array, except
184 * perhaps that the label may be different. So replace
185 * the label in the array instance with the label from the
186 * new instance, and discard the new instance.
187 */
188 nss_ZFreeIf(object->instances[i]->label);
189 object->instances[i]->label = instance->label;
190 nssPKIObject_Unlock(object);
191 instance->label = NULL;
192 nssCryptokiObject_Destroy(instance);
193 return PR_SUCCESS;
194 }
195 newInstances = nss_ZREALLOCARRAY(object->instances,
196 nssCryptokiObject *,
197 object->numInstances + 1);
198 }
199 if (newInstances) {
200 object->instances = newInstances;
201 newInstances[object->numInstances++] = instance;
202 }
203 nssPKIObject_Unlock(object);
204 return (newInstances ? PR_SUCCESS : PR_FAILURE);
205 }
206
207 NSS_IMPLEMENT PRBool
208 nssPKIObject_HasInstance (
209 nssPKIObject *object,
210 nssCryptokiObject *instance
211 )
212 {
213 PRUint32 i;
214 PRBool hasIt = PR_FALSE;;
215 nssPKIObject_Lock(object);
216 for (i=0; i<object->numInstances; i++) {
217 if (nssCryptokiObject_Equal(object->instances[i], instance)) {
218 hasIt = PR_TRUE;
219 break;
220 }
221 }
222 nssPKIObject_Unlock(object);
223 return hasIt;
224 }
225
226 NSS_IMPLEMENT PRStatus
227 nssPKIObject_RemoveInstanceForToken (
228 nssPKIObject *object,
229 NSSToken *token
230 )
231 {
232 PRUint32 i;
233 nssCryptokiObject *instanceToRemove = NULL;
234 nssPKIObject_Lock(object);
235 if (object->numInstances == 0) {
236 nssPKIObject_Unlock(object);
237 return PR_SUCCESS;
238 }
239 for (i=0; i<object->numInstances; i++) {
240 if (object->instances[i]->token == token) {
241 instanceToRemove = object->instances[i];
242 object->instances[i] = object->instances[object->numInstances-1];
243 object->instances[object->numInstances-1] = NULL;
244 break;
245 }
246 }
247 if (--object->numInstances > 0) {
248 nssCryptokiObject **instances = nss_ZREALLOCARRAY(object->instances,
249 nssCryptokiObject *,
250 object->numInstances);
251 if (instances) {
252 object->instances = instances;
253 }
254 } else {
255 nss_ZFreeIf(object->instances);
256 }
257 nssCryptokiObject_Destroy(instanceToRemove);
258 nssPKIObject_Unlock(object);
259 return PR_SUCCESS;
260 }
261
262 /* this needs more thought on what will happen when there are multiple
263 * instances
264 */
265 NSS_IMPLEMENT PRStatus
266 nssPKIObject_DeleteStoredObject (
267 nssPKIObject *object,
268 NSSCallback *uhh,
269 PRBool isFriendly
270 )
271 {
272 PRUint32 i, numNotDestroyed;
273 PRStatus status = PR_SUCCESS;
274 numNotDestroyed = 0;
275 nssPKIObject_Lock(object);
276 for (i=0; i<object->numInstances; i++) {
277 nssCryptokiObject *instance = object->instances[i];
278 status = nssToken_DeleteStoredObject(instance);
279 object->instances[i] = NULL;
280 if (status == PR_SUCCESS) {
281 nssCryptokiObject_Destroy(instance);
282 } else {
283 object->instances[numNotDestroyed++] = instance;
284 }
285 }
286 if (numNotDestroyed == 0) {
287 nss_ZFreeIf(object->instances);
288 object->numInstances = 0;
289 } else {
290 object->numInstances = numNotDestroyed;
291 }
292 nssPKIObject_Unlock(object);
293 return status;
294 }
295
296 NSS_IMPLEMENT NSSToken **
297 nssPKIObject_GetTokens (
298 nssPKIObject *object,
299 PRStatus *statusOpt
300 )
301 {
302 NSSToken **tokens = NULL;
303 nssPKIObject_Lock(object);
304 if (object->numInstances > 0) {
305 tokens = nss_ZNEWARRAY(NULL, NSSToken *, object->numInstances + 1);
306 if (tokens) {
307 PRUint32 i;
308 for (i=0; i<object->numInstances; i++) {
309 tokens[i] = nssToken_AddRef(object->instances[i]->token);
310 }
311 }
312 }
313 nssPKIObject_Unlock(object);
314 if (statusOpt) *statusOpt = PR_SUCCESS; /* until more logic here */
315 return tokens;
316 }
317
318 NSS_IMPLEMENT NSSUTF8 *
319 nssPKIObject_GetNicknameForToken (
320 nssPKIObject *object,
321 NSSToken *tokenOpt
322 )
323 {
324 PRUint32 i;
325 NSSUTF8 *nickname = NULL;
326 nssPKIObject_Lock(object);
327 for (i=0; i<object->numInstances; i++) {
328 if ((!tokenOpt && object->instances[i]->label) ||
329 (object->instances[i]->token == tokenOpt))
330 {
331 /* Must copy, see bug 745548 */
332 nickname = nssUTF8_Duplicate(object->instances[i]->label, NULL);
333 break;
334 }
335 }
336 nssPKIObject_Unlock(object);
337 return nickname;
338 }
339
340 NSS_IMPLEMENT nssCryptokiObject **
341 nssPKIObject_GetInstances (
342 nssPKIObject *object
343 )
344 {
345 nssCryptokiObject **instances = NULL;
346 PRUint32 i;
347 if (object->numInstances == 0) {
348 return (nssCryptokiObject **)NULL;
349 }
350 nssPKIObject_Lock(object);
351 instances = nss_ZNEWARRAY(NULL, nssCryptokiObject *,
352 object->numInstances + 1);
353 if (instances) {
354 for (i=0; i<object->numInstances; i++) {
355 instances[i] = nssCryptokiObject_Clone(object->instances[i]);
356 }
357 }
358 nssPKIObject_Unlock(object);
359 return instances;
360 }
361
362 NSS_IMPLEMENT void
363 nssCertificateArray_Destroy (
364 NSSCertificate **certs
365 )
366 {
367 if (certs) {
368 NSSCertificate **certp;
369 for (certp = certs; *certp; certp++) {
370 if ((*certp)->decoding) {
371 CERTCertificate *cc = STAN_GetCERTCertificate(*certp);
372 if (cc) {
373 CERT_DestroyCertificate(cc);
374 }
375 continue;
376 }
377 nssCertificate_Destroy(*certp);
378 }
379 nss_ZFreeIf(certs);
380 }
381 }
382
383 NSS_IMPLEMENT void
384 NSSCertificateArray_Destroy (
385 NSSCertificate **certs
386 )
387 {
388 nssCertificateArray_Destroy(certs);
389 }
390
391 NSS_IMPLEMENT NSSCertificate **
392 nssCertificateArray_Join (
393 NSSCertificate **certs1,
394 NSSCertificate **certs2
395 )
396 {
397 if (certs1 && certs2) {
398 NSSCertificate **certs, **cp;
399 PRUint32 count = 0;
400 PRUint32 count1 = 0;
401 cp = certs1;
402 while (*cp++) count1++;
403 count = count1;
404 cp = certs2;
405 while (*cp++) count++;
406 certs = nss_ZREALLOCARRAY(certs1, NSSCertificate *, count + 1);
407 if (!certs) {
408 nss_ZFreeIf(certs1);
409 nss_ZFreeIf(certs2);
410 return (NSSCertificate **)NULL;
411 }
412 for (cp = certs2; *cp; cp++, count1++) {
413 certs[count1] = *cp;
414 }
415 nss_ZFreeIf(certs2);
416 return certs;
417 } else if (certs1) {
418 return certs1;
419 } else {
420 return certs2;
421 }
422 }
423
424 NSS_IMPLEMENT NSSCertificate *
425 nssCertificateArray_FindBestCertificate (
426 NSSCertificate **certs,
427 NSSTime *timeOpt,
428 const NSSUsage *usage,
429 NSSPolicies *policiesOpt
430 )
431 {
432 NSSCertificate *bestCert = NULL;
433 nssDecodedCert *bestdc = NULL;
434 NSSTime *time, sTime;
435 PRBool bestCertMatches = PR_FALSE;
436 PRBool thisCertMatches;
437 PRBool bestCertIsValidAtTime = PR_FALSE;
438 PRBool bestCertIsTrusted = PR_FALSE;
439
440 if (timeOpt) {
441 time = timeOpt;
442 } else {
443 NSSTime_Now(&sTime);
444 time = &sTime;
445 }
446 if (!certs) {
447 return (NSSCertificate *)NULL;
448 }
449 for (; *certs; certs++) {
450 nssDecodedCert *dc;
451 NSSCertificate *c = *certs;
452 dc = nssCertificate_GetDecoding(c);
453 if (!dc) continue;
454 thisCertMatches = dc->matchUsage(dc, usage);
455 if (!bestCert) {
456 /* always take the first cert, but remember whether or not
457 * the usage matched
458 */
459 bestCert = nssCertificate_AddRef(c);
460 bestCertMatches = thisCertMatches;
461 bestdc = dc;
462 continue;
463 } else {
464 if (bestCertMatches && !thisCertMatches) {
465 /* if already have a cert for this usage, and if this cert
466 * doesn't have the correct usage, continue
467 */
468 continue;
469 } else if (!bestCertMatches && thisCertMatches) {
470 /* this one does match usage, replace the other */
471 nssCertificate_Destroy(bestCert);
472 bestCert = nssCertificate_AddRef(c);
473 bestCertMatches = thisCertMatches;
474 bestdc = dc;
475 continue;
476 }
477 /* this cert match as well as any cert we've found so far,
478 * defer to time/policies
479 * */
480 }
481 /* time */
482 if (bestCertIsValidAtTime || bestdc->isValidAtTime(bestdc, time)) {
483 /* The current best cert is valid at time */
484 bestCertIsValidAtTime = PR_TRUE;
485 if (!dc->isValidAtTime(dc, time)) {
486 /* If the new cert isn't valid at time, it's not better */
487 continue;
488 }
489 } else {
490 /* The current best cert is not valid at time */
491 if (dc->isValidAtTime(dc, time)) {
492 /* If the new cert is valid at time, it's better */
493 nssCertificate_Destroy(bestCert);
494 bestCert = nssCertificate_AddRef(c);
495 bestdc = dc;
496 bestCertIsValidAtTime = PR_TRUE;
497 continue;
498 }
499 }
500 /* Either they are both valid at time, or neither valid.
501 * If only one is trusted for this usage, take it.
502 */
503 if (bestCertIsTrusted || bestdc->isTrustedForUsage(bestdc, usage)) {
504 bestCertIsTrusted = PR_TRUE;
505 if (!dc->isTrustedForUsage(dc, usage)) {
506 continue;
507 }
508 } else {
509 /* The current best cert is not trusted */
510 if (dc->isTrustedForUsage(dc, usage)) {
511 /* If the new cert is trusted, it's better */
512 nssCertificate_Destroy(bestCert);
513 bestCert = nssCertificate_AddRef(c);
514 bestdc = dc;
515 bestCertIsTrusted = PR_TRUE;
516 continue;
517 }
518 }
519 /* Otherwise, take the newer one. */
520 if (!bestdc->isNewerThan(bestdc, dc)) {
521 nssCertificate_Destroy(bestCert);
522 bestCert = nssCertificate_AddRef(c);
523 bestdc = dc;
524 continue;
525 }
526 /* policies */
527 /* XXX later -- defer to policies */
528 }
529 return bestCert;
530 }
531
532 NSS_IMPLEMENT PRStatus
533 nssCertificateArray_Traverse (
534 NSSCertificate **certs,
535 PRStatus (* callback)(NSSCertificate *c, void *arg),
536 void *arg
537 )
538 {
539 PRStatus status = PR_SUCCESS;
540 if (certs) {
541 NSSCertificate **certp;
542 for (certp = certs; *certp; certp++) {
543 status = (*callback)(*certp, arg);
544 if (status != PR_SUCCESS) {
545 break;
546 }
547 }
548 }
549 return status;
550 }
551
552
553 NSS_IMPLEMENT void
554 nssCRLArray_Destroy (
555 NSSCRL **crls
556 )
557 {
558 if (crls) {
559 NSSCRL **crlp;
560 for (crlp = crls; *crlp; crlp++) {
561 nssCRL_Destroy(*crlp);
562 }
563 nss_ZFreeIf(crls);
564 }
565 }
566
567 /*
568 * Object collections
569 */
570
571 typedef enum
572 {
573 pkiObjectType_Certificate = 0,
574 pkiObjectType_CRL = 1,
575 pkiObjectType_PrivateKey = 2,
576 pkiObjectType_PublicKey = 3
577 } pkiObjectType;
578
579 /* Each object is defined by a set of items that uniquely identify it.
580 * Here are the uid sets:
581 *
582 * NSSCertificate ==> { issuer, serial }
583 * NSSPrivateKey
584 * (RSA) ==> { modulus, public exponent }
585 *
586 */
587 #define MAX_ITEMS_FOR_UID 2
588
589 /* pkiObjectCollectionNode
590 *
591 * A node in the collection is the set of unique identifiers for a single
592 * object, along with either the actual object or a proto-object.
593 */
594 typedef struct
595 {
596 PRCList link;
597 PRBool haveObject;
598 nssPKIObject *object;
599 NSSItem uid[MAX_ITEMS_FOR_UID];
600 }
601 pkiObjectCollectionNode;
602
603 /* nssPKIObjectCollection
604 *
605 * The collection is the set of all objects, plus the interfaces needed
606 * to manage the objects.
607 *
608 */
609 struct nssPKIObjectCollectionStr
610 {
611 NSSArena *arena;
612 NSSTrustDomain *td;
613 NSSCryptoContext *cc;
614 PRCList head; /* list of pkiObjectCollectionNode's */
615 PRUint32 size;
616 pkiObjectType objectType;
617 void (* destroyObject)(nssPKIObject *o);
618 PRStatus (* getUIDFromObject)(nssPKIObject *o, NSSItem *uid);
619 PRStatus (* getUIDFromInstance)(nssCryptokiObject *co, NSSItem *uid,
620 NSSArena *arena);
621 nssPKIObject * (* createObject)(nssPKIObject *o);
622 nssPKILockType lockType; /* type of lock to use for new proto-objects */
623 };
624
625 static nssPKIObjectCollection *
626 nssPKIObjectCollection_Create (
627 NSSTrustDomain *td,
628 NSSCryptoContext *ccOpt,
629 nssPKILockType lockType
630 )
631 {
632 NSSArena *arena;
633 nssPKIObjectCollection *rvCollection = NULL;
634 arena = nssArena_Create();
635 if (!arena) {
636 return (nssPKIObjectCollection *)NULL;
637 }
638 rvCollection = nss_ZNEW(arena, nssPKIObjectCollection);
639 if (!rvCollection) {
640 goto loser;
641 }
642 PR_INIT_CLIST(&rvCollection->head);
643 rvCollection->arena = arena;
644 rvCollection->td = td; /* XXX */
645 rvCollection->cc = ccOpt;
646 rvCollection->lockType = lockType;
647 return rvCollection;
648 loser:
649 nssArena_Destroy(arena);
650 return (nssPKIObjectCollection *)NULL;
651 }
652
653 NSS_IMPLEMENT void
654 nssPKIObjectCollection_Destroy (
655 nssPKIObjectCollection *collection
656 )
657 {
658 if (collection) {
659 PRCList *link;
660 pkiObjectCollectionNode *node;
661 /* first destroy any objects in the collection */
662 link = PR_NEXT_LINK(&collection->head);
663 while (link != &collection->head) {
664 node = (pkiObjectCollectionNode *)link;
665 if (node->haveObject) {
666 (*collection->destroyObject)(node->object);
667 } else {
668 nssPKIObject_Destroy(node->object);
669 }
670 link = PR_NEXT_LINK(link);
671 }
672 /* then destroy it */
673 nssArena_Destroy(collection->arena);
674 }
675 }
676
677 NSS_IMPLEMENT PRUint32
678 nssPKIObjectCollection_Count (
679 nssPKIObjectCollection *collection
680 )
681 {
682 return collection->size;
683 }
684
685 NSS_IMPLEMENT PRStatus
686 nssPKIObjectCollection_AddObject (
687 nssPKIObjectCollection *collection,
688 nssPKIObject *object
689 )
690 {
691 pkiObjectCollectionNode *node;
692 node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
693 if (!node) {
694 return PR_FAILURE;
695 }
696 node->haveObject = PR_TRUE;
697 node->object = nssPKIObject_AddRef(object);
698 (*collection->getUIDFromObject)(object, node->uid);
699 PR_INIT_CLIST(&node->link);
700 PR_INSERT_BEFORE(&node->link, &collection->head);
701 collection->size++;
702 return PR_SUCCESS;
703 }
704
705 static pkiObjectCollectionNode *
706 find_instance_in_collection (
707 nssPKIObjectCollection *collection,
708 nssCryptokiObject *instance
709 )
710 {
711 PRCList *link;
712 pkiObjectCollectionNode *node;
713 link = PR_NEXT_LINK(&collection->head);
714 while (link != &collection->head) {
715 node = (pkiObjectCollectionNode *)link;
716 if (nssPKIObject_HasInstance(node->object, instance)) {
717 return node;
718 }
719 link = PR_NEXT_LINK(link);
720 }
721 return (pkiObjectCollectionNode *)NULL;
722 }
723
724 static pkiObjectCollectionNode *
725 find_object_in_collection (
726 nssPKIObjectCollection *collection,
727 NSSItem *uid
728 )
729 {
730 PRUint32 i;
731 PRStatus status;
732 PRCList *link;
733 pkiObjectCollectionNode *node;
734 link = PR_NEXT_LINK(&collection->head);
735 while (link != &collection->head) {
736 node = (pkiObjectCollectionNode *)link;
737 for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
738 if (!nssItem_Equal(&node->uid[i], &uid[i], &status)) {
739 break;
740 }
741 }
742 if (i == MAX_ITEMS_FOR_UID) {
743 return node;
744 }
745 link = PR_NEXT_LINK(link);
746 }
747 return (pkiObjectCollectionNode *)NULL;
748 }
749
750 static pkiObjectCollectionNode *
751 add_object_instance (
752 nssPKIObjectCollection *collection,
753 nssCryptokiObject *instance,
754 PRBool *foundIt
755 )
756 {
757 PRUint32 i;
758 PRStatus status;
759 pkiObjectCollectionNode *node;
760 nssArenaMark *mark = NULL;
761 NSSItem uid[MAX_ITEMS_FOR_UID];
762 nsslibc_memset(uid, 0, sizeof uid);
763 /* The list is traversed twice, first (here) looking to match the
764 * { token, handle } tuple, and if that is not found, below a search
765 * for unique identifier is done. Here, a match means this exact object
766 * instance is already in the collection, and we have nothing to do.
767 */
768 *foundIt = PR_FALSE;
769 node = find_instance_in_collection(collection, instance);
770 if (node) {
771 /* The collection is assumed to take over the instance. Since we
772 * are not using it, it must be destroyed.
773 */
774 nssCryptokiObject_Destroy(instance);
775 *foundIt = PR_TRUE;
776 return node;
777 }
778 mark = nssArena_Mark(collection->arena);
779 if (!mark) {
780 goto loser;
781 }
782 status = (*collection->getUIDFromInstance)(instance, uid,
783 collection->arena);
784 if (status != PR_SUCCESS) {
785 goto loser;
786 }
787 /* Search for unique identifier. A match here means the object exists
788 * in the collection, but does not have this instance, so the instance
789 * needs to be added.
790 */
791 node = find_object_in_collection(collection, uid);
792 if (node) {
793 /* This is an object with multiple instances */
794 status = nssPKIObject_AddInstance(node->object, instance);
795 } else {
796 /* This is a completely new object. Create a node for it. */
797 node = nss_ZNEW(collection->arena, pkiObjectCollectionNode);
798 if (!node) {
799 goto loser;
800 }
801 node->object = nssPKIObject_Create(NULL, instance,
802 collection->td, collection->cc,
803 collection->lockType);
804 if (!node->object) {
805 goto loser;
806 }
807 for (i=0; i<MAX_ITEMS_FOR_UID; i++) {
808 node->uid[i] = uid[i];
809 }
810 node->haveObject = PR_FALSE;
811 PR_INIT_CLIST(&node->link);
812 PR_INSERT_BEFORE(&node->link, &collection->head);
813 collection->size++;
814 status = PR_SUCCESS;
815 }
816 nssArena_Unmark(collection->arena, mark);
817 return node;
818 loser:
819 if (mark) {
820 nssArena_Release(collection->arena, mark);
821 }
822 nssCryptokiObject_Destroy(instance);
823 return (pkiObjectCollectionNode *)NULL;
824 }
825
826 NSS_IMPLEMENT PRStatus
827 nssPKIObjectCollection_AddInstances (
828 nssPKIObjectCollection *collection,
829 nssCryptokiObject **instances,
830 PRUint32 numInstances
831 )
832 {
833 PRStatus status = PR_SUCCESS;
834 PRUint32 i = 0;
835 PRBool foundIt;
836 pkiObjectCollectionNode *node;
837 if (instances) {
838 while ((!numInstances || i < numInstances) && *instances) {
839 if (status == PR_SUCCESS) {
840 node = add_object_instance(collection, *instances, &foundIt);
841 if (node == NULL) {
842 /* add_object_instance freed the current instance */
843 /* free the remaining instances */
844 status = PR_FAILURE;
845 }
846 } else {
847 nssCryptokiObject_Destroy(*instances);
848 }
849 instances++;
850 i++;
851 }
852 }
853 return status;
854 }
855
856 static void
857 nssPKIObjectCollection_RemoveNode (
858 nssPKIObjectCollection *collection,
859 pkiObjectCollectionNode *node
860 )
861 {
862 PR_REMOVE_LINK(&node->link);
863 collection->size--;
864 }
865
866 static PRStatus
867 nssPKIObjectCollection_GetObjects (
868 nssPKIObjectCollection *collection,
869 nssPKIObject **rvObjects,
870 PRUint32 rvSize
871 )
872 {
873 PRUint32 i = 0;
874 PRCList *link = PR_NEXT_LINK(&collection->head);
875 pkiObjectCollectionNode *node;
876 int error=0;
877 while ((i < rvSize) && (link != &collection->head)) {
878 node = (pkiObjectCollectionNode *)link;
879 if (!node->haveObject) {
880 /* Convert the proto-object to an object */
881 node->object = (*collection->createObject)(node->object);
882 if (!node->object) {
883 link = PR_NEXT_LINK(link);
884 /*remove bogus object from list*/
885 nssPKIObjectCollection_RemoveNode(collection,node);
886 error++;
887 continue;
888 }
889 node->haveObject = PR_TRUE;
890 }
891 rvObjects[i++] = nssPKIObject_AddRef(node->object);
892 link = PR_NEXT_LINK(link);
893 }
894 if (!error && *rvObjects == NULL) {
895 nss_SetError(NSS_ERROR_NOT_FOUND);
896 }
897 return PR_SUCCESS;
898 }
899
900 NSS_IMPLEMENT PRStatus
901 nssPKIObjectCollection_Traverse (
902 nssPKIObjectCollection *collection,
903 nssPKIObjectCallback *callback
904 )
905 {
906 PRStatus status;
907 PRCList *link = PR_NEXT_LINK(&collection->head);
908 pkiObjectCollectionNode *node;
909 while (link != &collection->head) {
910 node = (pkiObjectCollectionNode *)link;
911 if (!node->haveObject) {
912 node->object = (*collection->createObject)(node->object);
913 if (!node->object) {
914 link = PR_NEXT_LINK(link);
915 /*remove bogus object from list*/
916 nssPKIObjectCollection_RemoveNode(collection,node);
917 continue;
918 }
919 node->haveObject = PR_TRUE;
920 }
921 switch (collection->objectType) {
922 case pkiObjectType_Certificate:
923 status = (*callback->func.cert)((NSSCertificate *)node->object,
924 callback->arg);
925 break;
926 case pkiObjectType_CRL:
927 status = (*callback->func.crl)((NSSCRL *)node->object,
928 callback->arg);
929 break;
930 case pkiObjectType_PrivateKey:
931 status = (*callback->func.pvkey)((NSSPrivateKey *)node->object,
932 callback->arg);
933 break;
934 case pkiObjectType_PublicKey:
935 status = (*callback->func.pbkey)((NSSPublicKey *)node->object,
936 callback->arg);
937 break;
938 }
939 link = PR_NEXT_LINK(link);
940 }
941 return PR_SUCCESS;
942 }
943
944 NSS_IMPLEMENT PRStatus
945 nssPKIObjectCollection_AddInstanceAsObject (
946 nssPKIObjectCollection *collection,
947 nssCryptokiObject *instance
948 )
949 {
950 pkiObjectCollectionNode *node;
951 PRBool foundIt;
952 node = add_object_instance(collection, instance, &foundIt);
953 if (node == NULL) {
954 return PR_FAILURE;
955 }
956 if (!node->haveObject) {
957 node->object = (*collection->createObject)(node->object);
958 if (!node->object) {
959 /*remove bogus object from list*/
960 nssPKIObjectCollection_RemoveNode(collection,node);
961 return PR_FAILURE;
962 }
963 node->haveObject = PR_TRUE;
964 } else if (!foundIt) {
965 /* The instance was added to a pre-existing node. This
966 * function is *only* being used for certificates, and having
967 * multiple instances of certs in 3.X requires updating the
968 * CERTCertificate.
969 * But only do it if it was a new instance!!! If the same instance
970 * is encountered, we set *foundIt to true. Detect that here and
971 * ignore it.
972 */
973 STAN_ForceCERTCertificateUpdate((NSSCertificate *)node->object);
974 }
975 return PR_SUCCESS;
976 }
977
978 /*
979 * Certificate collections
980 */
981
982 static void
983 cert_destroyObject(nssPKIObject *o)
984 {
985 NSSCertificate *c = (NSSCertificate *)o;
986 if (c->decoding) {
987 CERTCertificate *cc = STAN_GetCERTCertificate(c);
988 if (cc) {
989 CERT_DestroyCertificate(cc);
990 return;
991 } /* else destroy it as NSSCertificate below */
992 }
993 nssCertificate_Destroy(c);
994 }
995
996 static PRStatus
997 cert_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
998 {
999 NSSCertificate *c = (NSSCertificate *)o;
1000 /* The builtins are still returning decoded serial numbers. Until
1001 * this compatibility issue is resolved, use the full DER of the
1002 * cert to uniquely identify it.
1003 */
1004 NSSDER *derCert;
1005 derCert = nssCertificate_GetEncoding(c);
1006 uid[0].data = NULL; uid[0].size = 0;
1007 uid[1].data = NULL; uid[1].size = 0;
1008 if (derCert != NULL) {
1009 uid[0] = *derCert;
1010 }
1011 return PR_SUCCESS;
1012 }
1013
1014 static PRStatus
1015 cert_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
1016 NSSArena *arena)
1017 {
1018 /* The builtins are still returning decoded serial numbers. Until
1019 * this compatibility issue is resolved, use the full DER of the
1020 * cert to uniquely identify it.
1021 */
1022 uid[1].data = NULL; uid[1].size = 0;
1023 return nssCryptokiCertificate_GetAttributes(instance,
1024 NULL, /* XXX sessionOpt */
1025 arena, /* arena */
1026 NULL, /* type */
1027 NULL, /* id */
1028 &uid[0], /* encoding */
1029 NULL, /* issuer */
1030 NULL, /* serial */
1031 NULL); /* subject */
1032 }
1033
1034 static nssPKIObject *
1035 cert_createObject(nssPKIObject *o)
1036 {
1037 NSSCertificate *cert;
1038 cert = nssCertificate_Create(o);
1039 /* if (STAN_GetCERTCertificate(cert) == NULL) {
1040 nssCertificate_Destroy(cert);
1041 return (nssPKIObject *)NULL;
1042 } */
1043 /* In 3.4, have to maintain uniqueness of cert pointers by caching all
1044 * certs. Cache the cert here, before returning. If it is already
1045 * cached, take the cached entry.
1046 */
1047 {
1048 NSSTrustDomain *td = o->trustDomain;
1049 nssTrustDomain_AddCertsToCache(td, &cert, 1);
1050 }
1051 return (nssPKIObject *)cert;
1052 }
1053
1054 NSS_IMPLEMENT nssPKIObjectCollection *
1055 nssCertificateCollection_Create (
1056 NSSTrustDomain *td,
1057 NSSCertificate **certsOpt
1058 )
1059 {
1060 PRStatus status;
1061 nssPKIObjectCollection *collection;
1062 collection = nssPKIObjectCollection_Create(td, NULL, nssPKIMonitor);
1063 collection->objectType = pkiObjectType_Certificate;
1064 collection->destroyObject = cert_destroyObject;
1065 collection->getUIDFromObject = cert_getUIDFromObject;
1066 collection->getUIDFromInstance = cert_getUIDFromInstance;
1067 collection->createObject = cert_createObject;
1068 if (certsOpt) {
1069 for (; *certsOpt; certsOpt++) {
1070 nssPKIObject *object = (nssPKIObject *)(*certsOpt);
1071 status = nssPKIObjectCollection_AddObject(collection, object);
1072 }
1073 }
1074 return collection;
1075 }
1076
1077 NSS_IMPLEMENT NSSCertificate **
1078 nssPKIObjectCollection_GetCertificates (
1079 nssPKIObjectCollection *collection,
1080 NSSCertificate **rvOpt,
1081 PRUint32 maximumOpt,
1082 NSSArena *arenaOpt
1083 )
1084 {
1085 PRStatus status;
1086 PRUint32 rvSize;
1087 PRBool allocated = PR_FALSE;
1088 if (collection->size == 0) {
1089 return (NSSCertificate **)NULL;
1090 }
1091 if (maximumOpt == 0) {
1092 rvSize = collection->size;
1093 } else {
1094 rvSize = PR_MIN(collection->size, maximumOpt);
1095 }
1096 if (!rvOpt) {
1097 rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCertificate *, rvSize + 1);
1098 if (!rvOpt) {
1099 return (NSSCertificate **)NULL;
1100 }
1101 allocated = PR_TRUE;
1102 }
1103 status = nssPKIObjectCollection_GetObjects(collection,
1104 (nssPKIObject **)rvOpt,
1105 rvSize);
1106 if (status != PR_SUCCESS) {
1107 if (allocated) {
1108 nss_ZFreeIf(rvOpt);
1109 }
1110 return (NSSCertificate **)NULL;
1111 }
1112 return rvOpt;
1113 }
1114
1115 /*
1116 * CRL/KRL collections
1117 */
1118
1119 static void
1120 crl_destroyObject(nssPKIObject *o)
1121 {
1122 NSSCRL *crl = (NSSCRL *)o;
1123 nssCRL_Destroy(crl);
1124 }
1125
1126 static PRStatus
1127 crl_getUIDFromObject(nssPKIObject *o, NSSItem *uid)
1128 {
1129 NSSCRL *crl = (NSSCRL *)o;
1130 NSSDER *encoding;
1131 encoding = nssCRL_GetEncoding(crl);
1132 if (!encoding) {
1133 nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
1134 return PR_FALSE;
1135 }
1136 uid[0] = *encoding;
1137 uid[1].data = NULL; uid[1].size = 0;
1138 return PR_SUCCESS;
1139 }
1140
1141 static PRStatus
1142 crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
1143 NSSArena *arena)
1144 {
1145 return nssCryptokiCRL_GetAttributes(instance,
1146 NULL, /* XXX sessionOpt */
1147 arena, /* arena */
1148 &uid[0], /* encoding */
1149 NULL, /* subject */
1150 NULL, /* class */
1151 NULL, /* url */
1152 NULL); /* isKRL */
1153 }
1154
1155 static nssPKIObject *
1156 crl_createObject(nssPKIObject *o)
1157 {
1158 return (nssPKIObject *)nssCRL_Create(o);
1159 }
1160
1161 NSS_IMPLEMENT nssPKIObjectCollection *
1162 nssCRLCollection_Create (
1163 NSSTrustDomain *td,
1164 NSSCRL **crlsOpt
1165 )
1166 {
1167 PRStatus status;
1168 nssPKIObjectCollection *collection;
1169 collection = nssPKIObjectCollection_Create(td, NULL, nssPKILock);
1170 collection->objectType = pkiObjectType_CRL;
1171 collection->destroyObject = crl_destroyObject;
1172 collection->getUIDFromObject = crl_getUIDFromObject;
1173 collection->getUIDFromInstance = crl_getUIDFromInstance;
1174 collection->createObject = crl_createObject;
1175 if (crlsOpt) {
1176 for (; *crlsOpt; crlsOpt++) {
1177 nssPKIObject *object = (nssPKIObject *)(*crlsOpt);
1178 status = nssPKIObjectCollection_AddObject(collection, object);
1179 }
1180 }
1181 return collection;
1182 }
1183
1184 NSS_IMPLEMENT NSSCRL **
1185 nssPKIObjectCollection_GetCRLs (
1186 nssPKIObjectCollection *collection,
1187 NSSCRL **rvOpt,
1188 PRUint32 maximumOpt,
1189 NSSArena *arenaOpt
1190 )
1191 {
1192 PRStatus status;
1193 PRUint32 rvSize;
1194 PRBool allocated = PR_FALSE;
1195 if (collection->size == 0) {
1196 return (NSSCRL **)NULL;
1197 }
1198 if (maximumOpt == 0) {
1199 rvSize = collection->size;
1200 } else {
1201 rvSize = PR_MIN(collection->size, maximumOpt);
1202 }
1203 if (!rvOpt) {
1204 rvOpt = nss_ZNEWARRAY(arenaOpt, NSSCRL *, rvSize + 1);
1205 if (!rvOpt) {
1206 return (NSSCRL **)NULL;
1207 }
1208 allocated = PR_TRUE;
1209 }
1210 status = nssPKIObjectCollection_GetObjects(collection,
1211 (nssPKIObject **)rvOpt,
1212 rvSize);
1213 if (status != PR_SUCCESS) {
1214 if (allocated) {
1215 nss_ZFreeIf(rvOpt);
1216 }
1217 return (NSSCRL **)NULL;
1218 }
1219 return rvOpt;
1220 }
1221
1222 /* how bad would it be to have a static now sitting around, updated whenever
1223 * this was called? would avoid repeated allocs...
1224 */
1225 NSS_IMPLEMENT NSSTime *
1226 NSSTime_Now (
1227 NSSTime *timeOpt
1228 )
1229 {
1230 return NSSTime_SetPRTime(timeOpt, PR_Now());
1231 }
1232
1233 NSS_IMPLEMENT NSSTime *
1234 NSSTime_SetPRTime (
1235 NSSTime *timeOpt,
1236 PRTime prTime
1237 )
1238 {
1239 NSSTime *rvTime;
1240 rvTime = (timeOpt) ? timeOpt : nss_ZNEW(NULL, NSSTime);
1241 if (rvTime) {
1242 rvTime->prTime = prTime;
1243 }
1244 return rvTime;
1245 }
1246
1247 NSS_IMPLEMENT PRTime
1248 NSSTime_GetPRTime (
1249 NSSTime *time
1250 )
1251 {
1252 return time->prTime;
1253 }
1254
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)