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_x500name.c andre@0: * andre@0: * X500Name Object Functions andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_x500name.h" andre@0: andre@0: /* --Private-X500Name-Functions------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_ToString_Helper andre@0: * DESCRIPTION: andre@0: * andre@0: * Helper function that creates a string representation of the X500Name andre@0: * pointed to by "name" and stores it at "pString". andre@0: * andre@0: * PARAMETERS andre@0: * "name" andre@0: * Address of X500Name 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 X500Name 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_X500Name_ToString_Helper( andre@0: PKIX_PL_X500Name *name, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: CERTName *nssDN = NULL; andre@0: char *utf8String = NULL; andre@0: PKIX_UInt32 utf8Length; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_ToString_Helper"); andre@0: PKIX_NULLCHECK_TWO(name, pString); andre@0: nssDN = &name->nssDN; andre@0: andre@0: /* this should really be called CERT_NameToUTF8 */ andre@0: utf8String = CERT_NameToAsciiInvertible(nssDN, CERT_N2A_INVERTIBLE); andre@0: if (!utf8String){ andre@0: PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED); andre@0: } andre@0: andre@0: PKIX_X500NAME_DEBUG("\t\tCalling PL_strlen).\n"); andre@0: utf8Length = PL_strlen(utf8String); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_UTF8, utf8String, utf8Length, pString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: PR_Free(utf8String); andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_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_X500Name_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *name = NULL; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), andre@0: PKIX_OBJECTNOTANX500NAME); andre@0: andre@0: name = (PKIX_PL_X500Name *)object; andre@0: andre@0: /* PORT_FreeArena will destroy arena, and, allocated on it, CERTName andre@0: * and SECItem */ andre@0: if (name->arena) { andre@0: PORT_FreeArena(name->arena, PR_FALSE); andre@0: name->arena = NULL; andre@0: } andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_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_X500Name_ToString( andre@0: PKIX_PL_Object *object, andre@0: PKIX_PL_String **pString, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *name = NULL; andre@0: char *string = NULL; andre@0: PKIX_UInt32 strLength = 0; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_toString"); andre@0: PKIX_NULLCHECK_TWO(object, pString); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), andre@0: PKIX_OBJECTNOTANX500NAME); andre@0: andre@0: name = (PKIX_PL_X500Name *)object; andre@0: string = CERT_NameToAscii(&name->nssDN); andre@0: if (!string){ andre@0: PKIX_ERROR(PKIX_CERTNAMETOASCIIFAILED); andre@0: } andre@0: strLength = PL_strlen(string); andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_Create andre@0: (PKIX_ESCASCII, string, strLength, pString, plContext), andre@0: PKIX_STRINGCREATEFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_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_X500Name_Hashcode( andre@0: PKIX_PL_Object *object, andre@0: PKIX_UInt32 *pHashcode, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *name = NULL; andre@0: SECItem *derBytes = NULL; andre@0: PKIX_UInt32 nameHash; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Hashcode"); andre@0: PKIX_NULLCHECK_TWO(object, pHashcode); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_X500NAME_TYPE, plContext), andre@0: PKIX_OBJECTNOTANX500NAME); andre@0: andre@0: name = (PKIX_PL_X500Name *)object; andre@0: andre@0: /* we hash over the bytes in the DER encoding */ andre@0: andre@0: derBytes = &name->derName; andre@0: andre@0: PKIX_CHECK(pkix_hash andre@0: (derBytes->data, derBytes->len, &nameHash, plContext), andre@0: PKIX_HASHFAILED); andre@0: andre@0: *pHashcode = nameHash; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_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_X500Name_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_UInt32 secondType; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_Equals"); andre@0: PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); andre@0: andre@0: /* test that firstObject is an X500Name */ andre@0: PKIX_CHECK(pkix_CheckType(firstObject, PKIX_X500NAME_TYPE, plContext), andre@0: PKIX_FIRSTOBJECTARGUMENTNOTANX500NAME); andre@0: andre@0: /* andre@0: * Since we know firstObject is an X500Name, 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 an X500Name, 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_X500NAME_TYPE) goto cleanup; andre@0: andre@0: PKIX_CHECK( andre@0: PKIX_PL_X500Name_Match((PKIX_PL_X500Name *)firstObject, andre@0: (PKIX_PL_X500Name *)secondObject, andre@0: pResult, plContext), andre@0: PKIX_X500NAMEMATCHFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_X500NAME_TYPE and its 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_X500Name_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(X500NAME, "pkix_pl_X500Name_RegisterSelf"); andre@0: andre@0: entry.description = "X500Name"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_PL_X500Name); andre@0: entry.destructor = pkix_pl_X500Name_Destroy; andre@0: entry.equalsFunction = pkix_pl_X500Name_Equals; andre@0: entry.hashcodeFunction = pkix_pl_X500Name_Hashcode; andre@0: entry.toStringFunction = pkix_pl_X500Name_ToString; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = pkix_duplicateImmutable; andre@0: andre@0: systemClasses[PKIX_X500NAME_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: #ifdef BUILD_LIBPKIX_TESTS andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_CreateFromUtf8 andre@0: * andre@0: * DESCRIPTION: andre@0: * Creates an X500Name object from the RFC1485 string representation pointed andre@0: * to by "stringRep", and stores the result at "pName". If the string cannot andre@0: * be successfully converted, a non-fatal error is returned. andre@0: * andre@0: * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed to be andre@0: * called only by pkix tests programs. andre@0: * andre@0: * PARAMETERS: andre@0: * "stringRep" andre@0: * Address of the RFC1485 string to be converted. Must be non-NULL. andre@0: * "pName" andre@0: * Address where the X500Name result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns an X500NAME 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_X500Name_CreateFromUtf8( andre@0: char *stringRep, andre@0: PKIX_PL_X500Name **pName, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_X500Name *x500Name = NULL; andre@0: PLArenaPool *arena = NULL; andre@0: CERTName *nssDN = NULL; andre@0: SECItem *resultSecItem = NULL; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_CreateFromUtf8"); andre@0: PKIX_NULLCHECK_TWO(pName, stringRep); andre@0: andre@0: nssDN = CERT_AsciiToName(stringRep); andre@0: if (nssDN == NULL) { andre@0: PKIX_ERROR(PKIX_COULDNOTCREATENSSDN); andre@0: } andre@0: andre@0: arena = nssDN->arena; andre@0: andre@0: /* create a PKIX_PL_X500Name object */ andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_X500NAME_TYPE, andre@0: sizeof (PKIX_PL_X500Name), andre@0: (PKIX_PL_Object **)&x500Name, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEX500NAMEOBJECT); andre@0: andre@0: /* populate the nssDN field */ andre@0: x500Name->arena = arena; andre@0: x500Name->nssDN.arena = arena; andre@0: x500Name->nssDN.rdns = nssDN->rdns; andre@0: andre@0: resultSecItem = andre@0: SEC_ASN1EncodeItem(arena, &x500Name->derName, nssDN, andre@0: CERT_NameTemplate); andre@0: andre@0: if (resultSecItem == NULL){ andre@0: PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); andre@0: } andre@0: andre@0: *pName = x500Name; andre@0: andre@0: cleanup: andre@0: andre@0: if (PKIX_ERROR_RECEIVED){ andre@0: if (x500Name) { andre@0: PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name, andre@0: plContext); andre@0: } else if (nssDN) { andre@0: CERT_DestroyName(nssDN); andre@0: } andre@0: } andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: #endif /* BUILD_LIBPKIX_TESTS */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_GetCERTName andre@0: * andre@0: * DESCRIPTION: andre@0: * andre@0: * Returns the pointer to CERTName member of X500Name structure. andre@0: * andre@0: * Returned pointed should not be freed.2 andre@0: * andre@0: * PARAMETERS: andre@0: * "xname" andre@0: * Address of X500Name whose OrganizationName is to be extracted. Must be andre@0: * non-NULL. andre@0: * "pCERTName" andre@0: * Address where result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_X500Name_GetCERTName( andre@0: PKIX_PL_X500Name *xname, andre@0: CERTName **pCERTName, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCERTName"); andre@0: PKIX_NULLCHECK_TWO(xname, pCERTName); andre@0: andre@0: *pCERTName = &xname->nssDN; andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* --Public-Functions------------------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_X500Name_CreateFromCERTName (see comments in pkix_pl_pki.h) andre@0: */ andre@0: andre@0: PKIX_Error * andre@0: PKIX_PL_X500Name_CreateFromCERTName( andre@0: SECItem *derName, andre@0: CERTName *name, andre@0: PKIX_PL_X500Name **pName, andre@0: void *plContext) andre@0: { andre@0: PLArenaPool *arena = NULL; andre@0: SECStatus rv = SECFailure; andre@0: PKIX_PL_X500Name *x500Name = NULL; andre@0: andre@0: PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_CreateFromCERTName"); andre@0: PKIX_NULLCHECK_ONE(pName); andre@0: if (derName == NULL && name == NULL) { andre@0: PKIX_ERROR(PKIX_NULLARGUMENT); andre@0: } andre@0: andre@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); andre@0: if (arena == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_X500NAME_TYPE, andre@0: sizeof (PKIX_PL_X500Name), andre@0: (PKIX_PL_Object **)&x500Name, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEX500NAMEOBJECT); andre@0: andre@0: x500Name->arena = arena; andre@0: x500Name->nssDN.arena = NULL; andre@0: andre@0: if (derName != NULL) { andre@0: rv = SECITEM_CopyItem(arena, &x500Name->derName, derName); andre@0: if (rv == SECFailure) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: } andre@0: andre@0: if (name != NULL) { andre@0: rv = CERT_CopyName(arena, &x500Name->nssDN, name); andre@0: if (rv == SECFailure) { andre@0: PKIX_ERROR(PKIX_CERTCOPYNAMEFAILED); andre@0: } andre@0: } else { andre@0: rv = SEC_QuickDERDecodeItem(arena, &x500Name->nssDN, andre@0: CERT_NameTemplate, andre@0: &x500Name->derName); andre@0: if (rv == SECFailure) { andre@0: PKIX_ERROR(PKIX_SECQUICKDERDECODERFAILED); andre@0: } andre@0: } andre@0: andre@0: *pName = x500Name; andre@0: andre@0: cleanup: andre@0: if (PKIX_ERROR_RECEIVED) { andre@0: if (x500Name) { andre@0: PKIX_PL_Object_DecRef((PKIX_PL_Object*)x500Name, andre@0: plContext); andre@0: } else if (arena) { andre@0: PORT_FreeArena(arena, PR_FALSE); andre@0: } andre@0: } andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: #ifdef BUILD_LIBPKIX_TESTS andre@0: /* andre@0: * FUNCTION: PKIX_PL_X500Name_Create (see comments in pkix_pl_pki.h) andre@0: * andre@0: * NOTE: ifdefed BUILD_LIBPKIX_TESTS function: this function is allowed andre@0: * to be called only by pkix tests programs. andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_X500Name_Create( andre@0: PKIX_PL_String *stringRep, andre@0: PKIX_PL_X500Name **pName, andre@0: void *plContext) andre@0: { andre@0: char *utf8String = NULL; andre@0: PKIX_UInt32 utf8Length = 0; andre@0: andre@0: PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Create"); andre@0: PKIX_NULLCHECK_TWO(pName, stringRep); andre@0: andre@0: /* andre@0: * convert the input PKIX_PL_String to PKIX_UTF8_NULL_TERM. andre@0: * we need to use this format specifier because andre@0: * CERT_AsciiToName expects a NULL-terminated UTF8 string. andre@0: * Since UTF8 allow NUL characters in the middle of the andre@0: * string, this is buggy. However, as a workaround, using andre@0: * PKIX_UTF8_NULL_TERM gives us a NULL-terminated UTF8 string. andre@0: */ andre@0: andre@0: PKIX_CHECK(PKIX_PL_String_GetEncoded andre@0: (stringRep, andre@0: PKIX_UTF8_NULL_TERM, andre@0: (void **)&utf8String, andre@0: &utf8Length, andre@0: plContext), andre@0: PKIX_STRINGGETENCODEDFAILED); andre@0: andre@0: PKIX_CHECK( andre@0: pkix_pl_X500Name_CreateFromUtf8(utf8String, andre@0: pName, plContext), andre@0: PKIX_X500NAMECREATEFROMUTF8FAILED); andre@0: andre@0: cleanup: andre@0: PKIX_FREE(utf8String); andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: #endif /* BUILD_LIBPKIX_TESTS */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_X500Name_Match (see comments in pkix_pl_pki.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_X500Name_Match( andre@0: PKIX_PL_X500Name *firstX500Name, andre@0: PKIX_PL_X500Name *secondX500Name, andre@0: PKIX_Boolean *pResult, andre@0: void *plContext) andre@0: { andre@0: SECItem *firstDerName = NULL; andre@0: SECItem *secondDerName = NULL; andre@0: SECComparison cmpResult; andre@0: andre@0: PKIX_ENTER(X500NAME, "PKIX_PL_X500Name_Match"); andre@0: PKIX_NULLCHECK_THREE(firstX500Name, secondX500Name, pResult); andre@0: andre@0: if (firstX500Name == secondX500Name){ andre@0: *pResult = PKIX_TRUE; andre@0: goto cleanup; andre@0: } andre@0: andre@0: firstDerName = &firstX500Name->derName; andre@0: secondDerName = &secondX500Name->derName; andre@0: andre@0: PKIX_NULLCHECK_TWO(firstDerName->data, secondDerName->data); andre@0: andre@0: cmpResult = SECITEM_CompareItem(firstDerName, secondDerName); andre@0: if (cmpResult != SECEqual) { andre@0: cmpResult = CERT_CompareName(&firstX500Name->nssDN, andre@0: &secondX500Name->nssDN); andre@0: } andre@0: andre@0: *pResult = (cmpResult == SECEqual); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_GetSECName andre@0: * andre@0: * DESCRIPTION: andre@0: * Returns a copy of CERTName DER representation allocated on passed in arena. andre@0: * If allocation on arena can not be done, NULL is stored at "pSECName". andre@0: * andre@0: * PARAMETERS: andre@0: * "xname" andre@0: * Address of X500Name whose CERTName flag is to be encoded. Must be andre@0: * non-NULL. andre@0: * "arena" andre@0: * Address of the PLArenaPool to be used in the encoding, and in which andre@0: * "pSECName" will be allocated. Must be non-NULL. andre@0: * "pSECName" andre@0: * Address where result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_X500Name_GetDERName( andre@0: PKIX_PL_X500Name *xname, andre@0: PLArenaPool *arena, andre@0: SECItem **pDERName, andre@0: void *plContext) andre@0: { andre@0: SECItem *derName = NULL; andre@0: andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetDERName"); andre@0: andre@0: PKIX_NULLCHECK_THREE(xname, arena, pDERName); andre@0: andre@0: /* Return NULL is X500Name was not created from DER */ andre@0: if (xname->derName.data == NULL) { andre@0: *pDERName = NULL; andre@0: goto cleanup; andre@0: } andre@0: andre@0: derName = SECITEM_ArenaDupItem(arena, &xname->derName); andre@0: if (derName == NULL) { andre@0: PKIX_ERROR(PKIX_OUTOFMEMORY); andre@0: } andre@0: andre@0: *pDERName = derName; andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_GetCommonName andre@0: * andre@0: * DESCRIPTION: andre@0: * Extracts the CommonName component of the X500Name object pointed to by andre@0: * "xname", and stores the result at "pCommonName". If the CommonName cannot andre@0: * be successfully extracted, NULL is stored at "pCommonName". andre@0: * andre@0: * The returned string must be freed with PORT_Free. andre@0: * andre@0: * PARAMETERS: andre@0: * "xname" andre@0: * Address of X500Name whose CommonName is to be extracted. Must be andre@0: * non-NULL. andre@0: * "pCommonName" andre@0: * Address where result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_X500Name_GetCommonName( andre@0: PKIX_PL_X500Name *xname, andre@0: unsigned char **pCommonName, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCommonName"); andre@0: PKIX_NULLCHECK_TWO(xname, pCommonName); andre@0: andre@0: *pCommonName = (unsigned char *)CERT_GetCommonName(&xname->nssDN); andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_GetCountryName andre@0: * andre@0: * DESCRIPTION: andre@0: * Extracts the CountryName component of the X500Name object pointed to by andre@0: * "xname", and stores the result at "pCountryName". If the CountryName cannot andre@0: * be successfully extracted, NULL is stored at "pCountryName". andre@0: * andre@0: * The returned string must be freed with PORT_Free. andre@0: * andre@0: * PARAMETERS: andre@0: * "xname" andre@0: * Address of X500Name whose CountryName is to be extracted. Must be andre@0: * non-NULL. andre@0: * "pCountryName" andre@0: * Address where result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_X500Name_GetCountryName( andre@0: PKIX_PL_X500Name *xname, andre@0: unsigned char **pCountryName, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetCountryName"); andre@0: PKIX_NULLCHECK_TWO(xname, pCountryName); andre@0: andre@0: *pCountryName = (unsigned char*)CERT_GetCountryName(&xname->nssDN); andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_X500Name_GetOrgName andre@0: * andre@0: * DESCRIPTION: andre@0: * Extracts the OrganizationName component of the X500Name object pointed to by andre@0: * "xname", and stores the result at "pOrgName". If the OrganizationName cannot andre@0: * be successfully extracted, NULL is stored at "pOrgName". andre@0: * andre@0: * The returned string must be freed with PORT_Free. andre@0: * andre@0: * PARAMETERS: andre@0: * "xname" andre@0: * Address of X500Name whose OrganizationName is to be extracted. Must be andre@0: * non-NULL. andre@0: * "pOrgName" andre@0: * Address where result will be stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_X500Name_GetOrgName( andre@0: PKIX_PL_X500Name *xname, andre@0: unsigned char **pOrgName, andre@0: void *plContext) andre@0: { andre@0: PKIX_ENTER(X500NAME, "pkix_pl_X500Name_GetOrgName"); andre@0: PKIX_NULLCHECK_TWO(xname, pOrgName); andre@0: andre@0: *pOrgName = (unsigned char*)CERT_GetOrgName(&xname->nssDN); andre@0: andre@0: PKIX_RETURN(X500NAME); andre@0: }