| Index: mozilla/security/nss/lib/certdb/genname.c
 | 
| ===================================================================
 | 
| --- mozilla/security/nss/lib/certdb/genname.c	(revision 191424)
 | 
| +++ mozilla/security/nss/lib/certdb/genname.c	(working copy)
 | 
| @@ -1,1861 +0,0 @@
 | 
| -/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
| -
 | 
| -#include "plarena.h"
 | 
| -#include "seccomon.h"
 | 
| -#include "secitem.h"
 | 
| -#include "secoidt.h"
 | 
| -#include "secasn1.h"
 | 
| -#include "secder.h"
 | 
| -#include "certt.h"
 | 
| -#include "cert.h"
 | 
| -#include "certi.h"
 | 
| -#include "xconst.h"
 | 
| -#include "secerr.h"
 | 
| -#include "secoid.h"
 | 
| -#include "prprf.h"
 | 
| -#include "genname.h"
 | 
| -
 | 
| -SEC_ASN1_MKSUB(SEC_AnyTemplate)
 | 
| -SEC_ASN1_MKSUB(SEC_IntegerTemplate)
 | 
| -SEC_ASN1_MKSUB(SEC_IA5StringTemplate)
 | 
| -SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
 | 
| -SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
 | 
| -
 | 
| -static const SEC_ASN1Template CERTNameConstraintTemplate[] = {
 | 
| -    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraint) },
 | 
| -    { SEC_ASN1_ANY, offsetof(CERTNameConstraint, DERName) },
 | 
| -    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 
 | 
| -          offsetof(CERTNameConstraint, min),
 | 
| -          SEC_ASN1_SUB(SEC_IntegerTemplate) }, 
 | 
| -    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 
 | 
| -          offsetof(CERTNameConstraint, max),
 | 
| -          SEC_ASN1_SUB(SEC_IntegerTemplate) },
 | 
| -    { 0, }
 | 
| -};
 | 
| -
 | 
| -const SEC_ASN1Template CERT_NameConstraintSubtreeSubTemplate[] = {
 | 
| -    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERTNameConstraintsTemplate[] = {
 | 
| -    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraints) },
 | 
| -    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
 | 
| -          offsetof(CERTNameConstraints, DERPermited), 
 | 
| -	  CERT_NameConstraintSubtreeSubTemplate},
 | 
| -    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
 | 
| -          offsetof(CERTNameConstraints, DERExcluded), 
 | 
| -	  CERT_NameConstraintSubtreeSubTemplate},
 | 
| -    { 0, }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -static const SEC_ASN1Template CERTOthNameTemplate[] = {
 | 
| -    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OtherName) },
 | 
| -    { SEC_ASN1_OBJECT_ID, 
 | 
| -	  offsetof(OtherName, oid) },
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
 | 
| -          SEC_ASN1_XTRN | 0, offsetof(OtherName, name),
 | 
| -          SEC_ASN1_SUB(SEC_AnyTemplate) },
 | 
| -    { 0, } 
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERTOtherNameTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0 ,
 | 
| -      offsetof(CERTGeneralName, name.OthName), CERTOthNameTemplate, 
 | 
| -      sizeof(CERTGeneralName) }
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERTOtherName2Template[] = {
 | 
| -    { SEC_ASN1_SEQUENCE | SEC_ASN1_CONTEXT_SPECIFIC | 0 ,
 | 
| -      0, NULL, sizeof(CERTGeneralName) },
 | 
| -    { SEC_ASN1_OBJECT_ID,
 | 
| -	  offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, oid) },
 | 
| -    { SEC_ASN1_ANY,
 | 
| -	  offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, name) },
 | 
| -    { 0, } 
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_RFC822NameTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1 ,
 | 
| -          offsetof(CERTGeneralName, name.other),
 | 
| -          SEC_ASN1_SUB(SEC_IA5StringTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_DNSNameTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2 ,
 | 
| -          offsetof(CERTGeneralName, name.other),
 | 
| -          SEC_ASN1_SUB(SEC_IA5StringTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_X400AddressTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 3,
 | 
| -          offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
 | 
| -          SEC_ASN1_XTRN | 4, offsetof(CERTGeneralName, derDirectoryName),
 | 
| -          SEC_ASN1_SUB(SEC_AnyTemplate), sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 5,
 | 
| -          offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_URITemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 6 ,
 | 
| -          offsetof(CERTGeneralName, name.other),
 | 
| -          SEC_ASN1_SUB(SEC_IA5StringTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_IPAddressTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 7 ,
 | 
| -          offsetof(CERTGeneralName, name.other),
 | 
| -          SEC_ASN1_SUB(SEC_OctetStringTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -static const SEC_ASN1Template CERT_RegisteredIDTemplate[] = {
 | 
| -    { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 8 ,
 | 
| -          offsetof(CERTGeneralName, name.other),
 | 
| -          SEC_ASN1_SUB(SEC_ObjectIDTemplate),
 | 
| -          sizeof (CERTGeneralName)}
 | 
| -};
 | 
| -
 | 
| -
 | 
| -const SEC_ASN1Template CERT_GeneralNamesTemplate[] = {
 | 
| -    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
 | 
| -};
 | 
| -
 | 
| -
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type)
 | 
| -{
 | 
| -    CERTGeneralName *name = arena 
 | 
| -                            ? PORT_ArenaZNew(arena, CERTGeneralName)
 | 
| -	                    : PORT_ZNew(CERTGeneralName);
 | 
| -    if (name) {
 | 
| -	name->type = type;
 | 
| -	name->l.prev = name->l.next = &name->l;
 | 
| -    }
 | 
| -    return name;
 | 
| -}
 | 
| -
 | 
| -/* Copy content of one General Name to another.
 | 
| -** Caller has allocated destination general name.
 | 
| -** This function does not change the destinate's GeneralName's list linkage.
 | 
| -*/
 | 
| -SECStatus
 | 
| -cert_CopyOneGeneralName(PRArenaPool      *arena, 
 | 
| -		        CERTGeneralName  *dest, 
 | 
| -		        CERTGeneralName  *src)
 | 
| -{
 | 
| -    SECStatus rv;
 | 
| -    void *mark = NULL;
 | 
| -
 | 
| -    PORT_Assert(dest != NULL);
 | 
| -    dest->type = src->type;
 | 
| -
 | 
| -    mark = PORT_ArenaMark(arena);
 | 
| -
 | 
| -    switch (src->type) {
 | 
| -    case certDirectoryName: 
 | 
| -	rv = SECITEM_CopyItem(arena, &dest->derDirectoryName, 
 | 
| -				      &src->derDirectoryName);
 | 
| -	if (rv == SECSuccess) 
 | 
| -	    rv = CERT_CopyName(arena, &dest->name.directoryName, 
 | 
| -				       &src->name.directoryName);
 | 
| -	break;
 | 
| -
 | 
| -    case certOtherName: 
 | 
| -	rv = SECITEM_CopyItem(arena, &dest->name.OthName.name, 
 | 
| -				      &src->name.OthName.name);
 | 
| -	if (rv == SECSuccess) 
 | 
| -	    rv = SECITEM_CopyItem(arena, &dest->name.OthName.oid, 
 | 
| -					  &src->name.OthName.oid);
 | 
| -	break;
 | 
| -
 | 
| -    default: 
 | 
| -	rv = SECITEM_CopyItem(arena, &dest->name.other, 
 | 
| -				      &src->name.other);
 | 
| -	break;
 | 
| -
 | 
| -    }
 | 
| -    if (rv != SECSuccess) {
 | 
| -        PORT_ArenaRelease(arena, mark);
 | 
| -    } else {
 | 
| -        PORT_ArenaUnmark(arena, mark);
 | 
| -    }
 | 
| -    return rv;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -void
 | 
| -CERT_DestroyGeneralNameList(CERTGeneralNameList *list)
 | 
| -{
 | 
| -    PZLock *lock;
 | 
| -
 | 
| -    if (list != NULL) {
 | 
| -	lock = list->lock;
 | 
| -	PZ_Lock(lock);
 | 
| -	if (--list->refCount <= 0 && list->arena != NULL) {
 | 
| -	    PORT_FreeArena(list->arena, PR_FALSE);
 | 
| -	    PZ_Unlock(lock);
 | 
| -	    PZ_DestroyLock(lock);
 | 
| -	} else {
 | 
| -	    PZ_Unlock(lock);
 | 
| -	}
 | 
| -    }
 | 
| -    return;
 | 
| -}
 | 
| -
 | 
| -CERTGeneralNameList *
 | 
| -CERT_CreateGeneralNameList(CERTGeneralName *name) {
 | 
| -    PRArenaPool *arena;
 | 
| -    CERTGeneralNameList *list = NULL;
 | 
| -
 | 
| -    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 | 
| -    if (arena == NULL) {
 | 
| -	goto done;
 | 
| -    }
 | 
| -    list = PORT_ArenaZNew(arena, CERTGeneralNameList);
 | 
| -    if (!list)
 | 
| -    	goto loser;
 | 
| -    if (name != NULL) {
 | 
| -	SECStatus rv;
 | 
| -	list->name = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
 | 
| -	if (!list->name)
 | 
| -	    goto loser;
 | 
| -	rv = CERT_CopyGeneralName(arena, list->name, name);
 | 
| -	if (rv != SECSuccess)
 | 
| -	    goto loser;
 | 
| -    }
 | 
| -    list->lock = PZ_NewLock(nssILockList);
 | 
| -    if (!list->lock)
 | 
| -    	goto loser;
 | 
| -    list->arena = arena;
 | 
| -    list->refCount = 1;
 | 
| -done:
 | 
| -    return list;
 | 
| -
 | 
| -loser:
 | 
| -    PORT_FreeArena(arena, PR_FALSE);
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -CERT_GetNextGeneralName(CERTGeneralName *current)
 | 
| -{
 | 
| -    PRCList *next;
 | 
| -    
 | 
| -    next = current->l.next;
 | 
| -    return (CERTGeneralName *) (((char *) next) - offsetof(CERTGeneralName, l));
 | 
| -}
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -CERT_GetPrevGeneralName(CERTGeneralName *current)
 | 
| -{
 | 
| -    PRCList *prev;
 | 
| -    prev = current->l.prev;
 | 
| -    return (CERTGeneralName *) (((char *) prev) - offsetof(CERTGeneralName, l));
 | 
| -}
 | 
| -
 | 
| -CERTNameConstraint *
 | 
| -CERT_GetNextNameConstraint(CERTNameConstraint *current)
 | 
| -{
 | 
| -    PRCList *next;
 | 
| -    
 | 
| -    next = current->l.next;
 | 
| -    return (CERTNameConstraint *) (((char *) next) - offsetof(CERTNameConstraint, l));
 | 
| -}
 | 
| -
 | 
| -CERTNameConstraint *
 | 
| -CERT_GetPrevNameConstraint(CERTNameConstraint *current)
 | 
| -{
 | 
| -    PRCList *prev;
 | 
| -    prev = current->l.prev;
 | 
| -    return (CERTNameConstraint *) (((char *) prev) - offsetof(CERTNameConstraint, l));
 | 
| -}
 | 
| -
 | 
| -SECItem *
 | 
| -CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, PRArenaPool *arena)
 | 
| -{
 | 
| -
 | 
| -    const SEC_ASN1Template * template;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    if (arena == NULL) {
 | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -	return NULL;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    if (dest == NULL) {
 | 
| -	dest = PORT_ArenaZNew(arena, SECItem);
 | 
| -	if (!dest)
 | 
| -	    goto loser;
 | 
| -    }
 | 
| -    if (genName->type == certDirectoryName) {
 | 
| -	if (genName->derDirectoryName.data == NULL) {
 | 
| -	    /* The field hasn't been encoded yet. */
 | 
| -            SECItem * pre_dest =
 | 
| -            SEC_ASN1EncodeItem (arena, &(genName->derDirectoryName),
 | 
| -                                &(genName->name.directoryName),
 | 
| -                                CERT_NameTemplate);
 | 
| -            if (!pre_dest)
 | 
| -                goto loser;
 | 
| -	}
 | 
| -	if (genName->derDirectoryName.data == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -    }
 | 
| -    switch (genName->type) {
 | 
| -    case certURI:           template = CERT_URITemplate;           break;
 | 
| -    case certRFC822Name:    template = CERT_RFC822NameTemplate;    break;
 | 
| -    case certDNSName:       template = CERT_DNSNameTemplate;       break;
 | 
| -    case certIPAddress:     template = CERT_IPAddressTemplate;     break;
 | 
| -    case certOtherName:     template = CERTOtherNameTemplate;      break;
 | 
| -    case certRegisterID:    template = CERT_RegisteredIDTemplate;  break;
 | 
| -         /* for this type, we expect the value is already encoded */
 | 
| -    case certEDIPartyName:  template = CERT_EDIPartyNameTemplate;  break;
 | 
| -	 /* for this type, we expect the value is already encoded */
 | 
| -    case certX400Address:   template = CERT_X400AddressTemplate;   break;
 | 
| -    case certDirectoryName: template = CERT_DirectoryNameTemplate; break;
 | 
| -    default:
 | 
| -	PORT_Assert(0); goto loser;
 | 
| -    }
 | 
| -    dest = SEC_ASN1EncodeItem(arena, dest, genName, template);
 | 
| -    if (!dest) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    /* TODO: unmark arena */
 | 
| -    return dest;
 | 
| -loser:
 | 
| -    /* TODO: release arena back to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -SECItem **
 | 
| -cert_EncodeGeneralNames(PRArenaPool *arena, CERTGeneralName *names)
 | 
| -{
 | 
| -    CERTGeneralName  *current_name;
 | 
| -    SECItem          **items = NULL;
 | 
| -    int              count = 0;
 | 
| -    int              i;
 | 
| -    PRCList          *head;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    /* TODO: mark arena */
 | 
| -    current_name = names;
 | 
| -    if (names != NULL) {
 | 
| -	count = 1;
 | 
| -    }
 | 
| -    head = &(names->l);
 | 
| -    while (current_name->l.next != head) {
 | 
| -	current_name = CERT_GetNextGeneralName(current_name);
 | 
| -	++count;
 | 
| -    }
 | 
| -    current_name = CERT_GetNextGeneralName(current_name);
 | 
| -    items = PORT_ArenaNewArray(arena, SECItem *, count + 1);
 | 
| -    if (items == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    for (i = 0; i < count; i++) {
 | 
| -	items[i] = CERT_EncodeGeneralName(current_name, (SECItem *)NULL, arena);
 | 
| -	if (items[i] == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -	current_name = CERT_GetNextGeneralName(current_name);
 | 
| -    }
 | 
| -    items[i] = NULL;
 | 
| -    /* TODO: unmark arena */
 | 
| -    return items;
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -CERT_DecodeGeneralName(PRArenaPool      *reqArena,
 | 
| -		       SECItem          *encodedName,
 | 
| -		       CERTGeneralName  *genName)
 | 
| -{
 | 
| -    const SEC_ASN1Template *         template;
 | 
| -    CERTGeneralNameType              genNameType;
 | 
| -    SECStatus                        rv = SECSuccess;
 | 
| -    SECItem* newEncodedName;
 | 
| -
 | 
| -    if (!reqArena) {
 | 
| -        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -        return NULL;
 | 
| -    }
 | 
| -    /* make a copy for decoding so the data decoded with QuickDER doesn't
 | 
| -       point to temporary memory */
 | 
| -    newEncodedName = SECITEM_ArenaDupItem(reqArena, encodedName);
 | 
| -    if (!newEncodedName) {
 | 
| -        return NULL;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    genNameType = (CERTGeneralNameType)((*(newEncodedName->data) & 0x0f) + 1);
 | 
| -    if (genName == NULL) {
 | 
| -	genName = CERT_NewGeneralName(reqArena, genNameType);
 | 
| -	if (!genName)
 | 
| -	    goto loser;
 | 
| -    } else {
 | 
| -	genName->type = genNameType;
 | 
| -	genName->l.prev = genName->l.next = &genName->l;
 | 
| -    }
 | 
| -
 | 
| -    switch (genNameType) {
 | 
| -    case certURI: 		template = CERT_URITemplate;           break;
 | 
| -    case certRFC822Name: 	template = CERT_RFC822NameTemplate;    break;
 | 
| -    case certDNSName: 		template = CERT_DNSNameTemplate;       break;
 | 
| -    case certIPAddress: 	template = CERT_IPAddressTemplate;     break;
 | 
| -    case certOtherName: 	template = CERTOtherNameTemplate;      break;
 | 
| -    case certRegisterID: 	template = CERT_RegisteredIDTemplate;  break;
 | 
| -    case certEDIPartyName: 	template = CERT_EDIPartyNameTemplate;  break;
 | 
| -    case certX400Address: 	template = CERT_X400AddressTemplate;   break;
 | 
| -    case certDirectoryName: 	template = CERT_DirectoryNameTemplate; break;
 | 
| -    default: 
 | 
| -        goto loser;
 | 
| -    }
 | 
| -    rv = SEC_QuickDERDecodeItem(reqArena, genName, template, newEncodedName);
 | 
| -    if (rv != SECSuccess) 
 | 
| -	goto loser;
 | 
| -    if (genNameType == certDirectoryName) {
 | 
| -	rv = SEC_QuickDERDecodeItem(reqArena, &(genName->name.directoryName), 
 | 
| -				CERT_NameTemplate, 
 | 
| -				&(genName->derDirectoryName));
 | 
| -        if (rv != SECSuccess)
 | 
| -	    goto loser;
 | 
| -    }
 | 
| -
 | 
| -    /* TODO: unmark arena */
 | 
| -    return genName;
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -cert_DecodeGeneralNames (PRArenaPool  *arena,
 | 
| -			 SECItem      **encodedGenName)
 | 
| -{
 | 
| -    PRCList                           *head = NULL;
 | 
| -    PRCList                           *tail = NULL;
 | 
| -    CERTGeneralName                   *currentName = NULL;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    if (!encodedGenName || !arena) {
 | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -	return NULL;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    while (*encodedGenName != NULL) {
 | 
| -	currentName = CERT_DecodeGeneralName(arena, *encodedGenName, NULL);
 | 
| -	if (currentName == NULL)
 | 
| -	    break;
 | 
| -	if (head == NULL) {
 | 
| -	    head = &(currentName->l);
 | 
| -	    tail = head;
 | 
| -	}
 | 
| -	currentName->l.next = head;
 | 
| -	currentName->l.prev = tail;
 | 
| -	tail = head->prev = tail->next = &(currentName->l);
 | 
| -	encodedGenName++;
 | 
| -    }
 | 
| -    if (currentName) {
 | 
| -	/* TODO: unmark arena */
 | 
| -	return CERT_GetNextGeneralName(currentName);
 | 
| -    }
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -void
 | 
| -CERT_DestroyGeneralName(CERTGeneralName *name)
 | 
| -{
 | 
| -    cert_DestroyGeneralNames(name);
 | 
| -}
 | 
| -
 | 
| -SECStatus
 | 
| -cert_DestroyGeneralNames(CERTGeneralName *name)
 | 
| -{
 | 
| -    CERTGeneralName    *first;
 | 
| -    CERTGeneralName    *next = NULL;
 | 
| -
 | 
| -
 | 
| -    first = name;
 | 
| -    do {
 | 
| -	next = CERT_GetNextGeneralName(name);
 | 
| -	PORT_Free(name);
 | 
| -	name = next;
 | 
| -    } while (name != first);
 | 
| -    return SECSuccess;
 | 
| -}
 | 
| -
 | 
| -static SECItem *
 | 
| -cert_EncodeNameConstraint(CERTNameConstraint  *constraint, 
 | 
| -			 SECItem             *dest,
 | 
| -			 PRArenaPool         *arena)
 | 
| -{
 | 
| -    PORT_Assert(arena);
 | 
| -    if (dest == NULL) {
 | 
| -	dest = PORT_ArenaZNew(arena, SECItem);
 | 
| -	if (dest == NULL) {
 | 
| -	    return NULL;
 | 
| -	}
 | 
| -    }
 | 
| -    CERT_EncodeGeneralName(&(constraint->name), &(constraint->DERName), arena);
 | 
| -    
 | 
| -    dest = SEC_ASN1EncodeItem (arena, dest, constraint,
 | 
| -			       CERTNameConstraintTemplate);
 | 
| -    return dest;
 | 
| -} 
 | 
| -
 | 
| -SECStatus 
 | 
| -cert_EncodeNameConstraintSubTree(CERTNameConstraint  *constraints,
 | 
| -			         PRArenaPool         *arena,
 | 
| -				 SECItem             ***dest,
 | 
| -				 PRBool              permited)
 | 
| -{
 | 
| -    CERTNameConstraint  *current_constraint = constraints;
 | 
| -    SECItem             **items = NULL;
 | 
| -    int                 count = 0;
 | 
| -    int                 i;
 | 
| -    PRCList             *head;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    /* TODO: mark arena */
 | 
| -    if (constraints != NULL) {
 | 
| -	count = 1;
 | 
| -    }
 | 
| -    head = &constraints->l;
 | 
| -    while (current_constraint->l.next != head) {
 | 
| -	current_constraint = CERT_GetNextNameConstraint(current_constraint);
 | 
| -	++count;
 | 
| -    }
 | 
| -    current_constraint = CERT_GetNextNameConstraint(current_constraint);
 | 
| -    items = PORT_ArenaZNewArray(arena, SECItem *, count + 1);
 | 
| -    if (items == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    for (i = 0; i < count; i++) {
 | 
| -	items[i] = cert_EncodeNameConstraint(current_constraint, 
 | 
| -					     (SECItem *) NULL, arena);
 | 
| -	if (items[i] == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -	current_constraint = CERT_GetNextNameConstraint(current_constraint);
 | 
| -    }
 | 
| -    *dest = items;
 | 
| -    if (*dest == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    /* TODO: unmark arena */
 | 
| -    return SECSuccess;
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -SECStatus 
 | 
| -cert_EncodeNameConstraints(CERTNameConstraints  *constraints,
 | 
| -			   PRArenaPool          *arena,
 | 
| -			   SECItem              *dest)
 | 
| -{
 | 
| -    SECStatus    rv = SECSuccess;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    /* TODO: mark arena */
 | 
| -    if (constraints->permited != NULL) {
 | 
| -	rv = cert_EncodeNameConstraintSubTree(constraints->permited, arena,
 | 
| -					      &constraints->DERPermited, 
 | 
| -					      PR_TRUE);
 | 
| -	if (rv == SECFailure) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -    }
 | 
| -    if (constraints->excluded != NULL) {
 | 
| -	rv = cert_EncodeNameConstraintSubTree(constraints->excluded, arena,
 | 
| -					      &constraints->DERExcluded, 
 | 
| -					      PR_FALSE);
 | 
| -	if (rv == SECFailure) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -    }
 | 
| -    dest = SEC_ASN1EncodeItem(arena, dest, constraints, 
 | 
| -			      CERTNameConstraintsTemplate);
 | 
| -    if (dest == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    /* TODO: unmark arena */
 | 
| -    return SECSuccess;
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -CERTNameConstraint *
 | 
| -cert_DecodeNameConstraint(PRArenaPool       *reqArena,
 | 
| -			  SECItem           *encodedConstraint)
 | 
| -{
 | 
| -    CERTNameConstraint     *constraint;
 | 
| -    SECStatus              rv = SECSuccess;
 | 
| -    CERTGeneralName        *temp;
 | 
| -    SECItem*               newEncodedConstraint;
 | 
| -
 | 
| -    if (!reqArena) {
 | 
| -        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -        return NULL;
 | 
| -    }
 | 
| -    newEncodedConstraint = SECITEM_ArenaDupItem(reqArena, encodedConstraint);
 | 
| -    if (!newEncodedConstraint) {
 | 
| -        return NULL;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    constraint = PORT_ArenaZNew(reqArena, CERTNameConstraint);
 | 
| -    if (!constraint)
 | 
| -    	goto loser;
 | 
| -    rv = SEC_QuickDERDecodeItem(reqArena, constraint,
 | 
| -                                CERTNameConstraintTemplate,
 | 
| -                                newEncodedConstraint);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    temp = CERT_DecodeGeneralName(reqArena, &(constraint->DERName),
 | 
| -                                  &(constraint->name));
 | 
| -    if (temp != &(constraint->name)) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -
 | 
| -    /* ### sjlee: since the name constraint contains only one 
 | 
| -     *            CERTGeneralName, the list within CERTGeneralName shouldn't 
 | 
| -     *            point anywhere else.  Otherwise, bad things will happen.
 | 
| -     */
 | 
| -    constraint->name.l.prev = constraint->name.l.next = &(constraint->name.l);
 | 
| -    /* TODO: unmark arena */
 | 
| -    return constraint;
 | 
| -loser:
 | 
| -    /* TODO: release arena back to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -CERTNameConstraint *
 | 
| -cert_DecodeNameConstraintSubTree(PRArenaPool   *arena,
 | 
| -				 SECItem       **subTree,
 | 
| -				 PRBool        permited)
 | 
| -{
 | 
| -    CERTNameConstraint   *current = NULL;
 | 
| -    CERTNameConstraint   *first = NULL;
 | 
| -    CERTNameConstraint   *last = NULL;
 | 
| -    int                  i = 0;
 | 
| -
 | 
| -    PORT_Assert(arena);
 | 
| -    /* TODO: mark arena */
 | 
| -    while (subTree[i] != NULL) {
 | 
| -	current = cert_DecodeNameConstraint(arena, subTree[i]);
 | 
| -	if (current == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -	if (last == NULL) {
 | 
| -	    first = last = current;
 | 
| -	}
 | 
| -	current->l.prev = &(last->l);
 | 
| -	current->l.next = last->l.next;
 | 
| -	last->l.next = &(current->l);
 | 
| -	i++;
 | 
| -    }
 | 
| -    first->l.prev = &(current->l);
 | 
| -    /* TODO: unmark arena */
 | 
| -    return first;
 | 
| -loser:
 | 
| -    /* TODO: release arena back to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -CERTNameConstraints *
 | 
| -cert_DecodeNameConstraints(PRArenaPool   *reqArena,
 | 
| -			   SECItem       *encodedConstraints)
 | 
| -{
 | 
| -    CERTNameConstraints   *constraints;
 | 
| -    SECStatus             rv;
 | 
| -    SECItem*              newEncodedConstraints;
 | 
| -
 | 
| -    if (!reqArena) {
 | 
| -        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -        return NULL;
 | 
| -    }
 | 
| -    PORT_Assert(encodedConstraints);
 | 
| -    newEncodedConstraints = SECITEM_ArenaDupItem(reqArena, encodedConstraints);
 | 
| -
 | 
| -    /* TODO: mark arena */
 | 
| -    constraints = PORT_ArenaZNew(reqArena, CERTNameConstraints);
 | 
| -    if (constraints == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = SEC_QuickDERDecodeItem(reqArena, constraints,
 | 
| -                                CERTNameConstraintsTemplate,
 | 
| -                                newEncodedConstraints);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    if (constraints->DERPermited != NULL && 
 | 
| -        constraints->DERPermited[0] != NULL) {
 | 
| -	constraints->permited = 
 | 
| -	    cert_DecodeNameConstraintSubTree(reqArena,
 | 
| -                                             constraints->DERPermited,
 | 
| -                                             PR_TRUE);
 | 
| -	if (constraints->permited == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -    }
 | 
| -    if (constraints->DERExcluded != NULL && 
 | 
| -        constraints->DERExcluded[0] != NULL) {
 | 
| -	constraints->excluded = 
 | 
| -	    cert_DecodeNameConstraintSubTree(reqArena,
 | 
| -                                             constraints->DERExcluded,
 | 
| -                                             PR_FALSE);
 | 
| -	if (constraints->excluded == NULL) {
 | 
| -	    goto loser;
 | 
| -	}
 | 
| -    }
 | 
| -    /* TODO: unmark arena */
 | 
| -    return constraints;
 | 
| -loser:
 | 
| -    /* TODO: release arena back to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -/* Copy a chain of one or more general names to a destination chain.
 | 
| -** Caller has allocated at least the first destination GeneralName struct. 
 | 
| -** Both source and destination chains are circular doubly-linked lists.
 | 
| -** The first source struct is copied to the first destination struct.
 | 
| -** If the source chain has more than one member, and the destination chain 
 | 
| -** has only one member, then this function allocates new structs for all but 
 | 
| -** the first copy from the arena and links them into the destination list.  
 | 
| -** If the destination struct is part of a list with more than one member,
 | 
| -** then this function traverses both the source and destination lists,
 | 
| -** copying each source struct to the corresponding dest struct.
 | 
| -** In that case, the destination list MUST contain at least as many 
 | 
| -** structs as the source list or some dest entries will be overwritten.
 | 
| -*/
 | 
| -SECStatus
 | 
| -CERT_CopyGeneralName(PRArenaPool      *arena, 
 | 
| -		     CERTGeneralName  *dest, 
 | 
| -		     CERTGeneralName  *src)
 | 
| -{
 | 
| -    SECStatus rv;
 | 
| -    CERTGeneralName *destHead = dest;
 | 
| -    CERTGeneralName *srcHead = src;
 | 
| -
 | 
| -    PORT_Assert(dest != NULL);
 | 
| -    if (!dest) {
 | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -        return SECFailure;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    do {
 | 
| -	rv = cert_CopyOneGeneralName(arena, dest, src);
 | 
| -	if (rv != SECSuccess)
 | 
| -	    goto loser;
 | 
| -	src = CERT_GetNextGeneralName(src);
 | 
| -	/* if there is only one general name, we shouldn't do this */
 | 
| -	if (src != srcHead) {
 | 
| -	    if (dest->l.next == &destHead->l) {
 | 
| -		CERTGeneralName *temp;
 | 
| -		temp = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
 | 
| -		if (!temp) 
 | 
| -		    goto loser;
 | 
| -		temp->l.next = &destHead->l;
 | 
| -		temp->l.prev = &dest->l;
 | 
| -		destHead->l.prev = &temp->l;
 | 
| -		dest->l.next = &temp->l;
 | 
| -		dest = temp;
 | 
| -	    } else {
 | 
| -		dest = CERT_GetNextGeneralName(dest);
 | 
| -	    }
 | 
| -	}
 | 
| -    } while (src != srcHead && rv == SECSuccess);
 | 
| -    /* TODO: unmark arena */
 | 
| -    return rv;
 | 
| -loser:
 | 
| -    /* TODO: release back to mark */
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -CERTGeneralNameList *
 | 
| -CERT_DupGeneralNameList(CERTGeneralNameList *list)
 | 
| -{
 | 
| -    if (list != NULL) {
 | 
| -	PZ_Lock(list->lock);
 | 
| -	list->refCount++;
 | 
| -	PZ_Unlock(list->lock);
 | 
| -    }
 | 
| -    return list;
 | 
| -}
 | 
| -
 | 
| -/* Allocate space and copy CERTNameConstraint from src to dest */
 | 
| -CERTNameConstraint *
 | 
| -CERT_CopyNameConstraint(PRArenaPool         *arena, 
 | 
| -			CERTNameConstraint  *dest, 
 | 
| -			CERTNameConstraint  *src)
 | 
| -{
 | 
| -    SECStatus  rv;
 | 
| -    
 | 
| -    /* TODO: mark arena */
 | 
| -    if (dest == NULL) {
 | 
| -	dest = PORT_ArenaZNew(arena, CERTNameConstraint);
 | 
| -	if (!dest)
 | 
| -	    goto loser;
 | 
| -	/* mark that it is not linked */
 | 
| -	dest->name.l.prev = dest->name.l.next = &(dest->name.l);
 | 
| -    }
 | 
| -    rv = CERT_CopyGeneralName(arena, &dest->name, &src->name);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = SECITEM_CopyItem(arena, &dest->DERName, &src->DERName);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = SECITEM_CopyItem(arena, &dest->min, &src->min);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = SECITEM_CopyItem(arena, &dest->max, &src->max);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    dest->l.prev = dest->l.next = &dest->l;
 | 
| -    /* TODO: unmark arena */
 | 
| -    return dest;
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -CERTGeneralName *
 | 
| -cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2)
 | 
| -{
 | 
| -    PRCList *begin1;
 | 
| -    PRCList *begin2;
 | 
| -    PRCList *end1;
 | 
| -    PRCList *end2;
 | 
| -
 | 
| -    if (list1 == NULL){
 | 
| -	return list2;
 | 
| -    } else if (list2 == NULL) {
 | 
| -	return list1;
 | 
| -    } else {
 | 
| -	begin1 = &list1->l;
 | 
| -	begin2 = &list2->l;
 | 
| -	end1 = list1->l.prev;
 | 
| -	end2 = list2->l.prev;
 | 
| -	end1->next = begin2;
 | 
| -	end2->next = begin1;
 | 
| -	begin1->prev = end2;
 | 
| -	begin2->prev = end1;
 | 
| -	return list1;
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -CERTNameConstraint *
 | 
| -cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2)
 | 
| -{
 | 
| -    PRCList *begin1;
 | 
| -    PRCList *begin2;
 | 
| -    PRCList *end1;
 | 
| -    PRCList *end2;
 | 
| -
 | 
| -    if (list1 == NULL){
 | 
| -	return list2;
 | 
| -    } else if (list2 == NULL) {
 | 
| -	return list1;
 | 
| -    } else {
 | 
| -	begin1 = &list1->l;
 | 
| -	begin2 = &list2->l;
 | 
| -	end1 = list1->l.prev;
 | 
| -	end2 = list2->l.prev;
 | 
| -	end1->next = begin2;
 | 
| -	end2->next = begin1;
 | 
| -	begin1->prev = end2;
 | 
| -	begin2->prev = end1;
 | 
| -	return list1;
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -
 | 
| -/* Add a CERTNameConstraint to the CERTNameConstraint list */
 | 
| -CERTNameConstraint *
 | 
| -CERT_AddNameConstraint(CERTNameConstraint *list, 
 | 
| -		       CERTNameConstraint *constraint)
 | 
| -{
 | 
| -    PORT_Assert(constraint != NULL);
 | 
| -    constraint->l.next = constraint->l.prev = &constraint->l;
 | 
| -    list = cert_CombineConstraintsLists(list, constraint);
 | 
| -    return list;
 | 
| -}
 | 
| -
 | 
| -
 | 
| -SECStatus
 | 
| -CERT_GetNameConstraintByType (CERTNameConstraint *constraints,
 | 
| -			      CERTGeneralNameType type, 
 | 
| -			      CERTNameConstraint **returnList,
 | 
| -			      PRArenaPool *arena)
 | 
| -{
 | 
| -    CERTNameConstraint *current = NULL;
 | 
| -    void               *mark = NULL;
 | 
| -
 | 
| -    *returnList = NULL;
 | 
| -    if (!constraints)
 | 
| -	return SECSuccess;
 | 
| -
 | 
| -    mark = PORT_ArenaMark(arena);
 | 
| -
 | 
| -    current = constraints;
 | 
| -    do {
 | 
| -	PORT_Assert(current->name.type);
 | 
| -	if (current->name.type == type) {
 | 
| -	    CERTNameConstraint *temp;
 | 
| -	    temp = CERT_CopyNameConstraint(arena, NULL, current);
 | 
| -	    if (temp == NULL) 
 | 
| -		goto loser;
 | 
| -	    *returnList = CERT_AddNameConstraint(*returnList, temp);
 | 
| -	}
 | 
| -	current = CERT_GetNextNameConstraint(current);
 | 
| -    } while (current != constraints);
 | 
| -    PORT_ArenaUnmark(arena, mark);
 | 
| -    return SECSuccess;
 | 
| -
 | 
| -loser:
 | 
| -    PORT_ArenaRelease(arena, mark);
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -void *
 | 
| -CERT_GetGeneralNameByType (CERTGeneralName *genNames,
 | 
| -			   CERTGeneralNameType type, PRBool derFormat)
 | 
| -{
 | 
| -    CERTGeneralName *current;
 | 
| -    
 | 
| -    if (!genNames)
 | 
| -	return NULL;
 | 
| -    current = genNames;
 | 
| -
 | 
| -    do {
 | 
| -	if (current->type == type) {
 | 
| -	    switch (type) {
 | 
| -	    case certDNSName:
 | 
| -	    case certEDIPartyName:
 | 
| -	    case certIPAddress:
 | 
| -	    case certRegisterID:
 | 
| -	    case certRFC822Name:
 | 
| -	    case certX400Address:
 | 
| -	    case certURI: 
 | 
| -		return (void *)¤t->name.other;           /* SECItem * */
 | 
| -
 | 
| -	    case certOtherName: 
 | 
| -		return (void *)¤t->name.OthName;         /* OthName * */
 | 
| -
 | 
| -	    case certDirectoryName: 
 | 
| -		return derFormat 
 | 
| -		       ? (void *)¤t->derDirectoryName    /* SECItem * */
 | 
| -		       : (void *)¤t->name.directoryName; /* CERTName * */
 | 
| -	    }
 | 
| -	    PORT_Assert(0); 
 | 
| -	    return NULL;
 | 
| -	}
 | 
| -	current = CERT_GetNextGeneralName(current);
 | 
| -    } while (current != genNames);
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -int
 | 
| -CERT_GetNamesLength(CERTGeneralName *names)
 | 
| -{
 | 
| -    int              length = 0;
 | 
| -    CERTGeneralName  *first;
 | 
| -
 | 
| -    first = names;
 | 
| -    if (names != NULL) {
 | 
| -	do {
 | 
| -	    length++;
 | 
| -	    names = CERT_GetNextGeneralName(names);
 | 
| -	} while (names != first);
 | 
| -    }
 | 
| -    return length;
 | 
| -}
 | 
| -
 | 
| -/* Creates new GeneralNames for any email addresses found in the 
 | 
| -** input DN, and links them onto the list for the DN.
 | 
| -*/
 | 
| -SECStatus
 | 
| -cert_ExtractDNEmailAddrs(CERTGeneralName *name, PLArenaPool *arena)
 | 
| -{
 | 
| -    CERTGeneralName *nameList = NULL;
 | 
| -    const CERTRDN  **nRDNs = (const CERTRDN **)(name->name.directoryName.rdns);
 | 
| -    SECStatus        rv        = SECSuccess;
 | 
| -
 | 
| -    PORT_Assert(name->type == certDirectoryName);
 | 
| -    if (name->type != certDirectoryName) {
 | 
| -        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -	return SECFailure;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    while (nRDNs && *nRDNs) { /* loop over RDNs */
 | 
| -	const CERTRDN *nRDN = *nRDNs++;
 | 
| -	CERTAVA **nAVAs = nRDN->avas;
 | 
| -	while (nAVAs && *nAVAs) { /* loop over AVAs */
 | 
| -	    int tag;
 | 
| -	    CERTAVA *nAVA = *nAVAs++;
 | 
| -	    tag = CERT_GetAVATag(nAVA);
 | 
| -	    if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS ||
 | 
| -		 tag == SEC_OID_RFC1274_MAIL) { /* email AVA */
 | 
| -		CERTGeneralName *newName = NULL;
 | 
| -		SECItem *avaValue = CERT_DecodeAVAValue(&nAVA->value);
 | 
| -		if (!avaValue)
 | 
| -		    goto loser;
 | 
| -		rv = SECFailure;
 | 
| -                newName = CERT_NewGeneralName(arena, certRFC822Name);
 | 
| -		if (newName) {
 | 
| -		   rv = SECITEM_CopyItem(arena, &newName->name.other, avaValue);
 | 
| -		}
 | 
| -		SECITEM_FreeItem(avaValue, PR_TRUE);
 | 
| -		if (rv != SECSuccess)
 | 
| -		    goto loser;
 | 
| -		nameList = cert_CombineNamesLists(nameList, newName);
 | 
| -	    } /* handle one email AVA */
 | 
| -	} /* loop over AVAs */
 | 
| -    } /* loop over RDNs */
 | 
| -    /* combine new names with old one. */
 | 
| -    name = cert_CombineNamesLists(name, nameList);
 | 
| -    /* TODO: unmark arena */
 | 
| -    return SECSuccess;
 | 
| -
 | 
| -loser:
 | 
| -    /* TODO: release arena back to mark */
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* Extract all names except Subject Common Name from a cert 
 | 
| -** in preparation for a name constraints test.
 | 
| -*/
 | 
| -CERTGeneralName *
 | 
| -CERT_GetCertificateNames(CERTCertificate *cert, PRArenaPool *arena)
 | 
| -{
 | 
| -    return CERT_GetConstrainedCertificateNames(cert, arena, PR_FALSE);
 | 
| -}
 | 
| -
 | 
| -/* This function is called by CERT_VerifyCertChain to extract all
 | 
| -** names from a cert in preparation for a name constraints test.
 | 
| -*/
 | 
| -CERTGeneralName *
 | 
| -CERT_GetConstrainedCertificateNames(CERTCertificate *cert, PRArenaPool *arena,
 | 
| -                                    PRBool includeSubjectCommonName)
 | 
| -{
 | 
| -    CERTGeneralName  *DN;
 | 
| -    CERTGeneralName  *SAN;
 | 
| -    PRUint32         numDNSNames = 0;
 | 
| -    SECStatus        rv;
 | 
| -
 | 
| -    if (!arena) {
 | 
| -    	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -	return NULL;
 | 
| -    }
 | 
| -    /* TODO: mark arena */
 | 
| -    DN = CERT_NewGeneralName(arena, certDirectoryName);
 | 
| -    if (DN == NULL) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = CERT_CopyName(arena, &DN->name.directoryName, &cert->subject);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    rv = SECITEM_CopyItem(arena, &DN->derDirectoryName, &cert->derSubject);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	goto loser;
 | 
| -    }
 | 
| -    /* Extract email addresses from DN, construct CERTGeneralName structs 
 | 
| -    ** for them, add them to the name list 
 | 
| -    */
 | 
| -    rv = cert_ExtractDNEmailAddrs(DN, arena);
 | 
| -    if (rv != SECSuccess)
 | 
| -        goto loser;
 | 
| -
 | 
| -    /* Now extract any GeneralNames from the subject name names extension. */
 | 
| -    SAN = cert_GetSubjectAltNameList(cert, arena);
 | 
| -    if (SAN) {
 | 
| -	numDNSNames = cert_CountDNSPatterns(SAN);
 | 
| -	DN = cert_CombineNamesLists(DN, SAN);
 | 
| -    }
 | 
| -    if (!numDNSNames && includeSubjectCommonName) {
 | 
| -	char *cn = CERT_GetCommonName(&cert->subject);
 | 
| -	if (cn) {
 | 
| -	    CERTGeneralName *CN = CERT_NewGeneralName(arena, certDNSName);
 | 
| -	    if (CN) {
 | 
| -		SECItem cnItem = {siBuffer, NULL, 0};
 | 
| -		cnItem.data = (unsigned char *)cn;
 | 
| -		cnItem.len  = strlen(cn);
 | 
| -		rv = SECITEM_CopyItem(arena, &CN->name.other, &cnItem);
 | 
| -		if (rv == SECSuccess) {
 | 
| -		    DN = cert_CombineNamesLists(DN, CN);
 | 
| -	        }
 | 
| -	    }
 | 
| -	    PORT_Free(cn);
 | 
| -	}
 | 
| -    }
 | 
| -    if (rv == SECSuccess) {
 | 
| -	/* TODO: unmark arena */
 | 
| -	return DN;
 | 
| -    }
 | 
| -loser:
 | 
| -    /* TODO: release arena to mark */
 | 
| -    return NULL;
 | 
| -}
 | 
| -
 | 
| -/* Returns SECSuccess if name matches constraint per RFC 3280 rules for 
 | 
| -** URI name constraints.  SECFailure otherwise.
 | 
| -** If the constraint begins with a dot, it is a domain name, otherwise
 | 
| -** It is a host name.  Examples:
 | 
| -**  Constraint            Name             Result
 | 
| -** ------------      ---------------      --------
 | 
| -**  foo.bar.com          foo.bar.com      matches
 | 
| -**  foo.bar.com          FoO.bAr.CoM      matches
 | 
| -**  foo.bar.com      www.foo.bar.com      no match
 | 
| -**  foo.bar.com        nofoo.bar.com      no match
 | 
| -** .foo.bar.com      www.foo.bar.com      matches
 | 
| -** .foo.bar.com        nofoo.bar.com      no match
 | 
| -** .foo.bar.com          foo.bar.com      no match
 | 
| -** .foo.bar.com     www..foo.bar.com      no match
 | 
| -*/
 | 
| -static SECStatus
 | 
| -compareURIN2C(const SECItem *name, const SECItem *constraint)
 | 
| -{
 | 
| -    int offset;
 | 
| -    /* The spec is silent on intepreting zero-length constraints.
 | 
| -    ** We interpret them as matching no URI names.
 | 
| -    */
 | 
| -    if (!constraint->len)
 | 
| -        return SECFailure;
 | 
| -    if (constraint->data[0] != '.') { 
 | 
| -    	/* constraint is a host name. */
 | 
| -    	if (name->len != constraint->len ||
 | 
| -	    PL_strncasecmp((char *)name->data, 
 | 
| -			   (char *)constraint->data, constraint->len))
 | 
| -	    return SECFailure;
 | 
| -    	return SECSuccess;
 | 
| -    }
 | 
| -    /* constraint is a domain name. */
 | 
| -    if (name->len < constraint->len)
 | 
| -        return SECFailure;
 | 
| -    offset = name->len - constraint->len;
 | 
| -    if (PL_strncasecmp((char *)(name->data + offset), 
 | 
| -		       (char *)constraint->data, constraint->len))
 | 
| -        return SECFailure;
 | 
| -    if (!offset || 
 | 
| -        (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
 | 
| -	return SECSuccess;
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38)
 | 
| -**
 | 
| -** DNS name restrictions are expressed as foo.bar.com.  Any DNS name
 | 
| -** that can be constructed by simply adding to the left hand side of the
 | 
| -** name satisfies the name constraint.  For example, www.foo.bar.com
 | 
| -** would satisfy the constraint but foo1.bar.com would not.
 | 
| -**
 | 
| -** But NIST's PKITS test suite requires that the constraint be treated
 | 
| -** as a domain name, and requires that any name added to the left hand
 | 
| -** side end in a dot ".".  Sensible, but not strictly following the RFC.
 | 
| -**
 | 
| -**  Constraint            Name            RFC 3280  NIST PKITS
 | 
| -** ------------      ---------------      --------  ----------
 | 
| -**  foo.bar.com          foo.bar.com      matches    matches
 | 
| -**  foo.bar.com          FoO.bAr.CoM      matches    matches
 | 
| -**  foo.bar.com      www.foo.bar.com      matches    matches
 | 
| -**  foo.bar.com        nofoo.bar.com      MATCHES    NO MATCH
 | 
| -** .foo.bar.com      www.foo.bar.com      matches    matches? disallowed?
 | 
| -** .foo.bar.com          foo.bar.com      no match   no match
 | 
| -** .foo.bar.com     www..foo.bar.com      matches    probably not 
 | 
| -**
 | 
| -** We will try to conform to NIST's PKITS tests, and the unstated 
 | 
| -** rules they imply.
 | 
| -*/
 | 
| -static SECStatus
 | 
| -compareDNSN2C(const SECItem *name, const SECItem *constraint)
 | 
| -{
 | 
| -    int offset;
 | 
| -    /* The spec is silent on intepreting zero-length constraints.
 | 
| -    ** We interpret them as matching all DNSnames.
 | 
| -    */
 | 
| -    if (!constraint->len)
 | 
| -        return SECSuccess;
 | 
| -    if (name->len < constraint->len)
 | 
| -        return SECFailure;
 | 
| -    offset = name->len - constraint->len;
 | 
| -    if (PL_strncasecmp((char *)(name->data + offset), 
 | 
| -		       (char *)constraint->data, constraint->len))
 | 
| -        return SECFailure;
 | 
| -    if (!offset || 
 | 
| -        (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
 | 
| -	return SECSuccess;
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* Returns SECSuccess if name matches constraint per RFC 3280 rules for
 | 
| -** internet email addresses.  SECFailure otherwise.
 | 
| -** If constraint contains a '@' then the two strings much match exactly.
 | 
| -** Else if constraint starts with a '.'. then it must match the right-most
 | 
| -** substring of the name, 
 | 
| -** else constraint string must match entire name after the name's '@'.
 | 
| -** Empty constraint string matches all names. All comparisons case insensitive.
 | 
| -*/
 | 
| -static SECStatus
 | 
| -compareRFC822N2C(const SECItem *name, const SECItem *constraint)
 | 
| -{
 | 
| -    int offset;
 | 
| -    if (!constraint->len)
 | 
| -        return SECSuccess;
 | 
| -    if (name->len < constraint->len)
 | 
| -        return SECFailure;
 | 
| -    if (constraint->len == 1 && constraint->data[0] == '.')
 | 
| -        return SECSuccess;
 | 
| -    for (offset = constraint->len - 1; offset >= 0; --offset) {
 | 
| -    	if (constraint->data[offset] == '@') {
 | 
| -	    return (name->len == constraint->len && 
 | 
| -	        !PL_strncasecmp((char *)name->data, 
 | 
| -				(char *)constraint->data, constraint->len))
 | 
| -		? SECSuccess : SECFailure;
 | 
| -	}
 | 
| -    }
 | 
| -    offset = name->len - constraint->len;
 | 
| -    if (PL_strncasecmp((char *)(name->data + offset), 
 | 
| -		       (char *)constraint->data, constraint->len))
 | 
| -        return SECFailure;
 | 
| -    if (constraint->data[0] == '.')
 | 
| -        return SECSuccess;
 | 
| -    if (offset > 0 && name->data[offset - 1] == '@')
 | 
| -        return SECSuccess;
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address.
 | 
| -** constraint contains an address of the same length, and a subnet mask
 | 
| -** of the same length.  Compare name's address to the constraint's 
 | 
| -** address, subject to the mask.
 | 
| -** Return SECSuccess if they match, SECFailure if they don't. 
 | 
| -*/
 | 
| -static SECStatus
 | 
| -compareIPaddrN2C(const SECItem *name, const SECItem *constraint)
 | 
| -{
 | 
| -    int i;
 | 
| -    if (name->len == 4 && constraint->len == 8) { /* ipv4 addr */
 | 
| -        for (i = 0; i < 4; i++) {
 | 
| -	    if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+4])
 | 
| -	        goto loser;
 | 
| -	}
 | 
| -	return SECSuccess;
 | 
| -    }
 | 
| -    if (name->len == 16 && constraint->len == 32) { /* ipv6 addr */
 | 
| -        for (i = 0; i < 16; i++) {
 | 
| -	    if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+16])
 | 
| -	        goto loser;
 | 
| -	}
 | 
| -	return SECSuccess;
 | 
| -    }
 | 
| -loser:
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* start with a SECItem that points to a URI.  Parse it lookingg for 
 | 
| -** a hostname.  Modify item->data and item->len to define the hostname,
 | 
| -** but do not modify and data at item->data.  
 | 
| -** If anything goes wrong, the contents of *item are undefined.
 | 
| -*/
 | 
| -static SECStatus
 | 
| -parseUriHostname(SECItem * item)
 | 
| -{
 | 
| -    int i;
 | 
| -    PRBool found = PR_FALSE;
 | 
| -    for (i = 0; (unsigned)(i+2) < item->len; ++i) {
 | 
| -	if (item->data[i  ] == ':' &&
 | 
| -	    item->data[i+1] == '/' &&
 | 
| -	    item->data[i+2] == '/') {
 | 
| -	    i += 3;
 | 
| -	    item->data += i;
 | 
| -	    item->len  -= i;
 | 
| -	    found = PR_TRUE;
 | 
| -	    break;
 | 
| -	}
 | 
| -    }
 | 
| -    if (!found) 
 | 
| -        return SECFailure;
 | 
| -    /* now look for a '/', which is an upper bound in the end of the name */
 | 
| -    for (i = 0; (unsigned)i < item->len; ++i) {
 | 
| -	if (item->data[i] == '/') {
 | 
| -	    item->len = i;
 | 
| -	    break;
 | 
| -	}
 | 
| -    }
 | 
| -    /* now look for a ':', which marks the end of the name */
 | 
| -    for (i = item->len; --i >= 0; ) {
 | 
| -        if (item->data[i] == ':') {
 | 
| -	    item->len = i;
 | 
| -	    break;
 | 
| -	}
 | 
| -    }
 | 
| -    /* now look for an '@', which marks the beginning of the hostname */
 | 
| -    for (i = 0; (unsigned)i < item->len; ++i) {
 | 
| -	if (item->data[i] == '@') {
 | 
| -	    ++i;
 | 
| -	    item->data += i;
 | 
| -	    item->len  -= i;
 | 
| -	    break;
 | 
| -	}
 | 
| -    }
 | 
| -    return item->len ? SECSuccess : SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* This function takes one name, and a list of constraints.
 | 
| -** It searches the constraints looking for a match.
 | 
| -** It returns SECSuccess if the name satisfies the constraints, i.e.,
 | 
| -** if excluded, then the name does not match any constraint, 
 | 
| -** if permitted, then the name matches at least one constraint.
 | 
| -** It returns SECFailure if the name fails to satisfy the constraints,
 | 
| -** or if some code fails (e.g. out of memory, or invalid constraint)
 | 
| -*/
 | 
| -SECStatus
 | 
| -cert_CompareNameWithConstraints(CERTGeneralName     *name, 
 | 
| -				CERTNameConstraint  *constraints,
 | 
| -				PRBool              excluded)
 | 
| -{
 | 
| -    SECStatus           rv     = SECSuccess;
 | 
| -    SECStatus           matched = SECFailure;
 | 
| -    CERTNameConstraint  *current;
 | 
| -
 | 
| -    PORT_Assert(constraints);  /* caller should not call with NULL */
 | 
| -    if (!constraints) {
 | 
| -	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 | 
| -        return SECFailure;
 | 
| -    }
 | 
| -
 | 
| -    current = constraints;
 | 
| -    do {
 | 
| -	rv = SECSuccess;
 | 
| -	matched = SECFailure;
 | 
| -	PORT_Assert(name->type == current->name.type);
 | 
| -	switch (name->type) {
 | 
| -
 | 
| -	case certDNSName:
 | 
| -	    matched = compareDNSN2C(&name->name.other, 
 | 
| -	                            ¤t->name.name.other);
 | 
| -	    break;
 | 
| -
 | 
| -	case certRFC822Name:
 | 
| -	    matched = compareRFC822N2C(&name->name.other, 
 | 
| -	                               ¤t->name.name.other);
 | 
| -	    break;
 | 
| -
 | 
| -	case certURI:
 | 
| -	    {
 | 
| -		/* make a modifiable copy of the URI SECItem. */
 | 
| -		SECItem uri = name->name.other;
 | 
| -		/* find the hostname in the URI */
 | 
| -		rv = parseUriHostname(&uri);
 | 
| -		if (rv == SECSuccess) {
 | 
| -		    /* does our hostname meet the constraint? */
 | 
| -		    matched = compareURIN2C(&uri, ¤t->name.name.other);
 | 
| -		}
 | 
| -	    }
 | 
| -	    break;
 | 
| -
 | 
| -	case certDirectoryName:
 | 
| -	    /* Determine if the constraint directory name is a "prefix"
 | 
| -	    ** for the directory name being tested. 
 | 
| -	    */
 | 
| -	  {
 | 
| -	    /* status defaults to SECEqual, so that a constraint with 
 | 
| -	    ** no AVAs will be a wildcard, matching all directory names.
 | 
| -	    */
 | 
| -	    SECComparison   status = SECEqual;
 | 
| -	    const CERTRDN **cRDNs = 
 | 
| -		    (const CERTRDN **)current->name.name.directoryName.rdns;  
 | 
| -	    const CERTRDN **nRDNs = 
 | 
| -		    (const CERTRDN **)name->name.directoryName.rdns;
 | 
| -	    while (cRDNs && *cRDNs && nRDNs && *nRDNs) { 
 | 
| -		/* loop over name RDNs and constraint RDNs in lock step */
 | 
| -		const CERTRDN *cRDN = *cRDNs++;
 | 
| -		const CERTRDN *nRDN = *nRDNs++;
 | 
| -		CERTAVA **cAVAs = cRDN->avas;
 | 
| -		while (cAVAs && *cAVAs) { /* loop over constraint AVAs */
 | 
| -		    CERTAVA *cAVA = *cAVAs++;
 | 
| -		    CERTAVA **nAVAs = nRDN->avas;
 | 
| -		    while (nAVAs && *nAVAs) { /* loop over name AVAs */
 | 
| -			CERTAVA *nAVA = *nAVAs++;
 | 
| -			status = CERT_CompareAVA(cAVA, nAVA);
 | 
| -			if (status == SECEqual) 
 | 
| -			    break;
 | 
| -		    } /* loop over name AVAs */
 | 
| -		    if (status != SECEqual) 
 | 
| -			break;
 | 
| -		} /* loop over constraint AVAs */
 | 
| -		if (status != SECEqual) 
 | 
| -		    break;
 | 
| -	    } /* loop over name RDNs and constraint RDNs */
 | 
| -	    matched = (status == SECEqual) ? SECSuccess : SECFailure;
 | 
| -	    break;
 | 
| -	  }
 | 
| -
 | 
| -	case certIPAddress:	/* type 8 */
 | 
| -	    matched = compareIPaddrN2C(&name->name.other, 
 | 
| -	                               ¤t->name.name.other);
 | 
| -	    break;
 | 
| -
 | 
| -	/* NSS does not know how to compare these "Other" type names with 
 | 
| -	** their respective constraints.  But it does know how to tell
 | 
| -	** if the constraint applies to the type of name (by comparing
 | 
| -	** the constraint OID to the name OID).  NSS makes no use of "Other"
 | 
| -	** type names at all, so NSS errs on the side of leniency for these 
 | 
| -	** types, provided that their OIDs match.  So, when an "Other"
 | 
| -	** name constraint appears in an excluded subtree, it never causes
 | 
| -	** a name to fail.  When an "Other" name constraint appears in a
 | 
| -	** permitted subtree, AND the constraint's OID matches the name's
 | 
| -	** OID, then name is treated as if it matches the constraint.
 | 
| -	*/
 | 
| -	case certOtherName:	/* type 1 */
 | 
| -	    matched = (!excluded &&
 | 
| -		       name->type == current->name.type &&
 | 
| -		       SECITEM_ItemsAreEqual(&name->name.OthName.oid,
 | 
| -					     ¤t->name.name.OthName.oid))
 | 
| -		 ? SECSuccess : SECFailure;
 | 
| -	    break;
 | 
| -
 | 
| -	/* NSS does not know how to compare these types of names with their
 | 
| -	** respective constraints.  But NSS makes no use of these types of 
 | 
| -	** names at all, so it errs on the side of leniency for these types.
 | 
| -	** Constraints for these types of names never cause the name to 
 | 
| -	** fail the constraints test.  NSS behaves as if the name matched
 | 
| -	** for permitted constraints, and did not match for excluded ones.
 | 
| -	*/
 | 
| -	case certX400Address:	/* type 4 */
 | 
| -	case certEDIPartyName:  /* type 6 */
 | 
| -	case certRegisterID:	/* type 9 */
 | 
| -	    matched = excluded ? SECFailure : SECSuccess;
 | 
| -	    break;
 | 
| -
 | 
| -	default: /* non-standard types are not supported */
 | 
| -	    rv = SECFailure;
 | 
| -	    break;
 | 
| -	}
 | 
| -	if (matched == SECSuccess || rv != SECSuccess)
 | 
| -	    break;
 | 
| -	current = CERT_GetNextNameConstraint(current);
 | 
| -    } while (current != constraints);
 | 
| -    if (rv == SECSuccess) {
 | 
| -        if (matched == SECSuccess) 
 | 
| -	    rv = excluded ? SECFailure : SECSuccess;
 | 
| -	else
 | 
| -	    rv = excluded ? SECSuccess : SECFailure;
 | 
| -	return rv;
 | 
| -    }
 | 
| -
 | 
| -    return SECFailure;
 | 
| -}
 | 
| -
 | 
| -/* Add and link a CERTGeneralName to a CERTNameConstraint list. Most
 | 
| -** likely the CERTNameConstraint passed in is either the permitted
 | 
| -** list or the excluded list of a CERTNameConstraints.
 | 
| -*/
 | 
| -SECStatus
 | 
| -CERT_AddNameConstraintByGeneralName(PLArenaPool *arena,
 | 
| -                                    CERTNameConstraint **constraints,
 | 
| -                                    CERTGeneralName *name)
 | 
| -{
 | 
| -    SECStatus rv;
 | 
| -    CERTNameConstraint *current = NULL;
 | 
| -    CERTNameConstraint *first = *constraints;
 | 
| -    void *mark = NULL;
 | 
| -
 | 
| -    mark = PORT_ArenaMark(arena);
 | 
| -
 | 
| -    current = PORT_ArenaZNew(arena, CERTNameConstraint);
 | 
| -    if (current == NULL) {
 | 
| -        rv = SECFailure;
 | 
| -        goto done;
 | 
| -    }
 | 
| -    
 | 
| -    rv = cert_CopyOneGeneralName(arena, ¤t->name, name);
 | 
| -    if (rv != SECSuccess) {
 | 
| -        goto done;
 | 
| -    }
 | 
| -    
 | 
| -    current->name.l.prev = current->name.l.next = &(current->name.l);
 | 
| -    
 | 
| -    if (first == NULL) {
 | 
| -        *constraints = current;
 | 
| -        PR_INIT_CLIST(¤t->l);
 | 
| -    } else {
 | 
| -        PR_INSERT_BEFORE(¤t->l, &first->l);
 | 
| -    }
 | 
| -
 | 
| -done:
 | 
| -    if (rv == SECFailure) {
 | 
| -        PORT_ArenaRelease(arena, mark);
 | 
| -    } else {
 | 
| -        PORT_ArenaUnmark(arena, mark);
 | 
| -    }
 | 
| -    return rv;
 | 
| -}
 | 
| -
 | 
| -/* Extract the name constraints extension from the CA cert. */
 | 
| -SECStatus
 | 
| -CERT_FindNameConstraintsExten(PRArenaPool      *arena,
 | 
| -                              CERTCertificate  *cert,
 | 
| -                              CERTNameConstraints **constraints)
 | 
| -{
 | 
| -    SECStatus            rv = SECSuccess;
 | 
| -    SECItem              constraintsExtension;
 | 
| -    void                *mark = NULL;
 | 
| -    
 | 
| -    *constraints = NULL;
 | 
| -
 | 
| -    rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, 
 | 
| -                                &constraintsExtension);
 | 
| -    if (rv != SECSuccess) {
 | 
| -        if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
 | 
| -            rv = SECSuccess;
 | 
| -        }
 | 
| -        return rv;
 | 
| -    }
 | 
| -
 | 
| -    mark = PORT_ArenaMark(arena);
 | 
| -
 | 
| -    *constraints = cert_DecodeNameConstraints(arena, &constraintsExtension);
 | 
| -    if (*constraints == NULL) { /* decode failed */
 | 
| -        rv = SECFailure;
 | 
| -    }
 | 
| -    PORT_Free (constraintsExtension.data);
 | 
| -
 | 
| -    if (rv == SECFailure) {
 | 
| -        PORT_ArenaRelease(arena, mark);
 | 
| -    } else {
 | 
| -        PORT_ArenaUnmark(arena, mark);
 | 
| -    }
 | 
| -
 | 
| -    return rv;
 | 
| -}
 | 
| -
 | 
| -/* Verify name against all the constraints relevant to that type of
 | 
| -** the name.
 | 
| -*/
 | 
| -SECStatus
 | 
| -CERT_CheckNameSpace(PRArenaPool          *arena,
 | 
| -                    CERTNameConstraints  *constraints,
 | 
| -                    CERTGeneralName      *currentName)
 | 
| -{
 | 
| -    CERTNameConstraint  *matchingConstraints;
 | 
| -    SECStatus            rv = SECSuccess;
 | 
| -    
 | 
| -    if (constraints->excluded != NULL) {
 | 
| -        rv = CERT_GetNameConstraintByType(constraints->excluded, 
 | 
| -                                          currentName->type, 
 | 
| -                                          &matchingConstraints, arena);
 | 
| -        if (rv == SECSuccess && matchingConstraints != NULL) {
 | 
| -            rv = cert_CompareNameWithConstraints(currentName, 
 | 
| -                                                 matchingConstraints,
 | 
| -                                                 PR_TRUE);
 | 
| -        }
 | 
| -        if (rv != SECSuccess) {
 | 
| -            return(rv);
 | 
| -        }
 | 
| -    }
 | 
| -    
 | 
| -    if (constraints->permited != NULL) {
 | 
| -        rv = CERT_GetNameConstraintByType(constraints->permited, 
 | 
| -                                          currentName->type, 
 | 
| -                                          &matchingConstraints, arena);
 | 
| -        if (rv == SECSuccess && matchingConstraints != NULL) {
 | 
| -            rv = cert_CompareNameWithConstraints(currentName, 
 | 
| -                                                 matchingConstraints,
 | 
| -                                                 PR_FALSE);
 | 
| -        }
 | 
| -        if (rv != SECSuccess) {
 | 
| -            return(rv);
 | 
| -        }
 | 
| -    }
 | 
| -
 | 
| -    return(SECSuccess);
 | 
| -}
 | 
| -
 | 
| -/* Extract the name constraints extension from the CA cert.
 | 
| -** Test each and every name in namesList against all the constraints
 | 
| -** relevant to that type of name.
 | 
| -** Returns NULL in pBadCert for success, if all names are acceptable.
 | 
| -** If some name is not acceptable, returns a pointer to the cert that
 | 
| -** contained that name.
 | 
| -*/
 | 
| -SECStatus
 | 
| -CERT_CompareNameSpace(CERTCertificate  *cert,
 | 
| -		      CERTGeneralName  *namesList,
 | 
| - 		      CERTCertificate **certsList,
 | 
| - 		      PRArenaPool      *reqArena,
 | 
| - 		      CERTCertificate **pBadCert)
 | 
| -{
 | 
| -    SECStatus            rv = SECSuccess;
 | 
| -    CERTNameConstraints  *constraints;
 | 
| -    CERTGeneralName      *currentName;
 | 
| -    int                  count = 0;
 | 
| -    CERTCertificate      *badCert = NULL;
 | 
| -
 | 
| -    /* If no names to check, then no names can be bad. */
 | 
| -    if (!namesList)
 | 
| -    	goto done;
 | 
| -    rv = CERT_FindNameConstraintsExten(reqArena, cert, &constraints);
 | 
| -    if (rv != SECSuccess) {
 | 
| -	count = -1;
 | 
| -	goto done;
 | 
| -    }
 | 
| -
 | 
| -    currentName = namesList;
 | 
| -    do {
 | 
| -	if (constraints){
 | 
| -	    rv = CERT_CheckNameSpace(reqArena, constraints, currentName);
 | 
| -	    if (rv != SECSuccess) {
 | 
| -		break;
 | 
| -	    }
 | 
| -	}
 | 
| - 	currentName = CERT_GetNextGeneralName(currentName);
 | 
| - 	count ++;
 | 
| -    } while (currentName != namesList);
 | 
| -
 | 
| -done:
 | 
| -    if (rv != SECSuccess) {
 | 
| -	badCert = (count >= 0) ? certsList[count] : cert;
 | 
| -    }
 | 
| -    if (pBadCert)
 | 
| -	*pBadCert = badCert;
 | 
| -
 | 
| -    return rv;
 | 
| -}
 | 
| -
 | 
| -#if 0
 | 
| -/* not exported from shared libs, not used.  Turn on if we ever need it. */
 | 
| -SECStatus
 | 
| -CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b)
 | 
| -{
 | 
| -    CERTGeneralName *currentA;
 | 
| -    CERTGeneralName *currentB;
 | 
| -    PRBool found;
 | 
| -
 | 
| -    currentA = a;
 | 
| -    currentB = b;
 | 
| -    if (a != NULL) {
 | 
| -	do { 
 | 
| -	    if (currentB == NULL) {
 | 
| -		return SECFailure;
 | 
| -	    }
 | 
| -	    currentB = CERT_GetNextGeneralName(currentB);
 | 
| -	    currentA = CERT_GetNextGeneralName(currentA);
 | 
| -	} while (currentA != a);
 | 
| -    }
 | 
| -    if (currentB != b) {
 | 
| -	return SECFailure;
 | 
| -    }
 | 
| -    currentA = a;
 | 
| -    do {
 | 
| -	currentB = b;
 | 
| -	found = PR_FALSE;
 | 
| -	do {
 | 
| -	    if (currentB->type == currentA->type) {
 | 
| -		switch (currentB->type) {
 | 
| -		  case certDNSName:
 | 
| -		  case certEDIPartyName:
 | 
| -		  case certIPAddress:
 | 
| -		  case certRegisterID:
 | 
| -		  case certRFC822Name:
 | 
| -		  case certX400Address:
 | 
| -		  case certURI:
 | 
| -		    if (SECITEM_CompareItem(¤tA->name.other,
 | 
| -					    ¤tB->name.other) 
 | 
| -			== SECEqual) {
 | 
| -			found = PR_TRUE;
 | 
| -		    }
 | 
| -		    break;
 | 
| -		  case certOtherName:
 | 
| -		    if (SECITEM_CompareItem(¤tA->name.OthName.oid,
 | 
| -					    ¤tB->name.OthName.oid) 
 | 
| -			== SECEqual &&
 | 
| -			SECITEM_CompareItem(¤tA->name.OthName.name,
 | 
| -					    ¤tB->name.OthName.name)
 | 
| -			== SECEqual) {
 | 
| -			found = PR_TRUE;
 | 
| -		    }
 | 
| -		    break;
 | 
| -		  case certDirectoryName:
 | 
| -		    if (CERT_CompareName(¤tA->name.directoryName,
 | 
| -					 ¤tB->name.directoryName)
 | 
| -			== SECEqual) {
 | 
| -			found = PR_TRUE;
 | 
| -		    }
 | 
| -		}
 | 
| -		    
 | 
| -	    }
 | 
| -	    currentB = CERT_GetNextGeneralName(currentB);
 | 
| -	} while (currentB != b && found != PR_TRUE);
 | 
| -	if (found != PR_TRUE) {
 | 
| -	    return SECFailure;
 | 
| -	}
 | 
| -	currentA = CERT_GetNextGeneralName(currentA);
 | 
| -    } while (currentA != a);
 | 
| -    return SECSuccess;
 | 
| -}
 | 
| -
 | 
| -SECStatus
 | 
| -CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b)
 | 
| -{
 | 
| -    SECStatus rv;
 | 
| -
 | 
| -    if (a == b) {
 | 
| -	return SECSuccess;
 | 
| -    }
 | 
| -    if (a != NULL && b != NULL) {
 | 
| -	PZ_Lock(a->lock);
 | 
| -	PZ_Lock(b->lock);
 | 
| -	rv = CERT_CompareGeneralName(a->name, b->name);
 | 
| -	PZ_Unlock(a->lock);
 | 
| -	PZ_Unlock(b->lock);
 | 
| -    } else {
 | 
| -	rv = SECFailure;
 | 
| -    }
 | 
| -    return rv;
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -#if 0
 | 
| -/* This function is not exported from NSS shared libraries, and is not
 | 
| -** used inside of NSS.
 | 
| -** XXX it doesn't check for failed allocations. :-(
 | 
| -*/
 | 
| -void *
 | 
| -CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list,
 | 
| -				  CERTGeneralNameType type,
 | 
| -				  PRArenaPool *arena)
 | 
| -{
 | 
| -    CERTName *name = NULL; 
 | 
| -    SECItem *item = NULL;
 | 
| -    OtherName *other = NULL;
 | 
| -    OtherName *tmpOther = NULL;
 | 
| -    void *data;
 | 
| -
 | 
| -    PZ_Lock(list->lock);
 | 
| -    data = CERT_GetGeneralNameByType(list->name, type, PR_FALSE);
 | 
| -    if (data != NULL) {
 | 
| -	switch (type) {
 | 
| -	  case certDNSName:
 | 
| -	  case certEDIPartyName:
 | 
| -	  case certIPAddress:
 | 
| -	  case certRegisterID:
 | 
| -	  case certRFC822Name:
 | 
| -	  case certX400Address:
 | 
| -	  case certURI:
 | 
| -	    if (arena != NULL) {
 | 
| -		item = PORT_ArenaNew(arena, SECItem);
 | 
| -		if (item != NULL) {
 | 
| -XXX		    SECITEM_CopyItem(arena, item, (SECItem *) data);
 | 
| -		}
 | 
| -	    } else { 
 | 
| -		item = SECITEM_DupItem((SECItem *) data);
 | 
| -	    }
 | 
| -	    PZ_Unlock(list->lock);
 | 
| -	    return item;
 | 
| -	  case certOtherName:
 | 
| -	    other = (OtherName *) data;
 | 
| -	    if (arena != NULL) {
 | 
| -		tmpOther = PORT_ArenaNew(arena, OtherName);
 | 
| -	    } else {
 | 
| -		tmpOther = PORT_New(OtherName);
 | 
| -	    }
 | 
| -	    if (tmpOther != NULL) {
 | 
| -XXX		SECITEM_CopyItem(arena, &tmpOther->oid, &other->oid);
 | 
| -XXX		SECITEM_CopyItem(arena, &tmpOther->name, &other->name);
 | 
| -	    }
 | 
| -	    PZ_Unlock(list->lock);
 | 
| -	    return tmpOther;
 | 
| -	  case certDirectoryName:
 | 
| -	    if (arena) {
 | 
| -		name = PORT_ArenaZNew(list->arena, CERTName);
 | 
| -		if (name) {
 | 
| -XXX		    CERT_CopyName(arena, name, (CERTName *) data);
 | 
| -		}
 | 
| -	    }
 | 
| -	    PZ_Unlock(list->lock);
 | 
| -	    return name;
 | 
| -	}
 | 
| -    }
 | 
| -    PZ_Unlock(list->lock);
 | 
| -    return NULL;
 | 
| -}
 | 
| -#endif
 | 
| -
 | 
| -#if 0
 | 
| -/* This function is not exported from NSS shared libraries, and is not
 | 
| -** used inside of NSS.
 | 
| -** XXX it should NOT be a void function, since it does allocations
 | 
| -** that can fail.
 | 
| -*/
 | 
| -void
 | 
| -CERT_AddGeneralNameToList(CERTGeneralNameList *list, 
 | 
| -			  CERTGeneralNameType type,
 | 
| -			  void *data, SECItem *oid)
 | 
| -{
 | 
| -    CERTGeneralName *name;
 | 
| -
 | 
| -    if (list != NULL && data != NULL) {
 | 
| -	PZ_Lock(list->lock);
 | 
| -	name = CERT_NewGeneralName(list->arena, type);
 | 
| -	if (!name)
 | 
| -	    goto done;
 | 
| -	switch (type) {
 | 
| -	  case certDNSName:
 | 
| -	  case certEDIPartyName:
 | 
| -	  case certIPAddress:
 | 
| -	  case certRegisterID:
 | 
| -	  case certRFC822Name:
 | 
| -	  case certX400Address:
 | 
| -	  case certURI:
 | 
| -XXX	    SECITEM_CopyItem(list->arena, &name->name.other, (SECItem *)data);
 | 
| -	    break;
 | 
| -	  case certOtherName:
 | 
| -XXX	    SECITEM_CopyItem(list->arena, &name->name.OthName.name,
 | 
| -			     (SECItem *) data);
 | 
| -XXX	    SECITEM_CopyItem(list->arena, &name->name.OthName.oid,
 | 
| -			     oid);
 | 
| -	    break;
 | 
| -	  case certDirectoryName:
 | 
| -XXX	    CERT_CopyName(list->arena, &name->name.directoryName,
 | 
| -			  (CERTName *) data);
 | 
| -	    break;
 | 
| -	}
 | 
| -	list->name = cert_CombineNamesLists(list->name, name);
 | 
| -	list->len++;
 | 
| -done:
 | 
| -	PZ_Unlock(list->lock);
 | 
| -    }
 | 
| -    return;
 | 
| -}
 | 
| -#endif
 | 
| 
 |