diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c')
-rw-r--r-- | security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c new file mode 100644 index 000000000..9e9a74c78 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_generalname.c @@ -0,0 +1,873 @@ +/* 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 */ |