diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix/util')
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/Makefile | 44 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/exports.gyp | 28 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/manifest.mn | 25 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_error.c | 565 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_error.h | 36 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_errpaths.c | 103 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_list.c | 1701 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_list.h | 95 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_logger.c | 1088 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_logger.h | 57 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_tools.c | 1525 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/pkix_tools.h | 1588 | ||||
-rw-r--r-- | security/nss/lib/libpkix/pkix/util/util.gyp | 27 |
13 files changed, 6882 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/util/Makefile b/security/nss/lib/libpkix/pkix/util/Makefile new file mode 100644 index 0000000000..2b5492506c --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/Makefile @@ -0,0 +1,44 @@ +#! gmake +# +# 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/. + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### + + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### diff --git a/security/nss/lib/libpkix/pkix/util/exports.gyp b/security/nss/lib/libpkix/pkix/util/exports.gyp new file mode 100644 index 0000000000..8318c6c347 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/exports.gyp @@ -0,0 +1,28 @@ +# 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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'lib_libpkix_pkix_util_exports', + 'type': 'none', + 'copies': [ + { + 'files': [ + 'pkix_error.h', + 'pkix_list.h', + 'pkix_logger.h', + 'pkix_tools.h' + ], + 'destination': '<(nss_private_dist_dir)/<(module)' + } + ] + } + ], + 'variables': { + 'module': 'nss' + } +} diff --git a/security/nss/lib/libpkix/pkix/util/manifest.mn b/security/nss/lib/libpkix/pkix/util/manifest.mn new file mode 100644 index 0000000000..e7d9f973c7 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/manifest.mn @@ -0,0 +1,25 @@ +# +# 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/. +CORE_DEPTH = ../../../.. + +PRIVATE_EXPORTS = \ + pkix_tools.h \ + pkix_error.h \ + pkix_logger.h \ + pkix_list.h \ + $(NULL) + +MODULE = nss + +CSRCS = \ + pkix_tools.c \ + pkix_error.c \ + pkix_logger.c \ + pkix_list.c \ + pkix_errpaths.c \ + $(NULL) + +LIBRARY_NAME = pkixutil +SHARED_LIBRARY = $(NULL) diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.c b/security/nss/lib/libpkix/pkix/util/pkix_error.c new file mode 100644 index 0000000000..9d730ca161 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_error.c @@ -0,0 +1,565 @@ +/* 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_error.c + * + * Error Object Functions + * + */ + +#include "pkix_error.h" + +#undef PKIX_ERRORENTRY + +#define PKIX_ERRORENTRY(name,desc,nsserr) #desc + +#if defined PKIX_ERROR_DESCRIPTION + +const char * const PKIX_ErrorText[] = +{ +#include "pkix_errorstrings.h" +}; + +#else + +#include "prprf.h" + +#endif /* PKIX_ERROR_DESCRIPTION */ + +extern const PKIX_Int32 PKIX_PLErrorIndex[]; + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_Error_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Equals( + PKIX_PL_Object *firstObject, + PKIX_PL_Object *secondObject, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_Error *firstError = NULL; + PKIX_Error *secondError = NULL; + PKIX_Error *firstCause = NULL; + PKIX_Error *secondCause = NULL; + PKIX_PL_Object *firstInfo = NULL; + PKIX_PL_Object *secondInfo = NULL; + PKIX_ERRORCLASS firstClass, secondClass; + PKIX_UInt32 secondType; + PKIX_Boolean boolResult, unequalFlag; + + PKIX_ENTER(ERROR, "pkix_Error_Equals"); + PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); + + unequalFlag = PKIX_FALSE; + + /* First just compare pointer values to save time */ + if (firstObject == secondObject) { + *pResult = PKIX_TRUE; + goto cleanup; + } else { + /* Result will only be set to true if all tests pass */ + *pResult = PKIX_FALSE; + } + + PKIX_CHECK(pkix_CheckType(firstObject, PKIX_ERROR_TYPE, plContext), + PKIX_FIRSTOBJECTNOTANERROROBJECT); + + PKIX_CHECK(PKIX_PL_Object_GetType + (secondObject, &secondType, plContext), + PKIX_ERRORGETTINGSECONDOBJECTTYPE); + + /* If types differ, then return false. Result is already set */ + if (secondType != PKIX_ERROR_TYPE) goto cleanup; + + /* It is safe to cast to PKIX_Error */ + firstError = (PKIX_Error *) firstObject; + secondError = (PKIX_Error *) secondObject; + + /* Compare error codes */ + firstClass = firstError->errClass; + secondClass = secondError->errClass; + + /* If codes differ, return false. Result is already set */ + if (firstClass != secondClass) goto cleanup; + + /* Compare causes */ + firstCause = firstError->cause; + secondCause = secondError->cause; + + /* Ensure that either both or none of the causes are NULL */ + if (((firstCause != NULL) && (secondCause == NULL))|| + ((firstCause == NULL) && (secondCause != NULL))) + unequalFlag = PKIX_TRUE; + + if ((firstCause != NULL) && (secondCause != NULL)) { + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object*)firstCause, + (PKIX_PL_Object*)secondCause, + &boolResult, + plContext), + PKIX_ERRORINRECURSIVEEQUALSCALL); + + /* Set the unequalFlag so that we return after dec refing */ + if (boolResult == 0) unequalFlag = PKIX_TRUE; + } + + /* If the cause errors are not equal, return null */ + if (unequalFlag) goto cleanup; + + /* Compare info fields */ + firstInfo = firstError->info; + secondInfo = secondError->info; + + if (firstInfo != secondInfo) goto cleanup; + + /* Ensure that either both or none of the infos are NULL */ + if (((firstInfo != NULL) && (secondInfo == NULL))|| + ((firstInfo == NULL) && (secondInfo != NULL))) + unequalFlag = PKIX_TRUE; + + if ((firstInfo != NULL) && (secondInfo != NULL)) { + + PKIX_CHECK(PKIX_PL_Object_Equals + ((PKIX_PL_Object*)firstInfo, + (PKIX_PL_Object*)secondInfo, + &boolResult, + plContext), + PKIX_ERRORINRECURSIVEEQUALSCALL); + + /* Set the unequalFlag so that we return after dec refing */ + if (boolResult == 0) unequalFlag = PKIX_TRUE; + } + + /* If the infos are not equal, return null */ + if (unequalFlag) goto cleanup; + + + /* Compare descs */ + if (firstError->errCode != secondError->errCode) { + unequalFlag = PKIX_TRUE; + } + + if (firstError->plErr != secondError->plErr) { + unequalFlag = PKIX_TRUE; + } + + /* If the unequalFlag was set, return false */ + if (unequalFlag) goto cleanup; + + /* Errors are equal in all fields at this point */ + *pResult = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: pkix_Error_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "pkix_Error_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), + PKIX_OBJECTNOTANERROR); + + error = (PKIX_Error *)object; + + PKIX_DECREF(error->cause); + + PKIX_DECREF(error->info); + +cleanup: + + PKIX_RETURN(ERROR); +} + + +/* XXX This is not thread safe */ +static PKIX_UInt32 pkix_error_cause_depth = 1; + +/* + * FUNCTION: pkix_Error_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_Error *error = NULL; + PKIX_Error *cause = NULL; + PKIX_PL_String *desc = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *causeString = NULL; + PKIX_PL_String *optCauseString = NULL; + PKIX_PL_String *errorNameString = NULL; + char *format = NULL; + PKIX_ERRORCLASS errClass; + + PKIX_ENTER(ERROR, "pkix_Error_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_ERROR_TYPE, plContext), + PKIX_OBJECTNOTANERROR); + + error = (PKIX_Error *)object; + + /* Get this error's errClass, description and the string of its cause */ + errClass = error->errClass; + + /* Get the description string */ + PKIX_Error_GetDescription(error, &desc, plContext); + + /* Get the cause */ + cause = error->cause; + + /* Get the causes's description string */ + if (cause != NULL) { + pkix_error_cause_depth++; + + /* Get the cause string */ + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)cause, &causeString, plContext), + PKIX_ERRORGETTINGCAUSESTRING); + + format = "\n*** Cause (%d): %s"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + format, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Create the optional Cause String */ + PKIX_CHECK(PKIX_PL_Sprintf + (&optCauseString, + plContext, + formatString, + pkix_error_cause_depth, + causeString), + PKIX_SPRINTFFAILED); + + PKIX_DECREF(formatString); + + pkix_error_cause_depth--; + } + + /* Create the Format String */ + if (optCauseString != NULL) { + format = "*** %s Error- %s%s"; + } else { + format = "*** %s Error- %s"; + } + + /* Ensure that error errClass is known, otherwise default to Object */ + if (errClass >= PKIX_NUMERRORCLASSES) { + errClass = 0; + } + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)PKIX_ERRORCLASSNAMES[errClass], + 0, + &errorNameString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + format, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + /* Create the output String */ + PKIX_CHECK(PKIX_PL_Sprintf + (pString, + plContext, + formatString, + errorNameString, + desc, + optCauseString), + PKIX_SPRINTFFAILED); + +cleanup: + + PKIX_DECREF(desc); + PKIX_DECREF(causeString); + PKIX_DECREF(formatString); + PKIX_DECREF(optCauseString); + PKIX_DECREF(errorNameString); + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: pkix_Error_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Error_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pResult, + void *plContext) +{ + PKIX_ENTER(ERROR, "pkix_Error_Hashcode"); + PKIX_NULLCHECK_TWO(object, pResult); + + /* XXX Unimplemented */ + /* XXX Need to make hashcodes equal when two errors are equal */ + *pResult = (PKIX_UInt32)((char *)object - (char *)NULL); + + PKIX_RETURN(ERROR); +} + +/* --Initializers------------------------------------------------- */ + +/* + * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a + * descriptive name for an error errClass. This is used by the default + * PKIX_PL_Error_ToString function. + * + * Note: PKIX_ERRORCLASSES is defined in pkixt.h as a list of error types. + * (More precisely, as a list of invocations of ERRMACRO(type).) The + * macro is expanded in pkixt.h to define error numbers, and here to + * provide corresponding strings. For example, since the fifth ERRMACRO + * entry is MUTEX, then PKIX_MUTEX_ERROR is defined in pkixt.h as 4, and + * PKIX_ERRORCLASSNAMES[4] is initialized here with the value "MUTEX". + */ +#undef ERRMACRO +#define ERRMACRO(type) #type + +const char * +PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES] = +{ + PKIX_ERRORCLASSES +}; + +/* + * FUNCTION: pkix_Error_RegisterSelf + * DESCRIPTION: + * Registers PKIX_ERROR_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_Error_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(ERROR, "pkix_Error_RegisterSelf"); + + entry.description = "Error"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_Error); + entry.destructor = pkix_Error_Destroy; + entry.equalsFunction = pkix_Error_Equals; + entry.hashcodeFunction = pkix_Error_Hashcode; + entry.toStringFunction = pkix_Error_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_duplicateImmutable; + + systemClasses[PKIX_ERROR_TYPE] = entry; + + PKIX_RETURN(ERROR); +} + +/* --Public-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_Error_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_Create( + PKIX_ERRORCLASS errClass, + PKIX_Error *cause, + PKIX_PL_Object *info, + PKIX_ERRORCODE errCode, + PKIX_Error **pError, + void *plContext) +{ + PKIX_Error *tempCause = NULL; + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "PKIX_Error_Create"); + + PKIX_NULLCHECK_ONE(pError); + + /* + * when called here, if PKIX_PL_Object_Alloc returns an error, + * it must be a PKIX_ALLOC_ERROR + */ + pkixErrorResult = PKIX_PL_Object_Alloc + (PKIX_ERROR_TYPE, + ((PKIX_UInt32)(sizeof (PKIX_Error))), + (PKIX_PL_Object **)&error, + plContext); + + if (pkixErrorResult) return (pkixErrorResult); + + error->errClass = errClass; + + /* Ensure we don't have a loop. Follow causes until NULL */ + for (tempCause = cause; + tempCause != NULL; + tempCause = tempCause->cause) { + /* If we detect a loop, throw a new error */ + if (tempCause == error) { + PKIX_ERROR(PKIX_LOOPOFERRORCAUSEDETECTED); + } + } + + PKIX_INCREF(cause); + error->cause = cause; + + PKIX_INCREF(info); + error->info = info; + + error->errCode = errCode; + + error->plErr = PKIX_PLErrorIndex[error->errCode]; + + *pError = error; + error = NULL; + +cleanup: + /* PKIX-XXX Fix for leak during error creation */ + PKIX_DECREF(error); + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetErrorClass (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetErrorClass( + PKIX_Error *error, + PKIX_ERRORCLASS *pClass, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorClass"); + PKIX_NULLCHECK_TWO(error, pClass); + + *pClass = error->errClass; + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetErrorCode (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetErrorCode( + PKIX_Error *error, + PKIX_ERRORCODE *pCode, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetErrorCode"); + PKIX_NULLCHECK_TWO(error, pCode); + + *pCode = error->errCode; + + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetCause (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetCause( + PKIX_Error *error, + PKIX_Error **pCause, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetCause"); + PKIX_NULLCHECK_TWO(error, pCause); + + if (error->cause != PKIX_ALLOC_ERROR()){ + PKIX_INCREF(error->cause); + } + + *pCause = error->cause; + +cleanup: + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetSupplementaryInfo (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetSupplementaryInfo( + PKIX_Error *error, + PKIX_PL_Object **pInfo, + void *plContext) +{ + PKIX_ENTER(ERROR, "PKIX_Error_GetSupplementaryInfo"); + PKIX_NULLCHECK_TWO(error, pInfo); + + PKIX_INCREF(error->info); + + *pInfo = error->info; + +cleanup: + PKIX_RETURN(ERROR); +} + +/* + * FUNCTION: PKIX_Error_GetDescription (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Error_GetDescription( + PKIX_Error *error, + PKIX_PL_String **pDesc, + void *plContext) +{ + PKIX_PL_String *descString = NULL; +#ifndef PKIX_ERROR_DESCRIPTION + char errorStr[32]; +#endif + + PKIX_ENTER(ERROR, "PKIX_Error_GetDescription"); + PKIX_NULLCHECK_TWO(error, pDesc); + +#ifndef PKIX_ERROR_DESCRIPTION + PR_snprintf(errorStr, 32, "Error code: %d", error->errCode); +#endif + + PKIX_PL_String_Create(PKIX_ESCASCII, +#if defined PKIX_ERROR_DESCRIPTION + (void *)PKIX_ErrorText[error->errCode], +#else + errorStr, +#endif + 0, + &descString, + plContext); + + *pDesc = descString; + + PKIX_RETURN(ERROR); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_error.h b/security/nss/lib/libpkix/pkix/util/pkix_error.h new file mode 100644 index 0000000000..ca4171ab17 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_error.h @@ -0,0 +1,36 @@ +/* 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_error.h + * + * Error Object Type Definition + * + */ + +#ifndef _PKIX_ERROR_H +#define _PKIX_ERROR_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct PKIX_ErrorStruct { + PKIX_ERRORCODE errCode; + PKIX_ERRORCLASS errClass; /* was formerly "code" */ + PKIX_Int32 plErr; + PKIX_Error *cause; + PKIX_PL_Object *info; +}; + +/* see source file for function documentation */ + +extern PKIX_Error * pkix_Error_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_ERROR_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c new file mode 100644 index 0000000000..a33ccf7ddb --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_errpaths.c @@ -0,0 +1,103 @@ +/* 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_errpaths.c + * + * Error Handling Helper Functions + * + */ + +#define PKIX_STDVARS_POINTER +#include "pkix_error.h" + +const PKIX_StdVars zeroStdVars; + +PKIX_Error* +PKIX_DoThrow(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass, + PKIX_ERRORCODE errCode, PKIX_ERRORCLASS overrideClass, + void *plContext) +{ + if (!pkixErrorReceived && !pkixErrorResult && pkixErrorList) { + pkixTempResult = PKIX_List_GetItem(pkixErrorList, 0, + (PKIX_PL_Object**)&pkixReturnResult, + plContext); + } else { + pkixTempResult = (PKIX_Error*)pkix_Throw(errClass, myFuncName, errCode, + overrideClass, pkixErrorResult, + &pkixReturnResult, plContext); + } + if (pkixReturnResult) { + if (pkixErrorResult != PKIX_ALLOC_ERROR()) { + PKIX_DECREF(pkixErrorResult); + } + pkixTempResult = pkixReturnResult; + } else if (pkixErrorResult) { + if (pkixTempResult != PKIX_ALLOC_ERROR()) { + PKIX_DECREF(pkixTempResult); + } + pkixTempResult = pkixErrorResult; + } + if (pkixErrorList) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorList, plContext); + pkixErrorList = NULL; + } + return pkixTempResult; +} + +PKIX_Error * +PKIX_DoReturn(PKIX_StdVars * stdVars, PKIX_ERRORCLASS errClass, + PKIX_Boolean doLogger, void *plContext) +{ + PKIX_OBJECT_UNLOCK(lockedObject); + if (pkixErrorReceived || pkixErrorResult || pkixErrorList) + return PKIX_DoThrow(stdVars, errClass, pkixErrorCode, pkixErrorClass, + plContext); + /* PKIX_DEBUG_EXIT(type); */ + if (doLogger) + _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, "<<<", PKIX_LOGGER_LEVEL_TRACE); + return NULL; +} + +/* PKIX_DoAddError - creates the list of received error if it does not exist + * yet and adds newly received error into the list. */ +void +PKIX_DoAddError(PKIX_StdVars *stdVars, PKIX_Error *error, void * plContext) +{ + PKIX_List *localList = NULL; + PKIX_Error *localError = NULL; + PKIX_Boolean listCreated = PKIX_FALSE; + + if (!pkixErrorList) { + localError = PKIX_List_Create(&localList, plContext); + if (localError) + goto cleanup; + listCreated = PKIX_TRUE; + } else { + localList = pkixErrorList; + } + + localError = PKIX_List_AppendItem(localList, (PKIX_PL_Object*)error, + plContext); + PORT_Assert (localError == NULL); + if (localError != NULL) { + if (listCreated) { + /* ignore the error code of DecRef function */ + PKIX_PL_Object_DecRef((PKIX_PL_Object*)localList, plContext); + localList = NULL; + } + } else { + pkixErrorList = localList; + } + +cleanup: + + if (localError && localError != PKIX_ALLOC_ERROR()) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)localError, plContext); + } + + if (error && error != PKIX_ALLOC_ERROR()) { + PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext); + } +} + diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.c b/security/nss/lib/libpkix/pkix/util/pkix_list.c new file mode 100644 index 0000000000..d02b66e6d6 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_list.c @@ -0,0 +1,1701 @@ +/* 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_list.c + * + * List Object Functions + * + */ + +#include "pkix_list.h" + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_List_Create_Internal + * DESCRIPTION: + * + * Creates a new List, using the Boolean value of "isHeader" to determine + * whether the new List should be a header, and stores it at "pList". The + * List is initially empty and holds no items. To initially add items to + * the List, use PKIX_List_AppendItem. + * + * PARAMETERS: + * "isHeader" + * Boolean value indicating whether new List should be a header. + * "pList" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_List_Create_Internal( + PKIX_Boolean isHeader, + PKIX_List **pList, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(LIST, "pkix_List_Create_Internal"); + PKIX_NULLCHECK_ONE(pList); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LIST_TYPE, + ((PKIX_UInt32)(sizeof (PKIX_List))), + (PKIX_PL_Object **)&list, plContext), + PKIX_ERRORCREATINGLISTITEM); + + list->item = NULL; + list->next = NULL; + list->immutable = PKIX_FALSE; + list->length = 0; + list->isHeader = isHeader; + + *pList = list; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *nextItem = NULL; + + PKIX_ENTER(LIST, "pkix_List_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a list */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + /* We have a valid list. DecRef its item and recurse on next */ + PKIX_DECREF(list->item); + while ((nextItem = list->next) != NULL) { + list->next = nextItem->next; + nextItem->next = NULL; + PKIX_DECREF(nextItem); + } + list->immutable = PKIX_FALSE; + list->length = 0; + list->isHeader = PKIX_FALSE; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_ToString_Helper + * DESCRIPTION: + * + * Helper function that creates a string representation of the List pointed + * to by "list" and stores its address in the object pointed to by "pString". + * + * PARAMETERS + * "list" + * Address of List whose string representation is desired. + * Must be non-NULL. + * "pString" + * Address of object pointer's destination. 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 List 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_List_ToString_Helper( + PKIX_List *list, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_PL_String *itemString = NULL; + PKIX_PL_String *nextString = NULL; + PKIX_PL_String *format = NULL; + PKIX_Boolean empty; + + PKIX_ENTER(LIST, "pkix_List_ToString_Helper"); + PKIX_NULLCHECK_TWO(list, pString); + + /* special case when list is the header */ + if (list->isHeader){ + + PKIX_CHECK(PKIX_List_IsEmpty(list, &empty, plContext), + PKIX_LISTISEMPTYFAILED); + + if (empty){ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "EMPTY", + 0, + &itemString, + plContext), + PKIX_ERRORCREATINGITEMSTRING); + (*pString) = itemString; + PKIX_DEBUG_EXIT(LIST); + return (NULL); + } else { + PKIX_CHECK(pkix_List_ToString_Helper + (list->next, &itemString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + } + + /* Create a string object from the format */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "%s", 0, &format, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (pString, plContext, format, itemString), + PKIX_SPRINTFFAILED); + } else { + /* Get a string for this list's item */ + if (list->item == NULL) { + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "(null)", + 0, + &itemString, + plContext), + PKIX_STRINGCREATEFAILED); + } else { + PKIX_CHECK(PKIX_PL_Object_ToString + ((PKIX_PL_Object*)list->item, + &itemString, + plContext), + PKIX_OBJECTTOSTRINGFAILED); + } + if (list->next == NULL) { + /* Just return the itemstring */ + (*pString) = itemString; + PKIX_DEBUG_EXIT(LIST); + return (NULL); + } + + /* Recursive call to get string for this list's next pointer */ + PKIX_CHECK(pkix_List_ToString_Helper + (list->next, &nextString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + + /* Create a string object from the format */ + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + "%s, %s", + 0, + &format, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (pString, + plContext, + format, + itemString, + nextString), + PKIX_SPRINTFFAILED); + } + +cleanup: + + PKIX_DECREF(itemString); + PKIX_DECREF(nextString); + PKIX_DECREF(format); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_String *listString = NULL; + PKIX_PL_String *format = NULL; + + PKIX_ENTER(LIST, "pkix_List_ToString"); + PKIX_NULLCHECK_TWO(object, pString); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_ToString_Helper(list, &listString, plContext), + PKIX_LISTTOSTRINGHELPERFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, "(%s)", 0, &format, plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf(pString, plContext, format, listString), + PKIX_SPRINTFFAILED); + +cleanup: + + PKIX_DECREF(listString); + PKIX_DECREF(format); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_List *firstList = NULL; + PKIX_List *secondList = NULL; + PKIX_UInt32 firstLength = 0; + PKIX_UInt32 secondLength = 0; + PKIX_PL_Object *firstItem = NULL; + PKIX_PL_Object *secondItem = NULL; + PKIX_UInt32 i = 0; + + PKIX_ENTER(LIST, "pkix_List_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + /* test that first is a List */ + PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext), + PKIX_FIRSTOBJECTNOTLIST); + + /* + * Since we know first is a List, if both references are + * identical, they must be equal + */ + if (first == second){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If second isn't a List, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LIST_TYPE) goto cleanup; + + firstList = (PKIX_List *)first; + secondList = (PKIX_List *)second; + + if ((!firstList->isHeader) && (!secondList->isHeader)){ + PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS); + } + + firstLength = firstList->length; + secondLength = secondList->length; + + cmpResult = PKIX_FALSE; + if (firstLength == secondLength){ + for (i = 0, cmpResult = PKIX_TRUE; + ((i < firstLength) && cmpResult); + i++){ + PKIX_CHECK(PKIX_List_GetItem + (firstList, i, &firstItem, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_GetItem + (secondList, i, &secondItem, plContext), + PKIX_LISTGETITEMFAILED); + + if ((!firstItem && secondItem) || + (firstItem && !secondItem)){ + cmpResult = PKIX_FALSE; + } else if (!firstItem && !secondItem){ + continue; + } else { + PKIX_CHECK(PKIX_PL_Object_Equals + (firstItem, + secondItem, + &cmpResult, + plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(firstItem); + PKIX_DECREF(secondItem); + } + } + } + + *pResult = cmpResult; + +cleanup: + + PKIX_DECREF(firstItem); + PKIX_DECREF(secondItem); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_Object *element = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 tempHash = 0; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "pkix_List_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + for (i = 0; i < length; i++){ + PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext), + PKIX_LISTGETITEMFAILED); + + if (!element){ + tempHash = 100; + } else { + PKIX_CHECK(PKIX_PL_Object_Hashcode + (element, &tempHash, plContext), + PKIX_LISTHASHCODEFAILED); + } + + hash = 31 * hash + tempHash; + + PKIX_DECREF(element); + } + + *pHashcode = hash; + +cleanup: + + PKIX_DECREF(element); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_List_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *listDuplicate = NULL; + + PKIX_ENTER(LIST, "pkix_List_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), + PKIX_OBJECTNOTLIST); + + list = (PKIX_List *)object; + + if (list->immutable){ + PKIX_CHECK(pkix_duplicateImmutable + (object, pNewObject, plContext), + PKIX_DUPLICATEIMMUTABLEFAILED); + } else { + + PKIX_CHECK(pkix_List_Create_Internal + (list->isHeader, &listDuplicate, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + listDuplicate->length = list->length; + + PKIX_INCREF(list->item); + listDuplicate->item = list->item; + + if (list->next == NULL){ + listDuplicate->next = NULL; + } else { + /* Recursively Duplicate list */ + PKIX_CHECK(pkix_List_Duplicate + ((PKIX_PL_Object *)list->next, + (PKIX_PL_Object **)&listDuplicate->next, + plContext), + PKIX_LISTDUPLICATEFAILED); + } + + *pNewObject = (PKIX_PL_Object *)listDuplicate; + } + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(listDuplicate); + } + + PKIX_RETURN(LIST); +} + + +/* + * FUNCTION: pkix_List_GetElement + * DESCRIPTION: + * + * Copies the "list"'s element at "index" into "element". The input List must + * be the header of the List (as opposed to being an element of the List). The + * index counts from zero and must be less than the List's length. This + * function does NOT increment the reference count of the List element since + * the returned element's reference will not be stored by the calling + * function. + * + * PARAMETERS: + * "list" + * Address of List (must be header) to get element from. Must be non-NULL. + * "index" + * Index of list to get element from. Must be less than List's length. + * "pElement" + * Address where object pointer will be 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 Fatal Error if the function fails in an unrecoverable way. + */ +static PKIX_Error * +pkix_List_GetElement( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_List **pElement, + void *plContext) +{ + PKIX_List *iterator = NULL; + PKIX_UInt32 length; + PKIX_UInt32 position = 0; + + PKIX_ENTER(LIST, "pkix_List_GetElement"); + PKIX_NULLCHECK_TWO(list, pElement); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + if (index >= length) { + PKIX_ERROR(PKIX_INDEXOUTOFBOUNDS); + } + + for (iterator = list; position++ <= index; iterator = iterator->next) + ; + + (*pElement) = iterator; + +cleanup: + + PKIX_RETURN(LIST); +} + + +/* + * FUNCTION: pkix_List_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LIST_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_List_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LIST, "pkix_List_RegisterSelf"); + + entry.description = "List"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_List); + entry.destructor = pkix_List_Destroy; + entry.equalsFunction = pkix_List_Equals; + entry.hashcodeFunction = pkix_List_Hashcode; + entry.toStringFunction = pkix_List_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_List_Duplicate; + + systemClasses[PKIX_LIST_TYPE] = entry; + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Contains + * DESCRIPTION: + * + * Checks a List pointed to by "list", to determine whether it includes + * an entry that is equal to the Object pointed to by "object", and stores + * the result in "pFound". + * + * PARAMETERS: + * "list" + * List to be searched; may be empty; must be non-NULL + * "object" + * Object to be checked for; must be non-NULL + * "pFound" + * Address where the result of the search 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 Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_Contains( + PKIX_List *list, + PKIX_PL_Object *object, + PKIX_Boolean *pFound, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(LIST, "pkix_List_Contains"); + PKIX_NULLCHECK_THREE(list, object, pFound); + + PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (list, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(PKIX_PL_Object_Equals + (object, current, &match, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + + if (match) { + break; + } + } + + *pFound = match; + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_Remove + * DESCRIPTION: + * + * Traverses the List pointed to by "list", to find and delete an entry + * that is equal to the Object pointed to by "object". If no such entry + * is found the function does not return an error. + * + * PARAMETERS: + * "list" + * List to be searched; may be empty; must be non-NULL + * "object" + * Object to be checked for and deleted, if found; 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 Validate Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_Remove( + PKIX_List *list, + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + PKIX_Boolean match = PKIX_FALSE; + + PKIX_ENTER(LIST, "pkix_List_Remove"); + PKIX_NULLCHECK_TWO(list, object); + + PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (list, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(PKIX_PL_Object_Equals + (object, current, &match, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + + if (match) { + PKIX_CHECK(PKIX_List_DeleteItem + (list, index, plContext), + PKIX_LISTDELETEITEMFAILED); + break; + } + } + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_RemoveItems + * DESCRIPTION: + * + * Traverses the List pointed to by "list", to find and delete an entry + * that is equal to the Object in the "deleteList". If no such entry + * is found the function does not return an error. + * + * PARAMETERS: + * "list" + * Object in "list" is checked for object in "deleteList" and deleted if + * found; may be empty; must be non-NULL + * "deleteList" + * List of objects to be searched ; may be empty; 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 Validate Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_RemoveItems( + PKIX_List *list, + PKIX_List *deleteList, + void *plContext) +{ + PKIX_PL_Object *current = NULL; + PKIX_UInt32 numEntries = 0; + PKIX_UInt32 index = 0; + + PKIX_ENTER(LIST, "pkix_List_RemoveItems"); + PKIX_NULLCHECK_TWO(list, deleteList); + + PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (index = 0; index < numEntries; index++) { + PKIX_CHECK(PKIX_List_GetItem + (deleteList, index, ¤t, plContext), + PKIX_LISTGETITEMFAILED); + + if (current) { + PKIX_CHECK(pkix_List_Remove + (list, current, plContext), + PKIX_OBJECTEQUALSFAILED); + + PKIX_DECREF(current); + } + } + +cleanup: + + PKIX_DECREF(current); + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_MergeLists + * DESCRIPTION: + * + * Creates a new list consisting of the items from "firstList", followed by + * the items on "secondList", returns the new list at "pMergedList". If + * both input lists are NULL or empty, the result is an empty list. If an error + * occurs, the result is NULL. + * + * PARAMETERS: + * "firstList" + * Address of list to be merged from. May be NULL or empty. + * "secondList" + * Address of list to be merged from. May be NULL or empty. + * "pMergedList" + * Address where returned object is stored. + * "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 List Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_MergeLists( + PKIX_List *firstList, + PKIX_List *secondList, + PKIX_List **pMergedList, + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_PL_Object *item = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(LIST, "pkix_List_MergeLists"); + PKIX_NULLCHECK_ONE(pMergedList); + + *pMergedList = NULL; + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + if (firstList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + + numItems = 0; + if (secondList != NULL) { + + PKIX_CHECK(PKIX_List_GetLength + (secondList, + &numItems, + plContext), + PKIX_LISTGETLENGTHFAILED); + + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (secondList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, item, plContext), PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + + *pMergedList = list; + list = NULL; + +cleanup: + PKIX_DECREF(list); + PKIX_DECREF(item); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_AppendList + * DESCRIPTION: + * + * Append items on "fromList" to the "toList". Item reference count on + * "toList" is not incremented, but items appended from "fromList" are + * incremented. + * + * PARAMETERS: + * "toList" + * Address of list to be appended to. Must be non-NULL. + * "fromList" + * Address of list to be appended from. May be NULL or empty. + * "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 List Error if the functions fails in a non-fatal way + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_AppendList( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext) +{ + PKIX_PL_Object *item = NULL; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(LIST, "pkix_List_AppendList"); + PKIX_NULLCHECK_ONE(toList); + + /* if fromList is NULL or is an empty list, no action */ + + if (fromList == NULL) { + goto cleanup; + } + + PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (numItems == 0) { + goto cleanup; + } + + for (i = 0; i < numItems; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, i, &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + } + +cleanup: + + PKIX_DECREF(item); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_AppendUnique + * DESCRIPTION: + * + * Adds each Object in the List pointed to by "fromList" to the List pointed + * to by "toList", if it is not already a member of that List. In other words, + * "toList" becomes the union of the two sets. + * + * PARAMETERS: + * "toList" + * Address of a List of Objects to be augmented by "fromList". Must be + * non-NULL, but may be empty. + * "fromList" + * Address of a List of Objects to be added, if not already present, to + * "toList". Must be non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_AppendUnique( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext) +{ + PKIX_Boolean isContained = PKIX_FALSE; + PKIX_UInt32 listLen = 0; + PKIX_UInt32 listIx = 0; + PKIX_PL_Object *object = NULL; + + PKIX_ENTER(BUILD, "pkix_List_AppendUnique"); + PKIX_NULLCHECK_TWO(fromList, toList); + + PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (listIx = 0; listIx < listLen; listIx++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, listIx, &object, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_List_Contains + (toList, object, &isContained, plContext), + PKIX_LISTCONTAINSFAILED); + + if (isContained == PKIX_FALSE) { + PKIX_CHECK(PKIX_List_AppendItem + (toList, object, plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(object); + } + +cleanup: + + PKIX_DECREF(object); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_QuickSort + * DESCRIPTION: + * + * Sorts List of Objects "fromList" using "comparatorCallback"'s result as + * comasrison key and returns the sorted List at "pSortedList". The sorting + * algorithm used is quick sort (n*logn). + * + * PARAMETERS: + * "fromList" + * Address of a List of Objects to be sorted. Must be non-NULL, but may be + * empty. + * "comparatorCallback" + * Address of callback function that will compare two Objects on the List. + * It should return -1 for less, 0 for equal and 1 for greater. The + * callback implementation chooses what in Objects to be compared. Must be + * non-NULL. + * "pSortedList" + * Address of a List of Objects that shall be sorted and returned. Must be + * non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_QuickSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext) +{ + PKIX_List *sortedList = NULL; + PKIX_List *lessList = NULL; + PKIX_List *greaterList = NULL; + PKIX_List *sortedLessList = NULL; + PKIX_List *sortedGreaterList = NULL; + PKIX_PL_Object *object = NULL; + PKIX_PL_Object *cmpObj = NULL; + PKIX_Int32 cmpResult = 0; + PKIX_UInt32 size = 0; + PKIX_UInt32 i; + + PKIX_ENTER(BUILD, "pkix_List_QuickSort"); + PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); + + PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + PKIX_CHECK(PKIX_List_Create(&lessList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_Create(&greaterList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetItem + (fromList, 0, &object, plContext), + PKIX_LISTGETITEMFAILED); + + /* + * Pick the first item on the list as the one to be compared. + * Separate rest of the itmes into two lists: less-than or greater- + * than lists. Sort those two lists recursively. Insert sorted + * less-than list before the picked item and append the greater- + * than list after the picked item. + */ + for (i = 1; i < size; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (fromList, i, &cmpObj, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext), + PKIX_COMPARATORCALLBACKFAILED); + + if (cmpResult >= 0) { + PKIX_CHECK(PKIX_List_AppendItem + (lessList, cmpObj, plContext), + PKIX_LISTAPPENDITEMFAILED); + } else { + PKIX_CHECK(PKIX_List_AppendItem + (greaterList, cmpObj, plContext), + PKIX_LISTAPPENDITEMFAILED); + } + PKIX_DECREF(cmpObj); + } + + PKIX_CHECK(PKIX_List_Create(&sortedList, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + PKIX_CHECK(pkix_List_QuickSort + (lessList, comparator, &sortedLessList, plContext), + PKIX_LISTQUICKSORTFAILED); + + PKIX_CHECK(pkix_List_AppendList + (sortedList, sortedLessList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } else { + PKIX_CHECK(pkix_List_AppendList + (sortedList, lessList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext), + PKIX_LISTAPPENDFAILED); + + PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + PKIX_CHECK(pkix_List_QuickSort + (greaterList, comparator, &sortedGreaterList, plContext), + PKIX_LISTQUICKSORTFAILED); + + PKIX_CHECK(pkix_List_AppendList + (sortedList, sortedGreaterList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } else { + PKIX_CHECK(pkix_List_AppendList + (sortedList, greaterList, plContext), + PKIX_LISTAPPENDLISTFAILED); + } + + *pSortedList = sortedList; + +cleanup: + + PKIX_DECREF(cmpObj); + PKIX_DECREF(object); + PKIX_DECREF(sortedGreaterList); + PKIX_DECREF(sortedLessList); + PKIX_DECREF(greaterList); + PKIX_DECREF(lessList); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: pkix_List_BubbleSort + * DESCRIPTION: + * + * Sorts List of Objects "fromList" using "comparatorCallback"'s result as + * comasrison key and returns the sorted List at "pSortedList". The sorting + * algorithm used is bubble sort (n*n). + * + * PARAMETERS: + * "fromList" + * Address of a List of Objects to be sorted. Must be non-NULL, but may be + * empty. + * "comparatorCallback" + * Address of callback function that will compare two Objects on the List. + * It should return -1 for less, 0 for equal and 1 for greater. The + * callback implementation chooses what in Objects to be compared. Must be + * non-NULL. + * "pSortedList" + * Address of a List of Objects that shall be sorted and returned. Must be + * non-NULL, but may be empty. + * "plContext" + * Platform-specific context pointer. + * THREAD SAFETY: + * Not Thread Safe - assumes exclusive access to "toList" + * (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns NULL if the function succeeds + * Returns a Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_List_BubbleSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext) +{ + PKIX_List *sortedList = NULL; + PKIX_PL_Object *cmpObj = NULL; + PKIX_PL_Object *leastObj = NULL; + PKIX_Int32 cmpResult = 0; + PKIX_UInt32 size = 0; + PKIX_UInt32 i, j; + + PKIX_ENTER(BUILD, "pkix_List_BubbleSort"); + PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); + + if (fromList->immutable) { + PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST); + } + PKIX_CHECK(pkix_List_Duplicate + ((PKIX_PL_Object *) fromList, + (PKIX_PL_Object **) &sortedList, + plContext), + PKIX_LISTDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext), + PKIX_LISTGETLENGTHFAILED); + + if (size > 1) { + + /* + * Move from the first of the item on the list, For each iteration, + * compare and swap the least value to the head of the comparisoning + * sub-list. + */ + for (i = 0; i < size - 1; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (sortedList, i, &leastObj, plContext), + PKIX_LISTGETITEMFAILED); + + for (j = i + 1; j < size; j++) { + PKIX_CHECK(PKIX_List_GetItem + (sortedList, j, &cmpObj, plContext), + PKIX_LISTGETITEMFAILED); + PKIX_CHECK(comparator + (leastObj, cmpObj, &cmpResult, plContext), + PKIX_COMPARATORCALLBACKFAILED); + if (cmpResult > 0) { + PKIX_CHECK(PKIX_List_SetItem + (sortedList, j, leastObj, plContext), + PKIX_LISTSETITEMFAILED); + + PKIX_DECREF(leastObj); + leastObj = cmpObj; + cmpObj = NULL; + } else { + PKIX_DECREF(cmpObj); + } + } + PKIX_CHECK(PKIX_List_SetItem + (sortedList, i, leastObj, plContext), + PKIX_LISTSETITEMFAILED); + + PKIX_DECREF(leastObj); + } + + } + + *pSortedList = sortedList; + sortedList = NULL; +cleanup: + + PKIX_DECREF(sortedList); + PKIX_DECREF(leastObj); + PKIX_DECREF(cmpObj); + + PKIX_RETURN(LIST); +} + +/* --Public-List-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_List_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_Create( + PKIX_List **pList, + void *plContext) +{ + PKIX_List *list = NULL; + + PKIX_ENTER(LIST, "PKIX_List_Create"); + PKIX_NULLCHECK_ONE(pList); + + PKIX_CHECK(pkix_List_Create_Internal(PKIX_TRUE, &list, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + *pList = list; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_SetImmutable (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_SetImmutable( + PKIX_List *list, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_SetImmutable"); + PKIX_NULLCHECK_ONE(list); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + list->immutable = PKIX_TRUE; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_IsImmutable (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_IsImmutable( + PKIX_List *list, + PKIX_Boolean *pImmutable, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_IsImmutable"); + PKIX_NULLCHECK_TWO(list, pImmutable); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + *pImmutable = list->immutable; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_GetLength (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_GetLength( + PKIX_List *list, + PKIX_UInt32 *pLength, + void *plContext) +{ + PKIX_ENTER(LIST, "PKIX_List_GetLength"); + PKIX_NULLCHECK_TWO(list, pLength); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + *pLength = list->length; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_IsEmpty (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_IsEmpty( + PKIX_List *list, + PKIX_Boolean *pEmpty, + void *plContext) +{ + PKIX_UInt32 length; + + PKIX_ENTER(LIST, "PKIX_List_IsEmpty"); + PKIX_NULLCHECK_TWO(list, pEmpty); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + if (length == 0){ + *pEmpty = PKIX_TRUE; + } else { + *pEmpty = PKIX_FALSE; + } + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_AppendItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_AppendItem( + PKIX_List *list, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *lastElement = NULL; + PKIX_List *newElement = NULL; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "PKIX_List_AppendItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + /* find last element of list and create new element there */ + + lastElement = list; + for (i = 0; i < length; i++){ + lastElement = lastElement->next; + } + + PKIX_CHECK(pkix_List_Create_Internal + (PKIX_FALSE, &newElement, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + PKIX_INCREF(item); + newElement->item = item; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + lastElement->next = newElement; + newElement = NULL; + list->length += 1; + +cleanup: + + PKIX_DECREF(newElement); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_InsertItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_InsertItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *element = NULL; + PKIX_List *newElem = NULL; + + PKIX_ENTER(LIST, "PKIX_List_InsertItem"); + PKIX_NULLCHECK_ONE(list); + + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + /* Create a new list object */ + PKIX_CHECK(pkix_List_Create_Internal(PKIX_FALSE, &newElem, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + if (list->length) { + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + /* Copy the old element's contents into the new element */ + newElem->item = element->item; + /* Add new item to the list */ + PKIX_INCREF(item); + element->item = item; + /* Set the new element's next pointer to the old element's next */ + newElem->next = element->next; + /* Set the old element's next pointer to the new element */ + element->next = newElem; + newElem = NULL; + } else { + PKIX_INCREF(item); + newElem->item = item; + newElem->next = NULL; + list->next = newElem; + newElem = NULL; + } + list->length++; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); +cleanup: + PKIX_DECREF(newElem); + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_GetItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_GetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object **pItem, + void *plContext) +{ + PKIX_List *element = NULL; + + PKIX_ENTER(LIST, "PKIX_List_GetItem"); + PKIX_NULLCHECK_TWO(list, pItem); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + PKIX_INCREF(element->item); + *pItem = element->item; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_SetItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_SetItem( + PKIX_List *list, + PKIX_UInt32 index, + PKIX_PL_Object *item, + void *plContext) +{ + PKIX_List *element; + + PKIX_ENTER(LIST, "PKIX_List_SetItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + /* DecRef old contents */ + PKIX_DECREF(element->item); + + /* Set New Contents */ + PKIX_INCREF(item); + element->item = item; + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_DeleteItem (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_DeleteItem( + PKIX_List *list, + PKIX_UInt32 index, + void *plContext) +{ + PKIX_List *element = NULL; + PKIX_List *prevElement = NULL; + PKIX_List *nextElement = NULL; + + PKIX_ENTER(LIST, "PKIX_List_DeleteItem"); + PKIX_NULLCHECK_ONE(list); + + if (list->immutable){ + PKIX_ERROR(PKIX_OPERATIONNOTPERMITTEDONIMMUTABLELIST); + } + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + PKIX_CHECK(pkix_List_GetElement(list, index, &element, plContext), + PKIX_LISTGETELEMENTFAILED); + + /* DecRef old contents */ + PKIX_DECREF(element->item); + + nextElement = element->next; + + if (nextElement != NULL) { + /* If the next element exists, splice it out. */ + + /* Don't need to change ref counts for targets of next */ + element->item = nextElement->item; + nextElement->item = NULL; + + /* Don't need to change ref counts for targets of next */ + element->next = nextElement->next; + nextElement->next = NULL; + + PKIX_DECREF(nextElement); + + } else { /* The element is at the tail of the list */ + if (index != 0) { + PKIX_CHECK(pkix_List_GetElement + (list, index-1, &prevElement, plContext), + PKIX_LISTGETELEMENTFAILED); + } else if (index == 0){ /* prevElement must be header */ + prevElement = list; + } + prevElement->next = NULL; + + /* Delete the element */ + PKIX_DECREF(element); + } + + PKIX_CHECK(PKIX_PL_Object_InvalidateCache + ((PKIX_PL_Object *)list, plContext), + PKIX_OBJECTINVALIDATECACHEFAILED); + + list->length = list->length - 1; + +cleanup: + + PKIX_RETURN(LIST); +} + +/* + * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_List_ReverseList( + PKIX_List *list, + PKIX_List **pReversedList, + void *plContext) +{ + PKIX_List *reversedList = NULL; + PKIX_PL_Object *item = NULL; + PKIX_PL_Object *duplicateItem = NULL; + PKIX_UInt32 length, i; + + PKIX_ENTER(LIST, "pkix_List_ReverseList"); + PKIX_NULLCHECK_TWO(list, pReversedList); + + if (!list->isHeader){ + PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); + } + + length = list->length; + + /* Create a new list object */ + PKIX_CHECK(PKIX_List_Create(&reversedList, plContext), + PKIX_LISTCREATEINTERNALFAILED); + + /* + * Starting with the last item and traversing backwards (from + * the original list), append each item to the reversed list + */ + + for (i = 1; i <= length; i++){ + PKIX_CHECK(PKIX_List_GetItem + (list, (length - i), &item, plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_Object_Duplicate + (item, &duplicateItem, plContext), + PKIX_LISTDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (reversedList, duplicateItem, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(item); + PKIX_DECREF(duplicateItem); + } + + *pReversedList = reversedList; + +cleanup: + + PKIX_DECREF(item); + PKIX_DECREF(duplicateItem); + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(reversedList); + } + + PKIX_RETURN(LIST); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_list.h b/security/nss/lib/libpkix/pkix/util/pkix_list.h new file mode 100644 index 0000000000..13e104f21a --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_list.h @@ -0,0 +1,95 @@ +/* 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_list.h + * + * List Object Type Definition + * + */ + +#ifndef _PKIX_LIST_H +#define _PKIX_LIST_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef PKIX_Error * +(*PKIX_List_SortComparatorCallback)( + PKIX_PL_Object *obj1, + PKIX_PL_Object *obj2, + PKIX_Int32 *pResult, + void *plContext); + +struct PKIX_ListStruct { + PKIX_PL_Object *item; + PKIX_List *next; + PKIX_Boolean immutable; + PKIX_UInt32 length; + PKIX_Boolean isHeader; +}; + +/* see source file for function documentation */ + +PKIX_Error *pkix_List_RegisterSelf(void *plContext); + +PKIX_Error * +pkix_List_Contains( + PKIX_List *list, + PKIX_PL_Object *object, + PKIX_Boolean *pFound, + void *plContext); + +PKIX_Error * +pkix_List_Remove( + PKIX_List *list, + PKIX_PL_Object *target, + void *plContext); + +PKIX_Error * +pkix_List_MergeLists( + PKIX_List *firstList, + PKIX_List *secondList, + PKIX_List **pMergedList, + void *plContext); + +PKIX_Error * +pkix_List_AppendList( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext); + +PKIX_Error * +pkix_List_AppendUnique( + PKIX_List *toList, + PKIX_List *fromList, + void *plContext); + +PKIX_Error * +pkix_List_RemoveItems( + PKIX_List *list, + PKIX_List *deleteList, + void *plContext); + +PKIX_Error * +pkix_List_QuickSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext); + +PKIX_Error * +pkix_List_BubbleSort( + PKIX_List *fromList, + PKIX_List_SortComparatorCallback comparator, + PKIX_List **pSortedList, + void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_LIST_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.c b/security/nss/lib/libpkix/pkix/util/pkix_logger.c new file mode 100644 index 0000000000..10f537a319 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c @@ -0,0 +1,1088 @@ +/* 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_logger.c + * + * Logger Object Functions + * + */ + +#include "pkix_logger.h" +#ifndef PKIX_ERROR_DESCRIPTION +#include "prprf.h" +#endif + +/* Global variable to keep PKIX_Logger List */ +PKIX_List *pkixLoggers = NULL; + +/* + * Once the Logger has been set, for any logging related operations, we have + * to go through the List to find a match, and if found, issue the + * corresponding callback. The overhead to check for DEBUG and TRACE in each + * PKIX function entering and exiting is very expensive (400X), and redundant + * if they are not the interest of the Logger. Therefore, the PKIX_Logger List + * pkixLoggers is separated into two lists based on its Loggers' trace level. + * + * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or + * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors + * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and + * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to + * pkixLoggersDebugTrace. + * + * Currently we provide five logging levels and the default setting are by: + * + * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level + * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level + * WARNING is not invoked as default + * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs + * compilation -DPKIX_<component>DEBUG flag to turn on + * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE + * level. TRACE provides duplicate information of DEBUG, but needs no + * recompilation and cannot choose component. To allow application + * to use DEBUG level, TRACE is put as last. + * + */ +PKIX_List *pkixLoggersErrors = NULL; +PKIX_List *pkixLoggersDebugTrace = NULL; + +/* To ensure atomic update on pkixLoggers lists */ +PKIX_PL_MonitorLock *pkixLoggerLock = NULL; + +/* --Private-Functions-------------------------------------------- */ + +/* + * FUNCTION: pkix_Logger_CheckErrors + * DESCRIPTION: + * + * This function goes through each PKIX_Logger at "pkixLoggersList" and + * checks if "maxLevel" and "logComponent" satisfies what is specified in the + * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and + * passes a PKIX_PL_String that is the concatenation of "message" and + * "message2" to the application for processing. + * Since this call is inserted into a handful of PKIX macros, no macros are + * applied in this function, to avoid infinite recursion. + * If an error occurs, this call is aborted. + * + * PARAMETERS: + * "pkixLoggersList" + * A list of PKIX_Loggers to be examined for invoking callback. Must be + * non-NULL. + * "message" + * Address of "message" to be logged. Must be non-NULL. + * "message2" + * Address of "message2" to be concatenated and logged. May be NULL. + * "logComponent" + * A PKIX_UInt32 that indicates the component the message is from. + * "maxLevel" + * A PKIX_UInt32 that represents the level of severity of the message. + * "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 Fatal Error if the function fails in an unrecoverable way + */ +PKIX_Error * +pkix_Logger_Check( + PKIX_List *pkixLoggersList, + const char *message, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 currentLevel, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *messageString = NULL; + PKIX_PL_String *message2String = NULL; + PKIX_PL_String *msgString = NULL; + PKIX_Error *error = NULL; + PKIX_Boolean needLogging = PKIX_FALSE; + PKIX_UInt32 i, length; + + /* + * We cannot use any the PKIX_ macros here, since this function is + * called from some of these macros. It can create infinite recursion. + */ + + if ((pkixLoggersList == NULL) || (message == NULL)) { + return(NULL); + } + + /* + * Disable all subsequent loggings to avoid recursion. The result is + * if other thread is calling this function at the same time, there + * won't be any logging because the pkixLoggersErrors and + * pkixLoggersDebugTrace are set to null. + * It would be nice if we provide control per thread (e.g. make + * plContext threadable) then we can avoid the recursion by setting + * flag at plContext. Then other thread's logging won't be affected. + * + * Also we need to use a reentrant Lock. Although we avoid recursion + * for TRACE. When there is an ERROR occurs in subsequent call, this + * function will be called. + */ + + error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext); + if (error) { return(NULL); } + + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + /* Convert message and message2 to String */ + error = PKIX_PL_String_Create + (PKIX_ESCASCII, message, 0, &messageString, plContext); + if (error) { goto cleanup; } + + if (message2) { + error = PKIX_PL_String_Create + (PKIX_ESCASCII, message2, 0, &message2String, plContext); + if (error) { goto cleanup; } + error = PKIX_PL_String_Create + (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext); + if (error) { goto cleanup; } + + } else { + error = PKIX_PL_String_Create + (PKIX_ESCASCII, "%s", 0, &formatString, plContext); + if (error) { goto cleanup; } + + } + + error = PKIX_PL_Sprintf + (&msgString, + plContext, + formatString, + messageString, + message2String); + if (error) { goto cleanup; } + + /* Go through the Logger list */ + + error = PKIX_List_GetLength(pkixLoggersList, &length, plContext); + if (error) { goto cleanup; } + + for (i = 0; i < length; i++) { + + error = PKIX_List_GetItem + (pkixLoggersList, + i, + (PKIX_PL_Object **) &logger, + plContext); + if (error) { goto cleanup; } + + /* Intended logging level less or equal than the max */ + needLogging = (currentLevel <= logger->maxLevel); + + if (needLogging && (logger->callback)) { + + /* + * We separate Logger into two lists based on log level + * but log level is not modified. We need to check here to + * avoid logging the higher log level (lower value) twice. + */ + if (pkixLoggersList == pkixLoggersErrors) { + needLogging = needLogging && + (currentLevel <= PKIX_LOGGER_LEVEL_WARNING); + } else if (pkixLoggersList == pkixLoggersDebugTrace) { + needLogging = needLogging && + (currentLevel > PKIX_LOGGER_LEVEL_WARNING); + } + + if (needLogging) { + if (logComponent == logger->logComponent) { + needLogging = PKIX_TRUE; + } else { + needLogging = PKIX_FALSE; + } + } + + if (needLogging) { + error = logger->callback + (logger, + msgString, + currentLevel, + logComponent, + plContext); + if (error) { goto cleanup; } + } + } + + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)logger, plContext); + logger = NULL; + if (error) { goto cleanup; } + + } + +cleanup: + + if (formatString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)formatString, plContext); + } + + if (messageString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)messageString, plContext); + } + + if (message2String) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)message2String, plContext); + } + + if (msgString) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)msgString, plContext); + } + + if (logger) { + error = PKIX_PL_Object_DecRef + ((PKIX_PL_Object *)logger, plContext); + } + + if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) { + pkixLoggersErrors = savedPkixLoggersErrors; + } + + if (pkixLoggersDebugTrace == NULL && + savedPkixLoggersDebugTrace != NULL) { + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + } + + error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext); + if (error) { return(NULL); } + + return(NULL); +} + +PKIX_Error * +pkix_Logger_CheckWithCode( + PKIX_List *pkixLoggersList, + PKIX_UInt32 errorCode, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 currentLevel, + void *plContext) +{ + char error[32]; + char *errorString = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode"); +#if defined PKIX_ERROR_DESCRIPTION + errorString = PKIX_ErrorText[errorCode]; +#else + PR_snprintf(error, 32, "Error code: %d", errorCode); + errorString = error; +#endif /* PKIX_ERROR_DESCRIPTION */ + + pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString, + message2, logComponent, + currentLevel, plContext); + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + PKIX_Logger *logger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a logger */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + /* We have a valid logger. DecRef its item and recurse on next */ + + logger->callback = NULL; + PKIX_DECREF(logger->context); + logger->logComponent = (PKIX_ERRORCLASS)0; + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_ToString + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_ToString( + PKIX_PL_Object *object, + PKIX_PL_String **pString, + void *plContext) +{ + PKIX_Logger *logger = NULL; + char *asciiFormat = NULL; + PKIX_PL_String *formatString = NULL; + PKIX_PL_String *contextString = NULL; + PKIX_PL_String *componentString = NULL; + PKIX_PL_String *loggerString = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper"); + PKIX_NULLCHECK_TWO(object, pString); + + /* Check that this object is a logger */ + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + asciiFormat = + "[\n" + "\tLogger: \n" + "\tContext: %s\n" + "\tMaximum Level: %d\n" + "\tComponent Name: %s\n" + "]\n"; + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + asciiFormat, + 0, + &formatString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_TOSTRING(logger->context, &contextString, plContext, + PKIX_OBJECTTOSTRINGFAILED); + + PKIX_CHECK(PKIX_PL_String_Create + (PKIX_ESCASCII, + (void *)PKIX_ERRORCLASSNAMES[logger->logComponent], + 0, + &componentString, + plContext), + PKIX_STRINGCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Sprintf + (&loggerString, + plContext, + formatString, + contextString, + logger->maxLevel, + componentString), + PKIX_SPRINTFFAILED); + + *pString = loggerString; + +cleanup: + + PKIX_DECREF(formatString); + PKIX_DECREF(contextString); + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Equals + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Equals( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_Boolean *pResult, + void *plContext) +{ + PKIX_UInt32 secondType; + PKIX_Boolean cmpResult; + PKIX_Logger *firstLogger = NULL; + PKIX_Logger *secondLogger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Equals"); + PKIX_NULLCHECK_THREE(first, second, pResult); + + /* test that first is a Logger */ + PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext), + PKIX_FIRSTOBJECTNOTLOGGER); + + /* + * Since we know first is a Logger, if both references are + * identical, they must be equal + */ + if (first == second){ + *pResult = PKIX_TRUE; + goto cleanup; + } + + /* + * If second isn't a Logger, we don't throw an error. + * We simply return a Boolean result of FALSE + */ + *pResult = PKIX_FALSE; + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); + if (secondType != PKIX_LOGGER_TYPE) goto cleanup; + + firstLogger = (PKIX_Logger *)first; + secondLogger = (PKIX_Logger *)second; + + cmpResult = PKIX_FALSE; + + if (firstLogger->callback != secondLogger->callback) { + goto cleanup; + } + + if (firstLogger->logComponent != secondLogger->logComponent) { + goto cleanup; + } + + PKIX_EQUALS + (firstLogger->context, + secondLogger->context, + &cmpResult, + plContext, + PKIX_OBJECTEQUALSFAILED); + + if (cmpResult == PKIX_FALSE) { + goto cleanup; + } + + if (firstLogger->maxLevel != secondLogger->maxLevel) { + goto cleanup; + } + + *pResult = cmpResult; + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_Hashcode + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Hashcode( + PKIX_PL_Object *object, + PKIX_UInt32 *pHashcode, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_UInt32 hash = 0; + PKIX_UInt32 tempHash = 0; + + PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode"); + PKIX_NULLCHECK_TWO(object, pHashcode); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *)object; + + PKIX_HASHCODE(logger->context, &tempHash, plContext, + PKIX_OBJECTHASHCODEFAILED); + + hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) + + logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent; + + *pHashcode = hash; + +cleanup: + + PKIX_RETURN(LOGGER); +} + + +/* + * FUNCTION: pkix_Logger_Duplicate + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_Logger_Duplicate( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + + PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_CHECK(pkix_CheckType + ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext), + PKIX_OBJECTNOTLOGGER); + + logger = (PKIX_Logger *) object; + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LOGGER_TYPE, + sizeof (PKIX_Logger), + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_COULDNOTCREATELOGGEROBJECT); + + dupLogger->callback = logger->callback; + dupLogger->maxLevel = logger->maxLevel; + + PKIX_DUPLICATE + (logger->context, + &dupLogger->context, + plContext, + PKIX_OBJECTDUPLICATEFAILED); + + dupLogger->logComponent = logger->logComponent; + + *pNewObject = (PKIX_PL_Object *) dupLogger; + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(dupLogger); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: pkix_Logger_RegisterSelf + * DESCRIPTION: + * Registers PKIX_LOGGER_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_Logger_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry entry; + + PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf"); + + entry.description = "Logger"; + entry.objCounter = 0; + entry.typeObjectSize = sizeof(PKIX_Logger); + entry.destructor = pkix_Logger_Destroy; + entry.equalsFunction = pkix_Logger_Equals; + entry.hashcodeFunction = pkix_Logger_Hashcode; + entry.toStringFunction = pkix_Logger_ToString; + entry.comparator = NULL; + entry.duplicateFunction = pkix_Logger_Duplicate; + + systemClasses[PKIX_LOGGER_TYPE] = entry; + + PKIX_RETURN(LOGGER); +} + +/* --Public-Logger-Functions--------------------------------------------- */ + +/* + * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_Create( + PKIX_Logger_LogCallback callback, + PKIX_PL_Object *loggerContext, + PKIX_Logger **pLogger, + void *plContext) +{ + PKIX_Logger *logger = NULL; + + PKIX_ENTER(LOGGER, "PKIX_Logger_Create"); + PKIX_NULLCHECK_ONE(pLogger); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_LOGGER_TYPE, + sizeof (PKIX_Logger), + (PKIX_PL_Object **)&logger, + plContext), + PKIX_COULDNOTCREATELOGGEROBJECT); + + logger->callback = callback; + logger->maxLevel = 0; + logger->logComponent = (PKIX_ERRORCLASS)0; + + PKIX_INCREF(loggerContext); + logger->context = loggerContext; + + *pLogger = logger; + logger = NULL; + +cleanup: + + PKIX_DECREF(logger); + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLogCallback( + PKIX_Logger *logger, + PKIX_Logger_LogCallback *pCallback, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback"); + PKIX_NULLCHECK_TWO(logger, pCallback); + + *pCallback = logger->callback; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLoggerContext( + PKIX_Logger *logger, + PKIX_PL_Object **pLoggerContext, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex"); + PKIX_NULLCHECK_TWO(logger, pLoggerContext); + + PKIX_INCREF(logger->context); + *pLoggerContext = logger->context; + +cleanup: + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 *pLevel, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel"); + PKIX_NULLCHECK_TWO(logger, pLevel); + + *pLevel = logger->maxLevel; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_SetMaxLoggingLevel( + PKIX_Logger *logger, + PKIX_UInt32 level, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel"); + PKIX_NULLCHECK_ONE(logger); + + if (level > PKIX_LOGGER_LEVEL_MAX) { + PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM); + } else { + logger->maxLevel = level; + } + +cleanup: + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_GetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS *pComponent, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent"); + PKIX_NULLCHECK_TWO(logger, pComponent); + + *pComponent = logger->logComponent; + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_Logger_SetLoggingComponent( + PKIX_Logger *logger, + PKIX_ERRORCLASS component, + void *plContext) +{ + PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent"); + PKIX_NULLCHECK_ONE(logger); + + logger->logComponent = component; + + PKIX_RETURN(LOGGER); +} + + +/* + * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are + * documented as not thread-safe. However they are thread-safe now. We need + * the lock when accessing the logger lists. + */ + +/* + * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_GetLoggers( + PKIX_List **pLoggers, /* list of PKIX_Logger */ + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + PKIX_UInt32 i, length; + PKIX_Boolean locked = PKIX_FALSE; + + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); + PKIX_NULLCHECK_ONE(pLoggers); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + /* + * Temporarily disable DEBUG/TRACE Logging to avoid possible + * deadlock: + * When the Logger List is being accessed, e.g. by PKIX_ENTER or + * PKIX_DECREF, pkix_Logger_Check may check whether logging + * is requested, creating a deadlock situation. + */ + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + if (pkixLoggers == NULL) { + length = 0; + } else { + PKIX_CHECK(PKIX_List_GetLength + (pkixLoggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + } + + /* Create a list and copy the pkixLoggers item to the list */ + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (pkixLoggers, + i, + (PKIX_PL_Object **) &logger, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DECREF(logger); + PKIX_DECREF(dupLogger); + } + + /* Set the list to be immutable */ + PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), + PKIX_LISTSETIMMUTABLEFAILED); + + *pLoggers = list; + +cleanup: + + PKIX_DECREF(logger); + + /* Restore logging capability */ + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + pkixLoggersErrors = savedPkixLoggersErrors; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_SetLoggers( + PKIX_List *loggers, /* list of PKIX_Logger */ + void *plContext) +{ + PKIX_List *list = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_Logger *logger = NULL; + PKIX_Logger *dupLogger = NULL; + PKIX_Boolean locked = PKIX_FALSE; + PKIX_UInt32 i, length; + + PKIX_ENTER(LOGGER, "PKIX_SetLoggers"); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + /* Disable tracing, etc. to avoid recursion and deadlock */ + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + /* discard any prior loggers */ + PKIX_DECREF(pkixLoggers); + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + + if (loggers != NULL) { + + PKIX_CHECK(PKIX_List_Create(&list, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (loggers, + i, + (PKIX_PL_Object **) &logger, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (list, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + /* Make two lists */ + + /* Put in pkixLoggersErrors in any case*/ + + if (savedPkixLoggersErrors == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersErrors, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersErrors, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { + + /* Put in pkixLoggersDebugTrace */ + + if (savedPkixLoggersDebugTrace == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersDebugTrace, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersDebugTrace, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + PKIX_DECREF(logger); + PKIX_DECREF(dupLogger); + + } + + pkixLoggers = list; + } + +cleanup: + + if (PKIX_ERROR_RECEIVED){ + PKIX_DECREF(list); + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + pkixLoggers = NULL; + } + + PKIX_DECREF(logger); + + /* Reenable logging capability with new lists */ + pkixLoggersErrors = savedPkixLoggersErrors; + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} + +/* + * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h) + */ +PKIX_Error * +PKIX_AddLogger( + PKIX_Logger *logger, + void *plContext) +{ + PKIX_Logger *dupLogger = NULL; + PKIX_Logger *addLogger = NULL; + PKIX_List *savedPkixLoggersErrors = NULL; + PKIX_List *savedPkixLoggersDebugTrace = NULL; + PKIX_Boolean locked = PKIX_FALSE; + PKIX_UInt32 i, length; + + PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); + PKIX_NULLCHECK_ONE(logger); + + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), + PKIX_MONITORLOCKENTERFAILED); + locked = PKIX_TRUE; + + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; + pkixLoggersDebugTrace = NULL; + savedPkixLoggersErrors = pkixLoggersErrors; + pkixLoggersErrors = NULL; + + PKIX_DECREF(savedPkixLoggersErrors); + PKIX_DECREF(savedPkixLoggersDebugTrace); + + if (pkixLoggers == NULL) { + + PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(pkix_Logger_Duplicate + ((PKIX_PL_Object *)logger, + (PKIX_PL_Object **)&dupLogger, + plContext), + PKIX_LOGGERDUPLICATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (pkixLoggers, + (PKIX_PL_Object *) dupLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ + for (i = 0; i < length; i++) { + + PKIX_CHECK(PKIX_List_GetItem + (pkixLoggers, + i, + (PKIX_PL_Object **) &addLogger, + plContext), + PKIX_LISTGETITEMFAILED); + + + /* Put in pkixLoggersErrors */ + + if (savedPkixLoggersErrors == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersErrors, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersErrors, + (PKIX_PL_Object *) addLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { + + /* Put in pkixLoggersDebugTrace */ + + if (savedPkixLoggersDebugTrace == NULL) { + + PKIX_CHECK(PKIX_List_Create + (&savedPkixLoggersDebugTrace, + plContext), + PKIX_LISTCREATEFAILED); + } + + PKIX_CHECK(PKIX_List_AppendItem + (savedPkixLoggersDebugTrace, + (PKIX_PL_Object *) addLogger, + plContext), + PKIX_LISTAPPENDITEMFAILED); + } + + PKIX_DECREF(addLogger); + + } + +cleanup: + + PKIX_DECREF(dupLogger); + PKIX_DECREF(addLogger); + + /* Restore logging capability */ + pkixLoggersErrors = savedPkixLoggersErrors; + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; + + if (locked) { + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), + PKIX_MONITORLOCKEXITFAILED); + } + + PKIX_RETURN(LOGGER); +} diff --git a/security/nss/lib/libpkix/pkix/util/pkix_logger.h b/security/nss/lib/libpkix/pkix/util/pkix_logger.h new file mode 100644 index 0000000000..9411aed2e2 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.h @@ -0,0 +1,57 @@ +/* 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_logger.h + * + * Logger Object Type Definition + * + */ + +#ifndef _PKIX_LOGGER_H +#define _PKIX_LOGGER_H + +#include "pkix_tools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern PKIX_List *pkixLoggers; +extern PKIX_List *pkixLoggersErrors; +extern PKIX_List *pkixLoggersDebugTrace; + +struct PKIX_LoggerStruct { + PKIX_Logger_LogCallback callback; + PKIX_PL_Object *context; + PKIX_UInt32 maxLevel; + PKIX_ERRORCLASS logComponent; +}; + +PKIX_Error * +pkix_Logger_Check( + PKIX_List *pkixLoggersList, + const char *message, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 maxLevel, + void *plContext); + +PKIX_Error * +pkix_Logger_CheckWithCode( + PKIX_List *pkixLoggersList, + PKIX_UInt32 errorCode, + const char *message2, + PKIX_ERRORCLASS logComponent, + PKIX_UInt32 maxLevel, + void *plContext); + +/* see source file for function documentation */ + +PKIX_Error *pkix_Logger_RegisterSelf(void *plContext); + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_LOGGER_H */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.c b/security/nss/lib/libpkix/pkix/util/pkix_tools.c new file mode 100644 index 0000000000..4c01f8da14 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.c @@ -0,0 +1,1525 @@ +/* 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_tools.c + * + * Private Utility Functions + * + */ + +#include "pkix_tools.h" + +#define CACHE_ITEM_PERIOD_SECONDS (3600) /* one hour */ + +/* + * This cahce period is only for CertCache. A Cert from a trusted CertStore + * should be checked more frequently for update new arrival, etc. + */ +#define CACHE_TRUST_ITEM_PERIOD_SECONDS (CACHE_ITEM_PERIOD_SECONDS/10) + +extern PKIX_PL_HashTable *cachedCertChainTable; +extern PKIX_PL_HashTable *cachedCertTable; +extern PKIX_PL_HashTable *cachedCrlEntryTable; + +/* Following variables are used to checked cache hits - can be taken out */ +extern int pkix_ccAddCount; +extern int pkix_ccLookupCount; +extern int pkix_ccRemoveCount; +extern int pkix_cAddCount; +extern int pkix_cLookupCount; +extern int pkix_cRemoveCount; +extern int pkix_ceAddCount; +extern int pkix_ceLookupCount; + +#ifdef PKIX_OBJECT_LEAK_TEST +/* Following variables are used for object leak test */ +char *nonNullValue = "Non Empty Value"; +PKIX_Boolean noErrorState = PKIX_TRUE; +PKIX_Boolean runningLeakTest; +PKIX_Boolean errorGenerated; +PKIX_UInt32 stackPosition; +PKIX_UInt32 *fnStackInvCountArr; +char **fnStackNameArr; +PLHashTable *fnInvTable; +PKIX_UInt32 testStartFnStackPosition; +char *errorFnStackString; +#endif /* PKIX_OBJECT_LEAK_TEST */ + +/* --Private-Functions-------------------------------------------- */ + +#ifdef PKIX_OBJECT_LEAK_TEST +/* + * FUNCTION: pkix_ErrorGen_Hash + * DESCRIPTION: + * + * Hash function to be used in object leak test hash table. + * + */ +PLHashNumber PR_CALLBACK +pkix_ErrorGen_Hash (const void *key) +{ + char *str = NULL; + PLHashNumber rv = (*(PRUint8*)key) << 5; + PRUint32 i, counter = 0; + PRUint8 *rvc = (PRUint8 *)&rv; + + while ((str = fnStackNameArr[counter++]) != NULL) { + PRUint32 len = strlen(str); + for( i = 0; i < len; i++ ) { + rvc[ i % sizeof(rv) ] ^= *str; + str++; + } + } + + return rv; +} + +#endif /* PKIX_OBJECT_LEAK_TEST */ + +/* + * FUNCTION: pkix_IsCertSelfIssued + * DESCRIPTION: + * + * Checks whether the Cert pointed to by "cert" is self-issued and stores the + * Boolean result at "pSelfIssued". A Cert is considered self-issued if the + * Cert's issuer matches the Cert's subject. If the subject or issuer is + * not specified, a PKIX_FALSE is returned. + * + * PARAMETERS: + * "cert" + * Address of Cert used to determine whether Cert is self-issued. + * Must be non-NULL. + * "pSelfIssued" + * Address where Boolean 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 Cert 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_IsCertSelfIssued( + PKIX_PL_Cert *cert, + PKIX_Boolean *pSelfIssued, + void *plContext) +{ + PKIX_PL_X500Name *subject = NULL; + PKIX_PL_X500Name *issuer = NULL; + + PKIX_ENTER(CERT, "pkix_IsCertSelfIssued"); + PKIX_NULLCHECK_TWO(cert, pSelfIssued); + + PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &subject, plContext), + PKIX_CERTGETSUBJECTFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetIssuer(cert, &issuer, plContext), + PKIX_CERTGETISSUERFAILED); + + if (subject == NULL || issuer == NULL) { + *pSelfIssued = PKIX_FALSE; + } else { + + PKIX_CHECK(PKIX_PL_X500Name_Match + (subject, issuer, pSelfIssued, plContext), + PKIX_X500NAMEMATCHFAILED); + } + +cleanup: + PKIX_DECREF(subject); + PKIX_DECREF(issuer); + + PKIX_RETURN(CERT); +} + +/* + * FUNCTION: pkix_Throw + * DESCRIPTION: + * + * Creates an Error using the value of "errorCode", the character array + * pointed to by "funcName", the character array pointed to by "errorText", + * and the Error pointed to by "cause" (if any), and stores it at "pError". + * + * If "cause" is not NULL and has an errorCode of "PKIX_FATAL_ERROR", + * then there is no point creating a new Error object. Rather, we simply + * store "cause" at "pError". + * + * PARAMETERS: + * "errorCode" + * Value of error code. + * "funcName" + * Address of EscASCII array representing name of function throwing error. + * Must be non-NULL. + * "errnum" + * PKIX_ERRMSGNUM of error description for new error. + * "cause" + * Address of Error representing error's cause. + * "pError" + * 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 an Error 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_Throw( + PKIX_ERRORCLASS errorClass, + const char *funcName, + PKIX_ERRORCODE errorCode, + PKIX_ERRORCLASS overrideClass, + PKIX_Error *cause, + PKIX_Error **pError, + void *plContext) +{ + PKIX_Error *error = NULL; + + PKIX_ENTER(ERROR, "pkix_Throw"); + PKIX_NULLCHECK_TWO(funcName, pError); + + *pError = NULL; + +#ifdef PKIX_OBJECT_LEAK_TEST + noErrorState = PKIX_TRUE; + if (pkixLog) { +#ifdef PKIX_ERROR_DESCRIPTION + PR_LOG(pkixLog, 4, ("Error in function \"%s\":\"%s\" with cause \"%s\"\n", + funcName, PKIX_ErrorText[errorCode], + (cause ? PKIX_ErrorText[cause->errCode] : "null"))); +#else + PR_LOG(pkixLog, 4, ("Error in function \"%s\": error code \"%d\"\n", + funcName, errorCode)); +#endif /* PKIX_ERROR_DESCRIPTION */ + PORT_Assert(strcmp(funcName, "PKIX_PL_Object_DecRef")); + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + + /* if cause has error class of PKIX_FATAL_ERROR, return immediately */ + if (cause) { + if (cause->errClass == PKIX_FATAL_ERROR){ + PKIX_INCREF(cause); + *pError = cause; + goto cleanup; + } + } + + if (overrideClass == PKIX_FATAL_ERROR){ + errorClass = overrideClass; + } + + pkixTempResult = PKIX_Error_Create(errorClass, cause, NULL, + errorCode, &error, plContext); + + if (!pkixTempResult) { + /* Setting plErr error code: + * get it from PORT_GetError if it is a leaf error and + * default error code does not exist(eq 0) */ + if (!cause && !error->plErr) { + error->plErr = PKIX_PL_GetPLErrorCode(); + } + } + + *pError = error; + +cleanup: + + PKIX_DEBUG_EXIT(ERROR); + pkixErrorClass = 0; +#ifdef PKIX_OBJECT_LEAK_TEST + noErrorState = PKIX_FALSE; + + if (runningLeakTest && fnStackNameArr) { + PR_LOG(pkixLog, 5, + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), + stackPosition, " ", fnStackNameArr[stackPosition], + stackPosition, myFuncName)); + fnStackNameArr[stackPosition--] = NULL; + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + return (pkixTempResult); +} + +/* + * FUNCTION: pkix_CheckTypes + * DESCRIPTION: + * + * Checks that the types of the Object pointed to by "first" and the Object + * pointed to by "second" are both equal to the value of "type". If they + * are not equal, a PKIX_Error is returned. + * + * PARAMETERS: + * "first" + * Address of first Object. Must be non-NULL. + * "second" + * Address of second Object. Must be non-NULL. + * "type" + * Value of type to check against. + * "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 an Error 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_CheckTypes( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_UInt32 type, + void *plContext) +{ + PKIX_UInt32 firstType, secondType; + + PKIX_ENTER(OBJECT, "pkix_CheckTypes"); + PKIX_NULLCHECK_TWO(first, second); + + PKIX_CHECK(PKIX_PL_Object_GetType(first, &firstType, plContext), + PKIX_COULDNOTGETFIRSTOBJECTTYPE); + + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), + PKIX_COULDNOTGETSECONDOBJECTTYPE); + + if ((firstType != type)||(firstType != secondType)) { + PKIX_ERROR(PKIX_OBJECTTYPESDONOTMATCH); + } + +cleanup: + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_CheckType + * DESCRIPTION: + * + * Checks that the type of the Object pointed to by "object" is equal to the + * value of "type". If it is not equal, a PKIX_Error is returned. + * + * PARAMETERS: + * "object" + * Address of Object. Must be non-NULL. + * "type" + * Value of type to check against. + * "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 an Error 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_CheckType( + PKIX_PL_Object *object, + PKIX_UInt32 type, + void *plContext) +{ + return (pkix_CheckTypes(object, object, type, plContext)); +} + +/* + * FUNCTION: pkix_hash + * DESCRIPTION: + * + * Computes a hash value for "length" bytes starting at the array of bytes + * pointed to by "bytes" and stores the result at "pHash". + * + * XXX To speed this up, we could probably read 32 bits at a time from + * bytes (maybe even 64 bits on some platforms) + * + * PARAMETERS: + * "bytes" + * Address of array of bytes to hash. Must be non-NULL. + * "length" + * Number of bytes to hash. + * "pHash" + * 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 Fatal Error if the function fails in an unrecoverable way. + */ +PKIX_Error * +pkix_hash( + const unsigned char *bytes, + PKIX_UInt32 length, + PKIX_UInt32 *pHash, + void *plContext) +{ + PKIX_UInt32 i; + PKIX_UInt32 hash; + + PKIX_ENTER(OBJECT, "pkix_hash"); + if (length != 0) { + PKIX_NULLCHECK_ONE(bytes); + } + PKIX_NULLCHECK_ONE(pHash); + + hash = 0; + for (i = 0; i < length; i++) { + /* hash = 31 * hash + bytes[i]; */ + hash = (hash << 5) - hash + bytes[i]; + } + + *pHash = hash; + + PKIX_RETURN(OBJECT); +} + +/* + * FUNCTION: pkix_countArray + * DESCRIPTION: + * + * Counts the number of elements in the null-terminated array of pointers + * pointed to by "array" and returns the result. + * + * PARAMETERS + * "array" + * Address of null-terminated array of pointers. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * Returns the number of elements in the array. + */ +PKIX_UInt32 +pkix_countArray(void **array) +{ + PKIX_UInt32 count = 0; + + if (array) { + while (*array++) { + count++; + } + } + return (count); +} + +/* + * FUNCTION: pkix_duplicateImmutable + * DESCRIPTION: + * + * Convenience callback function used for duplicating immutable objects. + * Since the objects can not be modified, this function simply increments the + * reference count on the object, and returns a reference to that object. + * + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) + */ +PKIX_Error * +pkix_duplicateImmutable( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext) +{ + PKIX_ENTER(OBJECT, "pkix_duplicateImmutable"); + PKIX_NULLCHECK_TWO(object, pNewObject); + + PKIX_INCREF(object); + + *pNewObject = object; + +cleanup: + PKIX_RETURN(OBJECT); +} + +/* --String-Encoding-Conversion-Functions------------------------ */ + +/* + * FUNCTION: pkix_hex2i + * DESCRIPTION: + * + * Converts hexadecimal character "c" to its integer value and returns result. + * + * PARAMETERS + * "c" + * Character to convert to a hex value. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * The hexadecimal value of "c". Otherwise -1. (Unsigned 0xFFFFFFFF). + */ +PKIX_UInt32 +pkix_hex2i(char c) +{ + if ((c >= '0')&&(c <= '9')) + return (c-'0'); + else if ((c >= 'a')&&(c <= 'f')) + return (c-'a'+10); + else if ((c >= 'A')&&(c <= 'F')) + return (c-'A'+10); + else + return ((PKIX_UInt32)(-1)); +} + +/* + * FUNCTION: pkix_i2hex + * DESCRIPTION: + * + * Converts integer value "digit" to its ASCII hex value + * + * PARAMETERS + * "digit" + * Value of integer to convert to ASCII hex value. Must be 0-15. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * The ASCII hexadecimal value of "digit". + */ +char +pkix_i2hex(char digit) +{ + if ((digit >= 0)&&(digit <= 9)) + return (digit+'0'); + else if ((digit >= 0xa)&&(digit <= 0xf)) + return (digit - 10 + 'a'); + else + return (-1); +} + +/* + * FUNCTION: pkix_isPlaintext + * DESCRIPTION: + * + * Returns whether character "c" is plaintext using EscASCII or EscASCII_Debug + * depending on the value of "debug". + * + * In EscASCII, [01, 7E] except '&' are plaintext. + * In EscASCII_Debug [20, 7E] except '&' are plaintext. + * + * PARAMETERS: + * "c" + * Character to check. + * "debug" + * Value of debug flag. + * THREAD SAFETY: + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * RETURNS: + * True if "c" is plaintext. + */ +PKIX_Boolean +pkix_isPlaintext(unsigned char c, PKIX_Boolean debug) { + return ((c >= 0x01)&&(c <= 0x7E)&&(c != '&')&&(!debug || (c >= 20))); +} + +/* --Cache-Functions------------------------ */ + +/* + * FUNCTION: pkix_CacheCertChain_Lookup + * DESCRIPTION: + * + * Look up CertChain Hash Table for a cached BuildResult based on "targetCert" + * and "anchors" as the hash keys. If there is no item to match the key, + * PKIX_FALSE is stored at "pFound". If an item is found, its cache time is + * compared to "testDate". If expired, the item is removed and PKIX_FALSE is + * stored at "pFound". Otherwise, PKIX_TRUE is stored at "pFound" and the + * BuildResult is stored at "pBuildResult". + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * Must be non-NULL. + * "testDate" + * Address of PKIX_PL_Date for verifying time validity and cache validity. + * May be NULL. If testDate is NULL, this cache item will not be out-dated. + * "pFound" + * Address of PKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pBuildResult" + * Address where BuildResult 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 an Error 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_CacheCertChain_Lookup( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_BuildResult **pBuildResult, + void *plContext) +{ + PKIX_List *cachedValues = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCertChainError = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_PL_Date *validityDate = NULL; + PKIX_Int32 cmpValidTimeResult = 0; + PKIX_Int32 cmpCacheTimeResult = 0; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Lookup"); + + PKIX_NULLCHECK_FOUR(targetCert, anchors, pFound, pBuildResult); + + *pFound = PKIX_FALSE; + + /* use trust anchors and target cert as hash key */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)targetCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)anchors, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertChainError = PKIX_PL_HashTable_Lookup + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedValues, + plContext); + + pkix_ccLookupCount++; + + /* retrieve data from hashed value list */ + + if (cachedValues != NULL && cachedCertChainError == NULL) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 0, + (PKIX_PL_Object **) &cacheValidUntilDate, + plContext), + PKIX_LISTGETITEMFAILED); + + /* check validity time and cache age time */ + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 1, + (PKIX_PL_Object **) &validityDate, + plContext), + PKIX_LISTGETITEMFAILED); + + /* if testDate is not set, this cache item is not out-dated */ + if (testDate) { + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)cacheValidUntilDate, + &cmpCacheTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)validityDate, + &cmpValidTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + /* certs' date are all valid and cache item is not old */ + if (cmpValidTimeResult <= 0 && cmpCacheTimeResult <=0) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 2, + (PKIX_PL_Object **) pBuildResult, + plContext), + PKIX_LISTGETITEMFAILED); + + *pFound = PKIX_TRUE; + + } else { + + pkix_ccRemoveCount++; + *pFound = PKIX_FALSE; + + /* out-dated item, remove it from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + } + } + +cleanup: + + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCertChainError); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(validityDate); + + PKIX_RETURN(BUILD); + +} + +/* + * FUNCTION: pkix_CacheCertChain_Remove + * DESCRIPTION: + * + * Remove CertChain Hash Table entry based on "targetCert" and "anchors" + * as the hash keys. If there is no item to match the key, no action is + * taken. + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * 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 an Error 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_CacheCertChain_Remove( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Remove"); + PKIX_NULLCHECK_TWO(targetCert, anchors); + + /* use trust anchors and target cert as hash key */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)targetCert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)anchors, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK_ONLY_FATAL(PKIX_PL_HashTable_Remove + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + + pkix_ccRemoveCount++; + +cleanup: + + PKIX_DECREF(cachedKeys); + + PKIX_RETURN(BUILD); + +} + +/* + * FUNCTION: pkix_CacheCertChain_Add + * DESCRIPTION: + * + * Add a BuildResult to the CertChain Hash Table for a "buildResult" with + * "targetCert" and "anchors" as the hash keys. + * "validityDate" is the most restricted notAfter date of all Certs in + * this CertChain and is verified when this BuildChain is retrieved. + * The hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "targetCert" + * Address of Target Cert as key to retrieve this CertChain. Must be + * non-NULL. + * "anchors" + * Address of PKIX_List of "anchors" is used as key to retrive CertChain. + * Must be non-NULL. + * "validityDate" + * Address of PKIX_PL_Date contains the most restriced notAfter time of + * all "certs". Must be non-NULL. + * Address of PKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "buildResult" + * Address of BuildResult to be cached. 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 an Error 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_CacheCertChain_Add( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *validityDate, + PKIX_BuildResult *buildResult, + void *plContext) +{ + PKIX_List *cachedValues = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCertChainError = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCertChain_Add"); + + PKIX_NULLCHECK_FOUR(targetCert, anchors, validityDate, buildResult); + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)targetCert, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)anchors, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds + (CACHE_ITEM_PERIOD_SECONDS, + &cacheValidUntilDate, + plContext), + PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cacheValidUntilDate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, (PKIX_PL_Object *)validityDate, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, (PKIX_PL_Object *)buildResult, plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertChainError = PKIX_PL_HashTable_Add + (cachedCertChainTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) cachedValues, + plContext); + + pkix_ccAddCount++; + + if (cachedCertChainError != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add for CertChain skipped: " + "entry existed\n"); + } + +cleanup: + + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCertChainError); + PKIX_DECREF(cacheValidUntilDate); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCert_Lookup + * DESCRIPTION: + * + * Look up Cert Hash Table for a cached item based on "store" and Subject in + * "certSelParams" as the hash keys and returns values Certs in "pCerts". + * If there isn't an item to match the key, a PKIX_FALSE is returned at + * "pFound". The item's cache time is verified with "testDate". If out-dated, + * this item is removed and PKIX_FALSE is returned at "pFound". + * This hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * If the CertStore this Cert is from is a trusted one, the cache period is + * shorter so cache can be updated more frequently. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certSelParams" + * Address of ComCertSelParams that its subject is used as key to retrieve + * this CertChain. Must be non-NULL. + * "testDate" + * Address of PKIX_PL_Date for verifying time cache validity. + * Must be non-NULL. If testDate is NULL, this cache item won't be out + * dated. + * "pFound" + * Address of KPKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pCerts" + * Address PKIX_List where the CertChain will be stored. Must be no-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 an Error 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_CacheCert_Lookup( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_List** pCerts, + void *plContext) +{ + PKIX_PL_Cert *cert = NULL; + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedValues = NULL; + PKIX_List *cachedCertList = NULL; + PKIX_List *selCertList = NULL; + PKIX_PL_X500Name *subject = NULL; + PKIX_PL_Date *invalidAfterDate = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_CertSelector *certSel = NULL; + PKIX_Error *cachedCertError = NULL; + PKIX_Error *selectorError = NULL; + PKIX_CertSelector_MatchCallback selectorMatch = NULL; + PKIX_Int32 cmpValidTimeResult = PKIX_FALSE; + PKIX_Int32 cmpCacheTimeResult = 0; + PKIX_UInt32 numItems = 0; + PKIX_UInt32 i; + + PKIX_ENTER(BUILD, "pkix_CacheCert_Lookup"); + PKIX_NULLCHECK_TWO(store, certSelParams); + PKIX_NULLCHECK_TWO(pFound, pCerts); + + *pFound = PKIX_FALSE; + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (certSelParams, &subject, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_NULLCHECK_ONE(subject); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)subject, plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertError = PKIX_PL_HashTable_Lookup + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedValues, + plContext); + pkix_cLookupCount++; + + if (cachedValues != NULL && cachedCertError == NULL) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 0, + (PKIX_PL_Object **) &cacheValidUntilDate, + plContext), + PKIX_LISTGETITEMFAILED); + + if (testDate) { + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)testDate, + (PKIX_PL_Object *)cacheValidUntilDate, + &cmpCacheTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + if (cmpCacheTimeResult <= 0) { + + PKIX_CHECK(PKIX_List_GetItem + (cachedValues, + 1, + (PKIX_PL_Object **) &cachedCertList, + plContext), + PKIX_LISTGETITEMFAILED); + + /* + * Certs put on cache satifies only for Subject, + * user selector and ComCertSelParams to filter. + */ + PKIX_CHECK(PKIX_CertSelector_Create + (NULL, NULL, &certSel, plContext), + PKIX_CERTSELECTORCREATEFAILED); + + PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams + (certSel, certSelParams, plContext), + PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); + + PKIX_CHECK(PKIX_CertSelector_GetMatchCallback + (certSel, &selectorMatch, plContext), + PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); + + PKIX_CHECK(PKIX_List_Create(&selCertList, plContext), + PKIX_LISTCREATEFAILED); + + /* + * If any of the Cert on the list is out-dated, invalidate + * this cache item. + */ + PKIX_CHECK(PKIX_List_GetLength + (cachedCertList, &numItems, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (i = 0; i < numItems; i++){ + + PKIX_CHECK(PKIX_List_GetItem + (cachedCertList, + i, + (PKIX_PL_Object **)&cert, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter + (cert, &invalidAfterDate, plContext), + PKIX_CERTGETVALIDITYNOTAFTERFAILED); + + if (testDate) { + PKIX_CHECK(PKIX_PL_Object_Compare + ((PKIX_PL_Object *)invalidAfterDate, + (PKIX_PL_Object *)testDate, + &cmpValidTimeResult, + plContext), + PKIX_OBJECTCOMPARATORFAILED); + } + + if (cmpValidTimeResult < 0) { + + pkix_cRemoveCount++; + *pFound = PKIX_FALSE; + + /* one cert is out-dated, remove item from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + goto cleanup; + } + + selectorError = selectorMatch(certSel, cert, plContext); + if (!selectorError){ + /* put on the return list */ + PKIX_CHECK(PKIX_List_AppendItem + (selCertList, + (PKIX_PL_Object *)cert, + plContext), + PKIX_LISTAPPENDITEMFAILED); + *pFound = PKIX_TRUE; + } else { + PKIX_DECREF(selectorError); + } + + PKIX_DECREF(cert); + PKIX_DECREF(invalidAfterDate); + + } + + if (*pFound) { + PKIX_INCREF(selCertList); + *pCerts = selCertList; + } + + } else { + + pkix_cRemoveCount++; + *pFound = PKIX_FALSE; + /* cache item is out-dated, remove it from cache */ + PKIX_CHECK(PKIX_PL_HashTable_Remove + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + plContext), + PKIX_HASHTABLEREMOVEFAILED); + } + + } + +cleanup: + + PKIX_DECREF(subject); + PKIX_DECREF(certSel); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedValues); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(cert); + PKIX_DECREF(cachedCertList); + PKIX_DECREF(selCertList); + PKIX_DECREF(invalidAfterDate); + PKIX_DECREF(cachedCertError); + PKIX_DECREF(selectorError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCert_Add + * DESCRIPTION: + * + * Add Cert Hash Table for a cached item based on "store" and Subject in + * "certSelParams" as the hash keys and have "certs" as the key value. + * This hashtable is maintained in the following ways: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * 2) A PKIX_PL_Date created with current time offset by constant + * CACHE_ITEM_PERIOD_SECONDS is attached to each item in the Hash Table. + * If the CertStore this Cert is from is a trusted one, the cache period is + * shorter so cache can be updated more frequently. + * When an item is retrieved, this date is compared against "testDate" for + * validity. If comparison indicates this item is expired, the item is + * removed from the bucket. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certSelParams" + * Address of ComCertSelParams that its subject is used as key to retrieve + * this CertChain. Must be non-NULL. + * "certs" + * Address PKIX_List of Certs will be stored. Must be no-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 an Error 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_CacheCert_Add( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_List* certs, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedValues = NULL; + PKIX_List *cachedCerts = NULL; + PKIX_PL_Date *cacheValidUntilDate = NULL; + PKIX_PL_X500Name *subject = NULL; + PKIX_Error *cachedCertError = NULL; + PKIX_CertStore_CheckTrustCallback trustCallback = NULL; + PKIX_UInt32 cachePeriod = CACHE_ITEM_PERIOD_SECONDS; + PKIX_UInt32 numCerts = 0; + + PKIX_ENTER(BUILD, "pkix_CacheCert_Add"); + PKIX_NULLCHECK_THREE(store, certSelParams, certs); + + PKIX_CHECK(PKIX_List_GetLength(certs, &numCerts, + plContext), + PKIX_LISTGETLENGTHFAILED); + if (numCerts == 0) { + /* Don't want to add an empty list. */ + goto cleanup; + } + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_ComCertSelParams_GetSubject + (certSelParams, &subject, plContext), + PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); + + PKIX_NULLCHECK_ONE(subject); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)subject, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_Create(&cachedValues, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_CertStore_GetTrustCallback + (store, &trustCallback, plContext), + PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); + + if (trustCallback) { + cachePeriod = CACHE_TRUST_ITEM_PERIOD_SECONDS; + } + + PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds + (cachePeriod, &cacheValidUntilDate, plContext), + PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cacheValidUntilDate, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_DUPLICATE(certs, &cachedCerts, plContext, + PKIX_OBJECTDUPLICATELISTFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedValues, + (PKIX_PL_Object *)cachedCerts, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCertError = PKIX_PL_HashTable_Add + (cachedCertTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) cachedValues, + plContext); + + pkix_cAddCount++; + + if (cachedCertError != NULL) { + PKIX_DEBUG("PKIX_PL_HashTable_Add for Certs skipped: " + "entry existed\n"); + } + +cleanup: + + PKIX_DECREF(subject); + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedValues); + PKIX_DECREF(cachedCerts); + PKIX_DECREF(cacheValidUntilDate); + PKIX_DECREF(cachedCertError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCrlEntry_Lookup + * DESCRIPTION: + * + * Look up CrlEntry Hash Table for a cached item based on "store", + * "certIssuer" and "certSerialNumber" as the hash keys and returns values + * "pCrls". If there isn't an item to match the key, a PKIX_FALSE is + * returned at "pFound". + * This hashtable is maintained in the following way: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certIssuer" + * Address of X500Name that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "certSerialNumber" + * Address of BigInt that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "pFound" + * Address of KPKIX_Boolean indicating valid data is found. + * Must be non-NULL. + * "pCrls" + * Address PKIX_List where the CRLEntry will be stored. Must be no-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 an Error 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_CacheCrlEntry_Lookup( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_Boolean *pFound, + PKIX_List** pCrls, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_List *cachedCrlEntryList = NULL; + PKIX_Error *cachedCrlEntryError = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Lookup"); + PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); + PKIX_NULLCHECK_TWO(pFound, pCrls); + + *pFound = PKIX_FALSE; + + /* Find CrlEntry(s) by issuer and serial number */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)certSerialNumber, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCrlEntryError = PKIX_PL_HashTable_Lookup + (cachedCrlEntryTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object **) &cachedCrlEntryList, + plContext); + pkix_ceLookupCount++; + + /* + * We don't need check Date to invalidate this cache item, + * the item is uniquely defined and won't be reverted. Let + * the FIFO for cleaning up. + */ + + if (cachedCrlEntryList != NULL && cachedCrlEntryError == NULL ) { + + PKIX_INCREF(cachedCrlEntryList); + *pCrls = cachedCrlEntryList; + + *pFound = PKIX_TRUE; + + } else { + + *pFound = PKIX_FALSE; + } + +cleanup: + + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCrlEntryList); + PKIX_DECREF(cachedCrlEntryError); + + PKIX_RETURN(BUILD); +} + +/* + * FUNCTION: pkix_CacheCrlEntry_Add + * DESCRIPTION: + * + * Look up CrlEntry Hash Table for a cached item based on "store", + * "certIssuer" and "certSerialNumber" as the hash keys and have "pCrls" as + * the hash value. If there isn't an item to match the key, a PKIX_FALSE is + * returned at "pFound". + * This hashtable is maintained in the following way: + * 1) When creating the hashtable, maximum bucket size can be specified (0 for + * unlimited). If items in a bucket reaches its full size, an new addition + * will trigger the removal of the old as FIFO sequence. + * + * PARAMETERS: + * "store" + * Address of CertStore as key to retrieve this CertChain. Must be + * non-NULL. + * "certIssuer" + * Address of X500Name that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "certSerialNumber" + * Address of BigInt that is used as key to retrieve the CRLEntries. + * Must be non-NULL. + * "crls" + * Address PKIX_List where the CRLEntry is stored. Must be no-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 an Error 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_CacheCrlEntry_Add( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_List* crls, + void *plContext) +{ + PKIX_List *cachedKeys = NULL; + PKIX_Error *cachedCrlEntryError = NULL; + + PKIX_ENTER(BUILD, "pkix_CacheCrlEntry_Add"); + PKIX_NULLCHECK_THREE(store, certIssuer, certSerialNumber); + PKIX_NULLCHECK_ONE(crls); + + /* Add CrlEntry(s) by issuer and serial number */ + + PKIX_CHECK(PKIX_List_Create(&cachedKeys, plContext), + PKIX_LISTCREATEFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)store, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, (PKIX_PL_Object *)certIssuer, plContext), + PKIX_LISTAPPENDITEMFAILED); + + PKIX_CHECK(PKIX_List_AppendItem + (cachedKeys, + (PKIX_PL_Object *)certSerialNumber, + plContext), + PKIX_LISTAPPENDITEMFAILED); + + cachedCrlEntryError = PKIX_PL_HashTable_Add + (cachedCrlEntryTable, + (PKIX_PL_Object *) cachedKeys, + (PKIX_PL_Object *) crls, + plContext); + pkix_ceAddCount++; + +cleanup: + + PKIX_DECREF(cachedKeys); + PKIX_DECREF(cachedCrlEntryError); + + PKIX_RETURN(BUILD); +} + +#ifdef PKIX_OBJECT_LEAK_TEST + +/* TEST_START_FN and testStartFnStackPosition define at what state + * of the stack the object leak testing should begin. The condition + * in pkix_CheckForGeneratedError works the following way: do leak + * testing if at position testStartFnStackPosition in stack array + * (fnStackNameArr) we have called function TEST_START_FN. + * Note, that stack array get filled only when executing libpkix + * functions. + * */ +#define TEST_START_FN "PKIX_BuildChain" + +PKIX_Error* +pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + char * fnName, + PKIX_Boolean *errSetFlag, + void * plContext) +{ + PKIX_Error *genErr = NULL; + PKIX_UInt32 pos = 0; + PKIX_UInt32 strLen = 0; + + if (fnName) { + if (fnStackNameArr[testStartFnStackPosition] == NULL || + strcmp(fnStackNameArr[testStartFnStackPosition], TEST_START_FN) + ) { + /* return with out error if not with in boundary */ + return NULL; + } + if (!strcmp(fnName, TEST_START_FN)) { + *errSetFlag = PKIX_TRUE; + noErrorState = PKIX_FALSE; + errorGenerated = PKIX_FALSE; + } + } + + if (noErrorState || errorGenerated) return NULL; + + if (fnName && ( + !strcmp(fnName, "PKIX_PL_Object_DecRef") || + !strcmp(fnName, "PKIX_PL_Object_Unlock") || + !strcmp(fnName, "pkix_UnlockObject") || + !strcmp(fnName, "pkix_Throw") || + !strcmp(fnName, "pkix_trace_dump_cert") || + !strcmp(fnName, "PKIX_PL_Free"))) { + /* do not generate error for this functions */ + noErrorState = PKIX_TRUE; + *errSetFlag = PKIX_TRUE; + return NULL; + } + + if (PL_HashTableLookup(fnInvTable, &fnStackInvCountArr[stackPosition - 1])) { + return NULL; + } + + PL_HashTableAdd(fnInvTable, &fnStackInvCountArr[stackPosition - 1], nonNullValue); + errorGenerated = PKIX_TRUE; + noErrorState = PKIX_TRUE; + genErr = PKIX_DoThrow(stdVars, errClass, PKIX_MEMLEAKGENERATEDERROR, + errClass, plContext); + while(fnStackNameArr[pos]) { + strLen += PORT_Strlen(fnStackNameArr[pos++]) + 1; + } + strLen += 1; /* end of line. */ + pos = 0; + errorFnStackString = PORT_ZAlloc(strLen); + while(fnStackNameArr[pos]) { + strcat(errorFnStackString, "/"); + strcat(errorFnStackString, fnStackNameArr[pos++]); + } + noErrorState = PKIX_FALSE; + + return genErr; +} +#endif /* PKIX_OBJECT_LEAK_TEST */ diff --git a/security/nss/lib/libpkix/pkix/util/pkix_tools.h b/security/nss/lib/libpkix/pkix/util/pkix_tools.h new file mode 100644 index 0000000000..5a8ef2741e --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/pkix_tools.h @@ -0,0 +1,1588 @@ +/* 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_tools.h + * + * Header for Utility Functions and Macros + * + */ + +#ifndef _PKIX_TOOLS_H +#define _PKIX_TOOLS_H + +#include "pkix.h" +#include <stddef.h> +#include <stdio.h> +#include "secport.h" +#include "prlong.h" + +/* private PKIX system headers */ +#include "pkix_basicconstraintschecker.h" +#include "pkix_buildresult.h" +#include "pkix_certchainchecker.h" +#include "pkix_certselector.h" +#include "pkix_comcertselparams.h" +#include "pkix_comcrlselparams.h" +#include "pkix_crlselector.h" +#include "pkix_error.h" +#include "pkix_expirationchecker.h" +#include "pkix_list.h" +#include "pkix_logger.h" +#include "pkix_namechainingchecker.h" +#include "pkix_nameconstraintschecker.h" +#include "pkix_policychecker.h" +#include "pkix_policynode.h" +#include "pkix_procparams.h" +#include "pkix_resourcelimits.h" +#include "pkix_revocationmethod.h" +#include "pkix_revocationchecker.h" +#include "pkix_crlchecker.h" +#include "pkix_ocspchecker.h" +#include "pkix_signaturechecker.h" +#include "pkix_store.h" +#include "pkix_targetcertchecker.h" +#include "pkix_validate.h" +#include "pkix_valresult.h" +#include "pkix_verifynode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct pkixStdVarsStr { + const char *aMyFuncName; + PKIX_Error *aPkixErrorResult; + PKIX_Error *aPkixTempResult; + PKIX_Error *aPkixReturnResult; + PKIX_ERRORCODE aPkixErrorCode; + PKIX_Boolean aPkixErrorReceived; + PKIX_Boolean aPkixTempErrorReceived; + PKIX_ERRORCLASS aPkixErrorClass; + PKIX_UInt32 aPkixType; + PKIX_PL_Object *aLockedObject; + PKIX_List *aPkixErrorList; +} PKIX_StdVars; + +#ifdef PKIX_STDVARS_POINTER +#define myFuncName stdVars->aMyFuncName +#define pkixErrorResult stdVars->aPkixErrorResult +#define pkixTempResult stdVars->aPkixTempResult +#define pkixReturnResult stdVars->aPkixReturnResult +#define pkixErrorCode stdVars->aPkixErrorCode +#define pkixErrorReceived stdVars->aPkixErrorReceived +#define pkixTempErrorReceived stdVars->aPkixTempErrorReceived +#define pkixErrorClass stdVars->aPkixErrorClass +#define pkixType stdVars->aPkixType +#define lockedObject stdVars->aLockedObject +#define pkixErrorList stdVars->aPkixErrorList +#define stdVarsPtr stdVars +#else +#define myFuncName stdVars.aMyFuncName +#define pkixErrorResult stdVars.aPkixErrorResult +#define pkixTempResult stdVars.aPkixTempResult +#define pkixReturnResult stdVars.aPkixReturnResult +#define pkixErrorCode stdVars.aPkixErrorCode +#define pkixErrorReceived stdVars.aPkixErrorReceived +#define pkixTempErrorReceived stdVars.aPkixTempErrorReceived +#define pkixErrorClass stdVars.aPkixErrorClass +#define pkixType stdVars.aPkixType +#define lockedObject stdVars.aLockedObject +#define pkixErrorList stdVars.aPkixErrorList +#define stdVarsPtr &stdVars +#endif + +extern PKIX_Error * PKIX_DoReturn(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + PKIX_Boolean doLogger, + void * plContext); + +extern PKIX_Error * PKIX_DoThrow(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + PKIX_ERRORCODE errCode, + PKIX_ERRORCLASS overrideClass, + void * plContext); + +extern void PKIX_DoAddError(PKIX_StdVars * stdVars, + PKIX_Error * error, + void * plContext); + +#ifdef PKIX_OBJECT_LEAK_TEST +extern PKIX_Error * pkix_CheckForGeneratedError(PKIX_StdVars * stdVars, + PKIX_ERRORCLASS errClass, + char * fnName, + PKIX_Boolean *errorStateSet, + void * plContext); +#endif /* PKIX_OBJECT_LEAK_TEST */ + +extern const PKIX_StdVars zeroStdVars; + +extern PRLogModuleInfo *pkixLog; + +/* + * UTILITY MACROS + * Documentation for these common utility macros can be found in the + * Implementation Guidelines document (Section 4.3) + * + * In general, macros with multiple statements (or a single "if" statement) + * use the "do {<body>} while (0)" technique in order to convert the multiple + * statements into one statement, thus avoiding the dangling else problem. + * For macros which ALWAYS exit with a "return" or "goto", there is no + * need to use this technique (and it yields compiler warnings of "statement + * not reached"), so we just use "{<body>}" to group the statements together. + */ + +#if !defined (PKIX_OBJECT_LEAK_TEST) + +#define PKIX_STD_VARS(funcName) \ + static const char cMyFuncName[] = {funcName}; \ + PKIX_StdVars stdVars = zeroStdVars; \ + myFuncName = cMyFuncName + + +#else /* PKIX_OBJECT_LEAK_TEST */ + +extern char **fnStackNameArr; +extern PKIX_UInt32 *fnStackInvCountArr; +extern PKIX_UInt32 stackPosition; +extern PKIX_Boolean noErrorState; +extern PKIX_Boolean errorGenerated; +extern PKIX_Boolean runningLeakTest; +extern PLHashTable *fnInvTable; +extern PKIX_UInt32 testStartFnStackPosition; +extern char *errorFnStackString; + +extern PLHashNumber PR_CALLBACK pkix_ErrorGen_Hash (const void *key); + +#define PKIX_STD_VARS(funcName) \ + static const char cMyFuncName[] = {funcName}; \ + PKIX_StdVars stdVars = zeroStdVars; \ + PKIX_Boolean errorSetFlag = PKIX_FALSE; \ + myFuncName = cMyFuncName; \ + if (runningLeakTest) { \ + if (fnStackNameArr) { \ + fnStackInvCountArr[stackPosition] += 1; \ + stackPosition += 1; \ + fnStackInvCountArr[stackPosition] = 0; \ + fnStackNameArr[stackPosition] = (char*)myFuncName; \ + fnStackNameArr[stackPosition + 1] = NULL; \ + PR_LOG(pkixLog, 5, \ + ("%s%*s+> %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + } \ + do { \ + pkixErrorResult = pkix_CheckForGeneratedError(&stdVars, PKIX_MEM_ERROR, \ + funcName, &errorSetFlag, \ + plContext); \ + if (pkixErrorResult) { \ + PR_LOG(pkixLog, 5, \ + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + fnStackNameArr[stackPosition--] = NULL; \ + if (errorSetFlag) { \ + noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \ + } \ + return pkixErrorResult; \ + } \ + } while (0); \ + } +#endif /* PKIX_OBJECT_LEAK_TEST */ + +#ifdef DEBUG +#define _PKIX_DEBUG_TRACE(cond, prefix, level) \ + do { \ + if (cond) { \ + pkix_Logger_Check(pkixLoggersDebugTrace, myFuncName, \ + prefix, pkixType, level, plContext); \ + } \ + } while (0) +#else +#define _PKIX_DEBUG_TRACE(cond, prefix, level) +#endif + +#define _PKIX_LOG_ERROR(code, level) \ + { \ + if (pkixLoggersErrors) { \ + pkix_Logger_CheckWithCode(pkixLoggersErrors, code, \ + NULL, pkixType, level, plContext); \ + } \ + } + +#define PKIX_ENTER(type, funcName) \ + PKIX_STD_VARS(funcName); \ + pkixType = PKIX_ ## type ## _ERROR; \ + PKIX_DEBUG_ENTER(type); \ + _PKIX_DEBUG_TRACE(pkixLoggersDebugTrace, ">>>", PKIX_LOGGER_LEVEL_TRACE); + +#define PKIX_ENTER_NO_LOGGER(type, funcName) \ + PKIX_STD_VARS(funcName); \ + pkixType = PKIX_ ## type ## _ERROR; \ + PKIX_DEBUG_ENTER(type); + +#define PKIX_DEBUG_ENTER(type) \ + PKIX_ ## type ## _DEBUG_ARG("( Entering %s).\n", myFuncName) + +#define PKIX_DEBUG_EXIT(type) \ + PKIX_ ## type ## _DEBUG_ARG("( Exiting %s).\n", myFuncName) + +#define PKIX_OBJECT_UNLOCK(obj) \ + do { \ + if (obj && lockedObject == (PKIX_PL_Object *)(obj)){ \ + pkixTempResult = \ + PKIX_PL_Object_Unlock \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + lockedObject = NULL; \ + } else { \ + PORT_Assert(lockedObject == NULL); \ + } \ + } while (0) + +#define PKIX_DECREF(obj) \ + do { \ + if (obj){ \ + pkixTempResult = PKIX_PL_Object_DecRef \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + obj = NULL; \ + } \ + } while (0) + +#define PKIX_THROW(type, descNum) \ + return PKIX_DoThrow(&stdVars, (PKIX_ ## type ## _ERROR), descNum, \ + pkixErrorClass, plContext); + +#ifdef PKIX_OBJECT_LEAK_TEST +#define PKIX_RETURN(type) \ + if (runningLeakTest && fnStackNameArr) { \ + PR_LOG(pkixLog, 5, \ + ("%s%*s<- %s(%d) - %s\n", (errorGenerated ? "*" : " "), \ + stackPosition, " ", fnStackNameArr[stackPosition], \ + stackPosition, myFuncName)); \ + fnStackNameArr[stackPosition--] = NULL; \ + if (errorSetFlag) noErrorState = (noErrorState) ? PKIX_FALSE : PKIX_TRUE; \ + } \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext); +#else +#define PKIX_RETURN(type) \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_TRUE, plContext); +#endif /* PKIX_OBJECT_LEAK_TEST */ + + +#if defined(DEBUG) && !defined(DEBUG_nb95248) +#define PKIX_RETURN_NO_LOGGER(type) \ + { \ + PKIX_OBJECT_UNLOCK(lockedObject); \ + if ((pkixErrorReceived) || (pkixErrorResult) || pkixErrorList) \ + PKIX_THROW(type, pkixErrorCode); \ + PKIX_DEBUG_EXIT(type); \ + return NULL; \ + } +#else +#define PKIX_RETURN_NO_LOGGER(type) \ + return PKIX_DoReturn(&stdVars, (PKIX_ ## type ## _ERROR), PKIX_FALSE, plContext); +#endif + +/* disable to disable ;-) */ +/* #define WANT_TRACE_CHECK_FAILURES */ + +#ifdef WANT_TRACE_CHECK_FAILURES +#define TRACE_CHECK_FAILURE(what, errorstring) \ + if (pkixLog) { \ + PR_LOG(pkixLog, PR_LOG_DEBUG, \ + ("====> [%s] failed: %s\n", #what, errorstring)); \ + } +#else +#define TRACE_CHECK_FAILURE(what, errorstring) +#endif + +#define PKIX_CHECK(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorClass = pkixErrorResult->errClass; \ + pkixErrorCode = descNum; \ + goto cleanup; \ + } \ + } while (0) + +/* like PKIX_CHECK but without goto cleanup */ +#define PKIX_CHECK_NO_GOTO(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorClass = pkixErrorResult->errClass; \ + pkixErrorCode = descNum; \ + } \ + } while (0) + +#define PKIX_CHECK_ONLY_FATAL(func, descNum) \ + do { \ + pkixTempErrorReceived = PKIX_FALSE; \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixTempErrorReceived = PKIX_TRUE; \ + pkixErrorClass = pkixErrorResult->errClass; \ + if (pkixErrorClass == PKIX_FATAL_ERROR) { \ + goto cleanup; \ + } \ + PKIX_DECREF(pkixErrorResult); \ + } \ + } while (0) + +#define PKIX_LOG_ERROR(descNum) \ + _PKIX_LOG_ERROR(descNum, PKIX_LOGGER_LEVEL_ERROR) + +#define PKIX_ERROR(descNum) \ + { \ + PKIX_LOG_ERROR(descNum) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + goto cleanup; \ + } + +#define PKIX_ERROR_ALLOC_ERROR() \ + { \ + PKIX_LOG_ERROR(PKIX_ALLOCERROR) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorResult = PKIX_ALLOC_ERROR(); \ + goto cleanup; \ + } + +#define PKIX_ERROR_FATAL(descNum) \ + { \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + pkixErrorClass = PKIX_FATAL_ERROR; \ + _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \ + goto cleanup; \ + } + +#define PKIX_CHECK_FATAL(func, descNum) \ + do { \ + pkixErrorResult = (func); \ + if (pkixErrorResult) { \ + TRACE_CHECK_FAILURE((func), PKIX_ErrorText[descNum]) \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = descNum; \ + pkixErrorClass = PKIX_FATAL_ERROR; \ + _PKIX_LOG_ERROR(pkixErrorCode, PKIX_LOGGER_LEVEL_FATALERROR); \ + goto fatal; \ + } \ + } while (0) + +#define PKIX_NULLCHECK_ONE(a) \ + do { \ + if ((a) == NULL){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_TWO(a, b) \ + do { \ + if (((a) == NULL) || ((b) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_THREE(a, b, c) \ + do { \ + if (((a) == NULL) || ((b) == NULL) || ((c) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_NULLCHECK_FOUR(a, b, c, d) \ + do { \ + if (((a) == NULL) || ((b) == NULL) || \ + ((c) == NULL) || ((d) == NULL)){ \ + pkixErrorReceived = PKIX_TRUE; \ + pkixErrorCode = PKIX_NULLARGUMENT; \ + PKIX_RETURN(FATAL); \ + } \ + } while (0) + +#define PKIX_OBJECT_LOCK(obj) \ + do { \ + if (obj) { \ + pkixTempResult = \ + PKIX_PL_Object_Lock((PKIX_PL_Object*)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(stdVarsPtr, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + pkixErrorCode = PKIX_OBJECTLOCKFAILED; \ + goto cleanup; \ + } \ + lockedObject = (PKIX_PL_Object *)(obj); \ + } \ + } while (0) + +#define PKIX_ERROR_CREATE(type, descNum, error) \ + { \ + pkixTempResult = (PKIX_Error*)pkix_Throw \ + (PKIX_ ## type ## _ERROR, myFuncName, \ + descNum, PKIX_ ## type ## _ERROR, pkixErrorResult, \ + &error, plContext); \ + if (pkixTempResult) { \ + error = pkixTempResult; \ + pkixTempResult = NULL; \ + } \ + } + + +#define PKIX_ERROR_RECEIVED \ + (pkixErrorReceived || pkixErrorResult || pkixTempErrorReceived || \ + pkixErrorList) + +#define PKIX_INCREF(obj) \ + do { \ + if (obj){ \ + pkixTempResult = PKIX_PL_Object_IncRef \ + ((PKIX_PL_Object *)(obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + goto cleanup; \ + } \ + } \ + } while (0) + +#define PKIX_FREE(obj) \ + do { \ + if (obj) { \ + pkixTempResult = PKIX_PL_Free((obj), plContext); \ + if (pkixTempResult) { \ + PKIX_DoAddError(&stdVars, pkixTempResult, plContext); \ + pkixTempResult = NULL; \ + } \ + obj = NULL; \ + } \ + } while (0) + +#define PKIX_EXACTLY_ONE_NULL(a, b) (((a) && !(b)) || ((b) && !(a))) + +/* DIGIT MACROS */ + +#define PKIX_ISDIGIT(c) (((c) >= '0') && ((c) <= '9')) + +#define PKIX_ISXDIGIT(c) \ + (PKIX_ISDIGIT(c) || ( (((c)|0x20) >= 'a') && (((c)|0x20) <= 'f') )) + +#define PKIX_TOSTRING(a, b, c, d) \ + do { \ + int descNum; \ + if ((a) != NULL) { \ + pkixErrorResult = \ + PKIX_PL_Object_ToString((PKIX_PL_Object *)(a), (b), (c)); \ + descNum = (d); \ + } else { \ + pkixErrorResult = \ + PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, (b), (c)); \ + descNum = PKIX_STRINGCREATEFAILED; \ + } \ + PKIX_CHECK(pkixErrorResult, descNum); \ + } while (0) + +#define PKIX_EQUALS(a, b, c, d, e) \ + do { \ + if ((a) != NULL && (b) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Equals\ + ((PKIX_PL_Object *)(a), \ + (PKIX_PL_Object*)(b), \ + (c), \ + (d)), \ + (e)); \ + } else if ((a) == NULL && (b) == NULL) { \ + *(c) = PKIX_TRUE; \ + } else { \ + *(c) = PKIX_FALSE; \ + } \ + } while (0) + +#define PKIX_HASHCODE(a, b, c, d) \ + do { \ + if ((a) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Hashcode\ + ((PKIX_PL_Object *)(a), (b), (c)), (d)); \ + } else { \ + *(b) = 0; \ + } \ + } while (0) + +#define PKIX_DUPLICATE(a, b, c, d) \ + do { \ + if ((a) != NULL) { \ + PKIX_CHECK(PKIX_PL_Object_Duplicate\ + ((PKIX_PL_Object *)(a), \ + (PKIX_PL_Object **)(b), \ + (c)), \ + (d)); \ + } else { \ + *(b) = (a); \ + } \ + } while (0) + +/* + * DEBUG MACROS + * + * Each type has an associated debug flag, which can + * be set on the compiler line using "-D<debugflag>". For convenience, + * "-DPKIX_DEBUGALL" turns on debug for all the components. + * + * If a type's debug flag is defined, then its two associated macros + * are defined: PKIX_type_DEBUG(expr) and PKIX_type_DEBUG_ARG(expr, arg), + * which call PKIX_DEBUG(expr) and PKIX_DEBUG_ARG(expr, arg) respectively, + * which, in turn, enable standard and consistently formatted output. + * + * If a type's debug flag is not defined, the two associated macros + * are defined as a NO-OP. As such, any PKIX_type_DEBUG or PKIX_type_DEBUG_ARG + * macros for an undefined type will be stripped from the code during + * pre-processing, thereby reducing code size. + */ + +#ifdef PKIX_DEBUGALL +#define PKIX_REFCOUNTDEBUG 1 +#define PKIX_MEMDEBUG 1 +#define PKIX_MUTEXDEBUG 1 +#define PKIX_OBJECTDEBUG 1 +#define PKIX_STRINGDEBUG 1 +#define PKIX_OIDDEBUG 1 +#define PKIX_LISTDEBUG 1 +#define PKIX_ERRORDEBUG 1 +#define PKIX_BYTEARRAYDEBUG 1 +#define PKIX_RWLOCKDEBUG 1 +#define PKIX_BIGINTDEBUG 1 +#define PKIX_HASHTABLEDEBUG 1 +#define PKIX_X500NAMEDEBUG 1 +#define PKIX_GENERALNAMEDEBUG 1 +#define PKIX_PUBLICKEYDEBUG 1 +#define PKIX_CERTDEBUG 1 +#define PKIX_HTTPCLIENTDEBUG 1 +#define PKIX_DATEDEBUG 1 +#define PKIX_TRUSTANCHORDEBUG 1 +#define PKIX_PROCESSINGPARAMSDEBUG 1 +#define PKIX_VALIDATEPARAMSDEBUG 1 +#define PKIX_VALIDATERESULTDEBUG 1 +#define PKIX_VALIDATEDEBUG 1 +#define PKIX_CERTCHAINCHECKERDEBUG 1 +#define PKIX_REVOCATIONCHECKERDEBUG 1 +#define PKIX_CERTSELECTORDEBUG 1 +#define PKIX_COMCERTSELPARAMSDEBUG 1 +#define PKIX_TARGETCERTCHECKERSTATEDEBUG 1 +#define PKIX_INITIALIZEPARAMSDEBUG 1 +#define PKIX_CERTBASICCONSTRAINTSDEBUG 1 +#define PKIX_CERTNAMECONSTRAINTSDEBUG 1 +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG 1 +#define PKIX_SUBJALTNAMECHECKERSTATEDEBUG 1 + +#define PKIX_CERTPOLICYQUALIFIERDEBUG 1 +#define PKIX_CERTPOLICYINFODEBUG 1 +#define PKIX_CERTPOLICYNODEDEBUG 1 +#define PKIX_CERTPOLICYCHECKERSTATEDEBUG 1 +#define PKIX_LIFECYCLEDEBUG 1 +#define PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG 1 +#define PKIX_CRLDEBUG 1 +#define PKIX_CRLENTRYDEBUG 1 +#define PKIX_CRLSELECTORDEBUG 1 +#define PKIX_COMCRLSELPARAMSDEBUG 1 +#define PKIX_CERTSTOREDEBUG 1 +#define PKIX_COLLECTIONCERTSTORECONTEXTDEBUG 1 +#define PKIX_DEFAULTCRLCHECKERSTATEDEBUG 1 +#define PKIX_CERTPOLICYMAPDEBUG 1 +#define PKIX_BUILDDEBUG 1 +#define PKIX_BUILDRESULTDEBUG 1 +#define PKIX_FORWARDBUILDERSTATEDEBUG 1 +#define PKIX_SIGNATURECHECKERSTATEDEBUG 1 +#define PKIX_USERDEFINEDMODULESDEBUG 1 +#define PKIX_CONTEXTDEBUG 1 +#define PKIX_DEFAULTREVOCATIONCHECKERDEBUG 1 +#define PKIX_LDAPREQUESTDEBUG 1 +#define PKIX_LDAPRESPONSEDEBUG 1 +#define PKIX_LDAPCLIENTDEBUG 1 +#define PKIX_LDAPDEFAULTCLIENTDEBUG 1 +#define PKIX_SOCKETDEBUG 1 +#define PKIX_RESOURCELIMITSDEBUG 1 +#define PKIX_LOGGERDEBUG 1 +#define PKIX_MONITORLOCKDEBUG 1 +#define PKIX_INFOACCESSDEBUG 1 +#define PKIX_AIAMGRDEBUG 1 +#define PKIX_OCSPCHECKERDEBUG 1 +#define PKIX_OCSPREQUESTDEBUG 1 +#define PKIX_OCSPRESPONSEDEBUG 1 +#define PKIX_HTTPDEFAULTCLIENTDEBUG 1 +#define PKIX_HTTPCERTSTORECONTEXTDEBUG 1 +#define PKIX_VERIFYNODEDEBUG 1 +#endif + +/* + * XXX Both PKIX_DEBUG and PKIX_DEBUG_ARG currently use printf. + * This needs to be replaced with Loggers. + */ + +#ifdef DEBUG +#define PKIX_DEBUG(expr) \ + do { \ + _PKIX_DEBUG_TRACE(pkixLoggersErrors, expr, PKIX_LOGGER_LEVEL_DEBUG); \ + (void) fprintf(stderr, "(%s: ", myFuncName); \ + (void) fprintf(stderr, expr); \ + } while (0) +#else +#define PKIX_DEBUG(expr) +#endif + +/* Logging doesn't support DEBUG with ARG: cannot convert control and arg */ +#define PKIX_DEBUG_ARG(expr, arg) \ + do { \ + (void) printf("(%s: ", myFuncName); \ + (void) printf(expr, arg); \ + } while (0) + +#if PKIX_FATALDEBUG +#define PKIX_FATAL_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_FATAL_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_FATAL_DEBUG(expr) +#define PKIX_FATAL_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REFCOUNTDEBUG +#define PKIX_REF_COUNT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REF_COUNT_DEBUG(expr) +#define PKIX_REF_COUNT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MEMDEBUG +#define PKIX_MEM_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MEM_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MEM_DEBUG(expr) +#define PKIX_MEM_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MUTEXDEBUG +#define PKIX_MUTEX_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MUTEX_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MUTEX_DEBUG(expr) +#define PKIX_MUTEX_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OBJECTDEBUG +#define PKIX_OBJECT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OBJECT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OBJECT_DEBUG(expr) +#define PKIX_OBJECT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_ERRORDEBUG +#define PKIX_ERROR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_ERROR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_ERROR_DEBUG(expr) +#define PKIX_ERROR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_STRINGDEBUG +#define PKIX_STRING_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_STRING_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_STRING_DEBUG(expr) +#define PKIX_STRING_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OIDDEBUG +#define PKIX_OID_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OID_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OID_DEBUG(expr) +#define PKIX_OID_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LISTDEBUG +#define PKIX_LIST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LIST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LIST_DEBUG(expr) +#define PKIX_LIST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_RWLOCKDEBUG +#define PKIX_RWLOCK_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_RWLOCK_DEBUG(expr) +#define PKIX_RWLOCK_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BYTEARRAYDEBUG +#define PKIX_BYTEARRAY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BYTEARRAY_DEBUG(expr) +#define PKIX_BYTEARRAY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HASHTABLEDEBUG +#define PKIX_HASHTABLE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HASHTABLE_DEBUG(expr) +#define PKIX_HASHTABLE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_X500NAMEDEBUG +#define PKIX_X500NAME_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_X500NAME_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_X500NAME_DEBUG(expr) +#define PKIX_X500NAME_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_GENERALNAMEDEBUG +#define PKIX_GENERALNAME_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_GENERALNAME_DEBUG(expr) +#define PKIX_GENERALNAME_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_PUBLICKEYDEBUG +#define PKIX_PUBLICKEY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_PUBLICKEY_DEBUG(expr) +#define PKIX_PUBLICKEY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTDEBUG +#define PKIX_CERT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERT_DEBUG(expr) +#define PKIX_CERT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLDPDEBUG +#define PKIX_CRLDP_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLDP_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLDP_DEBUG(expr) +#define PKIX_CRLDP_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPCLIENTDEBUG +#define PKIX_HTTPCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPCLIENT_DEBUG(expr) +#define PKIX_HTTPCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BIGINTDEBUG +#define PKIX_BIGINT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BIGINT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BIGINT_DEBUG(expr) +#define PKIX_BIGINT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_DATEDEBUG +#define PKIX_DATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_DATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_DATE_DEBUG(expr) +#define PKIX_DATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_TRUSTANCHORDEBUG +#define PKIX_TRUSTANCHOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_TRUSTANCHOR_DEBUG(expr) +#define PKIX_TRUSTANCHOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_PROCESSINGPARAMSDEBUG +#define PKIX_PROCESSINGPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_PROCESSINGPARAMS_DEBUG(expr) +#define PKIX_PROCESSINGPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATEPARAMSDEBUG +#define PKIX_VALIDATEPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATEPARAMS_DEBUG(expr) +#define PKIX_VALIDATEPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATERESULTDEBUG +#define PKIX_VALIDATERESULT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATERESULT_DEBUG(expr) +#define PKIX_VALIDATERESULT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VALIDATEDEBUG +#define PKIX_VALIDATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VALIDATE_DEBUG(expr) +#define PKIX_VALIDATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BUILDDEBUG +#define PKIX_BUILD_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BUILD_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BUILD_DEBUG(expr) +#define PKIX_BUILD_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTCHAINCHECKERDEBUG +#define PKIX_CERTCHAINCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTCHAINCHECKER_DEBUG(expr) +#define PKIX_CERTCHAINCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONCHECKERDEBUG +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONMETHODDEBUG +#define PKIX_REVOCATIONMETHOD_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONMETHOD_DEBUG(expr) +#define PKIX_REVOCATIONMETHOD_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTSELECTORDEBUG +#define PKIX_CERTSELECTOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTSELECTOR_DEBUG(expr) +#define PKIX_CERTSELECTOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COMCERTSELPARAMSDEBUG +#define PKIX_COMCERTSELPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COMCERTSELPARAMS_DEBUG(expr) +#define PKIX_COMCERTSELPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_TARGETCERTCHECKERSTATEDEBUG +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG(expr) +#define PKIX_TARGETCERTCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_INITIALIZEPARAMSDEBUG +#define PKIX_INITIALIZEPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_INITIALIZEPARAMS_DEBUG(expr) +#define PKIX_INITIALIZEPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTBASICCONSTRAINTSDEBUG +#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTBASICCONSTRAINTS_DEBUG(expr) +#define PKIX_CERTBASICCONSTRAINTS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTNAMECONSTRAINTSDEBUG +#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTNAMECONSTRAINTS_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTNAMECONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SUBJALTNAMECHECKERSTATEDEBUG +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG(expr) +#define PKIX_SUBJALTNAMECHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYQUALIFIERDEBUG +#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYQUALIFIER_DEBUG(expr) +#define PKIX_CERTPOLICYQUALIFIER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYINFODEBUG +#define PKIX_CERTPOLICYINFO_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYINFO_DEBUG(expr) +#define PKIX_CERTPOLICYINFO_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYNODEDEBUG +#define PKIX_CERTPOLICYNODE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYNODE_DEBUG(expr) +#define PKIX_CERTPOLICYNODE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYCHECKERSTATEDEBUG +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG(expr) +#define PKIX_CERTPOLICYCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LIFECYCLEDEBUG +#define PKIX_LIFECYCLE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LIFECYCLE_DEBUG(expr) +#define PKIX_LIFECYCLE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BASICCONSTRAINTSCHECKERSTATEDEBUG +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG(expr) +#define PKIX_BASICCONSTRAINTSCHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLDEBUG +#define PKIX_CRL_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRL_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRL_DEBUG(expr) +#define PKIX_CRL_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLENTRYDEBUG +#define PKIX_CRLENTRY_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLENTRY_DEBUG(expr) +#define PKIX_CRLENTRY_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLSELECTORDEBUG +#define PKIX_CRLSELECTOR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLSELECTOR_DEBUG(expr) +#define PKIX_CRLSELECTOR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COMCRLSELPARAMSDEBUG +#define PKIX_COMCRLSELPARAMS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COMCRLSELPARAMS_DEBUG(expr) +#define PKIX_COMCRLSELPARAMS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTSTOREDEBUG +#define PKIX_CERTSTORE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTSTORE_DEBUG(expr) +#define PKIX_CERTSTORE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_COLLECTIONCERTSTORECONTEXTDEBUG +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG(expr) +#define PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CRLCHECKERDEBUG +#define PKIX_CRLCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CRLCHECKER_DEBUG(expr) +#define PKIX_CRLCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTPOLICYMAPDEBUG +#define PKIX_CERTPOLICYMAP_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTPOLICYMAP_DEBUG(expr) +#define PKIX_CERTPOLICYMAP_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_BUILDRESULTDEBUG +#define PKIX_BUILDRESULT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_BUILDRESULT_DEBUG(expr) +#define PKIX_BUILDRESULT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_FORWARDBUILDERSTATEDEBUG +#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_FORWARDBUILDERSTATE_DEBUG(expr) +#define PKIX_FORWARDBUILDERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SIGNATURECHECKERSTATEDEBUG +#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SIGNATURECHECKERSTATE_DEBUG(expr) +#define PKIX_SIGNATURECHECKERSTATE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_USERDEFINEDMODULESDEBUG +#define PKIX_USERDEFINEDMODULES_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_USERDEFINEDMODULES_DEBUG(expr) +#define PKIX_USERDEFINEDMODULES_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CONTEXTDEBUG +#define PKIX_CONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CONTEXT_DEBUG(expr) +#define PKIX_CONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_REVOCATIONCHECKERDEBUG +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_REVOCATIONCHECKER_DEBUG(expr) +#define PKIX_REVOCATIONCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPREQUESTDEBUG +#define PKIX_LDAPREQUEST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPREQUEST_DEBUG(expr) +#define PKIX_LDAPREQUEST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPRESPONSEDEBUG +#define PKIX_LDAPRESPONSE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPRESPONSE_DEBUG(expr) +#define PKIX_LDAPRESPONSE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPCLIENTDEBUG +#define PKIX_LDAPCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPCLIENT_DEBUG(expr) +#define PKIX_LDAPCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LDAPDEFAULTCLIENTDEBUG +#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LDAPDEFAULTCLIENT_DEBUG(expr) +#define PKIX_LDAPDEFAULTCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_SOCKETDEBUG +#define PKIX_SOCKET_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_SOCKET_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_SOCKET_DEBUG(expr) +#define PKIX_SOCKET_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_RESOURCELIMITSDEBUG +#define PKIX_RESOURCELIMITS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_RESOURCELIMITS_DEBUG(expr) +#define PKIX_RESOURCELIMITS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_LOGGERDEBUG +#define PKIX_LOGGER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_LOGGER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_LOGGER_DEBUG(expr) +#define PKIX_LOGGER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_MONITORLOCKDEBUG +#define PKIX_MONITORLOCK_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_MONITORLOCK_DEBUG(expr) +#define PKIX_MONITORLOCK_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_INFOACCESSDEBUG +#define PKIX_INFOACCESS_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_INFOACCESS_DEBUG(expr) +#define PKIX_INFOACCESS_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_AIAMGRDEBUG +#define PKIX_AIAMGR_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_AIAMGR_DEBUG(expr) +#define PKIX_AIAMGR_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPCHECKERDEBUG +#define PKIX_OCSPCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPCHECKER_DEBUG(expr) +#define PKIX_OCSPCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPCERTIDDEBUG +#define PKIX_OCSPCERTID_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPCERTID_DEBUG(expr) +#define PKIX_OCSPCERTID_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPREQUESTDEBUG +#define PKIX_OCSPREQUEST_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPREQUEST_DEBUG(expr) +#define PKIX_OCSPREQUEST_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_OCSPRESPONSEDEBUG +#define PKIX_OCSPRESPONSE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_OCSPRESPONSE_DEBUG(expr) +#define PKIX_OCSPRESPONSE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPDEFAULTCLIENTDEBUG +#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPDEFAULTCLIENT_DEBUG(expr) +#define PKIX_HTTPDEFAULTCLIENT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_HTTPCERTSTORECONTEXTDEBUG +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG(expr) +#define PKIX_HTTPCERTSTORECONTEXT_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_VERIFYNODEDEBUG +#define PKIX_VERIFYNODE_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_VERIFYNODE_DEBUG(expr) +#define PKIX_VERIFYNODE_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_EKUCHECKER +#define PKIX_EKUCHECKER_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_EKUCHECKER_DEBUG(expr) +#define PKIX_EKUCHECKER_DEBUG_ARG(expr, arg) +#endif + +#if PKIX_CERTVFYPKIXDEBUG +#define PKIX_CERTVFYPKIX_DEBUG(expr) \ + PKIX_DEBUG(expr) +#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) \ + PKIX_DEBUG_ARG(expr, arg) +#else +#define PKIX_CERTVFYPKIX_DEBUG(expr) +#define PKIX_CERTVFYPKIX_DEBUG_ARG(expr, arg) +#endif + +/* + * All object types register themselves with the system using a + * pkix_ClassTable_Entry, which consists of a set of functions for that + * type and an ASCII string (char *) which is used by the default + * ToStringCallback (if necessary). System types register themselves directly + * when their respective PKIX_"type"_RegisterSelf functions are called. + * User-defined types can be registered using PKIX_PL_Object_RegisterType. + * (see comments in pkix_pl_system.h) + */ + +typedef struct pkix_ClassTable_EntryStruct pkix_ClassTable_Entry; +struct pkix_ClassTable_EntryStruct { + char *description; + PKIX_UInt32 objCounter; + PKIX_UInt32 typeObjectSize; + PKIX_PL_DestructorCallback destructor; + PKIX_PL_EqualsCallback equalsFunction; + PKIX_PL_HashcodeCallback hashcodeFunction; + PKIX_PL_ToStringCallback toStringFunction; + PKIX_PL_ComparatorCallback comparator; + PKIX_PL_DuplicateCallback duplicateFunction; +}; + +/* + * PKIX_ERRORCLASSNAMES is an array of strings, with each string holding a + * descriptive name for an error code. This is used by the default + * PKIX_PL_Error_ToString function. + */ +extern const char *PKIX_ERRORCLASSNAMES[PKIX_NUMERRORCLASSES]; + +#define MAX_STACK_DEPTH 1000 + +extern PRLogModuleInfo *pkixLog; + +#define PKIX_MAGIC_HEADER PR_UINT64(0xFEEDC0FFEEFACADE) +#define PKIX_MAGIC_HEADER_DESTROYED PR_UINT64(0xBAADF00DDEADBEEF) + +/* see source file for function documentation */ + +PKIX_Error * +pkix_IsCertSelfIssued( + PKIX_PL_Cert *cert, + PKIX_Boolean *pSelfIssued, + void *plContext); + +PKIX_Error * +pkix_Throw( + PKIX_ERRORCLASS errClass, + const char *funcName, + PKIX_ERRORCODE errorTextCode, + PKIX_ERRORCLASS overrideClass, + PKIX_Error *cause, + PKIX_Error **pError, + void *plContext); + +PKIX_Error * +pkix_CheckTypes( + PKIX_PL_Object *first, + PKIX_PL_Object *second, + PKIX_UInt32 type, + void *plContext); + +PKIX_Error * +pkix_CheckType( + PKIX_PL_Object *object, + PKIX_UInt32 type, + void *plContext); + +PKIX_Error * +pkix_hash( + const unsigned char *bytes, + PKIX_UInt32 length, + PKIX_UInt32 *hash, + void *plContext); + +PKIX_Error * +pkix_duplicateImmutable( + PKIX_PL_Object *object, + PKIX_PL_Object **pNewObject, + void *plContext); + +PKIX_UInt32 +pkix_countArray(void **array); + +PKIX_UInt32 +pkix_hex2i(char c); + +char +pkix_i2hex(char c); + +PKIX_Boolean +pkix_isPlaintext(unsigned char c, PKIX_Boolean debug); + +PKIX_Error * +pkix_CacheCertChain_Lookup( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_BuildResult **pBuildResult, + void *plContext); + +PKIX_Error * +pkix_CacheCertChain_Remove( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + void *plContext); + +PKIX_Error * +pkix_CacheCertChain_Add( + PKIX_PL_Cert* targetCert, + PKIX_List* anchors, + PKIX_PL_Date *validityDate, + PKIX_BuildResult *buildResult, + void *plContext); + +PKIX_Error * +pkix_CacheCert_Lookup( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_PL_Date *testDate, + PKIX_Boolean *pFound, + PKIX_List** pCerts, + void *plContext); + +PKIX_Error * +pkix_CacheCert_Add( + PKIX_CertStore *store, + PKIX_ComCertSelParams *certSelParams, + PKIX_List* certs, + void *plContext); + +PKIX_Error * +pkix_CacheCrlEntry_Lookup( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_Boolean *pFound, + PKIX_List** pCrlEntryList, + void *plContext); + +PKIX_Error * +pkix_CacheCrlEntry_Add( + PKIX_CertStore *store, + PKIX_PL_X500Name *certIssuer, + PKIX_PL_BigInt *certSerialNumber, + PKIX_List* crlEntryList, + void *plContext); + +#ifdef PR_LOGGING +void +pkix_trace_dump_cert( + const char *info, + PKIX_PL_Cert *cert, + void *plContext); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _PKIX_TOOLS_H */ diff --git a/security/nss/lib/libpkix/pkix/util/util.gyp b/security/nss/lib/libpkix/pkix/util/util.gyp new file mode 100644 index 0000000000..078852f52b --- /dev/null +++ b/security/nss/lib/libpkix/pkix/util/util.gyp @@ -0,0 +1,27 @@ +# 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/. +{ + 'includes': [ + '../../../../coreconf/config.gypi' + ], + 'targets': [ + { + 'target_name': 'pkixutil', + 'type': 'static_library', + 'sources': [ + 'pkix_error.c', + 'pkix_errpaths.c', + 'pkix_list.c', + 'pkix_logger.c', + 'pkix_tools.c' + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ] + } + ], + 'variables': { + 'module': 'nss' + } +}
\ No newline at end of file |