1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
52 SEC_ASN1_MKSUB(SEC_AnyTemplate)
53 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
54 SEC_ASN1_MKSUB(SEC_IA5StringTemplate)
55 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
56 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
58 static const SEC_ASN1Template CERTNameConstraintTemplate[] = {
59 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraint) },
60 { SEC_ASN1_ANY, offsetof(CERTNameConstraint, DERName) },
61 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
62 offsetof(CERTNameConstraint, min),
63 SEC_ASN1_SUB(SEC_IntegerTemplate) },
64 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
65 offsetof(CERTNameConstraint, max),
66 SEC_ASN1_SUB(SEC_IntegerTemplate) },
70 const SEC_ASN1Template CERT_NameConstraintSubtreeSubTemplate[] = {
71 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
74 static const SEC_ASN1Template CERTNameConstraintsTemplate[] = {
75 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraints) },
76 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
77 offsetof(CERTNameConstraints, DERPermited),
78 CERT_NameConstraintSubtreeSubTemplate},
79 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
80 offsetof(CERTNameConstraints, DERExcluded),
81 CERT_NameConstraintSubtreeSubTemplate},
86 static const SEC_ASN1Template CERTOthNameTemplate[] = {
87 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OtherName) },
89 offsetof(OtherName, oid) },
90 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
91 SEC_ASN1_XTRN | 0, offsetof(OtherName, name),
92 SEC_ASN1_SUB(SEC_AnyTemplate) },
96 static const SEC_ASN1Template CERTOtherNameTemplate[] = {
97 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0 ,
98 offsetof(CERTGeneralName, name.OthName), CERTOthNameTemplate,
99 sizeof(CERTGeneralName) }
102 static const SEC_ASN1Template CERTOtherName2Template[] = {
103 { SEC_ASN1_SEQUENCE | SEC_ASN1_CONTEXT_SPECIFIC | 0 ,
104 0, NULL, sizeof(CERTGeneralName) },
105 { SEC_ASN1_OBJECT_ID,
106 offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, oid) },
108 offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, name) },
112 static const SEC_ASN1Template CERT_RFC822NameTemplate[] = {
113 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1 ,
114 offsetof(CERTGeneralName, name.other),
115 SEC_ASN1_SUB(SEC_IA5StringTemplate),
116 sizeof (CERTGeneralName)}
119 static const SEC_ASN1Template CERT_DNSNameTemplate[] = {
120 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2 ,
121 offsetof(CERTGeneralName, name.other),
122 SEC_ASN1_SUB(SEC_IA5StringTemplate),
123 sizeof (CERTGeneralName)}
126 static const SEC_ASN1Template CERT_X400AddressTemplate[] = {
127 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 3,
128 offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
129 sizeof (CERTGeneralName)}
132 static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = {
133 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
134 SEC_ASN1_XTRN | 4, offsetof(CERTGeneralName, derDirectoryName),
135 SEC_ASN1_SUB(SEC_AnyTemplate), sizeof (CERTGeneralName)}
139 static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = {
140 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 5,
141 offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
142 sizeof (CERTGeneralName)}
145 static const SEC_ASN1Template CERT_URITemplate[] = {
146 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 6 ,
147 offsetof(CERTGeneralName, name.other),
148 SEC_ASN1_SUB(SEC_IA5StringTemplate),
149 sizeof (CERTGeneralName)}
152 static const SEC_ASN1Template CERT_IPAddressTemplate[] = {
153 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 7 ,
154 offsetof(CERTGeneralName, name.other),
155 SEC_ASN1_SUB(SEC_OctetStringTemplate),
156 sizeof (CERTGeneralName)}
159 static const SEC_ASN1Template CERT_RegisteredIDTemplate[] = {
160 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 8 ,
161 offsetof(CERTGeneralName, name.other),
162 SEC_ASN1_SUB(SEC_ObjectIDTemplate),
163 sizeof (CERTGeneralName)}
167 const SEC_ASN1Template CERT_GeneralNamesTemplate[] = {
168 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
174 CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type)
176 CERTGeneralName *name = arena
177 ? PORT_ArenaZNew(arena, CERTGeneralName)
178 : PORT_ZNew(CERTGeneralName);
181 name->l.prev = name->l.next = &name->l;
186 /* Copy content of one General Name to another.
187 ** Caller has allocated destination general name.
188 ** This function does not change the destinate's GeneralName's list linkage.
191 cert_CopyOneGeneralName(PRArenaPool *arena,
192 CERTGeneralName *dest,
193 CERTGeneralName *src)
198 PORT_Assert(dest != NULL);
199 dest->type = src->type;
201 mark = PORT_ArenaMark(arena);
204 case certDirectoryName:
205 rv = SECITEM_CopyItem(arena, &dest->derDirectoryName,
206 &src->derDirectoryName);
207 if (rv == SECSuccess)
208 rv = CERT_CopyName(arena, &dest->name.directoryName,
209 &src->name.directoryName);
213 rv = SECITEM_CopyItem(arena, &dest->name.OthName.name,
214 &src->name.OthName.name);
215 if (rv == SECSuccess)
216 rv = SECITEM_CopyItem(arena, &dest->name.OthName.oid,
217 &src->name.OthName.oid);
221 rv = SECITEM_CopyItem(arena, &dest->name.other,
226 if (rv != SECSuccess) {
227 PORT_ArenaRelease(arena, mark);
229 PORT_ArenaUnmark(arena, mark);
236 CERT_DestroyGeneralNameList(CERTGeneralNameList *list)
243 if (--list->refCount <= 0 && list->arena != NULL) {
244 PORT_FreeArena(list->arena, PR_FALSE);
246 PZ_DestroyLock(lock);
254 CERTGeneralNameList *
255 CERT_CreateGeneralNameList(CERTGeneralName *name) {
257 CERTGeneralNameList *list = NULL;
259 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
263 list = PORT_ArenaZNew(arena, CERTGeneralNameList);
268 list->name = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
271 rv = CERT_CopyGeneralName(arena, list->name, name);
272 if (rv != SECSuccess)
275 list->lock = PZ_NewLock(nssILockList);
284 PORT_FreeArena(arena, PR_FALSE);
289 CERT_GetNextGeneralName(CERTGeneralName *current)
293 next = current->l.next;
294 return (CERTGeneralName *) (((char *) next) - offsetof(CERTGeneralName, l));
298 CERT_GetPrevGeneralName(CERTGeneralName *current)
301 prev = current->l.prev;
302 return (CERTGeneralName *) (((char *) prev) - offsetof(CERTGeneralName, l));
306 CERT_GetNextNameConstraint(CERTNameConstraint *current)
310 next = current->l.next;
311 return (CERTNameConstraint *) (((char *) next) - offsetof(CERTNameConstraint, l));
315 CERT_GetPrevNameConstraint(CERTNameConstraint *current)
318 prev = current->l.prev;
319 return (CERTNameConstraint *) (((char *) prev) - offsetof(CERTNameConstraint, l));
323 CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, PRArenaPool *arena)
326 const SEC_ASN1Template * template;
330 PORT_SetError(SEC_ERROR_INVALID_ARGS);
333 /* TODO: mark arena */
335 dest = PORT_ArenaZNew(arena, SECItem);
339 if (genName->type == certDirectoryName) {
340 if (genName->derDirectoryName.data == NULL) {
341 /* The field hasn't been encoded yet. */
343 SEC_ASN1EncodeItem (arena, &(genName->derDirectoryName),
344 &(genName->name.directoryName),
349 if (genName->derDirectoryName.data == NULL) {
353 switch (genName->type) {
354 case certURI: template = CERT_URITemplate; break;
355 case certRFC822Name: template = CERT_RFC822NameTemplate; break;
356 case certDNSName: template = CERT_DNSNameTemplate; break;
357 case certIPAddress: template = CERT_IPAddressTemplate; break;
358 case certOtherName: template = CERTOtherNameTemplate; break;
359 case certRegisterID: template = CERT_RegisteredIDTemplate; break;
360 /* for this type, we expect the value is already encoded */
361 case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break;
362 /* for this type, we expect the value is already encoded */
363 case certX400Address: template = CERT_X400AddressTemplate; break;
364 case certDirectoryName: template = CERT_DirectoryNameTemplate; break;
366 PORT_Assert(0); goto loser;
368 dest = SEC_ASN1EncodeItem(arena, dest, genName, template);
372 /* TODO: unmark arena */
375 /* TODO: release arena back to mark */
380 cert_EncodeGeneralNames(PRArenaPool *arena, CERTGeneralName *names)
382 CERTGeneralName *current_name;
383 SECItem **items = NULL;
389 /* TODO: mark arena */
390 current_name = names;
395 while (current_name->l.next != head) {
396 current_name = CERT_GetNextGeneralName(current_name);
399 current_name = CERT_GetNextGeneralName(current_name);
400 items = PORT_ArenaNewArray(arena, SECItem *, count + 1);
404 for (i = 0; i < count; i++) {
405 items[i] = CERT_EncodeGeneralName(current_name, (SECItem *)NULL, arena);
406 if (items[i] == NULL) {
409 current_name = CERT_GetNextGeneralName(current_name);
412 /* TODO: unmark arena */
415 /* TODO: release arena to mark */
420 CERT_DecodeGeneralName(PRArenaPool *reqArena,
421 SECItem *encodedName,
422 CERTGeneralName *genName)
424 const SEC_ASN1Template * template;
425 CERTGeneralNameType genNameType;
426 SECStatus rv = SECSuccess;
427 SECItem* newEncodedName;
430 PORT_SetError(SEC_ERROR_INVALID_ARGS);
433 /* make a copy for decoding so the data decoded with QuickDER doesn't
434 point to temporary memory */
435 newEncodedName = SECITEM_ArenaDupItem(reqArena, encodedName);
436 if (!newEncodedName) {
439 /* TODO: mark arena */
440 genNameType = (CERTGeneralNameType)((*(newEncodedName->data) & 0x0f) + 1);
441 if (genName == NULL) {
442 genName = CERT_NewGeneralName(reqArena, genNameType);
446 genName->type = genNameType;
447 genName->l.prev = genName->l.next = &genName->l;
450 switch (genNameType) {
451 case certURI: template = CERT_URITemplate; break;
452 case certRFC822Name: template = CERT_RFC822NameTemplate; break;
453 case certDNSName: template = CERT_DNSNameTemplate; break;
454 case certIPAddress: template = CERT_IPAddressTemplate; break;
455 case certOtherName: template = CERTOtherNameTemplate; break;
456 case certRegisterID: template = CERT_RegisteredIDTemplate; break;
457 case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break;
458 case certX400Address: template = CERT_X400AddressTemplate; break;
459 case certDirectoryName: template = CERT_DirectoryNameTemplate; break;
463 rv = SEC_QuickDERDecodeItem(reqArena, genName, template, newEncodedName);
464 if (rv != SECSuccess)
466 if (genNameType == certDirectoryName) {
467 rv = SEC_QuickDERDecodeItem(reqArena, &(genName->name.directoryName),
469 &(genName->derDirectoryName));
470 if (rv != SECSuccess)
474 /* TODO: unmark arena */
477 /* TODO: release arena to mark */
482 cert_DecodeGeneralNames (PRArenaPool *arena,
483 SECItem **encodedGenName)
485 PRCList *head = NULL;
486 PRCList *tail = NULL;
487 CERTGeneralName *currentName = NULL;
490 if (!encodedGenName || !arena) {
491 PORT_SetError(SEC_ERROR_INVALID_ARGS);
494 /* TODO: mark arena */
495 while (*encodedGenName != NULL) {
496 currentName = CERT_DecodeGeneralName(arena, *encodedGenName, NULL);
497 if (currentName == NULL)
500 head = &(currentName->l);
503 currentName->l.next = head;
504 currentName->l.prev = tail;
505 tail = head->prev = tail->next = &(currentName->l);
509 /* TODO: unmark arena */
510 return CERT_GetNextGeneralName(currentName);
512 /* TODO: release arena to mark */
517 CERT_DestroyGeneralName(CERTGeneralName *name)
519 cert_DestroyGeneralNames(name);
523 cert_DestroyGeneralNames(CERTGeneralName *name)
525 CERTGeneralName *first;
526 CERTGeneralName *next = NULL;
531 next = CERT_GetNextGeneralName(name);
534 } while (name != first);
539 cert_EncodeNameConstraint(CERTNameConstraint *constraint,
545 dest = PORT_ArenaZNew(arena, SECItem);
550 CERT_EncodeGeneralName(&(constraint->name), &(constraint->DERName), arena);
552 dest = SEC_ASN1EncodeItem (arena, dest, constraint,
553 CERTNameConstraintTemplate);
558 cert_EncodeNameConstraintSubTree(CERTNameConstraint *constraints,
563 CERTNameConstraint *current_constraint = constraints;
564 SECItem **items = NULL;
570 /* TODO: mark arena */
571 if (constraints != NULL) {
574 head = &constraints->l;
575 while (current_constraint->l.next != head) {
576 current_constraint = CERT_GetNextNameConstraint(current_constraint);
579 current_constraint = CERT_GetNextNameConstraint(current_constraint);
580 items = PORT_ArenaZNewArray(arena, SECItem *, count + 1);
584 for (i = 0; i < count; i++) {
585 items[i] = cert_EncodeNameConstraint(current_constraint,
586 (SECItem *) NULL, arena);
587 if (items[i] == NULL) {
590 current_constraint = CERT_GetNextNameConstraint(current_constraint);
596 /* TODO: unmark arena */
599 /* TODO: release arena to mark */
604 cert_EncodeNameConstraints(CERTNameConstraints *constraints,
608 SECStatus rv = SECSuccess;
611 /* TODO: mark arena */
612 if (constraints->permited != NULL) {
613 rv = cert_EncodeNameConstraintSubTree(constraints->permited, arena,
614 &constraints->DERPermited,
616 if (rv == SECFailure) {
620 if (constraints->excluded != NULL) {
621 rv = cert_EncodeNameConstraintSubTree(constraints->excluded, arena,
622 &constraints->DERExcluded,
624 if (rv == SECFailure) {
628 dest = SEC_ASN1EncodeItem(arena, dest, constraints,
629 CERTNameConstraintsTemplate);
633 /* TODO: unmark arena */
636 /* TODO: release arena to mark */
642 cert_DecodeNameConstraint(PRArenaPool *reqArena,
643 SECItem *encodedConstraint)
645 CERTNameConstraint *constraint;
646 SECStatus rv = SECSuccess;
647 CERTGeneralName *temp;
648 SECItem* newEncodedConstraint;
651 PORT_SetError(SEC_ERROR_INVALID_ARGS);
654 newEncodedConstraint = SECITEM_ArenaDupItem(reqArena, encodedConstraint);
655 if (!newEncodedConstraint) {
658 /* TODO: mark arena */
659 constraint = PORT_ArenaZNew(reqArena, CERTNameConstraint);
662 rv = SEC_QuickDERDecodeItem(reqArena, constraint,
663 CERTNameConstraintTemplate,
664 newEncodedConstraint);
665 if (rv != SECSuccess) {
668 temp = CERT_DecodeGeneralName(reqArena, &(constraint->DERName),
669 &(constraint->name));
670 if (temp != &(constraint->name)) {
674 /* ### sjlee: since the name constraint contains only one
675 * CERTGeneralName, the list within CERTGeneralName shouldn't
676 * point anywhere else. Otherwise, bad things will happen.
678 constraint->name.l.prev = constraint->name.l.next = &(constraint->name.l);
679 /* TODO: unmark arena */
682 /* TODO: release arena back to mark */
687 cert_DecodeNameConstraintSubTree(PRArenaPool *arena,
691 CERTNameConstraint *current = NULL;
692 CERTNameConstraint *first = NULL;
693 CERTNameConstraint *last = NULL;
697 /* TODO: mark arena */
698 while (subTree[i] != NULL) {
699 current = cert_DecodeNameConstraint(arena, subTree[i]);
700 if (current == NULL) {
704 first = last = current;
706 current->l.prev = &(last->l);
707 current->l.next = last->l.next;
708 last->l.next = &(current->l);
711 first->l.prev = &(current->l);
712 /* TODO: unmark arena */
715 /* TODO: release arena back to mark */
719 CERTNameConstraints *
720 cert_DecodeNameConstraints(PRArenaPool *reqArena,
721 SECItem *encodedConstraints)
723 CERTNameConstraints *constraints;
725 SECItem* newEncodedConstraints;
728 PORT_SetError(SEC_ERROR_INVALID_ARGS);
731 PORT_Assert(encodedConstraints);
732 newEncodedConstraints = SECITEM_ArenaDupItem(reqArena, encodedConstraints);
734 /* TODO: mark arena */
735 constraints = PORT_ArenaZNew(reqArena, CERTNameConstraints);
736 if (constraints == NULL) {
739 rv = SEC_QuickDERDecodeItem(reqArena, constraints,
740 CERTNameConstraintsTemplate,
741 newEncodedConstraints);
742 if (rv != SECSuccess) {
745 if (constraints->DERPermited != NULL &&
746 constraints->DERPermited[0] != NULL) {
747 constraints->permited =
748 cert_DecodeNameConstraintSubTree(reqArena,
749 constraints->DERPermited,
751 if (constraints->permited == NULL) {
755 if (constraints->DERExcluded != NULL &&
756 constraints->DERExcluded[0] != NULL) {
757 constraints->excluded =
758 cert_DecodeNameConstraintSubTree(reqArena,
759 constraints->DERExcluded,
761 if (constraints->excluded == NULL) {
765 /* TODO: unmark arena */
768 /* TODO: release arena back to mark */
772 /* Copy a chain of one or more general names to a destination chain.
773 ** Caller has allocated at least the first destination GeneralName struct.
774 ** Both source and destination chains are circular doubly-linked lists.
775 ** The first source struct is copied to the first destination struct.
776 ** If the source chain has more than one member, and the destination chain
777 ** has only one member, then this function allocates new structs for all but
778 ** the first copy from the arena and links them into the destination list.
779 ** If the destination struct is part of a list with more than one member,
780 ** then this function traverses both the source and destination lists,
781 ** copying each source struct to the corresponding dest struct.
782 ** In that case, the destination list MUST contain at least as many
783 ** structs as the source list or some dest entries will be overwritten.
786 CERT_CopyGeneralName(PRArenaPool *arena,
787 CERTGeneralName *dest,
788 CERTGeneralName *src)
791 CERTGeneralName *destHead = dest;
792 CERTGeneralName *srcHead = src;
794 PORT_Assert(dest != NULL);
796 PORT_SetError(SEC_ERROR_INVALID_ARGS);
799 /* TODO: mark arena */
801 rv = cert_CopyOneGeneralName(arena, dest, src);
802 if (rv != SECSuccess)
804 src = CERT_GetNextGeneralName(src);
805 /* if there is only one general name, we shouldn't do this */
806 if (src != srcHead) {
807 if (dest->l.next == &destHead->l) {
808 CERTGeneralName *temp;
809 temp = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
812 temp->l.next = &destHead->l;
813 temp->l.prev = &dest->l;
814 destHead->l.prev = &temp->l;
815 dest->l.next = &temp->l;
818 dest = CERT_GetNextGeneralName(dest);
821 } while (src != srcHead && rv == SECSuccess);
822 /* TODO: unmark arena */
825 /* TODO: release back to mark */
830 CERTGeneralNameList *
831 CERT_DupGeneralNameList(CERTGeneralNameList *list)
836 PZ_Unlock(list->lock);
841 /* Allocate space and copy CERTNameConstraint from src to dest */
843 CERT_CopyNameConstraint(PRArenaPool *arena,
844 CERTNameConstraint *dest,
845 CERTNameConstraint *src)
849 /* TODO: mark arena */
851 dest = PORT_ArenaZNew(arena, CERTNameConstraint);
854 /* mark that it is not linked */
855 dest->name.l.prev = dest->name.l.next = &(dest->name.l);
857 rv = CERT_CopyGeneralName(arena, &dest->name, &src->name);
858 if (rv != SECSuccess) {
861 rv = SECITEM_CopyItem(arena, &dest->DERName, &src->DERName);
862 if (rv != SECSuccess) {
865 rv = SECITEM_CopyItem(arena, &dest->min, &src->min);
866 if (rv != SECSuccess) {
869 rv = SECITEM_CopyItem(arena, &dest->max, &src->max);
870 if (rv != SECSuccess) {
873 dest->l.prev = dest->l.next = &dest->l;
874 /* TODO: unmark arena */
877 /* TODO: release arena to mark */
883 cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2)
892 } else if (list2 == NULL) {
897 end1 = list1->l.prev;
898 end2 = list2->l.prev;
909 cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2)
918 } else if (list2 == NULL) {
923 end1 = list1->l.prev;
924 end2 = list2->l.prev;
934 /* Add a CERTNameConstraint to the CERTNameConstraint list */
936 CERT_AddNameConstraint(CERTNameConstraint *list,
937 CERTNameConstraint *constraint)
939 PORT_Assert(constraint != NULL);
940 constraint->l.next = constraint->l.prev = &constraint->l;
941 list = cert_CombineConstraintsLists(list, constraint);
947 CERT_GetNameConstraintByType (CERTNameConstraint *constraints,
948 CERTGeneralNameType type,
949 CERTNameConstraint **returnList,
952 CERTNameConstraint *current = NULL;
959 mark = PORT_ArenaMark(arena);
961 current = constraints;
963 PORT_Assert(current->name.type);
964 if (current->name.type == type) {
965 CERTNameConstraint *temp;
966 temp = CERT_CopyNameConstraint(arena, NULL, current);
969 *returnList = CERT_AddNameConstraint(*returnList, temp);
971 current = CERT_GetNextNameConstraint(current);
972 } while (current != constraints);
973 PORT_ArenaUnmark(arena, mark);
977 PORT_ArenaRelease(arena, mark);
982 CERT_GetGeneralNameByType (CERTGeneralName *genNames,
983 CERTGeneralNameType type, PRBool derFormat)
985 CERTGeneralName *current;
992 if (current->type == type) {
995 case certEDIPartyName:
999 case certX400Address:
1001 return (void *)¤t->name.other; /* SECItem * */
1004 return (void *)¤t->name.OthName; /* OthName * */
1006 case certDirectoryName:
1008 ? (void *)¤t->derDirectoryName /* SECItem * */
1009 : (void *)¤t->name.directoryName; /* CERTName * */
1014 current = CERT_GetNextGeneralName(current);
1015 } while (current != genNames);
1020 CERT_GetNamesLength(CERTGeneralName *names)
1023 CERTGeneralName *first;
1026 if (names != NULL) {
1029 names = CERT_GetNextGeneralName(names);
1030 } while (names != first);
1035 /* Creates new GeneralNames for any email addresses found in the
1036 ** input DN, and links them onto the list for the DN.
1039 cert_ExtractDNEmailAddrs(CERTGeneralName *name, PLArenaPool *arena)
1041 CERTGeneralName *nameList = NULL;
1042 const CERTRDN **nRDNs = (const CERTRDN **)(name->name.directoryName.rdns);
1043 SECStatus rv = SECSuccess;
1045 PORT_Assert(name->type == certDirectoryName);
1046 if (name->type != certDirectoryName) {
1047 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1050 /* TODO: mark arena */
1051 while (nRDNs && *nRDNs) { /* loop over RDNs */
1052 const CERTRDN *nRDN = *nRDNs++;
1053 CERTAVA **nAVAs = nRDN->avas;
1054 while (nAVAs && *nAVAs) { /* loop over AVAs */
1056 CERTAVA *nAVA = *nAVAs++;
1057 tag = CERT_GetAVATag(nAVA);
1058 if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS ||
1059 tag == SEC_OID_RFC1274_MAIL) { /* email AVA */
1060 CERTGeneralName *newName = NULL;
1061 SECItem *avaValue = CERT_DecodeAVAValue(&nAVA->value);
1065 newName = CERT_NewGeneralName(arena, certRFC822Name);
1067 rv = SECITEM_CopyItem(arena, &newName->name.other, avaValue);
1069 SECITEM_FreeItem(avaValue, PR_TRUE);
1070 if (rv != SECSuccess)
1072 nameList = cert_CombineNamesLists(nameList, newName);
1073 } /* handle one email AVA */
1074 } /* loop over AVAs */
1075 } /* loop over RDNs */
1076 /* combine new names with old one. */
1077 name = cert_CombineNamesLists(name, nameList);
1078 /* TODO: unmark arena */
1082 /* TODO: release arena back to mark */
1086 /* Extract all names except Subject Common Name from a cert
1087 ** in preparation for a name constraints test.
1090 CERT_GetCertificateNames(CERTCertificate *cert, PRArenaPool *arena)
1092 return CERT_GetConstrainedCertificateNames(cert, arena, PR_FALSE);
1095 /* This function is called by CERT_VerifyCertChain to extract all
1096 ** names from a cert in preparation for a name constraints test.
1099 CERT_GetConstrainedCertificateNames(CERTCertificate *cert, PRArenaPool *arena,
1100 PRBool includeSubjectCommonName)
1102 CERTGeneralName *DN;
1103 CERTGeneralName *SAN;
1104 PRUint32 numDNSNames = 0;
1108 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1111 /* TODO: mark arena */
1112 DN = CERT_NewGeneralName(arena, certDirectoryName);
1116 rv = CERT_CopyName(arena, &DN->name.directoryName, &cert->subject);
1117 if (rv != SECSuccess) {
1120 rv = SECITEM_CopyItem(arena, &DN->derDirectoryName, &cert->derSubject);
1121 if (rv != SECSuccess) {
1124 /* Extract email addresses from DN, construct CERTGeneralName structs
1125 ** for them, add them to the name list
1127 rv = cert_ExtractDNEmailAddrs(DN, arena);
1128 if (rv != SECSuccess)
1131 /* Now extract any GeneralNames from the subject name names extension. */
1132 SAN = cert_GetSubjectAltNameList(cert, arena);
1134 numDNSNames = cert_CountDNSPatterns(SAN);
1135 DN = cert_CombineNamesLists(DN, SAN);
1137 if (!numDNSNames && includeSubjectCommonName) {
1138 char *cn = CERT_GetCommonName(&cert->subject);
1140 CERTGeneralName *CN = CERT_NewGeneralName(arena, certDNSName);
1142 SECItem cnItem = {siBuffer, NULL, 0};
1143 cnItem.data = (unsigned char *)cn;
1144 cnItem.len = strlen(cn);
1145 rv = SECITEM_CopyItem(arena, &CN->name.other, &cnItem);
1146 if (rv == SECSuccess) {
1147 DN = cert_CombineNamesLists(DN, CN);
1153 if (rv == SECSuccess) {
1154 /* TODO: unmark arena */
1158 /* TODO: release arena to mark */
1162 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for
1163 ** URI name constraints. SECFailure otherwise.
1164 ** If the constraint begins with a dot, it is a domain name, otherwise
1165 ** It is a host name. Examples:
1166 ** Constraint Name Result
1167 ** ------------ --------------- --------
1168 ** foo.bar.com foo.bar.com matches
1169 ** foo.bar.com FoO.bAr.CoM matches
1170 ** foo.bar.com www.foo.bar.com no match
1171 ** foo.bar.com nofoo.bar.com no match
1172 ** .foo.bar.com www.foo.bar.com matches
1173 ** .foo.bar.com nofoo.bar.com no match
1174 ** .foo.bar.com foo.bar.com no match
1175 ** .foo.bar.com www..foo.bar.com no match
1178 compareURIN2C(const SECItem *name, const SECItem *constraint)
1181 /* The spec is silent on intepreting zero-length constraints.
1182 ** We interpret them as matching no URI names.
1184 if (!constraint->len)
1186 if (constraint->data[0] != '.') {
1187 /* constraint is a host name. */
1188 if (name->len != constraint->len ||
1189 PL_strncasecmp((char *)name->data,
1190 (char *)constraint->data, constraint->len))
1194 /* constraint is a domain name. */
1195 if (name->len < constraint->len)
1197 offset = name->len - constraint->len;
1198 if (PL_strncasecmp((char *)(name->data + offset),
1199 (char *)constraint->data, constraint->len))
1202 (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
1207 /* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38)
1209 ** DNS name restrictions are expressed as foo.bar.com. Any DNS name
1210 ** that can be constructed by simply adding to the left hand side of the
1211 ** name satisfies the name constraint. For example, www.foo.bar.com
1212 ** would satisfy the constraint but foo1.bar.com would not.
1214 ** But NIST's PKITS test suite requires that the constraint be treated
1215 ** as a domain name, and requires that any name added to the left hand
1216 ** side end in a dot ".". Sensible, but not strictly following the RFC.
1218 ** Constraint Name RFC 3280 NIST PKITS
1219 ** ------------ --------------- -------- ----------
1220 ** foo.bar.com foo.bar.com matches matches
1221 ** foo.bar.com FoO.bAr.CoM matches matches
1222 ** foo.bar.com www.foo.bar.com matches matches
1223 ** foo.bar.com nofoo.bar.com MATCHES NO MATCH
1224 ** .foo.bar.com www.foo.bar.com matches matches? disallowed?
1225 ** .foo.bar.com foo.bar.com no match no match
1226 ** .foo.bar.com www..foo.bar.com matches probably not
1228 ** We will try to conform to NIST's PKITS tests, and the unstated
1229 ** rules they imply.
1232 compareDNSN2C(const SECItem *name, const SECItem *constraint)
1235 /* The spec is silent on intepreting zero-length constraints.
1236 ** We interpret them as matching all DNSnames.
1238 if (!constraint->len)
1240 if (name->len < constraint->len)
1242 offset = name->len - constraint->len;
1243 if (PL_strncasecmp((char *)(name->data + offset),
1244 (char *)constraint->data, constraint->len))
1247 (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
1252 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for
1253 ** internet email addresses. SECFailure otherwise.
1254 ** If constraint contains a '@' then the two strings much match exactly.
1255 ** Else if constraint starts with a '.'. then it must match the right-most
1256 ** substring of the name,
1257 ** else constraint string must match entire name after the name's '@'.
1258 ** Empty constraint string matches all names. All comparisons case insensitive.
1261 compareRFC822N2C(const SECItem *name, const SECItem *constraint)
1264 if (!constraint->len)
1266 if (name->len < constraint->len)
1268 if (constraint->len == 1 && constraint->data[0] == '.')
1270 for (offset = constraint->len - 1; offset >= 0; --offset) {
1271 if (constraint->data[offset] == '@') {
1272 return (name->len == constraint->len &&
1273 !PL_strncasecmp((char *)name->data,
1274 (char *)constraint->data, constraint->len))
1275 ? SECSuccess : SECFailure;
1278 offset = name->len - constraint->len;
1279 if (PL_strncasecmp((char *)(name->data + offset),
1280 (char *)constraint->data, constraint->len))
1282 if (constraint->data[0] == '.')
1284 if (offset > 0 && name->data[offset - 1] == '@')
1289 /* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address.
1290 ** constraint contains an address of the same length, and a subnet mask
1291 ** of the same length. Compare name's address to the constraint's
1292 ** address, subject to the mask.
1293 ** Return SECSuccess if they match, SECFailure if they don't.
1296 compareIPaddrN2C(const SECItem *name, const SECItem *constraint)
1299 if (name->len == 4 && constraint->len == 8) { /* ipv4 addr */
1300 for (i = 0; i < 4; i++) {
1301 if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+4])
1306 if (name->len == 16 && constraint->len == 32) { /* ipv6 addr */
1307 for (i = 0; i < 16; i++) {
1308 if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+16])
1317 /* start with a SECItem that points to a URI. Parse it lookingg for
1318 ** a hostname. Modify item->data and item->len to define the hostname,
1319 ** but do not modify and data at item->data.
1320 ** If anything goes wrong, the contents of *item are undefined.
1323 parseUriHostname(SECItem * item)
1326 PRBool found = PR_FALSE;
1327 for (i = 0; (unsigned)(i+2) < item->len; ++i) {
1328 if (item->data[i ] == ':' &&
1329 item->data[i+1] == '/' &&
1330 item->data[i+2] == '/') {
1340 /* now look for a '/', which is an upper bound in the end of the name */
1341 for (i = 0; (unsigned)i < item->len; ++i) {
1342 if (item->data[i] == '/') {
1347 /* now look for a ':', which marks the end of the name */
1348 for (i = item->len; --i >= 0; ) {
1349 if (item->data[i] == ':') {
1354 /* now look for an '@', which marks the beginning of the hostname */
1355 for (i = 0; (unsigned)i < item->len; ++i) {
1356 if (item->data[i] == '@') {
1363 return item->len ? SECSuccess : SECFailure;
1366 /* This function takes one name, and a list of constraints.
1367 ** It searches the constraints looking for a match.
1368 ** It returns SECSuccess if the name satisfies the constraints, i.e.,
1369 ** if excluded, then the name does not match any constraint,
1370 ** if permitted, then the name matches at least one constraint.
1371 ** It returns SECFailure if the name fails to satisfy the constraints,
1372 ** or if some code fails (e.g. out of memory, or invalid constraint)
1375 cert_CompareNameWithConstraints(CERTGeneralName *name,
1376 CERTNameConstraint *constraints,
1379 SECStatus rv = SECSuccess;
1380 SECStatus matched = SECFailure;
1381 CERTNameConstraint *current;
1383 PORT_Assert(constraints); /* caller should not call with NULL */
1385 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1389 current = constraints;
1392 matched = SECFailure;
1393 PORT_Assert(name->type == current->name.type);
1394 switch (name->type) {
1397 matched = compareDNSN2C(&name->name.other,
1398 ¤t->name.name.other);
1401 case certRFC822Name:
1402 matched = compareRFC822N2C(&name->name.other,
1403 ¤t->name.name.other);
1408 /* make a modifiable copy of the URI SECItem. */
1409 SECItem uri = name->name.other;
1410 /* find the hostname in the URI */
1411 rv = parseUriHostname(&uri);
1412 if (rv == SECSuccess) {
1413 /* does our hostname meet the constraint? */
1414 matched = compareURIN2C(&uri, ¤t->name.name.other);
1419 case certDirectoryName:
1420 /* Determine if the constraint directory name is a "prefix"
1421 ** for the directory name being tested.
1424 /* status defaults to SECEqual, so that a constraint with
1425 ** no AVAs will be a wildcard, matching all directory names.
1427 SECComparison status = SECEqual;
1428 const CERTRDN **cRDNs =
1429 (const CERTRDN **)current->name.name.directoryName.rdns;
1430 const CERTRDN **nRDNs =
1431 (const CERTRDN **)name->name.directoryName.rdns;
1432 while (cRDNs && *cRDNs && nRDNs && *nRDNs) {
1433 /* loop over name RDNs and constraint RDNs in lock step */
1434 const CERTRDN *cRDN = *cRDNs++;
1435 const CERTRDN *nRDN = *nRDNs++;
1436 CERTAVA **cAVAs = cRDN->avas;
1437 while (cAVAs && *cAVAs) { /* loop over constraint AVAs */
1438 CERTAVA *cAVA = *cAVAs++;
1439 CERTAVA **nAVAs = nRDN->avas;
1440 while (nAVAs && *nAVAs) { /* loop over name AVAs */
1441 CERTAVA *nAVA = *nAVAs++;
1442 status = CERT_CompareAVA(cAVA, nAVA);
1443 if (status == SECEqual)
1445 } /* loop over name AVAs */
1446 if (status != SECEqual)
1448 } /* loop over constraint AVAs */
1449 if (status != SECEqual)
1451 } /* loop over name RDNs and constraint RDNs */
1452 matched = (status == SECEqual) ? SECSuccess : SECFailure;
1456 case certIPAddress: /* type 8 */
1457 matched = compareIPaddrN2C(&name->name.other,
1458 ¤t->name.name.other);
1461 /* NSS does not know how to compare these "Other" type names with
1462 ** their respective constraints. But it does know how to tell
1463 ** if the constraint applies to the type of name (by comparing
1464 ** the constraint OID to the name OID). NSS makes no use of "Other"
1465 ** type names at all, so NSS errs on the side of leniency for these
1466 ** types, provided that their OIDs match. So, when an "Other"
1467 ** name constraint appears in an excluded subtree, it never causes
1468 ** a name to fail. When an "Other" name constraint appears in a
1469 ** permitted subtree, AND the constraint's OID matches the name's
1470 ** OID, then name is treated as if it matches the constraint.
1472 case certOtherName: /* type 1 */
1473 matched = (!excluded &&
1474 name->type == current->name.type &&
1475 SECITEM_ItemsAreEqual(&name->name.OthName.oid,
1476 ¤t->name.name.OthName.oid))
1477 ? SECSuccess : SECFailure;
1480 /* NSS does not know how to compare these types of names with their
1481 ** respective constraints. But NSS makes no use of these types of
1482 ** names at all, so it errs on the side of leniency for these types.
1483 ** Constraints for these types of names never cause the name to
1484 ** fail the constraints test. NSS behaves as if the name matched
1485 ** for permitted constraints, and did not match for excluded ones.
1487 case certX400Address: /* type 4 */
1488 case certEDIPartyName: /* type 6 */
1489 case certRegisterID: /* type 9 */
1490 matched = excluded ? SECFailure : SECSuccess;
1493 default: /* non-standard types are not supported */
1497 if (matched == SECSuccess || rv != SECSuccess)
1499 current = CERT_GetNextNameConstraint(current);
1500 } while (current != constraints);
1501 if (rv == SECSuccess) {
1502 if (matched == SECSuccess)
1503 rv = excluded ? SECFailure : SECSuccess;
1505 rv = excluded ? SECSuccess : SECFailure;
1512 /* Add and link a CERTGeneralName to a CERTNameConstraint list. Most
1513 ** likely the CERTNameConstraint passed in is either the permitted
1514 ** list or the excluded list of a CERTNameConstraints.
1517 CERT_AddNameConstraintByGeneralName(PLArenaPool *arena,
1518 CERTNameConstraint **constraints,
1519 CERTGeneralName *name)
1522 CERTNameConstraint *current = NULL;
1523 CERTNameConstraint *first = *constraints;
1526 mark = PORT_ArenaMark(arena);
1528 current = PORT_ArenaZNew(arena, CERTNameConstraint);
1529 if (current == NULL) {
1534 rv = cert_CopyOneGeneralName(arena, ¤t->name, name);
1535 if (rv != SECSuccess) {
1539 current->name.l.prev = current->name.l.next = &(current->name.l);
1541 if (first == NULL) {
1542 *constraints = current;
1543 PR_INIT_CLIST(¤t->l);
1545 PR_INSERT_BEFORE(¤t->l, &first->l);
1549 if (rv == SECFailure) {
1550 PORT_ArenaRelease(arena, mark);
1552 PORT_ArenaUnmark(arena, mark);
1557 /* Extract the name constraints extension from the CA cert. */
1559 CERT_FindNameConstraintsExten(PRArenaPool *arena,
1560 CERTCertificate *cert,
1561 CERTNameConstraints **constraints)
1563 SECStatus rv = SECSuccess;
1564 SECItem constraintsExtension;
1567 *constraints = NULL;
1569 rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS,
1570 &constraintsExtension);
1571 if (rv != SECSuccess) {
1572 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
1578 mark = PORT_ArenaMark(arena);
1580 *constraints = cert_DecodeNameConstraints(arena, &constraintsExtension);
1581 if (*constraints == NULL) { /* decode failed */
1584 PORT_Free (constraintsExtension.data);
1586 if (rv == SECFailure) {
1587 PORT_ArenaRelease(arena, mark);
1589 PORT_ArenaUnmark(arena, mark);
1595 /* Verify name against all the constraints relevant to that type of
1599 CERT_CheckNameSpace(PRArenaPool *arena,
1600 CERTNameConstraints *constraints,
1601 CERTGeneralName *currentName)
1603 CERTNameConstraint *matchingConstraints;
1604 SECStatus rv = SECSuccess;
1606 if (constraints->excluded != NULL) {
1607 rv = CERT_GetNameConstraintByType(constraints->excluded,
1609 &matchingConstraints, arena);
1610 if (rv == SECSuccess && matchingConstraints != NULL) {
1611 rv = cert_CompareNameWithConstraints(currentName,
1612 matchingConstraints,
1615 if (rv != SECSuccess) {
1620 if (constraints->permited != NULL) {
1621 rv = CERT_GetNameConstraintByType(constraints->permited,
1623 &matchingConstraints, arena);
1624 if (rv == SECSuccess && matchingConstraints != NULL) {
1625 rv = cert_CompareNameWithConstraints(currentName,
1626 matchingConstraints,
1629 if (rv != SECSuccess) {
1637 /* Extract the name constraints extension from the CA cert.
1638 ** Test each and every name in namesList against all the constraints
1639 ** relevant to that type of name.
1640 ** Returns NULL in pBadCert for success, if all names are acceptable.
1641 ** If some name is not acceptable, returns a pointer to the cert that
1642 ** contained that name.
1645 CERT_CompareNameSpace(CERTCertificate *cert,
1646 CERTGeneralName *namesList,
1647 CERTCertificate **certsList,
1648 PRArenaPool *reqArena,
1649 CERTCertificate **pBadCert)
1651 SECStatus rv = SECSuccess;
1652 CERTNameConstraints *constraints;
1653 CERTGeneralName *currentName;
1655 CERTCertificate *badCert = NULL;
1657 /* If no names to check, then no names can be bad. */
1660 rv = CERT_FindNameConstraintsExten(reqArena, cert, &constraints);
1661 if (rv != SECSuccess) {
1666 currentName = namesList;
1669 rv = CERT_CheckNameSpace(reqArena, constraints, currentName);
1670 if (rv != SECSuccess) {
1674 currentName = CERT_GetNextGeneralName(currentName);
1676 } while (currentName != namesList);
1679 if (rv != SECSuccess) {
1680 badCert = (count >= 0) ? certsList[count] : cert;
1683 *pBadCert = badCert;
1689 /* not exported from shared libs, not used. Turn on if we ever need it. */
1691 CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b)
1693 CERTGeneralName *currentA;
1694 CERTGeneralName *currentB;
1701 if (currentB == NULL) {
1704 currentB = CERT_GetNextGeneralName(currentB);
1705 currentA = CERT_GetNextGeneralName(currentA);
1706 } while (currentA != a);
1708 if (currentB != b) {
1716 if (currentB->type == currentA->type) {
1717 switch (currentB->type) {
1719 case certEDIPartyName:
1721 case certRegisterID:
1722 case certRFC822Name:
1723 case certX400Address:
1725 if (SECITEM_CompareItem(¤tA->name.other,
1726 ¤tB->name.other)
1732 if (SECITEM_CompareItem(¤tA->name.OthName.oid,
1733 ¤tB->name.OthName.oid)
1735 SECITEM_CompareItem(¤tA->name.OthName.name,
1736 ¤tB->name.OthName.name)
1741 case certDirectoryName:
1742 if (CERT_CompareName(¤tA->name.directoryName,
1743 ¤tB->name.directoryName)
1750 currentB = CERT_GetNextGeneralName(currentB);
1751 } while (currentB != b && found != PR_TRUE);
1752 if (found != PR_TRUE) {
1755 currentA = CERT_GetNextGeneralName(currentA);
1756 } while (currentA != a);
1761 CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b)
1768 if (a != NULL && b != NULL) {
1771 rv = CERT_CompareGeneralName(a->name, b->name);
1782 /* This function is not exported from NSS shared libraries, and is not
1783 ** used inside of NSS.
1784 ** XXX it doesn't check for failed allocations. :-(
1787 CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list,
1788 CERTGeneralNameType type,
1791 CERTName *name = NULL;
1792 SECItem *item = NULL;
1793 OtherName *other = NULL;
1794 OtherName *tmpOther = NULL;
1797 PZ_Lock(list->lock);
1798 data = CERT_GetGeneralNameByType(list->name, type, PR_FALSE);
1802 case certEDIPartyName:
1804 case certRegisterID:
1805 case certRFC822Name:
1806 case certX400Address:
1808 if (arena != NULL) {
1809 item = PORT_ArenaNew(arena, SECItem);
1811 XXX SECITEM_CopyItem(arena, item, (SECItem *) data);
1814 item = SECITEM_DupItem((SECItem *) data);
1816 PZ_Unlock(list->lock);
1819 other = (OtherName *) data;
1820 if (arena != NULL) {
1821 tmpOther = PORT_ArenaNew(arena, OtherName);
1823 tmpOther = PORT_New(OtherName);
1825 if (tmpOther != NULL) {
1826 XXX SECITEM_CopyItem(arena, &tmpOther->oid, &other->oid);
1827 XXX SECITEM_CopyItem(arena, &tmpOther->name, &other->name);
1829 PZ_Unlock(list->lock);
1831 case certDirectoryName:
1833 name = PORT_ArenaZNew(list->arena, CERTName);
1835 XXX CERT_CopyName(arena, name, (CERTName *) data);
1838 PZ_Unlock(list->lock);
1842 PZ_Unlock(list->lock);
1848 /* This function is not exported from NSS shared libraries, and is not
1849 ** used inside of NSS.
1850 ** XXX it should NOT be a void function, since it does allocations
1854 CERT_AddGeneralNameToList(CERTGeneralNameList *list,
1855 CERTGeneralNameType type,
1856 void *data, SECItem *oid)
1858 CERTGeneralName *name;
1860 if (list != NULL && data != NULL) {
1861 PZ_Lock(list->lock);
1862 name = CERT_NewGeneralName(list->arena, type);
1867 case certEDIPartyName:
1869 case certRegisterID:
1870 case certRFC822Name:
1871 case certX400Address:
1873 XXX SECITEM_CopyItem(list->arena, &name->name.other, (SECItem *)data);
1876 XXX SECITEM_CopyItem(list->arena, &name->name.OthName.name,
1878 XXX SECITEM_CopyItem(list->arena, &name->name.OthName.oid,
1881 case certDirectoryName:
1882 XXX CERT_CopyName(list->arena, &name->name.directoryName,
1886 list->name = cert_CombineNamesLists(list->name, name);
1889 PZ_Unlock(list->lock);