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 /* This function is called by CERT_VerifyCertChain to extract all
1087 ** names from a cert in preparation for a name constraints test.
1090 CERT_GetCertificateNames(CERTCertificate
*cert
, PRArenaPool
*arena
)
1092 CERTGeneralName
*DN
;
1093 CERTGeneralName
*altName
= NULL
;
1094 SECItem altNameExtension
= {siBuffer
, NULL
, 0 };
1097 /* TODO: mark arena */
1098 DN
= CERT_NewGeneralName(arena
, certDirectoryName
);
1102 rv
= CERT_CopyName(arena
, &DN
->name
.directoryName
, &cert
->subject
);
1103 if (rv
!= SECSuccess
) {
1106 rv
= SECITEM_CopyItem(arena
, &DN
->derDirectoryName
, &cert
->derSubject
);
1107 if (rv
!= SECSuccess
) {
1110 /* Extract email addresses from DN, construct CERTGeneralName structs
1111 ** for them, add them to the name list
1113 rv
= cert_ExtractDNEmailAddrs(DN
, arena
);
1114 if (rv
!= SECSuccess
)
1117 /* Now extract any GeneralNames from the subject name names extension. */
1118 rv
= CERT_FindCertExtension(cert
, SEC_OID_X509_SUBJECT_ALT_NAME
,
1120 if (rv
== SECSuccess
) {
1121 altName
= CERT_DecodeAltNameExtension(arena
, &altNameExtension
);
1122 rv
= altName
? SECSuccess
: SECFailure
;
1124 if (rv
!= SECSuccess
&& PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND
)
1126 if (altNameExtension
.data
)
1127 SECITEM_FreeItem(&altNameExtension
, PR_FALSE
);
1128 if (rv
!= SECSuccess
)
1130 DN
= cert_CombineNamesLists(DN
, altName
);
1132 /* TODO: unmark arena */
1135 /* TODO: release arena to mark */
1139 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for
1140 ** URI name constraints. SECFailure otherwise.
1141 ** If the constraint begins with a dot, it is a domain name, otherwise
1142 ** It is a host name. Examples:
1143 ** Constraint Name Result
1144 ** ------------ --------------- --------
1145 ** foo.bar.com foo.bar.com matches
1146 ** foo.bar.com FoO.bAr.CoM matches
1147 ** foo.bar.com www.foo.bar.com no match
1148 ** foo.bar.com nofoo.bar.com no match
1149 ** .foo.bar.com www.foo.bar.com matches
1150 ** .foo.bar.com nofoo.bar.com no match
1151 ** .foo.bar.com foo.bar.com no match
1152 ** .foo.bar.com www..foo.bar.com no match
1155 compareURIN2C(const SECItem
*name
, const SECItem
*constraint
)
1158 /* The spec is silent on intepreting zero-length constraints.
1159 ** We interpret them as matching no URI names.
1161 if (!constraint
->len
)
1163 if (constraint
->data
[0] != '.') {
1164 /* constraint is a host name. */
1165 if (name
->len
!= constraint
->len
||
1166 PL_strncasecmp((char *)name
->data
,
1167 (char *)constraint
->data
, constraint
->len
))
1171 /* constraint is a domain name. */
1172 if (name
->len
< constraint
->len
)
1174 offset
= name
->len
- constraint
->len
;
1175 if (PL_strncasecmp((char *)(name
->data
+ offset
),
1176 (char *)constraint
->data
, constraint
->len
))
1179 (name
->data
[offset
- 1] == '.') + (constraint
->data
[0] == '.') == 1)
1184 /* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38)
1186 ** DNS name restrictions are expressed as foo.bar.com. Any DNS name
1187 ** that can be constructed by simply adding to the left hand side of the
1188 ** name satisfies the name constraint. For example, www.foo.bar.com
1189 ** would satisfy the constraint but foo1.bar.com would not.
1191 ** But NIST's PKITS test suite requires that the constraint be treated
1192 ** as a domain name, and requires that any name added to the left hand
1193 ** side end in a dot ".". Sensible, but not strictly following the RFC.
1195 ** Constraint Name RFC 3280 NIST PKITS
1196 ** ------------ --------------- -------- ----------
1197 ** foo.bar.com foo.bar.com matches matches
1198 ** foo.bar.com FoO.bAr.CoM matches matches
1199 ** foo.bar.com www.foo.bar.com matches matches
1200 ** foo.bar.com nofoo.bar.com MATCHES NO MATCH
1201 ** .foo.bar.com www.foo.bar.com matches matches? disallowed?
1202 ** .foo.bar.com foo.bar.com no match no match
1203 ** .foo.bar.com www..foo.bar.com matches probably not
1205 ** We will try to conform to NIST's PKITS tests, and the unstated
1206 ** rules they imply.
1209 compareDNSN2C(const SECItem
*name
, const SECItem
*constraint
)
1212 /* The spec is silent on intepreting zero-length constraints.
1213 ** We interpret them as matching all DNSnames.
1215 if (!constraint
->len
)
1217 if (name
->len
< constraint
->len
)
1219 offset
= name
->len
- constraint
->len
;
1220 if (PL_strncasecmp((char *)(name
->data
+ offset
),
1221 (char *)constraint
->data
, constraint
->len
))
1224 (name
->data
[offset
- 1] == '.') + (constraint
->data
[0] == '.') == 1)
1229 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for
1230 ** internet email addresses. SECFailure otherwise.
1231 ** If constraint contains a '@' then the two strings much match exactly.
1232 ** Else if constraint starts with a '.'. then it must match the right-most
1233 ** substring of the name,
1234 ** else constraint string must match entire name after the name's '@'.
1235 ** Empty constraint string matches all names. All comparisons case insensitive.
1238 compareRFC822N2C(const SECItem
*name
, const SECItem
*constraint
)
1241 if (!constraint
->len
)
1243 if (name
->len
< constraint
->len
)
1245 if (constraint
->len
== 1 && constraint
->data
[0] == '.')
1247 for (offset
= constraint
->len
- 1; offset
>= 0; --offset
) {
1248 if (constraint
->data
[offset
] == '@') {
1249 return (name
->len
== constraint
->len
&&
1250 !PL_strncasecmp((char *)name
->data
,
1251 (char *)constraint
->data
, constraint
->len
))
1252 ? SECSuccess
: SECFailure
;
1255 offset
= name
->len
- constraint
->len
;
1256 if (PL_strncasecmp((char *)(name
->data
+ offset
),
1257 (char *)constraint
->data
, constraint
->len
))
1259 if (constraint
->data
[0] == '.')
1261 if (offset
> 0 && name
->data
[offset
- 1] == '@')
1266 /* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address.
1267 ** constraint contains an address of the same length, and a subnet mask
1268 ** of the same length. Compare name's address to the constraint's
1269 ** address, subject to the mask.
1270 ** Return SECSuccess if they match, SECFailure if they don't.
1273 compareIPaddrN2C(const SECItem
*name
, const SECItem
*constraint
)
1276 if (name
->len
== 4 && constraint
->len
== 8) { /* ipv4 addr */
1277 for (i
= 0; i
< 4; i
++) {
1278 if ((name
->data
[i
] ^ constraint
->data
[i
]) & constraint
->data
[i
+4])
1283 if (name
->len
== 16 && constraint
->len
== 32) { /* ipv6 addr */
1284 for (i
= 0; i
< 16; i
++) {
1285 if ((name
->data
[i
] ^ constraint
->data
[i
]) & constraint
->data
[i
+16])
1294 /* start with a SECItem that points to a URI. Parse it lookingg for
1295 ** a hostname. Modify item->data and item->len to define the hostname,
1296 ** but do not modify and data at item->data.
1297 ** If anything goes wrong, the contents of *item are undefined.
1300 parseUriHostname(SECItem
* item
)
1303 PRBool found
= PR_FALSE
;
1304 for (i
= 0; (unsigned)(i
+2) < item
->len
; ++i
) {
1305 if (item
->data
[i
] == ':' &&
1306 item
->data
[i
+1] == '/' &&
1307 item
->data
[i
+2] == '/') {
1317 /* now look for a '/', which is an upper bound in the end of the name */
1318 for (i
= 0; (unsigned)i
< item
->len
; ++i
) {
1319 if (item
->data
[i
] == '/') {
1324 /* now look for a ':', which marks the end of the name */
1325 for (i
= item
->len
; --i
>= 0; ) {
1326 if (item
->data
[i
] == ':') {
1331 /* now look for an '@', which marks the beginning of the hostname */
1332 for (i
= 0; (unsigned)i
< item
->len
; ++i
) {
1333 if (item
->data
[i
] == '@') {
1340 return item
->len
? SECSuccess
: SECFailure
;
1343 /* This function takes one name, and a list of constraints.
1344 ** It searches the constraints looking for a match.
1345 ** It returns SECSuccess if the name satisfies the constraints, i.e.,
1346 ** if excluded, then the name does not match any constraint,
1347 ** if permitted, then the name matches at least one constraint.
1348 ** It returns SECFailure if the name fails to satisfy the constraints,
1349 ** or if some code fails (e.g. out of memory, or invalid constraint)
1352 cert_CompareNameWithConstraints(CERTGeneralName
*name
,
1353 CERTNameConstraint
*constraints
,
1356 SECStatus rv
= SECSuccess
;
1357 SECStatus matched
= SECFailure
;
1358 CERTNameConstraint
*current
;
1360 PORT_Assert(constraints
); /* caller should not call with NULL */
1362 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1366 current
= constraints
;
1369 matched
= SECFailure
;
1370 PORT_Assert(name
->type
== current
->name
.type
);
1371 switch (name
->type
) {
1374 matched
= compareDNSN2C(&name
->name
.other
,
1375 ¤t
->name
.name
.other
);
1378 case certRFC822Name
:
1379 matched
= compareRFC822N2C(&name
->name
.other
,
1380 ¤t
->name
.name
.other
);
1385 /* make a modifiable copy of the URI SECItem. */
1386 SECItem uri
= name
->name
.other
;
1387 /* find the hostname in the URI */
1388 rv
= parseUriHostname(&uri
);
1389 if (rv
== SECSuccess
) {
1390 /* does our hostname meet the constraint? */
1391 matched
= compareURIN2C(&uri
, ¤t
->name
.name
.other
);
1396 case certDirectoryName
:
1397 /* Determine if the constraint directory name is a "prefix"
1398 ** for the directory name being tested.
1401 /* status defaults to SECEqual, so that a constraint with
1402 ** no AVAs will be a wildcard, matching all directory names.
1404 SECComparison status
= SECEqual
;
1405 const CERTRDN
**cRDNs
=
1406 (const CERTRDN
**)current
->name
.name
.directoryName
.rdns
;
1407 const CERTRDN
**nRDNs
=
1408 (const CERTRDN
**)name
->name
.directoryName
.rdns
;
1409 while (cRDNs
&& *cRDNs
&& nRDNs
&& *nRDNs
) {
1410 /* loop over name RDNs and constraint RDNs in lock step */
1411 const CERTRDN
*cRDN
= *cRDNs
++;
1412 const CERTRDN
*nRDN
= *nRDNs
++;
1413 CERTAVA
**cAVAs
= cRDN
->avas
;
1414 while (cAVAs
&& *cAVAs
) { /* loop over constraint AVAs */
1415 CERTAVA
*cAVA
= *cAVAs
++;
1416 CERTAVA
**nAVAs
= nRDN
->avas
;
1417 while (nAVAs
&& *nAVAs
) { /* loop over name AVAs */
1418 CERTAVA
*nAVA
= *nAVAs
++;
1419 status
= CERT_CompareAVA(cAVA
, nAVA
);
1420 if (status
== SECEqual
)
1422 } /* loop over name AVAs */
1423 if (status
!= SECEqual
)
1425 } /* loop over constraint AVAs */
1426 if (status
!= SECEqual
)
1428 } /* loop over name RDNs and constraint RDNs */
1429 matched
= (status
== SECEqual
) ? SECSuccess
: SECFailure
;
1433 case certIPAddress
: /* type 8 */
1434 matched
= compareIPaddrN2C(&name
->name
.other
,
1435 ¤t
->name
.name
.other
);
1438 /* NSS does not know how to compare these "Other" type names with
1439 ** their respective constraints. But it does know how to tell
1440 ** if the constraint applies to the type of name (by comparing
1441 ** the constraint OID to the name OID). NSS makes no use of "Other"
1442 ** type names at all, so NSS errs on the side of leniency for these
1443 ** types, provided that their OIDs match. So, when an "Other"
1444 ** name constraint appears in an excluded subtree, it never causes
1445 ** a name to fail. When an "Other" name constraint appears in a
1446 ** permitted subtree, AND the constraint's OID matches the name's
1447 ** OID, then name is treated as if it matches the constraint.
1449 case certOtherName
: /* type 1 */
1450 matched
= (!excluded
&&
1451 name
->type
== current
->name
.type
&&
1452 SECITEM_ItemsAreEqual(&name
->name
.OthName
.oid
,
1453 ¤t
->name
.name
.OthName
.oid
))
1454 ? SECSuccess
: SECFailure
;
1457 /* NSS does not know how to compare these types of names with their
1458 ** respective constraints. But NSS makes no use of these types of
1459 ** names at all, so it errs on the side of leniency for these types.
1460 ** Constraints for these types of names never cause the name to
1461 ** fail the constraints test. NSS behaves as if the name matched
1462 ** for permitted constraints, and did not match for excluded ones.
1464 case certX400Address
: /* type 4 */
1465 case certEDIPartyName
: /* type 6 */
1466 case certRegisterID
: /* type 9 */
1467 matched
= excluded
? SECFailure
: SECSuccess
;
1470 default: /* non-standard types are not supported */
1474 if (matched
== SECSuccess
|| rv
!= SECSuccess
)
1476 current
= CERT_GetNextNameConstraint(current
);
1477 } while (current
!= constraints
);
1478 if (rv
== SECSuccess
) {
1479 if (matched
== SECSuccess
)
1480 rv
= excluded
? SECFailure
: SECSuccess
;
1482 rv
= excluded
? SECSuccess
: SECFailure
;
1489 /* Add and link a CERTGeneralName to a CERTNameConstraint list. Most
1490 ** likely the CERTNameConstraint passed in is either the permitted
1491 ** list or the excluded list of a CERTNameConstraints.
1494 CERT_AddNameConstraintByGeneralName(PLArenaPool
*arena
,
1495 CERTNameConstraint
**constraints
,
1496 CERTGeneralName
*name
)
1499 CERTNameConstraint
*current
= NULL
;
1500 CERTNameConstraint
*first
= *constraints
;
1503 mark
= PORT_ArenaMark(arena
);
1505 current
= PORT_ArenaZNew(arena
, CERTNameConstraint
);
1506 if (current
== NULL
) {
1511 rv
= cert_CopyOneGeneralName(arena
, ¤t
->name
, name
);
1512 if (rv
!= SECSuccess
) {
1516 current
->name
.l
.prev
= current
->name
.l
.next
= &(current
->name
.l
);
1518 if (first
== NULL
) {
1519 *constraints
= current
;
1520 PR_INIT_CLIST(¤t
->l
);
1522 PR_INSERT_BEFORE(¤t
->l
, &first
->l
);
1526 if (rv
== SECFailure
) {
1527 PORT_ArenaRelease(arena
, mark
);
1529 PORT_ArenaUnmark(arena
, mark
);
1534 /* Extract the name constraints extension from the CA cert. */
1536 CERT_FindNameConstraintsExten(PRArenaPool
*arena
,
1537 CERTCertificate
*cert
,
1538 CERTNameConstraints
**constraints
)
1540 SECStatus rv
= SECSuccess
;
1541 SECItem constraintsExtension
;
1544 *constraints
= NULL
;
1546 rv
= CERT_FindCertExtension(cert
, SEC_OID_X509_NAME_CONSTRAINTS
,
1547 &constraintsExtension
);
1548 if (rv
!= SECSuccess
) {
1549 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND
) {
1555 mark
= PORT_ArenaMark(arena
);
1557 *constraints
= cert_DecodeNameConstraints(arena
, &constraintsExtension
);
1558 if (*constraints
== NULL
) { /* decode failed */
1561 PORT_Free (constraintsExtension
.data
);
1563 if (rv
== SECFailure
) {
1564 PORT_ArenaRelease(arena
, mark
);
1566 PORT_ArenaUnmark(arena
, mark
);
1572 /* Verify name against all the constraints relevant to that type of
1576 CERT_CheckNameSpace(PRArenaPool
*arena
,
1577 CERTNameConstraints
*constraints
,
1578 CERTGeneralName
*currentName
)
1580 CERTNameConstraint
*matchingConstraints
;
1581 SECStatus rv
= SECSuccess
;
1583 if (constraints
->excluded
!= NULL
) {
1584 rv
= CERT_GetNameConstraintByType(constraints
->excluded
,
1586 &matchingConstraints
, arena
);
1587 if (rv
== SECSuccess
&& matchingConstraints
!= NULL
) {
1588 rv
= cert_CompareNameWithConstraints(currentName
,
1589 matchingConstraints
,
1592 if (rv
!= SECSuccess
) {
1597 if (constraints
->permited
!= NULL
) {
1598 rv
= CERT_GetNameConstraintByType(constraints
->permited
,
1600 &matchingConstraints
, arena
);
1601 if (rv
== SECSuccess
&& matchingConstraints
!= NULL
) {
1602 rv
= cert_CompareNameWithConstraints(currentName
,
1603 matchingConstraints
,
1606 if (rv
!= SECSuccess
) {
1614 /* Extract the name constraints extension from the CA cert.
1615 ** Test each and every name in namesList against all the constraints
1616 ** relevant to that type of name.
1617 ** Returns NULL in pBadCert for success, if all names are acceptable.
1618 ** If some name is not acceptable, returns a pointer to the cert that
1619 ** contained that name.
1622 CERT_CompareNameSpace(CERTCertificate
*cert
,
1623 CERTGeneralName
*namesList
,
1624 CERTCertificate
**certsList
,
1625 PRArenaPool
*reqArena
,
1626 CERTCertificate
**pBadCert
)
1628 SECStatus rv
= SECSuccess
;
1629 CERTNameConstraints
*constraints
;
1630 CERTGeneralName
*currentName
;
1632 CERTCertificate
*badCert
= NULL
;
1634 /* If no names to check, then no names can be bad. */
1637 rv
= CERT_FindNameConstraintsExten(reqArena
, cert
, &constraints
);
1638 if (rv
!= SECSuccess
) {
1643 currentName
= namesList
;
1646 rv
= CERT_CheckNameSpace(reqArena
, constraints
, currentName
);
1647 if (rv
!= SECSuccess
) {
1651 currentName
= CERT_GetNextGeneralName(currentName
);
1653 } while (currentName
!= namesList
);
1656 if (rv
!= SECSuccess
) {
1657 badCert
= (count
>= 0) ? certsList
[count
] : cert
;
1660 *pBadCert
= badCert
;
1665 /* Search the cert for an X509_SUBJECT_ALT_NAME extension.
1666 ** ASN1 Decode it into a list of alternate names.
1667 ** Search the list of alternate names for one with the NETSCAPE_NICKNAME OID.
1668 ** ASN1 Decode that name. Turn the result into a zString.
1669 ** Look for duplicate nickname already in the certdb.
1670 ** If one is found, create a nickname string that is not a duplicate.
1673 CERT_GetNickName(CERTCertificate
*cert
,
1674 CERTCertDBHandle
*handle
,
1675 PRArenaPool
*nicknameArena
)
1677 CERTGeneralName
*current
;
1678 CERTGeneralName
*names
;
1679 char *nickname
= NULL
;
1680 char *returnName
= NULL
;
1681 char *basename
= NULL
;
1682 PRArenaPool
*arena
= NULL
;
1683 CERTCertificate
*tmpcert
;
1687 SECItem altNameExtension
;
1690 if (handle
== NULL
) {
1691 handle
= CERT_GetDefaultCertDB();
1693 altNameExtension
.data
= NULL
;
1694 rv
= CERT_FindCertExtension(cert
, SEC_OID_X509_SUBJECT_ALT_NAME
,
1696 if (rv
!= SECSuccess
) {
1699 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1700 if (arena
== NULL
) {
1703 names
= CERT_DecodeAltNameExtension(arena
, &altNameExtension
);
1704 if (names
== NULL
) {
1709 if (current
->type
== certOtherName
&&
1710 SECOID_FindOIDTag(¤t
->name
.OthName
.oid
) ==
1711 SEC_OID_NETSCAPE_NICKNAME
) {
1715 current
= CERT_GetNextGeneralName(current
);
1716 } while (current
!= names
);
1720 rv
= SEC_QuickDERDecodeItem(arena
, &nick
,
1721 SEC_ASN1_GET(SEC_IA5StringTemplate
),
1722 ¤t
->name
.OthName
.name
);
1723 if (rv
!= SECSuccess
) {
1727 /* make a null terminated string out of nick, with room enough at
1728 ** the end to add on a number of up to 21 digits in length, (a signed
1729 ** 64-bit number in decimal) plus a space and a "#".
1731 nickname
= (char*)PORT_ZAlloc(nick
.len
+ 24);
1734 PORT_Strncpy(nickname
, (char *)nick
.data
, nick
.len
);
1736 /* Don't let this cert's nickname duplicate one already in the DB.
1737 ** If it does, create a variant of the nickname that doesn't.
1740 while ((tmpcert
= CERT_FindCertByNickname(handle
, nickname
)) != NULL
) {
1741 CERT_DestroyCertificate(tmpcert
);
1743 basename
= PORT_Strdup(nickname
);
1748 sprintf(nickname
, "%s #%d", basename
, count
);
1752 if (nicknameArena
) {
1753 returnName
= PORT_ArenaStrdup(nicknameArena
, nickname
);
1755 returnName
= nickname
;
1760 PORT_FreeArena(arena
, PR_FALSE
);
1762 PORT_Free(nickname
);
1764 PORT_Free(basename
);
1765 if (altNameExtension
.data
)
1766 PORT_Free(altNameExtension
.data
);
1771 /* not exported from shared libs, not used. Turn on if we ever need it. */
1773 CERT_CompareGeneralName(CERTGeneralName
*a
, CERTGeneralName
*b
)
1775 CERTGeneralName
*currentA
;
1776 CERTGeneralName
*currentB
;
1783 if (currentB
== NULL
) {
1786 currentB
= CERT_GetNextGeneralName(currentB
);
1787 currentA
= CERT_GetNextGeneralName(currentA
);
1788 } while (currentA
!= a
);
1790 if (currentB
!= b
) {
1798 if (currentB
->type
== currentA
->type
) {
1799 switch (currentB
->type
) {
1801 case certEDIPartyName
:
1803 case certRegisterID
:
1804 case certRFC822Name
:
1805 case certX400Address
:
1807 if (SECITEM_CompareItem(¤tA
->name
.other
,
1808 ¤tB
->name
.other
)
1814 if (SECITEM_CompareItem(¤tA
->name
.OthName
.oid
,
1815 ¤tB
->name
.OthName
.oid
)
1817 SECITEM_CompareItem(¤tA
->name
.OthName
.name
,
1818 ¤tB
->name
.OthName
.name
)
1823 case certDirectoryName
:
1824 if (CERT_CompareName(¤tA
->name
.directoryName
,
1825 ¤tB
->name
.directoryName
)
1832 currentB
= CERT_GetNextGeneralName(currentB
);
1833 } while (currentB
!= b
&& found
!= PR_TRUE
);
1834 if (found
!= PR_TRUE
) {
1837 currentA
= CERT_GetNextGeneralName(currentA
);
1838 } while (currentA
!= a
);
1843 CERT_CompareGeneralNameLists(CERTGeneralNameList
*a
, CERTGeneralNameList
*b
)
1850 if (a
!= NULL
&& b
!= NULL
) {
1853 rv
= CERT_CompareGeneralName(a
->name
, b
->name
);
1864 /* This function is not exported from NSS shared libraries, and is not
1865 ** used inside of NSS.
1866 ** XXX it doesn't check for failed allocations. :-(
1869 CERT_GetGeneralNameFromListByType(CERTGeneralNameList
*list
,
1870 CERTGeneralNameType type
,
1873 CERTName
*name
= NULL
;
1874 SECItem
*item
= NULL
;
1875 OtherName
*other
= NULL
;
1876 OtherName
*tmpOther
= NULL
;
1879 PZ_Lock(list
->lock
);
1880 data
= CERT_GetGeneralNameByType(list
->name
, type
, PR_FALSE
);
1884 case certEDIPartyName
:
1886 case certRegisterID
:
1887 case certRFC822Name
:
1888 case certX400Address
:
1890 if (arena
!= NULL
) {
1891 item
= PORT_ArenaNew(arena
, SECItem
);
1893 XXX
SECITEM_CopyItem(arena
, item
, (SECItem
*) data
);
1896 item
= SECITEM_DupItem((SECItem
*) data
);
1898 PZ_Unlock(list
->lock
);
1901 other
= (OtherName
*) data
;
1902 if (arena
!= NULL
) {
1903 tmpOther
= PORT_ArenaNew(arena
, OtherName
);
1905 tmpOther
= PORT_New(OtherName
);
1907 if (tmpOther
!= NULL
) {
1908 XXX
SECITEM_CopyItem(arena
, &tmpOther
->oid
, &other
->oid
);
1909 XXX
SECITEM_CopyItem(arena
, &tmpOther
->name
, &other
->name
);
1911 PZ_Unlock(list
->lock
);
1913 case certDirectoryName
:
1915 name
= PORT_ArenaZNew(list
->arena
, CERTName
);
1917 XXX
CERT_CopyName(arena
, name
, (CERTName
*) data
);
1920 PZ_Unlock(list
->lock
);
1924 PZ_Unlock(list
->lock
);
1930 /* This function is not exported from NSS shared libraries, and is not
1931 ** used inside of NSS.
1932 ** XXX it should NOT be a void function, since it does allocations
1936 CERT_AddGeneralNameToList(CERTGeneralNameList
*list
,
1937 CERTGeneralNameType type
,
1938 void *data
, SECItem
*oid
)
1940 CERTGeneralName
*name
;
1942 if (list
!= NULL
&& data
!= NULL
) {
1943 PZ_Lock(list
->lock
);
1944 name
= CERT_NewGeneralName(list
->arena
, type
);
1949 case certEDIPartyName
:
1951 case certRegisterID
:
1952 case certRFC822Name
:
1953 case certX400Address
:
1955 XXX
SECITEM_CopyItem(list
->arena
, &name
->name
.other
, (SECItem
*)data
);
1958 XXX
SECITEM_CopyItem(list
->arena
, &name
->name
.OthName
.name
,
1960 XXX
SECITEM_CopyItem(list
->arena
, &name
->name
.OthName
.oid
,
1963 case certDirectoryName
:
1964 XXX
CERT_CopyName(list
->arena
, &name
->name
.directoryName
,
1968 list
->name
= cert_CombineNamesLists(list
->name
, name
);
1971 PZ_Unlock(list
->lock
);