Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
/*
* pkix_pl_generalname.c
*
* GeneralName Object Definitions
*
*/
#include "pkix_pl_generalname.h"
/* --Private-GeneralName-Functions------------------------------------- */
/*
* FUNCTION: pkix_pl_GeneralName_GetNssGeneralName
* DESCRIPTION:
*
* Retrieves the NSS representation of the PKIX_PL_GeneralName pointed by
* "genName" and stores it at "pNssGenName". The NSS data type CERTGeneralName
* is stored in this object when the object was created.
*
* PARAMETERS:
* "genName"
* Address of PKIX_PL_GeneralName. Must be non-NULL.
* "pNssGenName"
* Address where CERTGeneralName will be stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a GeneralName Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_pl_GeneralName_GetNssGeneralName(
PKIX_PL_GeneralName *genName,
CERTGeneralName **pNssGenName,
void *plContext)
{
CERTGeneralName *nssGenName = NULL;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_GetNssGeneralName");
PKIX_NULLCHECK_THREE(genName, pNssGenName, genName->nssGeneralNameList);
nssGenName = genName->nssGeneralNameList->name;
*pNssGenName = nssGenName;
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_OtherName_Create
* DESCRIPTION:
*
* Creates new OtherName which represents the CERTGeneralName pointed to by
* "nssAltName" and stores it at "pOtherName".
*
* PARAMETERS:
* "nssAltName"
* Address of CERTGeneralName. Must be non-NULL.
* "pOtherName"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a GeneralName Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_pl_OtherName_Create(
CERTGeneralName *nssAltName,
OtherName **pOtherName,
void *plContext)
{
OtherName *otherName = NULL;
SECItem secItemName;
SECItem secItemOID;
SECStatus rv;
PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create");
PKIX_NULLCHECK_TWO(nssAltName, pOtherName);
PKIX_CHECK(PKIX_PL_Malloc
(sizeof (OtherName), (void **)&otherName, plContext),
PKIX_MALLOCFAILED);
/* make a copy of the name field */
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
rv = SECITEM_CopyItem
(NULL, &otherName->name, &nssAltName->name.OthName.name);
if (rv != SECSuccess) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
/* make a copy of the oid field */
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
rv = SECITEM_CopyItem
(NULL, &otherName->oid, &nssAltName->name.OthName.oid);
if (rv != SECSuccess) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
*pOtherName = otherName;
cleanup:
if (otherName && PKIX_ERROR_RECEIVED){
secItemName = otherName->name;
secItemOID = otherName->oid;
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
SECITEM_FreeItem(&secItemName, PR_FALSE);
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
SECITEM_FreeItem(&secItemOID, PR_FALSE);
PKIX_FREE(otherName);
otherName = NULL;
}
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_DirectoryName_Create
* DESCRIPTION:
*
* Creates a new X500Name which represents the directoryName component of the
* CERTGeneralName pointed to by "nssAltName" and stores it at "pX500Name".
*
* PARAMETERS:
* "nssAltName"
* Address of CERTGeneralName. Must be non-NULL.
* "pX500Name"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a GeneralName Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_pl_DirectoryName_Create(
CERTGeneralName *nssAltName,
PKIX_PL_X500Name **pX500Name,
void *plContext)
{
PKIX_PL_X500Name *pkixDN = NULL;
CERTName *dirName = NULL;
PKIX_PL_String *pkixDNString = NULL;
char *utf8String = NULL;
PKIX_ENTER(GENERALNAME, "pkix_pl_DirectoryName_Create");
PKIX_NULLCHECK_TWO(nssAltName, pX500Name);
dirName = &nssAltName->name.directoryName;
PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName(NULL, dirName,
&pkixDN, plContext),
PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
*pX500Name = pkixDN;
cleanup:
PR_Free(utf8String);
PKIX_DECREF(pkixDNString);
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_Create
* DESCRIPTION:
*
* Creates new GeneralName which represents the CERTGeneralName pointed to by
* "nssAltName" and stores it at "pGenName".
*
* PARAMETERS:
* "nssAltName"
* Address of CERTGeneralName. Must be non-NULL.
* "pGenName"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a GeneralName Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
PKIX_Error *
pkix_pl_GeneralName_Create(
CERTGeneralName *nssAltName,
PKIX_PL_GeneralName **pGenName,
void *plContext)
{
PKIX_PL_GeneralName *genName = NULL;
PKIX_PL_X500Name *pkixDN = NULL;
PKIX_PL_OID *pkixOID = NULL;
OtherName *otherName = NULL;
CERTGeneralNameList *nssGenNameList = NULL;
CERTGeneralNameType nameType;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
PKIX_NULLCHECK_TWO(nssAltName, pGenName);
/* create a PKIX_PL_GeneralName object */
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_GENERALNAME_TYPE,
sizeof (PKIX_PL_GeneralName),
(PKIX_PL_Object **)&genName,
plContext),
PKIX_COULDNOTCREATEOBJECT);
nameType = nssAltName->type;
/*
* We use CERT_CreateGeneralNameList to create just one CERTGeneralName
* item for memory allocation reason. If we want to just create one
* item, we have to use the calling path CERT_NewGeneralName, then
* CERT_CopyOneGeneralName. With this calling path, if we pass
* the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
* call to CERT_CopyName, it assumes arena should be valid, hence
* segmentation error (not sure this is a NSS bug, certainly it is
* not consistent). But on the other hand, we don't want to keep an
* arena record here explicitely for every PKIX_PL_GeneralName.
* So I concluded it is better to use CERT_CreateGeneralNameList,
* which keeps an arena pointer in its data structure and also masks
* out details calls from this libpkix level.
*/
PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
nssGenNameList = CERT_CreateGeneralNameList(nssAltName);
if (nssGenNameList == NULL) {
PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
}
genName->nssGeneralNameList = nssGenNameList;
/* initialize fields */
genName->type = nameType;
genName->directoryName = NULL;
genName->OthName = NULL;
genName->other = NULL;
genName->oid = NULL;
switch (nameType){
case certOtherName:
PKIX_CHECK(pkix_pl_OtherName_Create
(nssAltName, &otherName, plContext),
PKIX_OTHERNAMECREATEFAILED);
genName->OthName = otherName;
break;
case certDirectoryName:
PKIX_CHECK(pkix_pl_DirectoryName_Create
(nssAltName, &pkixDN, plContext),
PKIX_DIRECTORYNAMECREATEFAILED);
genName->directoryName = pkixDN;
break;
case certRegisterID:
PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other,
&pkixOID, plContext),
PKIX_OIDCREATEFAILED);
genName->oid = pkixOID;
break;
case certDNSName:
case certEDIPartyName:
case certIPAddress:
case certRFC822Name:
case certX400Address:
case certURI:
genName->other = SECITEM_DupItem(&nssAltName->name.other);
if (!genName->other) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
break;
default:
PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
}
*pGenName = genName;
genName = NULL;
cleanup:
PKIX_DECREF(genName);
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_ToString_Helper
* DESCRIPTION:
*
* Helper function that creates a string representation of the GeneralName
* pointed to by "name" and stores it at "pString" Different mechanisms are
* used to create the string, depending on the type of the GeneralName.
*
* PARAMETERS
* "name"
* Address of GeneralName whose string representation is desired.
* Must be non-NULL.
* "pString"
* Address where object pointer will be stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a GeneralName Error if the function fails in a non-fatal way.
* Returns a Fatal Error if the function fails in an unrecoverable way.
*/
static PKIX_Error *
pkix_pl_GeneralName_ToString_Helper(
PKIX_PL_GeneralName *name,
PKIX_PL_String **pString,
void *plContext)
{
PKIX_PL_X500Name *pkixDN = NULL;
PKIX_PL_OID *pkixOID = NULL;
char *x400AsciiName = NULL;
char *ediPartyName = NULL;
char *asciiName = NULL;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper");
PKIX_NULLCHECK_TWO(name, pString);
switch (name->type) {
case certRFC822Name:
case certDNSName:
case certURI:
/*
* Note that we can't use PKIX_ESCASCII here because
* name->other->data is not guaranteed to be null-terminated.
*/
PKIX_NULLCHECK_ONE(name->other);
PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8,
(name->other)->data,
(name->other)->len,
pString,
plContext),
PKIX_STRINGCREATEFAILED);
break;
case certEDIPartyName:
/* XXX print out the actual bytes */
ediPartyName = "EDIPartyName: <DER-encoded value>";
PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
ediPartyName,
0,
pString,
plContext),
PKIX_STRINGCREATEFAILED);
break;
case certX400Address:
/* XXX print out the actual bytes */
x400AsciiName = "X400Address: <DER-encoded value>";
PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
x400AsciiName,
0,
pString,
plContext),
PKIX_STRINGCREATEFAILED);
break;
case certIPAddress:
PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii
(name->other, &asciiName, plContext),
PKIX_IPADDRBYTES2ASCIIFAILED);
PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
asciiName,
0,
pString,
plContext),
PKIX_STRINGCREATEFAILED);
break;
case certOtherName:
PKIX_NULLCHECK_ONE(name->OthName);
/* we only print type-id - don't know how to print value */
/* XXX print out the bytes of the value */
PKIX_CHECK(pkix_pl_oidBytes2Ascii
(&name->OthName->oid, &asciiName, plContext),
PKIX_OIDBYTES2ASCIIFAILED);
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII,
asciiName,
0,
pString,
plContext),
PKIX_STRINGCREATEFAILED);
break;
case certRegisterID:
pkixOID = name->oid;
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object *)pkixOID, pString, plContext),
PKIX_OIDTOSTRINGFAILED);
break;
case certDirectoryName:
pkixDN = name->directoryName;
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object *)pkixDN, pString, plContext),
PKIX_X500NAMETOSTRINGFAILED);
break;
default:
PKIX_ERROR
(PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED);
}
cleanup:
PKIX_FREE(asciiName);
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_GeneralName_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
PKIX_PL_GeneralName *name = NULL;
SECItem secItemName;
SECItem secItemOID;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy");
PKIX_NULLCHECK_ONE(object);
PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
PKIX_OBJECTNOTGENERALNAME);
name = (PKIX_PL_GeneralName *)object;
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
SECITEM_FreeItem(name->other, PR_TRUE);
name->other = NULL;
if (name->OthName){
secItemName = name->OthName->name;
secItemOID = name->OthName->oid;
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
SECITEM_FreeItem(&secItemName, PR_FALSE);
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
SECITEM_FreeItem(&secItemOID, PR_FALSE);
PKIX_FREE(name->OthName);
name->OthName = NULL;
}
if (name->nssGeneralNameList != NULL) {
PKIX_GENERALNAME_DEBUG
("\t\tCalling CERT_DestroyGeneralNameList).\n");
CERT_DestroyGeneralNameList(name->nssGeneralNameList);
}
PKIX_DECREF(name->directoryName);
PKIX_DECREF(name->oid);
cleanup:
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_ToString
* (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_GeneralName_ToString(
PKIX_PL_Object *object,
PKIX_PL_String **pString,
void *plContext)
{
PKIX_PL_String *nameString = NULL;
PKIX_PL_GeneralName *name = NULL;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_toString");
PKIX_NULLCHECK_TWO(object, pString);
PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
PKIX_OBJECTNOTGENERALNAME);
name = (PKIX_PL_GeneralName *)object;
PKIX_CHECK(pkix_pl_GeneralName_ToString_Helper
(name, &nameString, plContext),
PKIX_GENERALNAMETOSTRINGHELPERFAILED);
*pString = nameString;
cleanup:
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_Hashcode
* (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_GeneralName_Hashcode(
PKIX_PL_Object *object,
PKIX_UInt32 *pHashcode,
void *plContext)
{
PKIX_PL_GeneralName *name = NULL;
PKIX_UInt32 firstHash, secondHash, nameHash;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode");
PKIX_NULLCHECK_TWO(object, pHashcode);
PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
PKIX_OBJECTNOTGENERALNAME);
name = (PKIX_PL_GeneralName *)object;
switch (name->type) {
case certRFC822Name:
case certDNSName:
case certX400Address:
case certEDIPartyName:
case certURI:
case certIPAddress:
PKIX_NULLCHECK_ONE(name->other);
PKIX_CHECK(pkix_hash
((const unsigned char *)
name->other->data,
name->other->len,
&nameHash,
plContext),
PKIX_HASHFAILED);
break;
case certRegisterID:
PKIX_CHECK(PKIX_PL_Object_Hashcode
((PKIX_PL_Object *)name->oid,
&nameHash,
plContext),
PKIX_OIDHASHCODEFAILED);
break;
case certOtherName:
PKIX_NULLCHECK_ONE(name->OthName);
PKIX_CHECK(pkix_hash
((const unsigned char *)
name->OthName->oid.data,
name->OthName->oid.len,
&firstHash,
plContext),
PKIX_HASHFAILED);
PKIX_CHECK(pkix_hash
((const unsigned char *)
name->OthName->name.data,
name->OthName->name.len,
&secondHash,
plContext),
PKIX_HASHFAILED);
nameHash = firstHash + secondHash;
break;
case certDirectoryName:
PKIX_CHECK(PKIX_PL_Object_Hashcode
((PKIX_PL_Object *)
name->directoryName,
&nameHash,
plContext),
PKIX_X500NAMEHASHCODEFAILED);
break;
}
*pHashcode = nameHash;
cleanup:
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_Equals
* (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_GeneralName_Equals(
PKIX_PL_Object *firstObject,
PKIX_PL_Object *secondObject,
PKIX_Boolean *pResult,
void *plContext)
{
PKIX_PL_GeneralName *firstName = NULL;
PKIX_PL_GeneralName *secondName = NULL;
PKIX_UInt32 secondType;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Equals");
PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
/* test that firstObject is a GeneralName */
PKIX_CHECK(pkix_CheckType
(firstObject, PKIX_GENERALNAME_TYPE, plContext),
PKIX_FIRSTOBJECTNOTGENERALNAME);
/*
* Since we know firstObject is a GeneralName, if both references are
* identical, they must be equal
*/
if (firstObject == secondObject){
*pResult = PKIX_TRUE;
goto cleanup;
}
/*
* If secondObject isn't a GeneralName, we don't throw an error.
* We simply return a Boolean result of FALSE
*/
*pResult = PKIX_FALSE;
PKIX_CHECK(PKIX_PL_Object_GetType
(secondObject, &secondType, plContext),
PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
if (secondType != PKIX_GENERALNAME_TYPE){
goto cleanup;
}
firstName = (PKIX_PL_GeneralName *)firstObject;
secondName = (PKIX_PL_GeneralName *)secondObject;
if (firstName->type != secondName->type){
goto cleanup;
}
switch (firstName->type) {
case certRFC822Name:
case certDNSName:
case certX400Address:
case certEDIPartyName:
case certURI:
case certIPAddress:
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
if (SECITEM_CompareItem(firstName->other,
secondName->other) != SECEqual) {
goto cleanup;
}
break;
case certRegisterID:
PKIX_CHECK(PKIX_PL_Object_Equals
((PKIX_PL_Object *)firstName->oid,
(PKIX_PL_Object *)secondName->oid,
pResult,
plContext),
PKIX_OIDEQUALSFAILED);
goto cleanup;
case certOtherName:
PKIX_NULLCHECK_TWO(firstName->OthName, secondName->OthName);
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
if (SECITEM_CompareItem(&firstName->OthName->oid,
&secondName->OthName->oid)
!= SECEqual ||
SECITEM_CompareItem(&firstName->OthName->name,
&secondName->OthName->name)
!= SECEqual) {
goto cleanup;
}
break;
case certDirectoryName:
PKIX_CHECK(PKIX_PL_Object_Equals
((PKIX_PL_Object *)firstName->directoryName,
(PKIX_PL_Object *)secondName->directoryName,
pResult,
plContext),
PKIX_X500NAMEEQUALSFAILED);
goto cleanup;
}
*pResult = PKIX_TRUE;
cleanup:
PKIX_RETURN(GENERALNAME);
}
/*
* FUNCTION: pkix_pl_GeneralName_RegisterSelf
* DESCRIPTION:
* Registers PKIX_GENERALNAME_TYPE and related functions with systemClasses[]
* THREAD SAFETY:
* Not Thread Safe - for performance and complexity reasons
*
* Since this function is only called by PKIX_PL_Initialize, which should
* only be called once, it is acceptable that this function is not
* thread-safe.
*/
PKIX_Error *
pkix_pl_GeneralName_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_RegisterSelf");
entry.description = "GeneralName";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(PKIX_PL_GeneralName);
entry.destructor = pkix_pl_GeneralName_Destroy;
entry.equalsFunction = pkix_pl_GeneralName_Equals;
entry.hashcodeFunction = pkix_pl_GeneralName_Hashcode;
entry.toStringFunction = pkix_pl_GeneralName_ToString;
entry.comparator = NULL;
entry.duplicateFunction = pkix_duplicateImmutable;
systemClasses[PKIX_GENERALNAME_TYPE] = entry;
PKIX_RETURN(GENERALNAME);
}
/* --Public-Functions------------------------------------------------------- */
#ifdef BUILD_LIBPKIX_TESTS
/*
* FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h)
*/
PKIX_Error *
PKIX_PL_GeneralName_Create(
PKIX_UInt32 nameType,
PKIX_PL_String *stringRep,
PKIX_PL_GeneralName **pGName,
void *plContext)
{
PKIX_PL_X500Name *pkixDN = NULL;
PKIX_PL_OID *pkixOID = NULL;
SECItem *secItem = NULL;
char *asciiString = NULL;
PKIX_UInt32 length = 0;
PKIX_PL_GeneralName *genName = NULL;
CERTGeneralName *nssGenName = NULL;
CERTGeneralNameList *nssGenNameList = NULL;
CERTName *nssCertName = NULL;
PLArenaPool *arena = NULL;
PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create");
PKIX_NULLCHECK_TWO(pGName, stringRep);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stringRep,
PKIX_ESCASCII,
(void **)&asciiString,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
/* Create a temporary CERTGeneralName */
PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n");
length = PL_strlen(asciiString);
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
secItem = SECITEM_AllocItem(NULL, NULL, length);
PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n");
(void) PORT_Memcpy(secItem->data, asciiString, length);
PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n");
nssGenName = CERT_NewGeneralName(arena, nameType);
if (nssGenName == NULL) {
PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED);
}
switch (nameType) {
case certRFC822Name:
case certDNSName:
case certURI:
nssGenName->name.other = *secItem;
break;
case certDirectoryName:
PKIX_CHECK(PKIX_PL_X500Name_Create
(stringRep, &pkixDN, plContext),
PKIX_X500NAMECREATEFAILED);
PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n");
nssCertName = CERT_AsciiToName(asciiString);
nssGenName->name.directoryName = *nssCertName;
break;
case certRegisterID:
PKIX_CHECK(PKIX_PL_OID_Create
(asciiString, &pkixOID, plContext),
PKIX_OIDCREATEFAILED);
nssGenName->name.other = *secItem;
break;
default:
/* including IPAddress, EDIPartyName, OtherName, X400Address */
PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE);
}
/* create a PKIX_PL_GeneralName object */
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_GENERALNAME_TYPE,
sizeof (PKIX_PL_GeneralName),
(PKIX_PL_Object **)&genName,
plContext),
PKIX_COULDNOTCREATEOBJECT);
/* create a CERTGeneralNameList */
nssGenName->type = nameType;
PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
nssGenNameList = CERT_CreateGeneralNameList(nssGenName);
if (nssGenNameList == NULL) {
PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
}
genName->nssGeneralNameList = nssGenNameList;
/* initialize fields */
genName->type = nameType;
genName->directoryName = pkixDN;
genName->OthName = NULL;
genName->other = secItem;
genName->oid = pkixOID;
*pGName = genName;
cleanup:
PKIX_FREE(asciiString);
if (nssCertName != NULL) {
PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n");
CERT_DestroyName(nssCertName);
}
if (arena){ /* will free nssGenName */
PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
if (PKIX_ERROR_RECEIVED){
PKIX_DECREF(pkixDN);
PKIX_DECREF(pkixOID);
PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
if (secItem){
SECITEM_FreeItem(secItem, PR_TRUE);
secItem = NULL;
}
}
PKIX_RETURN(GENERALNAME);
}
#endif /* BUILD_LIBPKIX_TESTS */