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