blob: affea8741daac7b5b72d0801be5e587a8188def3 [file] [log] [blame]
/* 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_nameconstraints.c
*
* Name Constraints Object Functions Definitions
*
*/
#include "pkix_pl_nameconstraints.h"
/* --Private-NameConstraints-Functions----------------------------- */
/*
* FUNCTION: pkix_pl_CertNameConstraints_GetPermitted
* DESCRIPTION:
*
* This function retrieve name constraints permitted list from NSS
* data in "nameConstraints" and returns a PKIX_PL_GeneralName list
* in "pPermittedList".
*
* PARAMETERS
* "nameConstraints"
* Address of CertNameConstraints which has a pointer to
* CERTNameConstraints data. Must be non-NULL.
* "pPermittedList"
* Address where returned permitted name list is stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Conditionally Thread Safe
* (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a NameConstraints 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_CertNameConstraints_GetPermitted(
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_List **pPermittedList,
void *plContext)
{
CERTNameConstraints *nssNameConstraints = NULL;
CERTNameConstraints **nssNameConstraintsList = NULL;
CERTNameConstraint *nssPermitted = NULL;
CERTNameConstraint *firstPermitted = NULL;
PKIX_List *permittedList = NULL;
PKIX_PL_GeneralName *name = NULL;
PKIX_UInt32 numItems = 0;
PKIX_UInt32 i;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_GetPermitted");
PKIX_NULLCHECK_TWO(nameConstraints, pPermittedList);
/*
* nssNameConstraints is an array of CERTNameConstraints
* pointers where CERTNameConstraints keep its permitted and excluded
* lists as pointer array of CERTNameConstraint.
*/
if (nameConstraints->permittedList == NULL) {
PKIX_OBJECT_LOCK(nameConstraints);
if (nameConstraints->permittedList == NULL) {
PKIX_CHECK(PKIX_List_Create(&permittedList, plContext),
PKIX_LISTCREATEFAILED);
numItems = nameConstraints->numNssNameConstraints;
nssNameConstraintsList =
nameConstraints->nssNameConstraintsList;
for (i = 0; i < numItems; i++) {
PKIX_NULLCHECK_ONE(nssNameConstraintsList);
nssNameConstraints = *(nssNameConstraintsList + i);
PKIX_NULLCHECK_ONE(nssNameConstraints);
if (nssNameConstraints->permited != NULL) {
nssPermitted = nssNameConstraints->permited;
firstPermitted = nssPermitted;
do {
PKIX_CHECK(pkix_pl_GeneralName_Create
(&nssPermitted->name, &name, plContext),
PKIX_GENERALNAMECREATEFAILED);
PKIX_CHECK(PKIX_List_AppendItem
(permittedList,
(PKIX_PL_Object *)name,
plContext),
PKIX_LISTAPPENDITEMFAILED);
PKIX_DECREF(name);
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_GetNextNameConstraint\n");
nssPermitted = CERT_GetNextNameConstraint
(nssPermitted);
} while (nssPermitted != firstPermitted);
}
}
PKIX_CHECK(PKIX_List_SetImmutable(permittedList, plContext),
PKIX_LISTSETIMMUTABLEFAILED);
nameConstraints->permittedList = permittedList;
}
PKIX_OBJECT_UNLOCK(nameConstraints);
}
PKIX_INCREF(nameConstraints->permittedList);
*pPermittedList = nameConstraints->permittedList;
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_GetExcluded
* DESCRIPTION:
*
* This function retrieve name constraints excluded list from NSS
* data in "nameConstraints" and returns a PKIX_PL_GeneralName list
* in "pExcludedList".
*
* PARAMETERS
* "nameConstraints"
* Address of CertNameConstraints which has a pointer to NSS data.
* Must be non-NULL.
* "pPermittedList"
* Address where returned excluded name list is stored. Must be non-NULL.
* "plContext" - Platform-specific context pointer.
* THREAD SAFETY:
* Conditionally Thread Safe
* (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds.
* Returns a NameConstraints 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_CertNameConstraints_GetExcluded(
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_List **pExcludedList,
void *plContext)
{
CERTNameConstraints *nssNameConstraints = NULL;
CERTNameConstraints **nssNameConstraintsList = NULL;
CERTNameConstraint *nssExcluded = NULL;
CERTNameConstraint *firstExcluded = NULL;
PKIX_List *excludedList = NULL;
PKIX_PL_GeneralName *name = NULL;
PKIX_UInt32 numItems = 0;
PKIX_UInt32 i;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_GetExcluded");
PKIX_NULLCHECK_TWO(nameConstraints, pExcludedList);
if (nameConstraints->excludedList == NULL) {
PKIX_OBJECT_LOCK(nameConstraints);
if (nameConstraints->excludedList == NULL) {
PKIX_CHECK(PKIX_List_Create(&excludedList, plContext),
PKIX_LISTCREATEFAILED);
numItems = nameConstraints->numNssNameConstraints;
nssNameConstraintsList =
nameConstraints->nssNameConstraintsList;
for (i = 0; i < numItems; i++) {
PKIX_NULLCHECK_ONE(nssNameConstraintsList);
nssNameConstraints = *(nssNameConstraintsList + i);
PKIX_NULLCHECK_ONE(nssNameConstraints);
if (nssNameConstraints->excluded != NULL) {
nssExcluded = nssNameConstraints->excluded;
firstExcluded = nssExcluded;
do {
PKIX_CHECK(pkix_pl_GeneralName_Create
(&nssExcluded->name, &name, plContext),
PKIX_GENERALNAMECREATEFAILED);
PKIX_CHECK(PKIX_List_AppendItem
(excludedList,
(PKIX_PL_Object *)name,
plContext),
PKIX_LISTAPPENDITEMFAILED);
PKIX_DECREF(name);
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_GetNextNameConstraint\n");
nssExcluded = CERT_GetNextNameConstraint
(nssExcluded);
} while (nssExcluded != firstExcluded);
}
}
PKIX_CHECK(PKIX_List_SetImmutable(excludedList, plContext),
PKIX_LISTSETIMMUTABLEFAILED);
nameConstraints->excludedList = excludedList;
}
PKIX_OBJECT_UNLOCK(nameConstraints);
}
PKIX_INCREF(nameConstraints->excludedList);
*pExcludedList = nameConstraints->excludedList;
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
* DESCRIPTION:
*
* This function checks if CERTGeneralNames in "nssSubjectNames" comply
* with the permitted and excluded names in "nameConstraints". It returns
* PKIX_TRUE in "pCheckPass", if the Names satify the name space of the
* permitted list and if the Names are not in the excluded list. Otherwise,
* it returns PKIX_FALSE.
*
* PARAMETERS
* "nssSubjectNames"
* List of CERTGeneralName that nameConstraints verification is based on.
* "nameConstraints"
* Address of CertNameConstraints that provides lists of permitted
* and excluded names. Must be non-NULL.
* "pCheckPass"
* Address where PKIX_TRUE is returned if the all names in "nameList" are
* valid.
* "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 NameConstraints 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_CertNameConstraints_CheckNameSpaceNssNames(
CERTGeneralName *nssSubjectNames,
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_Boolean *pCheckPass,
void *plContext)
{
CERTNameConstraints **nssNameConstraintsList = NULL;
CERTNameConstraints *nssNameConstraints = NULL;
CERTGeneralName *nssMatchName = NULL;
PLArenaPool *arena = NULL;
PKIX_UInt32 numItems = 0;
PKIX_UInt32 i;
SECStatus status = SECSuccess;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_CheckNameSpaceNssNames");
PKIX_NULLCHECK_THREE(nssSubjectNames, nameConstraints, pCheckPass);
*pCheckPass = PKIX_TRUE;
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
nssMatchName = nssSubjectNames;
nssNameConstraintsList = nameConstraints->nssNameConstraintsList;
/*
* CERTNameConstraint items in each permitted or excluded list
* is verified as OR condition. That means, if one item matched,
* then the checking on the remaining items on the list is skipped.
* (see NSS cert_CompareNameWithConstraints(...)).
* Items on PKIX_PL_NameConstraint's nssNameConstraints are verified
* as AND condition. PKIX_PL_NameConstraint keeps an array of pointers
* of CERTNameConstraints resulting from merging multiple
* PKIX_PL_NameConstraints. Since each CERTNameConstraint are created
* for different entity, a union condition of these entities then is
* performed.
*/
do {
numItems = nameConstraints->numNssNameConstraints;
for (i = 0; i < numItems; i++) {
PKIX_NULLCHECK_ONE(nssNameConstraintsList);
nssNameConstraints = *(nssNameConstraintsList + i);
PKIX_NULLCHECK_ONE(nssNameConstraints);
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_CheckNameSpace\n");
status = CERT_CheckNameSpace
(arena, nssNameConstraints, nssMatchName);
if (status != SECSuccess) {
break;
}
}
if (status != SECSuccess) {
break;
}
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_GetNextGeneralName\n");
nssMatchName = CERT_GetNextGeneralName(nssMatchName);
} while (nssMatchName != nssSubjectNames);
if (status == SECFailure) {
*pCheckPass = PKIX_FALSE;
}
cleanup:
if (arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_NameConstraints_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_CertNameConstraints_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Destroy");
PKIX_NULLCHECK_ONE(object);
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
nameConstraints = (PKIX_PL_CertNameConstraints *)object;
PKIX_CHECK(PKIX_PL_Free
(nameConstraints->nssNameConstraintsList, plContext),
PKIX_FREEFAILED);
if (nameConstraints->arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(nameConstraints->arena, PR_FALSE);
nameConstraints->arena = NULL;
}
PKIX_DECREF(nameConstraints->permittedList);
PKIX_DECREF(nameConstraints->excludedList);
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_ToString_Helper
* DESCRIPTION:
*
* Helper function that creates a string representation of the object
* NameConstraints and stores it at "pString".
*
* PARAMETERS
* "nameConstraints"
* Address of CertNameConstraints whose string representation is
* desired. Must be non-NULL.
* "pString"
* Address where string 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 NameConstraints 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_CertNameConstraints_ToString_Helper(
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_PL_String **pString,
void *plContext)
{
char *asciiFormat = NULL;
PKIX_PL_String *formatString = NULL;
PKIX_List *permittedList = NULL;
PKIX_List *excludedList = NULL;
PKIX_PL_String *permittedListString = NULL;
PKIX_PL_String *excludedListString = NULL;
PKIX_PL_String *nameConstraintsString = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_ToString_Helper");
PKIX_NULLCHECK_TWO(nameConstraints, pString);
asciiFormat =
"[\n"
"\t\tPermitted Name: %s\n"
"\t\tExcluded Name: %s\n"
"\t]\n";
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII,
asciiFormat,
0,
&formatString,
plContext),
PKIX_STRINGCREATEFAILED);
PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
(nameConstraints, &permittedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
PKIX_TOSTRING(permittedList, &permittedListString, plContext,
PKIX_LISTTOSTRINGFAILED);
PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
(nameConstraints, &excludedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
PKIX_TOSTRING(excludedList, &excludedListString, plContext,
PKIX_LISTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_Sprintf
(&nameConstraintsString,
plContext,
formatString,
permittedListString,
excludedListString),
PKIX_SPRINTFFAILED);
*pString = nameConstraintsString;
cleanup:
PKIX_DECREF(formatString);
PKIX_DECREF(permittedList);
PKIX_DECREF(excludedList);
PKIX_DECREF(permittedListString);
PKIX_DECREF(excludedListString);
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_ToString
* (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_CertNameConstraints_ToString(
PKIX_PL_Object *object,
PKIX_PL_String **pString,
void *plContext)
{
PKIX_PL_String *nameConstraintsString = NULL;
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_ToString");
PKIX_NULLCHECK_TWO(object, pString);
PKIX_CHECK(pkix_CheckType(
object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
nameConstraints = (PKIX_PL_CertNameConstraints *)object;
PKIX_CHECK(pkix_pl_CertNameConstraints_ToString_Helper
(nameConstraints, &nameConstraintsString, plContext),
PKIX_CERTNAMECONSTRAINTSTOSTRINGHELPERFAILED);
*pString = nameConstraintsString;
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_Hashcode
* (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_CertNameConstraints_Hashcode(
PKIX_PL_Object *object,
PKIX_UInt32 *pHashcode,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
PKIX_List *permittedList = NULL;
PKIX_List *excludedList = NULL;
PKIX_UInt32 permitHash = 0;
PKIX_UInt32 excludeHash = 0;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Hashcode");
PKIX_NULLCHECK_TWO(object, pHashcode);
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
PKIX_OBJECTNOTCERTNAMECONSTRAINTS);
nameConstraints = (PKIX_PL_CertNameConstraints *)object;
PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
(nameConstraints, &permittedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
PKIX_HASHCODE(permittedList, &permitHash, plContext,
PKIX_OBJECTHASHCODEFAILED);
PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
(nameConstraints, &excludedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
PKIX_HASHCODE(excludedList, &excludeHash, plContext,
PKIX_OBJECTHASHCODEFAILED);
*pHashcode = (((permitHash << 7) + excludeHash) << 7) +
nameConstraints->numNssNameConstraints;
cleanup:
PKIX_DECREF(permittedList);
PKIX_DECREF(excludedList);
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_Equals
* (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_pl_CertNameConstraints_Equals(
PKIX_PL_Object *firstObject,
PKIX_PL_Object *secondObject,
PKIX_Boolean *pResult,
void *plContext)
{
PKIX_PL_CertNameConstraints *firstNC = NULL;
PKIX_PL_CertNameConstraints *secondNC = NULL;
PKIX_List *firstPermittedList = NULL;
PKIX_List *secondPermittedList = NULL;
PKIX_List *firstExcludedList = NULL;
PKIX_List *secondExcludedList = NULL;
PKIX_UInt32 secondType;
PKIX_Boolean cmpResult = PKIX_FALSE;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Equals");
PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
/* test that firstObject is a CertNameConstraints */
PKIX_CHECK(pkix_CheckType
(firstObject, PKIX_CERTNAMECONSTRAINTS_TYPE, plContext),
PKIX_FIRSTOBJECTNOTCERTNAMECONSTRAINTS);
firstNC = (PKIX_PL_CertNameConstraints *)firstObject;
secondNC = (PKIX_PL_CertNameConstraints *)secondObject;
/*
* Since we know firstObject is a CertNameConstraints, if both
* references are identical, they must be equal
*/
if (firstNC == secondNC){
*pResult = PKIX_TRUE;
goto cleanup;
}
/*
* If secondNC isn't a CertNameConstraints, we don't throw an error.
* We simply return a Boolean result of FALSE
*/
*pResult = PKIX_FALSE;
PKIX_CHECK(PKIX_PL_Object_GetType
((PKIX_PL_Object *)secondNC, &secondType, plContext),
PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
if (secondType != PKIX_CERTNAMECONSTRAINTS_TYPE) {
goto cleanup;
}
PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
(firstNC, &firstPermittedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
PKIX_CHECK(pkix_pl_CertNameConstraints_GetPermitted
(secondNC, &secondPermittedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETPERMITTEDFAILED);
PKIX_EQUALS
(firstPermittedList, secondPermittedList, &cmpResult, plContext,
PKIX_OBJECTEQUALSFAILED);
if (cmpResult != PKIX_TRUE) {
goto cleanup;
}
PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
(firstNC, &firstExcludedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
PKIX_CHECK(pkix_pl_CertNameConstraints_GetExcluded
(secondNC, &secondExcludedList, plContext),
PKIX_CERTNAMECONSTRAINTSGETEXCLUDEDFAILED);
PKIX_EQUALS
(firstExcludedList, secondExcludedList, &cmpResult, plContext,
PKIX_OBJECTEQUALSFAILED);
if (cmpResult != PKIX_TRUE) {
goto cleanup;
}
/*
* numNssNameConstraints is not checked because it is basically a
* merge count, it cannot determine the data equality.
*/
*pResult = PKIX_TRUE;
cleanup:
PKIX_DECREF(firstPermittedList);
PKIX_DECREF(secondPermittedList);
PKIX_DECREF(firstExcludedList);
PKIX_DECREF(secondExcludedList);
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_RegisterSelf
* DESCRIPTION:
* Registers PKIX_CERTNAMECONSTRAINTS_TYPE and its 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_CertNameConstraints_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_RegisterSelf");
entry.description = "CertNameConstraints";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(PKIX_PL_CertNameConstraints);
entry.destructor = pkix_pl_CertNameConstraints_Destroy;
entry.equalsFunction = pkix_pl_CertNameConstraints_Equals;
entry.hashcodeFunction = pkix_pl_CertNameConstraints_Hashcode;
entry.toStringFunction = pkix_pl_CertNameConstraints_ToString;
entry.comparator = NULL;
entry.duplicateFunction = pkix_duplicateImmutable;
systemClasses[PKIX_CERTNAMECONSTRAINTS_TYPE] = entry;
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_Create_Helper
*
* DESCRIPTION:
* This function retrieves name constraints in "nssNameConstraints",
* converts and stores the result in a PKIX_PL_CertNameConstraints object.
*
* PARAMETERS
* "nssNameConstraints"
* Address of CERTNameConstraints that contains this object's data.
* Must be non-NULL.
* "pNameConstraints"
* Address where object pointer will be stored. Must be non-NULL.
* A NULL value will be returned if there is no Name Constraints extension.
* "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 NameConstraints 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_CertNameConstraints_Create_Helper(
CERTNameConstraints *nssNameConstraints,
PKIX_PL_CertNameConstraints **pNameConstraints,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
CERTNameConstraints **nssNameConstraintPtr = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_Create_Helper");
PKIX_NULLCHECK_TWO(nssNameConstraints, pNameConstraints);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_CERTNAMECONSTRAINTS_TYPE,
sizeof (PKIX_PL_CertNameConstraints),
(PKIX_PL_Object **)&nameConstraints,
plContext),
PKIX_COULDNOTCREATECERTNAMECONSTRAINTSOBJECT);
PKIX_CHECK(PKIX_PL_Malloc
(sizeof (CERTNameConstraint *),
(void *)&nssNameConstraintPtr,
plContext),
PKIX_MALLOCFAILED);
nameConstraints->numNssNameConstraints = 1;
nameConstraints->nssNameConstraintsList = nssNameConstraintPtr;
*nssNameConstraintPtr = nssNameConstraints;
nameConstraints->permittedList = NULL;
nameConstraints->excludedList = NULL;
nameConstraints->arena = NULL;
*pNameConstraints = nameConstraints;
cleanup:
if (PKIX_ERROR_RECEIVED){
PKIX_DECREF(nameConstraints);
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_Create
*
* DESCRIPTION:
* function that allocates and initialize the object CertNameConstraints.
*
* PARAMETERS
* "nssCert"
* Address of CERT that contains this object's data.
* Must be non-NULL.
* "pNameConstraints"
* Address where object pointer will be stored. Must be non-NULL.
* A NULL value will be returned if there is no Name Constraints extension.
* "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 NameConstraints 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_CertNameConstraints_Create(
CERTCertificate *nssCert,
PKIX_PL_CertNameConstraints **pNameConstraints,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
CERTNameConstraints *nssNameConstraints = NULL;
PLArenaPool *arena = NULL;
SECStatus status;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Create");
PKIX_NULLCHECK_THREE(nssCert, pNameConstraints, nssCert->arena);
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_FindNameConstraintsExten\n");
status = CERT_FindNameConstraintsExten
(arena, nssCert, &nssNameConstraints);
if (status != SECSuccess) {
PKIX_ERROR(PKIX_DECODINGCERTNAMECONSTRAINTSFAILED);
}
if (nssNameConstraints == NULL) {
*pNameConstraints = NULL;
if (arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
goto cleanup;
}
PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
(nssNameConstraints, &nameConstraints, plContext),
PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
nameConstraints->arena = arena;
*pNameConstraints = nameConstraints;
cleanup:
if (PKIX_ERROR_RECEIVED){
if (arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_CreateByMerge
*
* DESCRIPTION:
*
* This function allocates and creates a PKIX_PL_NameConstraint object
* for merging. It also allocates CERTNameConstraints data space for the
* merged NSS NameConstraints data.
*
* PARAMETERS
* "pNameConstraints"
* Address where object pointer will be stored and returned.
* 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 NameConstraints 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_CertNameConstraints_CreateByMerge(
PKIX_PL_CertNameConstraints **pNameConstraints,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
CERTNameConstraints *nssNameConstraints = NULL;
PLArenaPool *arena = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_CreateByMerge");
PKIX_NULLCHECK_ONE(pNameConstraints);
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena).\n");
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
if (nssNameConstraints == NULL) {
PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
}
nssNameConstraints->permited = NULL;
nssNameConstraints->excluded = NULL;
nssNameConstraints->DERPermited = NULL;
nssNameConstraints->DERExcluded = NULL;
PKIX_CHECK(pkix_pl_CertNameConstraints_Create_Helper
(nssNameConstraints, &nameConstraints, plContext),
PKIX_CERTNAMECONSTRAINTSCREATEHELPERFAILED);
nameConstraints->arena = arena;
*pNameConstraints = nameConstraints;
cleanup:
if (PKIX_ERROR_RECEIVED){
if (arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_CopyNssNameConstraints
*
* DESCRIPTION:
*
* This function allocates and copies data to a NSS CERTNameConstraints from
* the NameConstraints given by "srcNC" and stores the result at "pDestNC". It
* copies items on both the permitted and excluded lists, but not the
* DERPermited and DERExcluded.
*
* PARAMETERS
* "arena"
* Memory pool where object data is allocated from. Must be non-NULL.
* "srcNC"
* Address of the NameConstraints to copy from. Must be non-NULL.
* "pDestNC"
* Address where new copied object is stored and returned.
* 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 NameConstraints 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_CertNameConstraints_CopyNssNameConstraints(
PLArenaPool *arena,
CERTNameConstraints *srcNC,
CERTNameConstraints **pDestNC,
void *plContext)
{
CERTNameConstraints *nssNameConstraints = NULL;
CERTNameConstraint *nssNameConstraintHead = NULL;
CERTNameConstraint *nssCurrent = NULL;
CERTNameConstraint *nssCopyTo = NULL;
CERTNameConstraint *nssCopyFrom = NULL;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"pkix_pl_CertNameConstraints_CopyNssNameConstraints");
PKIX_NULLCHECK_THREE(arena, srcNC, pDestNC);
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_ArenaZNew).\n");
nssNameConstraints = PORT_ArenaZNew(arena, CERTNameConstraints);
if (nssNameConstraints == NULL) {
PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
}
if (srcNC->permited) {
nssCopyFrom = srcNC->permited;
do {
nssCopyTo = NULL;
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_CopyNameConstraint).\n");
nssCopyTo = CERT_CopyNameConstraint
(arena, nssCopyTo, nssCopyFrom);
if (nssCopyTo == NULL) {
PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
}
if (nssCurrent == NULL) {
nssCurrent = nssNameConstraintHead = nssCopyTo;
} else {
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_AddNameConstraint).\n");
nssCurrent = CERT_AddNameConstraint
(nssCurrent, nssCopyTo);
}
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_GetNextNameConstrain).\n");
nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
} while (nssCopyFrom != srcNC->permited);
nssNameConstraints->permited = nssNameConstraintHead;
}
if (srcNC->excluded) {
nssCurrent = NULL;
nssCopyFrom = srcNC->excluded;
do {
/*
* Cannot use CERT_DupGeneralNameList, which just increments
* refcount. We need our own copy since arena is for each
* PKIX_PL_NameConstraints. Perhaps contribute this code
* as CERT_CopyGeneralNameList (in the future).
*/
nssCopyTo = NULL;
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_CopyNameConstraint).\n");
nssCopyTo = CERT_CopyNameConstraint
(arena, nssCopyTo, nssCopyFrom);
if (nssCopyTo == NULL) {
PKIX_ERROR(PKIX_CERTCOPYNAMECONSTRAINTFAILED);
}
if (nssCurrent == NULL) {
nssCurrent = nssNameConstraintHead = nssCopyTo;
} else {
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_AddNameConstraint).\n");
nssCurrent = CERT_AddNameConstraint
(nssCurrent, nssCopyTo);
}
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_GetNextNameConstrain).\n");
nssCopyFrom = CERT_GetNextNameConstraint(nssCopyFrom);
} while (nssCopyFrom != srcNC->excluded);
nssNameConstraints->excluded = nssNameConstraintHead;
}
*pDestNC = nssNameConstraints;
cleanup:
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/*
* FUNCTION: pkix_pl_CertNameConstraints_Merge
*
* DESCRIPTION:
*
* This function merges two NameConstraints pointed to by "firstNC" and
* "secondNC" and stores the result in "pMergedNC".
*
* PARAMETERS
* "firstNC"
* Address of the first NameConstraints to be merged. Must be non-NULL.
* "secondNC"
* Address of the second NameConstraints to be merged. Must be non-NULL.
* "pMergedNC"
* Address where the merge result is stored and returned. 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 NameConstraints 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_CertNameConstraints_Merge(
PKIX_PL_CertNameConstraints *firstNC,
PKIX_PL_CertNameConstraints *secondNC,
PKIX_PL_CertNameConstraints **pMergedNC,
void *plContext)
{
PKIX_PL_CertNameConstraints *nameConstraints = NULL;
CERTNameConstraints **nssNCto = NULL;
CERTNameConstraints **nssNCfrom = NULL;
CERTNameConstraints *nssNameConstraints = NULL;
PKIX_UInt32 numNssItems = 0;
PKIX_UInt32 i;
PKIX_ENTER(CERTNAMECONSTRAINTS, "pkix_pl_CertNameConstraints_Merge");
PKIX_NULLCHECK_THREE(firstNC, secondNC, pMergedNC);
PKIX_CHECK(pkix_pl_CertNameConstraints_CreateByMerge
(&nameConstraints, plContext),
PKIX_CERTNAMECONSTRAINTSCREATEBYMERGEFAILED);
/* Merge NSSCertConstraint lists */
numNssItems = firstNC->numNssNameConstraints +
secondNC->numNssNameConstraints;
/* Free the default space (only one entry) allocated by create */
PKIX_CHECK(PKIX_PL_Free
(nameConstraints->nssNameConstraintsList, plContext),
PKIX_FREEFAILED);
/* Reallocate the size we need */
PKIX_CHECK(PKIX_PL_Malloc
(numNssItems * sizeof (CERTNameConstraint *),
(void *)&nssNCto,
plContext),
PKIX_MALLOCFAILED);
nameConstraints->nssNameConstraintsList = nssNCto;
nssNCfrom = firstNC->nssNameConstraintsList;
for (i = 0; i < firstNC->numNssNameConstraints; i++) {
PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
(nameConstraints->arena,
*nssNCfrom,
&nssNameConstraints,
plContext),
PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
*nssNCto = nssNameConstraints;
nssNCto++;
nssNCfrom++;
}
nssNCfrom = secondNC->nssNameConstraintsList;
for (i = 0; i < secondNC->numNssNameConstraints; i++) {
PKIX_CHECK(pkix_pl_CertNameConstraints_CopyNssNameConstraints
(nameConstraints->arena,
*nssNCfrom,
&nssNameConstraints,
plContext),
PKIX_CERTNAMECONSTRAINTSCOPYNSSNAMECONSTRAINTSFAILED);
*nssNCto = nssNameConstraints;
nssNCto++;
nssNCfrom++;
}
nameConstraints->numNssNameConstraints = numNssItems;
nameConstraints->permittedList = NULL;
nameConstraints->excludedList = NULL;
*pMergedNC = nameConstraints;
cleanup:
if (PKIX_ERROR_RECEIVED){
PKIX_DECREF(nameConstraints);
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}
/* --Public-NameConstraints-Functions-------------------------------- */
/*
* FUNCTION: PKIX_PL_CertNameConstraints_CheckNamesInNameSpace
* (see comments in pkix_pl_system.h)
*/
PKIX_Error *
PKIX_PL_CertNameConstraints_CheckNamesInNameSpace(
PKIX_List *nameList, /* List of PKIX_PL_GeneralName */
PKIX_PL_CertNameConstraints *nameConstraints,
PKIX_Boolean *pCheckPass,
void *plContext)
{
CERTNameConstraints **nssNameConstraintsList = NULL;
CERTNameConstraints *nssNameConstraints = NULL;
CERTGeneralName *nssMatchName = NULL;
PLArenaPool *arena = NULL;
PKIX_PL_GeneralName *name = NULL;
PKIX_UInt32 numNameItems = 0;
PKIX_UInt32 numNCItems = 0;
PKIX_UInt32 i, j;
SECStatus status = SECSuccess;
PKIX_ENTER(CERTNAMECONSTRAINTS,
"PKIX_PL_CertNameConstraints_CheckNamesInNameSpace");
PKIX_NULLCHECK_TWO(nameConstraints, pCheckPass);
*pCheckPass = PKIX_TRUE;
if (nameList != NULL) {
PKIX_CERTNAMECONSTRAINTS_DEBUG("\t\tCalling PORT_NewArena\n");
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
PKIX_ERROR(PKIX_OUTOFMEMORY);
}
nssNameConstraintsList =
nameConstraints->nssNameConstraintsList;
PKIX_NULLCHECK_ONE(nssNameConstraintsList);
numNCItems = nameConstraints->numNssNameConstraints;
PKIX_CHECK(PKIX_List_GetLength
(nameList, &numNameItems, plContext),
PKIX_LISTGETLENGTHFAILED);
for (i = 0; i < numNameItems; i++) {
PKIX_CHECK(PKIX_List_GetItem
(nameList,
i,
(PKIX_PL_Object **) &name,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_pl_GeneralName_GetNssGeneralName
(name, &nssMatchName, plContext),
PKIX_GENERALNAMEGETNSSGENERALNAMEFAILED);
PKIX_DECREF(name);
for (j = 0; j < numNCItems; j++) {
nssNameConstraints = *(nssNameConstraintsList + j);
PKIX_NULLCHECK_ONE(nssNameConstraints);
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling CERT_CheckNameSpace\n");
status = CERT_CheckNameSpace
(arena, nssNameConstraints, nssMatchName);
if (status != SECSuccess) {
break;
}
}
if (status != SECSuccess) {
break;
}
}
}
if (status == SECFailure) {
*pCheckPass = PKIX_FALSE;
}
cleanup:
if (arena){
PKIX_CERTNAMECONSTRAINTS_DEBUG
("\t\tCalling PORT_FreeArena).\n");
PORT_FreeArena(arena, PR_FALSE);
}
PKIX_RETURN(CERTNAMECONSTRAINTS);
}