security/nss/lib/certdb/genname.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "plarena.h"
     6 #include "seccomon.h"
     7 #include "secitem.h"
     8 #include "secoidt.h"
     9 #include "secasn1.h"
    10 #include "secder.h"
    11 #include "certt.h"
    12 #include "cert.h"
    13 #include "certi.h"
    14 #include "xconst.h"
    15 #include "secerr.h"
    16 #include "secoid.h"
    17 #include "prprf.h"
    18 #include "genname.h"
    20 SEC_ASN1_MKSUB(SEC_AnyTemplate)
    21 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
    22 SEC_ASN1_MKSUB(SEC_IA5StringTemplate)
    23 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
    24 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
    26 static const SEC_ASN1Template CERTNameConstraintTemplate[] = {
    27     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraint) },
    28     { SEC_ASN1_ANY, offsetof(CERTNameConstraint, DERName) },
    29     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, 
    30           offsetof(CERTNameConstraint, min),
    31           SEC_ASN1_SUB(SEC_IntegerTemplate) }, 
    32     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, 
    33           offsetof(CERTNameConstraint, max),
    34           SEC_ASN1_SUB(SEC_IntegerTemplate) },
    35     { 0, }
    36 };
    38 const SEC_ASN1Template CERT_NameConstraintSubtreeSubTemplate[] = {
    39     { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
    40 };
    42 static const SEC_ASN1Template CERTNameConstraintsTemplate[] = {
    43     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraints) },
    44     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
    45           offsetof(CERTNameConstraints, DERPermited), 
    46 	  CERT_NameConstraintSubtreeSubTemplate},
    47     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
    48           offsetof(CERTNameConstraints, DERExcluded), 
    49 	  CERT_NameConstraintSubtreeSubTemplate},
    50     { 0, }
    51 };
    54 static const SEC_ASN1Template CERTOthNameTemplate[] = {
    55     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OtherName) },
    56     { SEC_ASN1_OBJECT_ID, 
    57 	  offsetof(OtherName, oid) },
    58     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
    59           SEC_ASN1_XTRN | 0, offsetof(OtherName, name),
    60           SEC_ASN1_SUB(SEC_AnyTemplate) },
    61     { 0, } 
    62 };
    64 static const SEC_ASN1Template CERTOtherNameTemplate[] = {
    65     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0 ,
    66       offsetof(CERTGeneralName, name.OthName), CERTOthNameTemplate, 
    67       sizeof(CERTGeneralName) }
    68 };
    70 static const SEC_ASN1Template CERTOtherName2Template[] = {
    71     { SEC_ASN1_SEQUENCE | SEC_ASN1_CONTEXT_SPECIFIC | 0 ,
    72       0, NULL, sizeof(CERTGeneralName) },
    73     { SEC_ASN1_OBJECT_ID,
    74 	  offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, oid) },
    75     { SEC_ASN1_ANY,
    76 	  offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, name) },
    77     { 0, } 
    78 };
    80 static const SEC_ASN1Template CERT_RFC822NameTemplate[] = {
    81     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1 ,
    82           offsetof(CERTGeneralName, name.other),
    83           SEC_ASN1_SUB(SEC_IA5StringTemplate),
    84           sizeof (CERTGeneralName)}
    85 };
    87 static const SEC_ASN1Template CERT_DNSNameTemplate[] = {
    88     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2 ,
    89           offsetof(CERTGeneralName, name.other),
    90           SEC_ASN1_SUB(SEC_IA5StringTemplate),
    91           sizeof (CERTGeneralName)}
    92 };
    94 static const SEC_ASN1Template CERT_X400AddressTemplate[] = {
    95     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 3,
    96           offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
    97           sizeof (CERTGeneralName)}
    98 };
   100 static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = {
   101     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
   102           SEC_ASN1_XTRN | 4, offsetof(CERTGeneralName, derDirectoryName),
   103           SEC_ASN1_SUB(SEC_AnyTemplate), sizeof (CERTGeneralName)}
   104 };
   107 static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = {
   108     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 5,
   109           offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate),
   110           sizeof (CERTGeneralName)}
   111 };
   113 static const SEC_ASN1Template CERT_URITemplate[] = {
   114     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 6 ,
   115           offsetof(CERTGeneralName, name.other),
   116           SEC_ASN1_SUB(SEC_IA5StringTemplate),
   117           sizeof (CERTGeneralName)}
   118 };
   120 static const SEC_ASN1Template CERT_IPAddressTemplate[] = {
   121     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 7 ,
   122           offsetof(CERTGeneralName, name.other),
   123           SEC_ASN1_SUB(SEC_OctetStringTemplate),
   124           sizeof (CERTGeneralName)}
   125 };
   127 static const SEC_ASN1Template CERT_RegisteredIDTemplate[] = {
   128     { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 8 ,
   129           offsetof(CERTGeneralName, name.other),
   130           SEC_ASN1_SUB(SEC_ObjectIDTemplate),
   131           sizeof (CERTGeneralName)}
   132 };
   135 const SEC_ASN1Template CERT_GeneralNamesTemplate[] = {
   136     { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) }
   137 };
   140 static struct {
   141     CERTGeneralNameType type;
   142     char *name;
   143 } typesArray[] = {
   144     { certOtherName, "other" },
   145     { certRFC822Name, "email" },
   146     { certRFC822Name, "rfc822" },
   147     { certDNSName, "dns" },
   148     { certX400Address, "x400" },
   149     { certX400Address, "x400addr" },
   150     { certDirectoryName, "directory" },
   151     { certDirectoryName, "dn" },
   152     { certEDIPartyName, "edi" },
   153     { certEDIPartyName, "ediparty" },
   154     { certURI, "uri" },
   155     { certIPAddress, "ip" },
   156     { certIPAddress, "ipaddr" },
   157     { certRegisterID, "registerid" }
   158 };
   160 CERTGeneralNameType
   161 CERT_GetGeneralNameTypeFromString(const char *string)
   162 {
   163     int types_count = sizeof(typesArray)/sizeof(typesArray[0]);
   164     int i;
   166     for (i=0; i < types_count; i++) {
   167         if (PORT_Strcasecmp(string, typesArray[i].name) == 0) {
   168             return typesArray[i].type;
   169         }
   170     }
   171     return 0;
   172 }
   174 CERTGeneralName *
   175 CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type)
   176 {
   177     CERTGeneralName *name = arena 
   178                             ? PORT_ArenaZNew(arena, CERTGeneralName)
   179 	                    : PORT_ZNew(CERTGeneralName);
   180     if (name) {
   181 	name->type = type;
   182 	name->l.prev = name->l.next = &name->l;
   183     }
   184     return name;
   185 }
   187 /* Copy content of one General Name to another.
   188 ** Caller has allocated destination general name.
   189 ** This function does not change the destinate's GeneralName's list linkage.
   190 */
   191 SECStatus
   192 cert_CopyOneGeneralName(PLArenaPool      *arena,
   193 		        CERTGeneralName  *dest, 
   194 		        CERTGeneralName  *src)
   195 {
   196     SECStatus rv;
   197     void *mark = NULL;
   199     PORT_Assert(dest != NULL);
   200     dest->type = src->type;
   202     mark = PORT_ArenaMark(arena);
   204     switch (src->type) {
   205     case certDirectoryName: 
   206 	rv = SECITEM_CopyItem(arena, &dest->derDirectoryName, 
   207 				      &src->derDirectoryName);
   208 	if (rv == SECSuccess) 
   209 	    rv = CERT_CopyName(arena, &dest->name.directoryName, 
   210 				       &src->name.directoryName);
   211 	break;
   213     case certOtherName: 
   214 	rv = SECITEM_CopyItem(arena, &dest->name.OthName.name, 
   215 				      &src->name.OthName.name);
   216 	if (rv == SECSuccess) 
   217 	    rv = SECITEM_CopyItem(arena, &dest->name.OthName.oid, 
   218 					  &src->name.OthName.oid);
   219 	break;
   221     default: 
   222 	rv = SECITEM_CopyItem(arena, &dest->name.other, 
   223 				      &src->name.other);
   224 	break;
   226     }
   227     if (rv != SECSuccess) {
   228         PORT_ArenaRelease(arena, mark);
   229     } else {
   230         PORT_ArenaUnmark(arena, mark);
   231     }
   232     return rv;
   233 }
   236 void
   237 CERT_DestroyGeneralNameList(CERTGeneralNameList *list)
   238 {
   239     PZLock *lock;
   241     if (list != NULL) {
   242 	lock = list->lock;
   243 	PZ_Lock(lock);
   244 	if (--list->refCount <= 0 && list->arena != NULL) {
   245 	    PORT_FreeArena(list->arena, PR_FALSE);
   246 	    PZ_Unlock(lock);
   247 	    PZ_DestroyLock(lock);
   248 	} else {
   249 	    PZ_Unlock(lock);
   250 	}
   251     }
   252     return;
   253 }
   255 CERTGeneralNameList *
   256 CERT_CreateGeneralNameList(CERTGeneralName *name) {
   257     PLArenaPool *arena;
   258     CERTGeneralNameList *list = NULL;
   260     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   261     if (arena == NULL) {
   262 	goto done;
   263     }
   264     list = PORT_ArenaZNew(arena, CERTGeneralNameList);
   265     if (!list)
   266     	goto loser;
   267     if (name != NULL) {
   268 	SECStatus rv;
   269 	list->name = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
   270 	if (!list->name)
   271 	    goto loser;
   272 	rv = CERT_CopyGeneralName(arena, list->name, name);
   273 	if (rv != SECSuccess)
   274 	    goto loser;
   275     }
   276     list->lock = PZ_NewLock(nssILockList);
   277     if (!list->lock)
   278     	goto loser;
   279     list->arena = arena;
   280     list->refCount = 1;
   281 done:
   282     return list;
   284 loser:
   285     PORT_FreeArena(arena, PR_FALSE);
   286     return NULL;
   287 }
   289 CERTGeneralName *
   290 CERT_GetNextGeneralName(CERTGeneralName *current)
   291 {
   292     PRCList *next;
   294     next = current->l.next;
   295     return (CERTGeneralName *) (((char *) next) - offsetof(CERTGeneralName, l));
   296 }
   298 CERTGeneralName *
   299 CERT_GetPrevGeneralName(CERTGeneralName *current)
   300 {
   301     PRCList *prev;
   302     prev = current->l.prev;
   303     return (CERTGeneralName *) (((char *) prev) - offsetof(CERTGeneralName, l));
   304 }
   306 CERTNameConstraint *
   307 CERT_GetNextNameConstraint(CERTNameConstraint *current)
   308 {
   309     PRCList *next;
   311     next = current->l.next;
   312     return (CERTNameConstraint *) (((char *) next) - offsetof(CERTNameConstraint, l));
   313 }
   315 CERTNameConstraint *
   316 CERT_GetPrevNameConstraint(CERTNameConstraint *current)
   317 {
   318     PRCList *prev;
   319     prev = current->l.prev;
   320     return (CERTNameConstraint *) (((char *) prev) - offsetof(CERTNameConstraint, l));
   321 }
   323 SECItem *
   324 CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, PLArenaPool *arena)
   325 {
   327     const SEC_ASN1Template * template;
   329     PORT_Assert(arena);
   330     if (arena == NULL) {
   331 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   332 	return NULL;
   333     }
   334     /* TODO: mark arena */
   335     if (dest == NULL) {
   336 	dest = PORT_ArenaZNew(arena, SECItem);
   337 	if (!dest)
   338 	    goto loser;
   339     }
   340     if (genName->type == certDirectoryName) {
   341 	if (genName->derDirectoryName.data == NULL) {
   342 	    /* The field hasn't been encoded yet. */
   343             SECItem * pre_dest =
   344             SEC_ASN1EncodeItem (arena, &(genName->derDirectoryName),
   345                                 &(genName->name.directoryName),
   346                                 CERT_NameTemplate);
   347             if (!pre_dest)
   348                 goto loser;
   349 	}
   350 	if (genName->derDirectoryName.data == NULL) {
   351 	    goto loser;
   352 	}
   353     }
   354     switch (genName->type) {
   355     case certURI:           template = CERT_URITemplate;           break;
   356     case certRFC822Name:    template = CERT_RFC822NameTemplate;    break;
   357     case certDNSName:       template = CERT_DNSNameTemplate;       break;
   358     case certIPAddress:     template = CERT_IPAddressTemplate;     break;
   359     case certOtherName:     template = CERTOtherNameTemplate;      break;
   360     case certRegisterID:    template = CERT_RegisteredIDTemplate;  break;
   361          /* for this type, we expect the value is already encoded */
   362     case certEDIPartyName:  template = CERT_EDIPartyNameTemplate;  break;
   363 	 /* for this type, we expect the value is already encoded */
   364     case certX400Address:   template = CERT_X400AddressTemplate;   break;
   365     case certDirectoryName: template = CERT_DirectoryNameTemplate; break;
   366     default:
   367 	PORT_Assert(0); goto loser;
   368     }
   369     dest = SEC_ASN1EncodeItem(arena, dest, genName, template);
   370     if (!dest) {
   371 	goto loser;
   372     }
   373     /* TODO: unmark arena */
   374     return dest;
   375 loser:
   376     /* TODO: release arena back to mark */
   377     return NULL;
   378 }
   380 SECItem **
   381 cert_EncodeGeneralNames(PLArenaPool *arena, CERTGeneralName *names)
   382 {
   383     CERTGeneralName  *current_name;
   384     SECItem          **items = NULL;
   385     int              count = 0;
   386     int              i;
   387     PRCList          *head;
   389     PORT_Assert(arena);
   390     /* TODO: mark arena */
   391     current_name = names;
   392     if (names != NULL) {
   393 	count = 1;
   394     }
   395     head = &(names->l);
   396     while (current_name->l.next != head) {
   397 	current_name = CERT_GetNextGeneralName(current_name);
   398 	++count;
   399     }
   400     current_name = CERT_GetNextGeneralName(current_name);
   401     items = PORT_ArenaNewArray(arena, SECItem *, count + 1);
   402     if (items == NULL) {
   403 	goto loser;
   404     }
   405     for (i = 0; i < count; i++) {
   406 	items[i] = CERT_EncodeGeneralName(current_name, (SECItem *)NULL, arena);
   407 	if (items[i] == NULL) {
   408 	    goto loser;
   409 	}
   410 	current_name = CERT_GetNextGeneralName(current_name);
   411     }
   412     items[i] = NULL;
   413     /* TODO: unmark arena */
   414     return items;
   415 loser:
   416     /* TODO: release arena to mark */
   417     return NULL;
   418 }
   420 CERTGeneralName *
   421 CERT_DecodeGeneralName(PLArenaPool      *reqArena,
   422 		       SECItem          *encodedName,
   423 		       CERTGeneralName  *genName)
   424 {
   425     const SEC_ASN1Template *         template;
   426     CERTGeneralNameType              genNameType;
   427     SECStatus                        rv = SECSuccess;
   428     SECItem* newEncodedName;
   430     if (!reqArena) {
   431         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   432         return NULL;
   433     }
   434     /* make a copy for decoding so the data decoded with QuickDER doesn't
   435        point to temporary memory */
   436     newEncodedName = SECITEM_ArenaDupItem(reqArena, encodedName);
   437     if (!newEncodedName) {
   438         return NULL;
   439     }
   440     /* TODO: mark arena */
   441     genNameType = (CERTGeneralNameType)((*(newEncodedName->data) & 0x0f) + 1);
   442     if (genName == NULL) {
   443 	genName = CERT_NewGeneralName(reqArena, genNameType);
   444 	if (!genName)
   445 	    goto loser;
   446     } else {
   447 	genName->type = genNameType;
   448 	genName->l.prev = genName->l.next = &genName->l;
   449     }
   451     switch (genNameType) {
   452     case certURI: 		template = CERT_URITemplate;           break;
   453     case certRFC822Name: 	template = CERT_RFC822NameTemplate;    break;
   454     case certDNSName: 		template = CERT_DNSNameTemplate;       break;
   455     case certIPAddress: 	template = CERT_IPAddressTemplate;     break;
   456     case certOtherName: 	template = CERTOtherNameTemplate;      break;
   457     case certRegisterID: 	template = CERT_RegisteredIDTemplate;  break;
   458     case certEDIPartyName: 	template = CERT_EDIPartyNameTemplate;  break;
   459     case certX400Address: 	template = CERT_X400AddressTemplate;   break;
   460     case certDirectoryName: 	template = CERT_DirectoryNameTemplate; break;
   461     default: 
   462         goto loser;
   463     }
   464     rv = SEC_QuickDERDecodeItem(reqArena, genName, template, newEncodedName);
   465     if (rv != SECSuccess) 
   466 	goto loser;
   467     if (genNameType == certDirectoryName) {
   468 	rv = SEC_QuickDERDecodeItem(reqArena, &(genName->name.directoryName), 
   469 				CERT_NameTemplate, 
   470 				&(genName->derDirectoryName));
   471         if (rv != SECSuccess)
   472 	    goto loser;
   473     }
   475     /* TODO: unmark arena */
   476     return genName;
   477 loser:
   478     /* TODO: release arena to mark */
   479     return NULL;
   480 }
   482 CERTGeneralName *
   483 cert_DecodeGeneralNames (PLArenaPool  *arena,
   484 			 SECItem      **encodedGenName)
   485 {
   486     PRCList                           *head = NULL;
   487     PRCList                           *tail = NULL;
   488     CERTGeneralName                   *currentName = NULL;
   490     PORT_Assert(arena);
   491     if (!encodedGenName || !arena) {
   492 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   493 	return NULL;
   494     }
   495     /* TODO: mark arena */
   496     while (*encodedGenName != NULL) {
   497 	currentName = CERT_DecodeGeneralName(arena, *encodedGenName, NULL);
   498 	if (currentName == NULL)
   499 	    break;
   500 	if (head == NULL) {
   501 	    head = &(currentName->l);
   502 	    tail = head;
   503 	}
   504 	currentName->l.next = head;
   505 	currentName->l.prev = tail;
   506 	tail = head->prev = tail->next = &(currentName->l);
   507 	encodedGenName++;
   508     }
   509     if (currentName) {
   510 	/* TODO: unmark arena */
   511 	return CERT_GetNextGeneralName(currentName);
   512     }
   513     /* TODO: release arena to mark */
   514     return NULL;
   515 }
   517 void
   518 CERT_DestroyGeneralName(CERTGeneralName *name)
   519 {
   520     cert_DestroyGeneralNames(name);
   521 }
   523 SECStatus
   524 cert_DestroyGeneralNames(CERTGeneralName *name)
   525 {
   526     CERTGeneralName    *first;
   527     CERTGeneralName    *next = NULL;
   530     first = name;
   531     do {
   532 	next = CERT_GetNextGeneralName(name);
   533 	PORT_Free(name);
   534 	name = next;
   535     } while (name != first);
   536     return SECSuccess;
   537 }
   539 static SECItem *
   540 cert_EncodeNameConstraint(CERTNameConstraint  *constraint, 
   541 			 SECItem             *dest,
   542 			 PLArenaPool         *arena)
   543 {
   544     PORT_Assert(arena);
   545     if (dest == NULL) {
   546 	dest = PORT_ArenaZNew(arena, SECItem);
   547 	if (dest == NULL) {
   548 	    return NULL;
   549 	}
   550     }
   551     CERT_EncodeGeneralName(&(constraint->name), &(constraint->DERName), arena);
   553     dest = SEC_ASN1EncodeItem (arena, dest, constraint,
   554 			       CERTNameConstraintTemplate);
   555     return dest;
   556 } 
   558 SECStatus 
   559 cert_EncodeNameConstraintSubTree(CERTNameConstraint  *constraints,
   560 			         PLArenaPool         *arena,
   561 				 SECItem             ***dest,
   562 				 PRBool              permited)
   563 {
   564     CERTNameConstraint  *current_constraint = constraints;
   565     SECItem             **items = NULL;
   566     int                 count = 0;
   567     int                 i;
   568     PRCList             *head;
   570     PORT_Assert(arena);
   571     /* TODO: mark arena */
   572     if (constraints != NULL) {
   573 	count = 1;
   574     }
   575     head = &constraints->l;
   576     while (current_constraint->l.next != head) {
   577 	current_constraint = CERT_GetNextNameConstraint(current_constraint);
   578 	++count;
   579     }
   580     current_constraint = CERT_GetNextNameConstraint(current_constraint);
   581     items = PORT_ArenaZNewArray(arena, SECItem *, count + 1);
   582     if (items == NULL) {
   583 	goto loser;
   584     }
   585     for (i = 0; i < count; i++) {
   586 	items[i] = cert_EncodeNameConstraint(current_constraint, 
   587 					     (SECItem *) NULL, arena);
   588 	if (items[i] == NULL) {
   589 	    goto loser;
   590 	}
   591 	current_constraint = CERT_GetNextNameConstraint(current_constraint);
   592     }
   593     *dest = items;
   594     if (*dest == NULL) {
   595 	goto loser;
   596     }
   597     /* TODO: unmark arena */
   598     return SECSuccess;
   599 loser:
   600     /* TODO: release arena to mark */
   601     return SECFailure;
   602 }
   604 SECStatus 
   605 cert_EncodeNameConstraints(CERTNameConstraints  *constraints,
   606 			   PLArenaPool          *arena,
   607 			   SECItem              *dest)
   608 {
   609     SECStatus    rv = SECSuccess;
   611     PORT_Assert(arena);
   612     /* TODO: mark arena */
   613     if (constraints->permited != NULL) {
   614 	rv = cert_EncodeNameConstraintSubTree(constraints->permited, arena,
   615 					      &constraints->DERPermited, 
   616 					      PR_TRUE);
   617 	if (rv == SECFailure) {
   618 	    goto loser;
   619 	}
   620     }
   621     if (constraints->excluded != NULL) {
   622 	rv = cert_EncodeNameConstraintSubTree(constraints->excluded, arena,
   623 					      &constraints->DERExcluded, 
   624 					      PR_FALSE);
   625 	if (rv == SECFailure) {
   626 	    goto loser;
   627 	}
   628     }
   629     dest = SEC_ASN1EncodeItem(arena, dest, constraints, 
   630 			      CERTNameConstraintsTemplate);
   631     if (dest == NULL) {
   632 	goto loser;
   633     }
   634     /* TODO: unmark arena */
   635     return SECSuccess;
   636 loser:
   637     /* TODO: release arena to mark */
   638     return SECFailure;
   639 }
   642 CERTNameConstraint *
   643 cert_DecodeNameConstraint(PLArenaPool       *reqArena,
   644 			  SECItem           *encodedConstraint)
   645 {
   646     CERTNameConstraint     *constraint;
   647     SECStatus              rv = SECSuccess;
   648     CERTGeneralName        *temp;
   649     SECItem*               newEncodedConstraint;
   651     if (!reqArena) {
   652         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   653         return NULL;
   654     }
   655     newEncodedConstraint = SECITEM_ArenaDupItem(reqArena, encodedConstraint);
   656     if (!newEncodedConstraint) {
   657         return NULL;
   658     }
   659     /* TODO: mark arena */
   660     constraint = PORT_ArenaZNew(reqArena, CERTNameConstraint);
   661     if (!constraint)
   662     	goto loser;
   663     rv = SEC_QuickDERDecodeItem(reqArena, constraint,
   664                                 CERTNameConstraintTemplate,
   665                                 newEncodedConstraint);
   666     if (rv != SECSuccess) {
   667 	goto loser;
   668     }
   669     temp = CERT_DecodeGeneralName(reqArena, &(constraint->DERName),
   670                                   &(constraint->name));
   671     if (temp != &(constraint->name)) {
   672 	goto loser;
   673     }
   675     /* ### sjlee: since the name constraint contains only one 
   676      *            CERTGeneralName, the list within CERTGeneralName shouldn't 
   677      *            point anywhere else.  Otherwise, bad things will happen.
   678      */
   679     constraint->name.l.prev = constraint->name.l.next = &(constraint->name.l);
   680     /* TODO: unmark arena */
   681     return constraint;
   682 loser:
   683     /* TODO: release arena back to mark */
   684     return NULL;
   685 }
   687 CERTNameConstraint *
   688 cert_DecodeNameConstraintSubTree(PLArenaPool   *arena,
   689 				 SECItem       **subTree,
   690 				 PRBool        permited)
   691 {
   692     CERTNameConstraint   *current = NULL;
   693     CERTNameConstraint   *first = NULL;
   694     CERTNameConstraint   *last = NULL;
   695     int                  i = 0;
   697     PORT_Assert(arena);
   698     /* TODO: mark arena */
   699     while (subTree[i] != NULL) {
   700 	current = cert_DecodeNameConstraint(arena, subTree[i]);
   701 	if (current == NULL) {
   702 	    goto loser;
   703 	}
   704 	if (last == NULL) {
   705 	    first = last = current;
   706 	}
   707 	current->l.prev = &(last->l);
   708 	current->l.next = last->l.next;
   709 	last->l.next = &(current->l);
   710 	i++;
   711     }
   712     first->l.prev = &(current->l);
   713     /* TODO: unmark arena */
   714     return first;
   715 loser:
   716     /* TODO: release arena back to mark */
   717     return NULL;
   718 }
   720 CERTNameConstraints *
   721 cert_DecodeNameConstraints(PLArenaPool   *reqArena,
   722 			   const SECItem *encodedConstraints)
   723 {
   724     CERTNameConstraints   *constraints;
   725     SECStatus             rv;
   726     SECItem*              newEncodedConstraints;
   728     if (!reqArena) {
   729         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   730         return NULL;
   731     }
   732     PORT_Assert(encodedConstraints);
   733     newEncodedConstraints = SECITEM_ArenaDupItem(reqArena, encodedConstraints);
   735     /* TODO: mark arena */
   736     constraints = PORT_ArenaZNew(reqArena, CERTNameConstraints);
   737     if (constraints == NULL) {
   738 	goto loser;
   739     }
   740     rv = SEC_QuickDERDecodeItem(reqArena, constraints,
   741                                 CERTNameConstraintsTemplate,
   742                                 newEncodedConstraints);
   743     if (rv != SECSuccess) {
   744 	goto loser;
   745     }
   746     if (constraints->DERPermited != NULL && 
   747         constraints->DERPermited[0] != NULL) {
   748 	constraints->permited = 
   749 	    cert_DecodeNameConstraintSubTree(reqArena,
   750                                              constraints->DERPermited,
   751                                              PR_TRUE);
   752 	if (constraints->permited == NULL) {
   753 	    goto loser;
   754 	}
   755     }
   756     if (constraints->DERExcluded != NULL && 
   757         constraints->DERExcluded[0] != NULL) {
   758 	constraints->excluded = 
   759 	    cert_DecodeNameConstraintSubTree(reqArena,
   760                                              constraints->DERExcluded,
   761                                              PR_FALSE);
   762 	if (constraints->excluded == NULL) {
   763 	    goto loser;
   764 	}
   765     }
   766     /* TODO: unmark arena */
   767     return constraints;
   768 loser:
   769     /* TODO: release arena back to mark */
   770     return NULL;
   771 }
   773 /* Copy a chain of one or more general names to a destination chain.
   774 ** Caller has allocated at least the first destination GeneralName struct. 
   775 ** Both source and destination chains are circular doubly-linked lists.
   776 ** The first source struct is copied to the first destination struct.
   777 ** If the source chain has more than one member, and the destination chain 
   778 ** has only one member, then this function allocates new structs for all but 
   779 ** the first copy from the arena and links them into the destination list.  
   780 ** If the destination struct is part of a list with more than one member,
   781 ** then this function traverses both the source and destination lists,
   782 ** copying each source struct to the corresponding dest struct.
   783 ** In that case, the destination list MUST contain at least as many 
   784 ** structs as the source list or some dest entries will be overwritten.
   785 */
   786 SECStatus
   787 CERT_CopyGeneralName(PLArenaPool      *arena,
   788 		     CERTGeneralName  *dest, 
   789 		     CERTGeneralName  *src)
   790 {
   791     SECStatus rv;
   792     CERTGeneralName *destHead = dest;
   793     CERTGeneralName *srcHead = src;
   795     PORT_Assert(dest != NULL);
   796     if (!dest) {
   797 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
   798         return SECFailure;
   799     }
   800     /* TODO: mark arena */
   801     do {
   802 	rv = cert_CopyOneGeneralName(arena, dest, src);
   803 	if (rv != SECSuccess)
   804 	    goto loser;
   805 	src = CERT_GetNextGeneralName(src);
   806 	/* if there is only one general name, we shouldn't do this */
   807 	if (src != srcHead) {
   808 	    if (dest->l.next == &destHead->l) {
   809 		CERTGeneralName *temp;
   810 		temp = CERT_NewGeneralName(arena, (CERTGeneralNameType)0);
   811 		if (!temp) 
   812 		    goto loser;
   813 		temp->l.next = &destHead->l;
   814 		temp->l.prev = &dest->l;
   815 		destHead->l.prev = &temp->l;
   816 		dest->l.next = &temp->l;
   817 		dest = temp;
   818 	    } else {
   819 		dest = CERT_GetNextGeneralName(dest);
   820 	    }
   821 	}
   822     } while (src != srcHead && rv == SECSuccess);
   823     /* TODO: unmark arena */
   824     return rv;
   825 loser:
   826     /* TODO: release back to mark */
   827     return SECFailure;
   828 }
   831 CERTGeneralNameList *
   832 CERT_DupGeneralNameList(CERTGeneralNameList *list)
   833 {
   834     if (list != NULL) {
   835 	PZ_Lock(list->lock);
   836 	list->refCount++;
   837 	PZ_Unlock(list->lock);
   838     }
   839     return list;
   840 }
   842 /* Allocate space and copy CERTNameConstraint from src to dest */
   843 CERTNameConstraint *
   844 CERT_CopyNameConstraint(PLArenaPool         *arena,
   845 			CERTNameConstraint  *dest, 
   846 			CERTNameConstraint  *src)
   847 {
   848     SECStatus  rv;
   850     /* TODO: mark arena */
   851     if (dest == NULL) {
   852 	dest = PORT_ArenaZNew(arena, CERTNameConstraint);
   853 	if (!dest)
   854 	    goto loser;
   855 	/* mark that it is not linked */
   856 	dest->name.l.prev = dest->name.l.next = &(dest->name.l);
   857     }
   858     rv = CERT_CopyGeneralName(arena, &dest->name, &src->name);
   859     if (rv != SECSuccess) {
   860 	goto loser;
   861     }
   862     rv = SECITEM_CopyItem(arena, &dest->DERName, &src->DERName);
   863     if (rv != SECSuccess) {
   864 	goto loser;
   865     }
   866     rv = SECITEM_CopyItem(arena, &dest->min, &src->min);
   867     if (rv != SECSuccess) {
   868 	goto loser;
   869     }
   870     rv = SECITEM_CopyItem(arena, &dest->max, &src->max);
   871     if (rv != SECSuccess) {
   872 	goto loser;
   873     }
   874     dest->l.prev = dest->l.next = &dest->l;
   875     /* TODO: unmark arena */
   876     return dest;
   877 loser:
   878     /* TODO: release arena to mark */
   879     return NULL;
   880 }
   883 CERTGeneralName *
   884 cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2)
   885 {
   886     PRCList *begin1;
   887     PRCList *begin2;
   888     PRCList *end1;
   889     PRCList *end2;
   891     if (list1 == NULL){
   892 	return list2;
   893     } else if (list2 == NULL) {
   894 	return list1;
   895     } else {
   896 	begin1 = &list1->l;
   897 	begin2 = &list2->l;
   898 	end1 = list1->l.prev;
   899 	end2 = list2->l.prev;
   900 	end1->next = begin2;
   901 	end2->next = begin1;
   902 	begin1->prev = end2;
   903 	begin2->prev = end1;
   904 	return list1;
   905     }
   906 }
   909 CERTNameConstraint *
   910 cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2)
   911 {
   912     PRCList *begin1;
   913     PRCList *begin2;
   914     PRCList *end1;
   915     PRCList *end2;
   917     if (list1 == NULL){
   918 	return list2;
   919     } else if (list2 == NULL) {
   920 	return list1;
   921     } else {
   922 	begin1 = &list1->l;
   923 	begin2 = &list2->l;
   924 	end1 = list1->l.prev;
   925 	end2 = list2->l.prev;
   926 	end1->next = begin2;
   927 	end2->next = begin1;
   928 	begin1->prev = end2;
   929 	begin2->prev = end1;
   930 	return list1;
   931     }
   932 }
   935 /* Add a CERTNameConstraint to the CERTNameConstraint list */
   936 CERTNameConstraint *
   937 CERT_AddNameConstraint(CERTNameConstraint *list, 
   938 		       CERTNameConstraint *constraint)
   939 {
   940     PORT_Assert(constraint != NULL);
   941     constraint->l.next = constraint->l.prev = &constraint->l;
   942     list = cert_CombineConstraintsLists(list, constraint);
   943     return list;
   944 }
   947 SECStatus
   948 CERT_GetNameConstraintByType (CERTNameConstraint *constraints,
   949 			      CERTGeneralNameType type, 
   950 			      CERTNameConstraint **returnList,
   951 			      PLArenaPool *arena)
   952 {
   953     CERTNameConstraint *current = NULL;
   954     void               *mark = NULL;
   956     *returnList = NULL;
   957     if (!constraints)
   958 	return SECSuccess;
   960     mark = PORT_ArenaMark(arena);
   962     current = constraints;
   963     do {
   964 	PORT_Assert(current->name.type);
   965 	if (current->name.type == type) {
   966 	    CERTNameConstraint *temp;
   967 	    temp = CERT_CopyNameConstraint(arena, NULL, current);
   968 	    if (temp == NULL) 
   969 		goto loser;
   970 	    *returnList = CERT_AddNameConstraint(*returnList, temp);
   971 	}
   972 	current = CERT_GetNextNameConstraint(current);
   973     } while (current != constraints);
   974     PORT_ArenaUnmark(arena, mark);
   975     return SECSuccess;
   977 loser:
   978     PORT_ArenaRelease(arena, mark);
   979     return SECFailure;
   980 }
   982 void *
   983 CERT_GetGeneralNameByType (CERTGeneralName *genNames,
   984 			   CERTGeneralNameType type, PRBool derFormat)
   985 {
   986     CERTGeneralName *current;
   988     if (!genNames)
   989 	return NULL;
   990     current = genNames;
   992     do {
   993 	if (current->type == type) {
   994 	    switch (type) {
   995 	    case certDNSName:
   996 	    case certEDIPartyName:
   997 	    case certIPAddress:
   998 	    case certRegisterID:
   999 	    case certRFC822Name:
  1000 	    case certX400Address:
  1001 	    case certURI: 
  1002 		return (void *)&current->name.other;           /* SECItem * */
  1004 	    case certOtherName: 
  1005 		return (void *)&current->name.OthName;         /* OthName * */
  1007 	    case certDirectoryName: 
  1008 		return derFormat 
  1009 		       ? (void *)&current->derDirectoryName    /* SECItem * */
  1010 		       : (void *)&current->name.directoryName; /* CERTName * */
  1012 	    PORT_Assert(0); 
  1013 	    return NULL;
  1015 	current = CERT_GetNextGeneralName(current);
  1016     } while (current != genNames);
  1017     return NULL;
  1020 int
  1021 CERT_GetNamesLength(CERTGeneralName *names)
  1023     int              length = 0;
  1024     CERTGeneralName  *first;
  1026     first = names;
  1027     if (names != NULL) {
  1028 	do {
  1029 	    length++;
  1030 	    names = CERT_GetNextGeneralName(names);
  1031 	} while (names != first);
  1033     return length;
  1036 /* Creates new GeneralNames for any email addresses found in the 
  1037 ** input DN, and links them onto the list for the DN.
  1038 */
  1039 SECStatus
  1040 cert_ExtractDNEmailAddrs(CERTGeneralName *name, PLArenaPool *arena)
  1042     CERTGeneralName *nameList = NULL;
  1043     const CERTRDN  **nRDNs = (const CERTRDN **)(name->name.directoryName.rdns);
  1044     SECStatus        rv        = SECSuccess;
  1046     PORT_Assert(name->type == certDirectoryName);
  1047     if (name->type != certDirectoryName) {
  1048         PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1049 	return SECFailure;
  1051     /* TODO: mark arena */
  1052     while (nRDNs && *nRDNs) { /* loop over RDNs */
  1053 	const CERTRDN *nRDN = *nRDNs++;
  1054 	CERTAVA **nAVAs = nRDN->avas;
  1055 	while (nAVAs && *nAVAs) { /* loop over AVAs */
  1056 	    int tag;
  1057 	    CERTAVA *nAVA = *nAVAs++;
  1058 	    tag = CERT_GetAVATag(nAVA);
  1059 	    if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS ||
  1060 		 tag == SEC_OID_RFC1274_MAIL) { /* email AVA */
  1061 		CERTGeneralName *newName = NULL;
  1062 		SECItem *avaValue = CERT_DecodeAVAValue(&nAVA->value);
  1063 		if (!avaValue)
  1064 		    goto loser;
  1065 		rv = SECFailure;
  1066                 newName = CERT_NewGeneralName(arena, certRFC822Name);
  1067 		if (newName) {
  1068 		   rv = SECITEM_CopyItem(arena, &newName->name.other, avaValue);
  1070 		SECITEM_FreeItem(avaValue, PR_TRUE);
  1071 		if (rv != SECSuccess)
  1072 		    goto loser;
  1073 		nameList = cert_CombineNamesLists(nameList, newName);
  1074 	    } /* handle one email AVA */
  1075 	} /* loop over AVAs */
  1076     } /* loop over RDNs */
  1077     /* combine new names with old one. */
  1078     name = cert_CombineNamesLists(name, nameList);
  1079     /* TODO: unmark arena */
  1080     return SECSuccess;
  1082 loser:
  1083     /* TODO: release arena back to mark */
  1084     return SECFailure;
  1087 /* Extract all names except Subject Common Name from a cert 
  1088 ** in preparation for a name constraints test.
  1089 */
  1090 CERTGeneralName *
  1091 CERT_GetCertificateNames(CERTCertificate *cert, PLArenaPool *arena)
  1093     return CERT_GetConstrainedCertificateNames(cert, arena, PR_FALSE);
  1096 /* This function is called by CERT_VerifyCertChain to extract all
  1097 ** names from a cert in preparation for a name constraints test.
  1098 */
  1099 CERTGeneralName *
  1100 CERT_GetConstrainedCertificateNames(const CERTCertificate *cert,
  1101                                     PLArenaPool *arena,
  1102                                     PRBool includeSubjectCommonName)
  1104     CERTGeneralName  *DN;
  1105     CERTGeneralName  *SAN;
  1106     PRUint32         numDNSNames = 0;
  1107     SECStatus        rv;
  1109     if (!arena) {
  1110     	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1111 	return NULL;
  1113     /* TODO: mark arena */
  1114     DN = CERT_NewGeneralName(arena, certDirectoryName);
  1115     if (DN == NULL) {
  1116 	goto loser;
  1118     rv = CERT_CopyName(arena, &DN->name.directoryName, &cert->subject);
  1119     if (rv != SECSuccess) {
  1120 	goto loser;
  1122     rv = SECITEM_CopyItem(arena, &DN->derDirectoryName, &cert->derSubject);
  1123     if (rv != SECSuccess) {
  1124 	goto loser;
  1126     /* Extract email addresses from DN, construct CERTGeneralName structs 
  1127     ** for them, add them to the name list 
  1128     */
  1129     rv = cert_ExtractDNEmailAddrs(DN, arena);
  1130     if (rv != SECSuccess)
  1131         goto loser;
  1133     /* Now extract any GeneralNames from the subject name names extension. */
  1134     SAN = cert_GetSubjectAltNameList(cert, arena);
  1135     if (SAN) {
  1136 	numDNSNames = cert_CountDNSPatterns(SAN);
  1137 	DN = cert_CombineNamesLists(DN, SAN);
  1139     if (!numDNSNames && includeSubjectCommonName) {
  1140 	char *cn = CERT_GetCommonName(&cert->subject);
  1141 	if (cn) {
  1142 	    CERTGeneralName *CN = CERT_NewGeneralName(arena, certDNSName);
  1143 	    if (CN) {
  1144 		SECItem cnItem = {siBuffer, NULL, 0};
  1145 		cnItem.data = (unsigned char *)cn;
  1146 		cnItem.len  = strlen(cn);
  1147 		rv = SECITEM_CopyItem(arena, &CN->name.other, &cnItem);
  1148 		if (rv == SECSuccess) {
  1149 		    DN = cert_CombineNamesLists(DN, CN);
  1152 	    PORT_Free(cn);
  1155     if (rv == SECSuccess) {
  1156 	/* TODO: unmark arena */
  1157 	return DN;
  1159 loser:
  1160     /* TODO: release arena to mark */
  1161     return NULL;
  1164 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for 
  1165 ** URI name constraints.  SECFailure otherwise.
  1166 ** If the constraint begins with a dot, it is a domain name, otherwise
  1167 ** It is a host name.  Examples:
  1168 **  Constraint            Name             Result
  1169 ** ------------      ---------------      --------
  1170 **  foo.bar.com          foo.bar.com      matches
  1171 **  foo.bar.com          FoO.bAr.CoM      matches
  1172 **  foo.bar.com      www.foo.bar.com      no match
  1173 **  foo.bar.com        nofoo.bar.com      no match
  1174 ** .foo.bar.com      www.foo.bar.com      matches
  1175 ** .foo.bar.com        nofoo.bar.com      no match
  1176 ** .foo.bar.com          foo.bar.com      no match
  1177 ** .foo.bar.com     www..foo.bar.com      no match
  1178 */
  1179 static SECStatus
  1180 compareURIN2C(const SECItem *name, const SECItem *constraint)
  1182     int offset;
  1183     /* The spec is silent on intepreting zero-length constraints.
  1184     ** We interpret them as matching no URI names.
  1185     */
  1186     if (!constraint->len)
  1187         return SECFailure;
  1188     if (constraint->data[0] != '.') { 
  1189     	/* constraint is a host name. */
  1190     	if (name->len != constraint->len ||
  1191 	    PL_strncasecmp((char *)name->data, 
  1192 			   (char *)constraint->data, constraint->len))
  1193 	    return SECFailure;
  1194     	return SECSuccess;
  1196     /* constraint is a domain name. */
  1197     if (name->len < constraint->len)
  1198         return SECFailure;
  1199     offset = name->len - constraint->len;
  1200     if (PL_strncasecmp((char *)(name->data + offset), 
  1201 		       (char *)constraint->data, constraint->len))
  1202         return SECFailure;
  1203     if (!offset || 
  1204         (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
  1205 	return SECSuccess;
  1206     return SECFailure;
  1209 /* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38)
  1210 **
  1211 ** DNS name restrictions are expressed as foo.bar.com.  Any DNS name
  1212 ** that can be constructed by simply adding to the left hand side of the
  1213 ** name satisfies the name constraint.  For example, www.foo.bar.com
  1214 ** would satisfy the constraint but foo1.bar.com would not.
  1215 **
  1216 ** But NIST's PKITS test suite requires that the constraint be treated
  1217 ** as a domain name, and requires that any name added to the left hand
  1218 ** side end in a dot ".".  Sensible, but not strictly following the RFC.
  1219 **
  1220 **  Constraint            Name            RFC 3280  NIST PKITS
  1221 ** ------------      ---------------      --------  ----------
  1222 **  foo.bar.com          foo.bar.com      matches    matches
  1223 **  foo.bar.com          FoO.bAr.CoM      matches    matches
  1224 **  foo.bar.com      www.foo.bar.com      matches    matches
  1225 **  foo.bar.com        nofoo.bar.com      MATCHES    NO MATCH
  1226 ** .foo.bar.com      www.foo.bar.com      matches    matches? disallowed?
  1227 ** .foo.bar.com          foo.bar.com      no match   no match
  1228 ** .foo.bar.com     www..foo.bar.com      matches    probably not 
  1229 **
  1230 ** We will try to conform to NIST's PKITS tests, and the unstated 
  1231 ** rules they imply.
  1232 */
  1233 static SECStatus
  1234 compareDNSN2C(const SECItem *name, const SECItem *constraint)
  1236     int offset;
  1237     /* The spec is silent on intepreting zero-length constraints.
  1238     ** We interpret them as matching all DNSnames.
  1239     */
  1240     if (!constraint->len)
  1241         return SECSuccess;
  1242     if (name->len < constraint->len)
  1243         return SECFailure;
  1244     offset = name->len - constraint->len;
  1245     if (PL_strncasecmp((char *)(name->data + offset), 
  1246 		       (char *)constraint->data, constraint->len))
  1247         return SECFailure;
  1248     if (!offset || 
  1249         (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1)
  1250 	return SECSuccess;
  1251     return SECFailure;
  1254 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for
  1255 ** internet email addresses.  SECFailure otherwise.
  1256 ** If constraint contains a '@' then the two strings much match exactly.
  1257 ** Else if constraint starts with a '.'. then it must match the right-most
  1258 ** substring of the name, 
  1259 ** else constraint string must match entire name after the name's '@'.
  1260 ** Empty constraint string matches all names. All comparisons case insensitive.
  1261 */
  1262 static SECStatus
  1263 compareRFC822N2C(const SECItem *name, const SECItem *constraint)
  1265     int offset;
  1266     if (!constraint->len)
  1267         return SECSuccess;
  1268     if (name->len < constraint->len)
  1269         return SECFailure;
  1270     if (constraint->len == 1 && constraint->data[0] == '.')
  1271         return SECSuccess;
  1272     for (offset = constraint->len - 1; offset >= 0; --offset) {
  1273     	if (constraint->data[offset] == '@') {
  1274 	    return (name->len == constraint->len && 
  1275 	        !PL_strncasecmp((char *)name->data, 
  1276 				(char *)constraint->data, constraint->len))
  1277 		? SECSuccess : SECFailure;
  1280     offset = name->len - constraint->len;
  1281     if (PL_strncasecmp((char *)(name->data + offset), 
  1282 		       (char *)constraint->data, constraint->len))
  1283         return SECFailure;
  1284     if (constraint->data[0] == '.')
  1285         return SECSuccess;
  1286     if (offset > 0 && name->data[offset - 1] == '@')
  1287         return SECSuccess;
  1288     return SECFailure;
  1291 /* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address.
  1292 ** constraint contains an address of the same length, and a subnet mask
  1293 ** of the same length.  Compare name's address to the constraint's 
  1294 ** address, subject to the mask.
  1295 ** Return SECSuccess if they match, SECFailure if they don't. 
  1296 */
  1297 static SECStatus
  1298 compareIPaddrN2C(const SECItem *name, const SECItem *constraint)
  1300     int i;
  1301     if (name->len == 4 && constraint->len == 8) { /* ipv4 addr */
  1302         for (i = 0; i < 4; i++) {
  1303 	    if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+4])
  1304 	        goto loser;
  1306 	return SECSuccess;
  1308     if (name->len == 16 && constraint->len == 32) { /* ipv6 addr */
  1309         for (i = 0; i < 16; i++) {
  1310 	    if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+16])
  1311 	        goto loser;
  1313 	return SECSuccess;
  1315 loser:
  1316     return SECFailure;
  1319 /* start with a SECItem that points to a URI.  Parse it lookingg for 
  1320 ** a hostname.  Modify item->data and item->len to define the hostname,
  1321 ** but do not modify and data at item->data.  
  1322 ** If anything goes wrong, the contents of *item are undefined.
  1323 */
  1324 static SECStatus
  1325 parseUriHostname(SECItem * item)
  1327     int i;
  1328     PRBool found = PR_FALSE;
  1329     for (i = 0; (unsigned)(i+2) < item->len; ++i) {
  1330 	if (item->data[i  ] == ':' &&
  1331 	    item->data[i+1] == '/' &&
  1332 	    item->data[i+2] == '/') {
  1333 	    i += 3;
  1334 	    item->data += i;
  1335 	    item->len  -= i;
  1336 	    found = PR_TRUE;
  1337 	    break;
  1340     if (!found) 
  1341         return SECFailure;
  1342     /* now look for a '/', which is an upper bound in the end of the name */
  1343     for (i = 0; (unsigned)i < item->len; ++i) {
  1344 	if (item->data[i] == '/') {
  1345 	    item->len = i;
  1346 	    break;
  1349     /* now look for a ':', which marks the end of the name */
  1350     for (i = item->len; --i >= 0; ) {
  1351         if (item->data[i] == ':') {
  1352 	    item->len = i;
  1353 	    break;
  1356     /* now look for an '@', which marks the beginning of the hostname */
  1357     for (i = 0; (unsigned)i < item->len; ++i) {
  1358 	if (item->data[i] == '@') {
  1359 	    ++i;
  1360 	    item->data += i;
  1361 	    item->len  -= i;
  1362 	    break;
  1365     return item->len ? SECSuccess : SECFailure;
  1368 /* This function takes one name, and a list of constraints.
  1369 ** It searches the constraints looking for a match.
  1370 ** It returns SECSuccess if the name satisfies the constraints, i.e.,
  1371 ** if excluded, then the name does not match any constraint, 
  1372 ** if permitted, then the name matches at least one constraint.
  1373 ** It returns SECFailure if the name fails to satisfy the constraints,
  1374 ** or if some code fails (e.g. out of memory, or invalid constraint)
  1375 */
  1376 SECStatus
  1377 cert_CompareNameWithConstraints(const CERTGeneralName     *name,
  1378 				const CERTNameConstraint  *constraints,
  1379 				PRBool              excluded)
  1381     SECStatus           rv     = SECSuccess;
  1382     SECStatus           matched = SECFailure;
  1383     const CERTNameConstraint *current;
  1385     PORT_Assert(constraints);  /* caller should not call with NULL */
  1386     if (!constraints) {
  1387 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1388         return SECFailure;
  1391     current = constraints;
  1392     do {
  1393 	rv = SECSuccess;
  1394 	matched = SECFailure;
  1395 	PORT_Assert(name->type == current->name.type);
  1396 	switch (name->type) {
  1398 	case certDNSName:
  1399 	    matched = compareDNSN2C(&name->name.other, 
  1400 	                            &current->name.name.other);
  1401 	    break;
  1403 	case certRFC822Name:
  1404 	    matched = compareRFC822N2C(&name->name.other, 
  1405 	                               &current->name.name.other);
  1406 	    break;
  1408 	case certURI:
  1410 		/* make a modifiable copy of the URI SECItem. */
  1411 		SECItem uri = name->name.other;
  1412 		/* find the hostname in the URI */
  1413 		rv = parseUriHostname(&uri);
  1414 		if (rv == SECSuccess) {
  1415 		    /* does our hostname meet the constraint? */
  1416 		    matched = compareURIN2C(&uri, &current->name.name.other);
  1419 	    break;
  1421 	case certDirectoryName:
  1422 	    /* Determine if the constraint directory name is a "prefix"
  1423 	    ** for the directory name being tested. 
  1424 	    */
  1426 	    /* status defaults to SECEqual, so that a constraint with 
  1427 	    ** no AVAs will be a wildcard, matching all directory names.
  1428 	    */
  1429 	    SECComparison   status = SECEqual;
  1430 	    const CERTRDN **cRDNs = 
  1431 		    (const CERTRDN **)current->name.name.directoryName.rdns;  
  1432 	    const CERTRDN **nRDNs = 
  1433 		    (const CERTRDN **)name->name.directoryName.rdns;
  1434 	    while (cRDNs && *cRDNs && nRDNs && *nRDNs) { 
  1435 		/* loop over name RDNs and constraint RDNs in lock step */
  1436 		const CERTRDN *cRDN = *cRDNs++;
  1437 		const CERTRDN *nRDN = *nRDNs++;
  1438 		CERTAVA **cAVAs = cRDN->avas;
  1439 		while (cAVAs && *cAVAs) { /* loop over constraint AVAs */
  1440 		    CERTAVA *cAVA = *cAVAs++;
  1441 		    CERTAVA **nAVAs = nRDN->avas;
  1442 		    while (nAVAs && *nAVAs) { /* loop over name AVAs */
  1443 			CERTAVA *nAVA = *nAVAs++;
  1444 			status = CERT_CompareAVA(cAVA, nAVA);
  1445 			if (status == SECEqual) 
  1446 			    break;
  1447 		    } /* loop over name AVAs */
  1448 		    if (status != SECEqual) 
  1449 			break;
  1450 		} /* loop over constraint AVAs */
  1451 		if (status != SECEqual) 
  1452 		    break;
  1453 	    } /* loop over name RDNs and constraint RDNs */
  1454 	    matched = (status == SECEqual) ? SECSuccess : SECFailure;
  1455 	    break;
  1458 	case certIPAddress:	/* type 8 */
  1459 	    matched = compareIPaddrN2C(&name->name.other, 
  1460 	                               &current->name.name.other);
  1461 	    break;
  1463 	/* NSS does not know how to compare these "Other" type names with 
  1464 	** their respective constraints.  But it does know how to tell
  1465 	** if the constraint applies to the type of name (by comparing
  1466 	** the constraint OID to the name OID).  NSS makes no use of "Other"
  1467 	** type names at all, so NSS errs on the side of leniency for these 
  1468 	** types, provided that their OIDs match.  So, when an "Other"
  1469 	** name constraint appears in an excluded subtree, it never causes
  1470 	** a name to fail.  When an "Other" name constraint appears in a
  1471 	** permitted subtree, AND the constraint's OID matches the name's
  1472 	** OID, then name is treated as if it matches the constraint.
  1473 	*/
  1474 	case certOtherName:	/* type 1 */
  1475 	    matched = (!excluded &&
  1476 		       name->type == current->name.type &&
  1477 		       SECITEM_ItemsAreEqual(&name->name.OthName.oid,
  1478 					     &current->name.name.OthName.oid))
  1479 		 ? SECSuccess : SECFailure;
  1480 	    break;
  1482 	/* NSS does not know how to compare these types of names with their
  1483 	** respective constraints.  But NSS makes no use of these types of 
  1484 	** names at all, so it errs on the side of leniency for these types.
  1485 	** Constraints for these types of names never cause the name to 
  1486 	** fail the constraints test.  NSS behaves as if the name matched
  1487 	** for permitted constraints, and did not match for excluded ones.
  1488 	*/
  1489 	case certX400Address:	/* type 4 */
  1490 	case certEDIPartyName:  /* type 6 */
  1491 	case certRegisterID:	/* type 9 */
  1492 	    matched = excluded ? SECFailure : SECSuccess;
  1493 	    break;
  1495 	default: /* non-standard types are not supported */
  1496 	    rv = SECFailure;
  1497 	    break;
  1499 	if (matched == SECSuccess || rv != SECSuccess)
  1500 	    break;
  1501 	current = CERT_GetNextNameConstraint((CERTNameConstraint*)current);
  1502     } while (current != constraints);
  1503     if (rv == SECSuccess) {
  1504         if (matched == SECSuccess) 
  1505 	    rv = excluded ? SECFailure : SECSuccess;
  1506 	else
  1507 	    rv = excluded ? SECSuccess : SECFailure;
  1508 	return rv;
  1511     return SECFailure;
  1514 /* Add and link a CERTGeneralName to a CERTNameConstraint list. Most
  1515 ** likely the CERTNameConstraint passed in is either the permitted
  1516 ** list or the excluded list of a CERTNameConstraints.
  1517 */
  1518 SECStatus
  1519 CERT_AddNameConstraintByGeneralName(PLArenaPool *arena,
  1520                                     CERTNameConstraint **constraints,
  1521                                     CERTGeneralName *name)
  1523     SECStatus rv;
  1524     CERTNameConstraint *current = NULL;
  1525     CERTNameConstraint *first = *constraints;
  1526     void *mark = NULL;
  1528     mark = PORT_ArenaMark(arena);
  1530     current = PORT_ArenaZNew(arena, CERTNameConstraint);
  1531     if (current == NULL) {
  1532         rv = SECFailure;
  1533         goto done;
  1536     rv = cert_CopyOneGeneralName(arena, &current->name, name);
  1537     if (rv != SECSuccess) {
  1538         goto done;
  1541     current->name.l.prev = current->name.l.next = &(current->name.l);
  1543     if (first == NULL) {
  1544         *constraints = current;
  1545         PR_INIT_CLIST(&current->l);
  1546     } else {
  1547         PR_INSERT_BEFORE(&current->l, &first->l);
  1550 done:
  1551     if (rv == SECFailure) {
  1552         PORT_ArenaRelease(arena, mark);
  1553     } else {
  1554         PORT_ArenaUnmark(arena, mark);
  1556     return rv;
  1559 /* Add name constraints to certain certs that do not include name constraints
  1560  * This is the core of the implementation for bug 952572.
  1561  */
  1563 static SECStatus
  1564 getNameExtensionsBuiltIn(CERTCertificate  *cert,
  1565                          SECItem *extensions)
  1567   const char constraintFranceGov[] = "\x30\x5D" /* sequence len = 93*/
  1568                                      "\xA0\x5B" /* element len =91 */
  1569                                      "\x30\x05" /* sequence len 5 */
  1570                                      "\x82\x03" /* entry len 3 */
  1571                                      ".fr"
  1572                                      "\x30\x05\x82\x03" /* sequence len5, entry len 3 */
  1573                                      ".gp"
  1574                                      "\x30\x05\x82\x03"
  1575                                      ".gf"
  1576                                      "\x30\x05\x82\x03"
  1577                                      ".mq"
  1578                                      "\x30\x05\x82\x03"
  1579                                      ".re"
  1580                                      "\x30\x05\x82\x03"
  1581                                      ".yt"
  1582                                      "\x30\x05\x82\x03"
  1583                                      ".pm"
  1584                                      "\x30\x05\x82\x03"
  1585                                      ".bl"
  1586                                      "\x30\x05\x82\x03"
  1587                                      ".mf"
  1588                                      "\x30\x05\x82\x03"
  1589                                      ".wf"
  1590                                      "\x30\x05\x82\x03"
  1591                                      ".pf"
  1592                                      "\x30\x05\x82\x03"
  1593                                      ".nc"
  1594                                      "\x30\x05\x82\x03"
  1595                                      ".tf";
  1597   /* The stringified value for the subject is:
  1598      E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR
  1599    */
  1600   const char rawANSSISubject[] = "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04"
  1601                                  "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03"
  1602                                  "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65"
  1603                                  "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05"
  1604                                  "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03"
  1605                                  "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44"
  1606                                  "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13"
  1607                                  "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06"
  1608                                  "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41"
  1609                                  "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7"
  1610                                  "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40"
  1611                                  "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75"
  1612                                  "\x76\x2E\x66\x72";
  1614   const SECItem anssi_subject = {0, (unsigned char *) rawANSSISubject,
  1615                                  sizeof(rawANSSISubject)-1};
  1616   const SECItem permitFranceGovNC = {0, (unsigned char *) constraintFranceGov,
  1617                                      sizeof(constraintFranceGov)-1};
  1619   if (SECITEM_ItemsAreEqual(&cert->derSubject, &anssi_subject)) {
  1620     SECStatus rv;
  1621     rv = SECITEM_CopyItem(NULL, extensions, &permitFranceGovNC);
  1622     return rv;
  1624   PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
  1625   return SECFailure;
  1628 /* Extract the name constraints extension from the CA cert. */
  1629 SECStatus
  1630 CERT_FindNameConstraintsExten(PLArenaPool      *arena,
  1631                               CERTCertificate  *cert,
  1632                               CERTNameConstraints **constraints)
  1634     SECStatus            rv = SECSuccess;
  1635     SECItem              constraintsExtension;
  1636     void                *mark = NULL;
  1638     *constraints = NULL;
  1640     rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, 
  1641                                 &constraintsExtension);
  1642     if (rv != SECSuccess) {
  1643         if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
  1644             return rv;
  1646         rv = getNameExtensionsBuiltIn(cert, &constraintsExtension);
  1647         if (rv != SECSuccess) {
  1648           if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
  1649             return SECSuccess;
  1651           return rv;
  1655     mark = PORT_ArenaMark(arena);
  1657     *constraints = cert_DecodeNameConstraints(arena, &constraintsExtension);
  1658     if (*constraints == NULL) { /* decode failed */
  1659         rv = SECFailure;
  1661     PORT_Free (constraintsExtension.data);
  1663     if (rv == SECFailure) {
  1664         PORT_ArenaRelease(arena, mark);
  1665     } else {
  1666         PORT_ArenaUnmark(arena, mark);
  1669     return rv;
  1672 /* Verify name against all the constraints relevant to that type of
  1673 ** the name.
  1674 */
  1675 SECStatus
  1676 CERT_CheckNameSpace(PLArenaPool          *arena,
  1677                     const CERTNameConstraints *constraints,
  1678                     const CERTGeneralName     *currentName)
  1680     CERTNameConstraint  *matchingConstraints;
  1681     SECStatus            rv = SECSuccess;
  1683     if (constraints->excluded != NULL) {
  1684         rv = CERT_GetNameConstraintByType(constraints->excluded, 
  1685                                           currentName->type, 
  1686                                           &matchingConstraints, arena);
  1687         if (rv == SECSuccess && matchingConstraints != NULL) {
  1688             rv = cert_CompareNameWithConstraints(currentName, 
  1689                                                  matchingConstraints,
  1690                                                  PR_TRUE);
  1692         if (rv != SECSuccess) {
  1693             return(rv);
  1697     if (constraints->permited != NULL) {
  1698         rv = CERT_GetNameConstraintByType(constraints->permited, 
  1699                                           currentName->type, 
  1700                                           &matchingConstraints, arena);
  1701         if (rv == SECSuccess && matchingConstraints != NULL) {
  1702             rv = cert_CompareNameWithConstraints(currentName, 
  1703                                                  matchingConstraints,
  1704                                                  PR_FALSE);
  1706         if (rv != SECSuccess) {
  1707             return(rv);
  1711     return(SECSuccess);
  1714 /* Extract the name constraints extension from the CA cert.
  1715 ** Test each and every name in namesList against all the constraints
  1716 ** relevant to that type of name.
  1717 ** Returns NULL in pBadCert for success, if all names are acceptable.
  1718 ** If some name is not acceptable, returns a pointer to the cert that
  1719 ** contained that name.
  1720 */
  1721 SECStatus
  1722 CERT_CompareNameSpace(CERTCertificate  *cert,
  1723 		      CERTGeneralName  *namesList,
  1724  		      CERTCertificate **certsList,
  1725  		      PLArenaPool      *reqArena,
  1726  		      CERTCertificate **pBadCert)
  1728     SECStatus            rv = SECSuccess;
  1729     CERTNameConstraints  *constraints;
  1730     CERTGeneralName      *currentName;
  1731     int                  count = 0;
  1732     CERTCertificate      *badCert = NULL;
  1734     /* If no names to check, then no names can be bad. */
  1735     if (!namesList)
  1736     	goto done;
  1737     rv = CERT_FindNameConstraintsExten(reqArena, cert, &constraints);
  1738     if (rv != SECSuccess) {
  1739 	count = -1;
  1740 	goto done;
  1743     currentName = namesList;
  1744     do {
  1745 	if (constraints){
  1746 	    rv = CERT_CheckNameSpace(reqArena, constraints, currentName);
  1747 	    if (rv != SECSuccess) {
  1748 		break;
  1751  	currentName = CERT_GetNextGeneralName(currentName);
  1752  	count ++;
  1753     } while (currentName != namesList);
  1755 done:
  1756     if (rv != SECSuccess) {
  1757 	badCert = (count >= 0) ? certsList[count] : cert;
  1759     if (pBadCert)
  1760 	*pBadCert = badCert;
  1762     return rv;
  1765 #if 0
  1766 /* not exported from shared libs, not used.  Turn on if we ever need it. */
  1767 SECStatus
  1768 CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b)
  1770     CERTGeneralName *currentA;
  1771     CERTGeneralName *currentB;
  1772     PRBool found;
  1774     currentA = a;
  1775     currentB = b;
  1776     if (a != NULL) {
  1777 	do { 
  1778 	    if (currentB == NULL) {
  1779 		return SECFailure;
  1781 	    currentB = CERT_GetNextGeneralName(currentB);
  1782 	    currentA = CERT_GetNextGeneralName(currentA);
  1783 	} while (currentA != a);
  1785     if (currentB != b) {
  1786 	return SECFailure;
  1788     currentA = a;
  1789     do {
  1790 	currentB = b;
  1791 	found = PR_FALSE;
  1792 	do {
  1793 	    if (currentB->type == currentA->type) {
  1794 		switch (currentB->type) {
  1795 		  case certDNSName:
  1796 		  case certEDIPartyName:
  1797 		  case certIPAddress:
  1798 		  case certRegisterID:
  1799 		  case certRFC822Name:
  1800 		  case certX400Address:
  1801 		  case certURI:
  1802 		    if (SECITEM_CompareItem(&currentA->name.other,
  1803 					    &currentB->name.other) 
  1804 			== SECEqual) {
  1805 			found = PR_TRUE;
  1807 		    break;
  1808 		  case certOtherName:
  1809 		    if (SECITEM_CompareItem(&currentA->name.OthName.oid,
  1810 					    &currentB->name.OthName.oid) 
  1811 			== SECEqual &&
  1812 			SECITEM_CompareItem(&currentA->name.OthName.name,
  1813 					    &currentB->name.OthName.name)
  1814 			== SECEqual) {
  1815 			found = PR_TRUE;
  1817 		    break;
  1818 		  case certDirectoryName:
  1819 		    if (CERT_CompareName(&currentA->name.directoryName,
  1820 					 &currentB->name.directoryName)
  1821 			== SECEqual) {
  1822 			found = PR_TRUE;
  1827 	    currentB = CERT_GetNextGeneralName(currentB);
  1828 	} while (currentB != b && found != PR_TRUE);
  1829 	if (found != PR_TRUE) {
  1830 	    return SECFailure;
  1832 	currentA = CERT_GetNextGeneralName(currentA);
  1833     } while (currentA != a);
  1834     return SECSuccess;
  1837 SECStatus
  1838 CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b)
  1840     SECStatus rv;
  1842     if (a == b) {
  1843 	return SECSuccess;
  1845     if (a != NULL && b != NULL) {
  1846 	PZ_Lock(a->lock);
  1847 	PZ_Lock(b->lock);
  1848 	rv = CERT_CompareGeneralName(a->name, b->name);
  1849 	PZ_Unlock(a->lock);
  1850 	PZ_Unlock(b->lock);
  1851     } else {
  1852 	rv = SECFailure;
  1854     return rv;
  1856 #endif
  1858 #if 0
  1859 /* This function is not exported from NSS shared libraries, and is not
  1860 ** used inside of NSS.
  1861 ** XXX it doesn't check for failed allocations. :-(
  1862 */
  1863 void *
  1864 CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list,
  1865 				  CERTGeneralNameType type,
  1866 				  PLArenaPool *arena)
  1868     CERTName *name = NULL; 
  1869     SECItem *item = NULL;
  1870     OtherName *other = NULL;
  1871     OtherName *tmpOther = NULL;
  1872     void *data;
  1874     PZ_Lock(list->lock);
  1875     data = CERT_GetGeneralNameByType(list->name, type, PR_FALSE);
  1876     if (data != NULL) {
  1877 	switch (type) {
  1878 	  case certDNSName:
  1879 	  case certEDIPartyName:
  1880 	  case certIPAddress:
  1881 	  case certRegisterID:
  1882 	  case certRFC822Name:
  1883 	  case certX400Address:
  1884 	  case certURI:
  1885 	    if (arena != NULL) {
  1886 		item = PORT_ArenaNew(arena, SECItem);
  1887 		if (item != NULL) {
  1888 XXX		    SECITEM_CopyItem(arena, item, (SECItem *) data);
  1890 	    } else { 
  1891 		item = SECITEM_DupItem((SECItem *) data);
  1893 	    PZ_Unlock(list->lock);
  1894 	    return item;
  1895 	  case certOtherName:
  1896 	    other = (OtherName *) data;
  1897 	    if (arena != NULL) {
  1898 		tmpOther = PORT_ArenaNew(arena, OtherName);
  1899 	    } else {
  1900 		tmpOther = PORT_New(OtherName);
  1902 	    if (tmpOther != NULL) {
  1903 XXX		SECITEM_CopyItem(arena, &tmpOther->oid, &other->oid);
  1904 XXX		SECITEM_CopyItem(arena, &tmpOther->name, &other->name);
  1906 	    PZ_Unlock(list->lock);
  1907 	    return tmpOther;
  1908 	  case certDirectoryName:
  1909 	    if (arena) {
  1910 		name = PORT_ArenaZNew(list->arena, CERTName);
  1911 		if (name) {
  1912 XXX		    CERT_CopyName(arena, name, (CERTName *) data);
  1915 	    PZ_Unlock(list->lock);
  1916 	    return name;
  1919     PZ_Unlock(list->lock);
  1920     return NULL;
  1922 #endif
  1924 #if 0
  1925 /* This function is not exported from NSS shared libraries, and is not
  1926 ** used inside of NSS.
  1927 ** XXX it should NOT be a void function, since it does allocations
  1928 ** that can fail.
  1929 */
  1930 void
  1931 CERT_AddGeneralNameToList(CERTGeneralNameList *list, 
  1932 			  CERTGeneralNameType type,
  1933 			  void *data, SECItem *oid)
  1935     CERTGeneralName *name;
  1937     if (list != NULL && data != NULL) {
  1938 	PZ_Lock(list->lock);
  1939 	name = CERT_NewGeneralName(list->arena, type);
  1940 	if (!name)
  1941 	    goto done;
  1942 	switch (type) {
  1943 	  case certDNSName:
  1944 	  case certEDIPartyName:
  1945 	  case certIPAddress:
  1946 	  case certRegisterID:
  1947 	  case certRFC822Name:
  1948 	  case certX400Address:
  1949 	  case certURI:
  1950 XXX	    SECITEM_CopyItem(list->arena, &name->name.other, (SECItem *)data);
  1951 	    break;
  1952 	  case certOtherName:
  1953 XXX	    SECITEM_CopyItem(list->arena, &name->name.OthName.name,
  1954 			     (SECItem *) data);
  1955 XXX	    SECITEM_CopyItem(list->arena, &name->name.OthName.oid,
  1956 			     oid);
  1957 	    break;
  1958 	  case certDirectoryName:
  1959 XXX	    CERT_CopyName(list->arena, &name->name.directoryName,
  1960 			  (CERTName *) data);
  1961 	    break;
  1963 	list->name = cert_CombineNamesLists(list->name, name);
  1964 	list->len++;
  1965 done:
  1966 	PZ_Unlock(list->lock);
  1968     return;
  1970 #endif

mercurial