security/nss/lib/libpkix/pkix/util/pkix_logger.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * pkix_logger.c
     6  *
     7  * Logger Object Functions
     8  *
     9  */
    11 #include "pkix_logger.h"
    12 #ifndef PKIX_ERROR_DESCRIPTION
    13 #include "prprf.h"
    14 #endif
    16 /* Global variable to keep PKIX_Logger List */
    17 PKIX_List *pkixLoggers = NULL;
    19 /*
    20  * Once the Logger has been set, for any logging related operations, we have
    21  * to go through the List to find a match, and if found, issue the
    22  * corresponding callback. The overhead to check for DEBUG and TRACE in each
    23  * PKIX function entering and exiting is very expensive (400X), and redundant
    24  * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
    25  * pkixLoggers is separated into two lists based on its Loggers' trace level.
    26  *
    27  * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
    28  * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
    29  * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
    30  * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
    31  * pkixLoggersDebugTrace.
    32  *
    33  * Currently we provide five logging levels and the default setting are by:
    34  *
    35  *     PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
    36  *     PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
    37  *     WARNING is not invoked as default
    38  *     PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
    39  *         compilation -DPKIX_<component>DEBUG flag to turn on 
    40  *     PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
    41  *         level. TRACE provides duplicate information of DEBUG, but needs no
    42  *         recompilation and cannot choose component. To allow application
    43  *         to use DEBUG level, TRACE is put as last.
    44  *
    45  */
    46 PKIX_List *pkixLoggersErrors = NULL;
    47 PKIX_List *pkixLoggersDebugTrace = NULL;
    49 /* To ensure atomic update on pkixLoggers lists */
    50 PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
    52 /* --Private-Functions-------------------------------------------- */
    54 /*
    55  * FUNCTION: pkix_Logger_CheckErrors
    56  * DESCRIPTION:
    57  *
    58  *  This function goes through each PKIX_Logger at "pkixLoggersList" and
    59  *  checks if "maxLevel" and "logComponent" satisfies what is specified in the
    60  *  PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
    61  *  passes a PKIX_PL_String that is the concatenation of "message" and 
    62  *  "message2" to the application for processing. 
    63  *  Since this call is inserted into a handful of PKIX macros, no macros are
    64  *  applied in this function, to avoid infinite recursion.
    65  *  If an error occurs, this call is aborted.
    66  *
    67  * PARAMETERS:
    68  *  "pkixLoggersList"
    69  *      A list of PKIX_Loggers to be examined for invoking callback. Must be
    70  *      non-NULL.
    71  *  "message"
    72  *      Address of "message" to be logged. Must be non-NULL.
    73  *  "message2"
    74  *      Address of "message2" to be concatenated and logged. May be NULL.
    75  *  "logComponent"
    76  *      A PKIX_UInt32 that indicates the component the message is from.
    77  *  "maxLevel"
    78  *      A PKIX_UInt32 that represents the level of severity of the message.
    79  *  "plContext"
    80  *      Platform-specific context pointer.
    81  * THREAD SAFETY:
    82  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    83  * RETURNS:
    84  *  Returns NULL if the function succeeds
    85  *  Returns a Fatal Error if the function fails in an unrecoverable way
    86  */
    87 PKIX_Error *
    88 pkix_Logger_Check(
    89         PKIX_List *pkixLoggersList,
    90         const char *message,
    91         const char *message2,
    92         PKIX_ERRORCLASS logComponent,
    93         PKIX_UInt32 currentLevel,
    94         void *plContext)
    95 {
    96         PKIX_Logger *logger = NULL;
    97         PKIX_List *savedPkixLoggersErrors = NULL;
    98         PKIX_List *savedPkixLoggersDebugTrace = NULL;
    99         PKIX_PL_String *formatString = NULL;
   100         PKIX_PL_String *messageString = NULL;
   101         PKIX_PL_String *message2String = NULL;
   102         PKIX_PL_String *msgString = NULL;
   103         PKIX_Error *error = NULL;
   104         PKIX_Boolean needLogging = PKIX_FALSE;
   105         PKIX_UInt32 i, length;
   107         /*
   108          * We cannot use any the PKIX_ macros here, since this function is
   109          * called from some of these macros. It can create infinite recursion.
   110          */
   112         if ((pkixLoggersList == NULL) || (message == NULL)) {
   113                 return(NULL);
   114         }
   116         /*
   117          * Disable all subsequent loggings to avoid recursion. The result is
   118          * if other thread is calling this function at the same time, there
   119          * won't be any logging because the pkixLoggersErrors and
   120          * pkixLoggersDebugTrace are set to null.
   121          * It would be nice if we provide control per thread (e.g. make
   122          * plContext threadable) then we can avoid the recursion by setting
   123          * flag at plContext. Then other thread's logging won't be affected.
   124          *
   125          * Also we need to use a reentrant Lock. Although we avoid recursion
   126          * for TRACE. When there is an ERROR occurs in subsequent call, this
   127          * function will be called.
   128          */
   130         error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
   131         if (error) { return(NULL); }
   133         savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   134         pkixLoggersDebugTrace = NULL;
   135         savedPkixLoggersErrors = pkixLoggersErrors;
   136         pkixLoggersErrors = NULL;
   138         /* Convert message and message2 to String */
   139         error = PKIX_PL_String_Create
   140                     (PKIX_ESCASCII, message, 0, &messageString, plContext);
   141         if (error) { goto cleanup; }
   143         if (message2) {
   144                 error = PKIX_PL_String_Create
   145                     (PKIX_ESCASCII, message2, 0, &message2String, plContext);
   146                 if (error) { goto cleanup; }
   147                 error = PKIX_PL_String_Create
   148                     (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
   149                 if (error) { goto cleanup; }
   151         } else {
   152                 error = PKIX_PL_String_Create
   153                     (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
   154                 if (error) { goto cleanup; }
   156         }
   158         error = PKIX_PL_Sprintf
   159                     (&msgString,
   160                     plContext,
   161                     formatString,
   162                     messageString,
   163                     message2String);
   164         if (error) { goto cleanup; }
   166         /* Go through the Logger list */
   168         error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
   169         if (error) { goto cleanup; }
   171         for (i = 0; i < length; i++) {
   173                 error = PKIX_List_GetItem
   174                     (pkixLoggersList,
   175                     i,
   176                     (PKIX_PL_Object **) &logger,
   177                     plContext);
   178                 if (error) { goto cleanup; }
   180                 /* Intended logging level less or equal than the max */
   181                 needLogging = (currentLevel <= logger->maxLevel);
   183                 if (needLogging && (logger->callback)) {
   185                     /*
   186                      * We separate Logger into two lists based on log level
   187                      * but log level is not modified. We need to check here to
   188                      * avoid logging the higher log level (lower value) twice.
   189                      */
   190                     if (pkixLoggersList == pkixLoggersErrors) {
   191                             needLogging = needLogging && 
   192                                 (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
   193                     } else if (pkixLoggersList == pkixLoggersDebugTrace) {
   194                             needLogging = needLogging && 
   195                                 (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
   196                     }
   198                     if (needLogging) {
   199                         if (logComponent == logger->logComponent) {
   200                             needLogging = PKIX_TRUE;
   201                         } else {
   202                             needLogging = PKIX_FALSE;
   203                         }
   204                     }
   206                     if (needLogging) {
   207                         error = logger->callback
   208                                 (logger,
   209                                 msgString,
   210                                 currentLevel,
   211                                 logComponent,
   212                                 plContext);
   213                         if (error) { goto cleanup; }
   214                     }
   215                 }
   217                 error = PKIX_PL_Object_DecRef
   218                         ((PKIX_PL_Object *)logger, plContext);
   219                 logger = NULL;
   220                 if (error) { goto cleanup; }
   222         }
   224 cleanup:
   226         if (formatString) {
   227                 error = PKIX_PL_Object_DecRef
   228                         ((PKIX_PL_Object *)formatString, plContext);
   229         }
   231         if (messageString) {
   232                 error = PKIX_PL_Object_DecRef
   233                          ((PKIX_PL_Object *)messageString, plContext);
   234         }
   236         if (message2String) {
   237                 error = PKIX_PL_Object_DecRef
   238                         ((PKIX_PL_Object *)message2String, plContext);
   239         }
   241         if (msgString) {
   242                 error = PKIX_PL_Object_DecRef
   243                         ((PKIX_PL_Object *)msgString, plContext);
   244         }
   246         if (logger) {
   247                 error = PKIX_PL_Object_DecRef
   248                         ((PKIX_PL_Object *)logger, plContext);
   249         }
   251         if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
   252                 pkixLoggersErrors = savedPkixLoggersErrors;
   253         } 
   255         if (pkixLoggersDebugTrace == NULL && 
   256            savedPkixLoggersDebugTrace != NULL) {
   257                 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   258         }
   260         error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
   261         if (error) { return(NULL); }
   263         return(NULL);
   264 }
   266 PKIX_Error *
   267 pkix_Logger_CheckWithCode(
   268         PKIX_List *pkixLoggersList,
   269         PKIX_UInt32 errorCode,
   270         const char *message2,
   271         PKIX_ERRORCLASS logComponent,
   272         PKIX_UInt32 currentLevel,
   273         void *plContext)
   274 {
   275     char error[32];
   276     char *errorString = NULL;
   278     PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
   279 #if defined PKIX_ERROR_DESCRIPTION
   280     errorString = PKIX_ErrorText[errorCode];
   281 #else
   282     PR_snprintf(error, 32, "Error code: %d", errorCode);
   283     errorString = error;
   284 #endif /* PKIX_ERROR_DESCRIPTION */
   286     pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
   287                                         message2, logComponent,
   288                                         currentLevel, plContext);
   289     PKIX_RETURN(LOGGER);
   290 }
   292 /*
   293  * FUNCTION: pkix_Logger_Destroy
   294  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
   295  */
   296 static PKIX_Error *
   297 pkix_Logger_Destroy(
   298         PKIX_PL_Object *object,
   299         void *plContext)
   300 {
   301         PKIX_Logger *logger = NULL;
   303         PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
   304         PKIX_NULLCHECK_ONE(object);
   306         /* Check that this object is a logger */
   307         PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   308                     PKIX_OBJECTNOTLOGGER);
   310         logger = (PKIX_Logger *)object;
   312         /* We have a valid logger. DecRef its item and recurse on next */
   314         logger->callback = NULL;
   315         PKIX_DECREF(logger->context);
   316         logger->logComponent = (PKIX_ERRORCLASS)NULL;
   318 cleanup:
   320         PKIX_RETURN(LOGGER);
   321 }
   323 /*
   324  * FUNCTION: pkix_Logger_ToString
   325  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   326  */
   327 static PKIX_Error *
   328 pkix_Logger_ToString(
   329         PKIX_PL_Object *object,
   330         PKIX_PL_String **pString,
   331         void *plContext)
   332 {
   333         PKIX_Logger *logger = NULL;
   334         char *asciiFormat = NULL;
   335         PKIX_PL_String *formatString = NULL;
   336         PKIX_PL_String *contextString = NULL;
   337         PKIX_PL_String *componentString = NULL;
   338         PKIX_PL_String *loggerString = NULL;
   340         PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
   341         PKIX_NULLCHECK_TWO(object, pString);
   343         /* Check that this object is a logger */
   344         PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   345                     PKIX_OBJECTNOTLOGGER);
   347         logger = (PKIX_Logger *)object;
   349         asciiFormat =
   350                 "[\n"
   351                 "\tLogger: \n"
   352                 "\tContext:          %s\n"
   353                 "\tMaximum Level:    %d\n"
   354                 "\tComponent Name:   %s\n"
   355                 "]\n";
   357         PKIX_CHECK(PKIX_PL_String_Create
   358                     (PKIX_ESCASCII,
   359                     asciiFormat,
   360                     0,
   361                     &formatString,
   362                     plContext),
   363                     PKIX_STRINGCREATEFAILED);
   365         PKIX_TOSTRING(logger->context, &contextString, plContext,
   366                 PKIX_OBJECTTOSTRINGFAILED);
   368         PKIX_CHECK(PKIX_PL_String_Create
   369                 (PKIX_ESCASCII,
   370                 (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
   371                 0,
   372                 &componentString,
   373                 plContext),
   374                 PKIX_STRINGCREATEFAILED);
   376         PKIX_CHECK(PKIX_PL_Sprintf
   377                 (&loggerString,
   378                 plContext,
   379                 formatString,
   380                 contextString,
   381                 logger->maxLevel,
   382                 componentString),
   383                 PKIX_SPRINTFFAILED);
   385         *pString = loggerString;
   387 cleanup:
   389         PKIX_DECREF(formatString);
   390         PKIX_DECREF(contextString);
   391         PKIX_RETURN(LOGGER);
   392 }
   394 /*
   395  * FUNCTION: pkix_Logger_Equals
   396  * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
   397  */
   398 static PKIX_Error *
   399 pkix_Logger_Equals(
   400         PKIX_PL_Object *first,
   401         PKIX_PL_Object *second,
   402         PKIX_Boolean *pResult,
   403         void *plContext)
   404 {
   405         PKIX_UInt32 secondType;
   406         PKIX_Boolean cmpResult;
   407         PKIX_Logger *firstLogger = NULL;
   408         PKIX_Logger *secondLogger = NULL;
   410         PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
   411         PKIX_NULLCHECK_THREE(first, second, pResult);
   413         /* test that first is a Logger */
   414         PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
   415                 PKIX_FIRSTOBJECTNOTLOGGER);
   417         /*
   418          * Since we know first is a Logger, if both references are
   419          * identical, they must be equal
   420          */
   421         if (first == second){
   422                 *pResult = PKIX_TRUE;
   423                 goto cleanup;
   424         }
   426         /*
   427          * If second isn't a Logger, we don't throw an error.
   428          * We simply return a Boolean result of FALSE
   429          */
   430         *pResult = PKIX_FALSE;
   431         PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
   432                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
   433         if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
   435         firstLogger = (PKIX_Logger *)first;
   436         secondLogger = (PKIX_Logger *)second;
   438         cmpResult = PKIX_FALSE;
   440         if (firstLogger->callback != secondLogger->callback) {
   441                 goto cleanup;
   442         }
   444         if (firstLogger->logComponent != secondLogger->logComponent) {
   445                 goto cleanup;
   446         }
   448         PKIX_EQUALS  
   449                 (firstLogger->context,
   450                 secondLogger->context,
   451                 &cmpResult,
   452                 plContext,
   453                 PKIX_OBJECTEQUALSFAILED);
   455         if (cmpResult == PKIX_FALSE) {
   456                 goto cleanup;
   457         }
   459         if (firstLogger->maxLevel != secondLogger->maxLevel) {
   460                 goto cleanup;
   461         }
   463         *pResult = cmpResult;
   465 cleanup:
   467         PKIX_RETURN(LOGGER);
   468 }
   470 /*
   471  * FUNCTION: pkix_Logger_Hashcode
   472  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
   473  */
   474 static PKIX_Error *
   475 pkix_Logger_Hashcode(
   476         PKIX_PL_Object *object,
   477         PKIX_UInt32 *pHashcode,
   478         void *plContext)
   479 {
   480         PKIX_Logger *logger = NULL;
   481         PKIX_UInt32 hash = 0;
   482         PKIX_UInt32 tempHash = 0;
   484         PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
   485         PKIX_NULLCHECK_TWO(object, pHashcode);
   487         PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   488                     PKIX_OBJECTNOTLOGGER);
   490         logger = (PKIX_Logger *)object;
   492         PKIX_HASHCODE(logger->context, &tempHash, plContext,
   493                 PKIX_OBJECTHASHCODEFAILED);
   495         hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) +
   496                 logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
   498         *pHashcode = hash;
   500 cleanup:
   502         PKIX_RETURN(LOGGER);
   503 }
   506 /*
   507  * FUNCTION: pkix_Logger_Duplicate
   508  * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
   509  */
   510 static PKIX_Error *
   511 pkix_Logger_Duplicate(
   512         PKIX_PL_Object *object,
   513         PKIX_PL_Object **pNewObject,
   514         void *plContext)
   515 {
   516         PKIX_Logger *logger = NULL;
   517         PKIX_Logger *dupLogger = NULL;
   519         PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
   520         PKIX_NULLCHECK_TWO(object, pNewObject);
   522         PKIX_CHECK(pkix_CheckType
   523                     ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
   524                     PKIX_OBJECTNOTLOGGER);
   526         logger = (PKIX_Logger *) object;
   528         PKIX_CHECK(PKIX_PL_Object_Alloc
   529                     (PKIX_LOGGER_TYPE,
   530                     sizeof (PKIX_Logger),
   531                     (PKIX_PL_Object **)&dupLogger,
   532                     plContext),
   533                     PKIX_COULDNOTCREATELOGGEROBJECT);
   535         dupLogger->callback = logger->callback;
   536         dupLogger->maxLevel = logger->maxLevel;
   538         PKIX_DUPLICATE
   539                     (logger->context,
   540                     &dupLogger->context,
   541                     plContext,
   542                     PKIX_OBJECTDUPLICATEFAILED);
   544         dupLogger->logComponent = logger->logComponent;
   546         *pNewObject = (PKIX_PL_Object *) dupLogger;
   548 cleanup:
   550         if (PKIX_ERROR_RECEIVED){
   551                 PKIX_DECREF(dupLogger);
   552         }
   554         PKIX_RETURN(LOGGER);
   555 }
   557 /*
   558  * FUNCTION: pkix_Logger_RegisterSelf
   559  * DESCRIPTION:
   560  *  Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
   561  * THREAD SAFETY:
   562  *  Not Thread Safe - for performance and complexity reasons
   563  *
   564  *  Since this function is only called by PKIX_PL_Initialize, which should
   565  *  only be called once, it is acceptable that this function is not
   566  *  thread-safe.
   567  */
   568 PKIX_Error *
   569 pkix_Logger_RegisterSelf(void *plContext)
   570 {
   571         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   572         pkix_ClassTable_Entry entry;
   574         PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
   576         entry.description = "Logger";
   577         entry.objCounter = 0;
   578         entry.typeObjectSize = sizeof(PKIX_Logger);
   579         entry.destructor = pkix_Logger_Destroy;
   580         entry.equalsFunction = pkix_Logger_Equals;
   581         entry.hashcodeFunction = pkix_Logger_Hashcode;
   582         entry.toStringFunction = pkix_Logger_ToString;
   583         entry.comparator = NULL;
   584         entry.duplicateFunction = pkix_Logger_Duplicate;
   586         systemClasses[PKIX_LOGGER_TYPE] = entry;
   588         PKIX_RETURN(LOGGER);
   589 }
   591 /* --Public-Logger-Functions--------------------------------------------- */
   593 /*
   594  * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
   595  */
   596 PKIX_Error *
   597 PKIX_Logger_Create(
   598         PKIX_Logger_LogCallback callback,
   599         PKIX_PL_Object *loggerContext,
   600         PKIX_Logger **pLogger,
   601         void *plContext)
   602 {
   603         PKIX_Logger *logger = NULL;
   605         PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
   606         PKIX_NULLCHECK_ONE(pLogger);
   608         PKIX_CHECK(PKIX_PL_Object_Alloc
   609                     (PKIX_LOGGER_TYPE,
   610                     sizeof (PKIX_Logger),
   611                     (PKIX_PL_Object **)&logger,
   612                     plContext),
   613                     PKIX_COULDNOTCREATELOGGEROBJECT);
   615         logger->callback = callback;
   616         logger->maxLevel = 0;
   617         logger->logComponent = (PKIX_ERRORCLASS)NULL;
   619         PKIX_INCREF(loggerContext);
   620         logger->context = loggerContext;
   622         *pLogger = logger;
   623         logger = NULL;
   625 cleanup:
   627         PKIX_DECREF(logger);
   629         PKIX_RETURN(LOGGER);
   630 }
   632 /*
   633  * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
   634  */
   635 PKIX_Error *
   636 PKIX_Logger_GetLogCallback(
   637         PKIX_Logger *logger,
   638         PKIX_Logger_LogCallback *pCallback,
   639         void *plContext)
   640 {
   641         PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
   642         PKIX_NULLCHECK_TWO(logger, pCallback);
   644         *pCallback = logger->callback;
   646         PKIX_RETURN(LOGGER);
   647 }
   649 /*
   650  * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
   651  */
   652 PKIX_Error *
   653 PKIX_Logger_GetLoggerContext(
   654         PKIX_Logger *logger,
   655         PKIX_PL_Object **pLoggerContext,
   656         void *plContext)
   657 {
   658         PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
   659         PKIX_NULLCHECK_TWO(logger, pLoggerContext);
   661         PKIX_INCREF(logger->context);
   662         *pLoggerContext = logger->context;
   664 cleanup:
   665         PKIX_RETURN(LOGGER);
   666 }
   668 /*
   669  * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
   670  */
   671 PKIX_Error *
   672 PKIX_Logger_GetMaxLoggingLevel(
   673         PKIX_Logger *logger,
   674         PKIX_UInt32 *pLevel,
   675         void *plContext)
   676 {
   677         PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
   678         PKIX_NULLCHECK_TWO(logger, pLevel);
   680         *pLevel = logger->maxLevel;
   682         PKIX_RETURN(LOGGER);
   683 }
   685 /*
   686  * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
   687  */
   688 PKIX_Error *
   689 PKIX_Logger_SetMaxLoggingLevel(
   690         PKIX_Logger *logger,
   691         PKIX_UInt32 level,
   692         void *plContext)
   693 {
   694         PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
   695         PKIX_NULLCHECK_ONE(logger);
   697         if (level > PKIX_LOGGER_LEVEL_MAX) {
   698                 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
   699         } else {
   700                 logger->maxLevel = level;
   701         }
   703 cleanup:
   705         PKIX_RETURN(LOGGER);
   706 }
   708 /*
   709  * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
   710  */
   711 PKIX_Error *
   712 PKIX_Logger_GetLoggingComponent(
   713         PKIX_Logger *logger,
   714         PKIX_ERRORCLASS *pComponent,
   715         void *plContext)
   716 {
   717         PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
   718         PKIX_NULLCHECK_TWO(logger, pComponent);
   720         *pComponent = logger->logComponent;
   722         PKIX_RETURN(LOGGER);
   723 }
   725 /*
   726  * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
   727  */
   728 PKIX_Error *
   729 PKIX_Logger_SetLoggingComponent(
   730         PKIX_Logger *logger,
   731         PKIX_ERRORCLASS component,
   732         void *plContext)
   733 {
   734         PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
   735         PKIX_NULLCHECK_ONE(logger);
   737         logger->logComponent = component;
   739         PKIX_RETURN(LOGGER);
   740 }
   743 /*
   744  * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
   745  * documented as not thread-safe. However they are thread-safe now. We need
   746  * the lock when accessing the logger lists.
   747  */
   749 /*
   750  * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
   751  */
   752 PKIX_Error *
   753 PKIX_GetLoggers(
   754         PKIX_List **pLoggers,  /* list of PKIX_Logger */
   755         void *plContext)
   756 {
   757         PKIX_List *list = NULL;
   758         PKIX_List *savedPkixLoggersDebugTrace = NULL;
   759         PKIX_List *savedPkixLoggersErrors = NULL;
   760         PKIX_Logger *logger = NULL;
   761         PKIX_Logger *dupLogger = NULL;
   762         PKIX_UInt32 i, length;
   763         PKIX_Boolean locked = PKIX_FALSE;
   765         PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
   766         PKIX_NULLCHECK_ONE(pLoggers);
   768         PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   769                 PKIX_MONITORLOCKENTERFAILED);
   770         locked = PKIX_TRUE;
   772         /*
   773          * Temporarily disable DEBUG/TRACE Logging to avoid possible
   774          * deadlock:
   775          * When the Logger List is being accessed, e.g. by PKIX_ENTER or
   776          * PKIX_DECREF, pkix_Logger_Check may check whether logging
   777          * is requested, creating a deadlock situation.
   778          */
   779         savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   780         pkixLoggersDebugTrace = NULL;
   781         savedPkixLoggersErrors = pkixLoggersErrors;
   782         pkixLoggersErrors = NULL;
   784         if (pkixLoggers == NULL) {
   785                 length = 0;
   786         } else {
   787                 PKIX_CHECK(PKIX_List_GetLength
   788                     (pkixLoggers, &length, plContext),
   789                     PKIX_LISTGETLENGTHFAILED);
   790         }
   792         /* Create a list and copy the pkixLoggers item to the list */
   793         PKIX_CHECK(PKIX_List_Create(&list, plContext),
   794                     PKIX_LISTCREATEFAILED);
   796         for (i = 0; i < length; i++) {
   798             PKIX_CHECK(PKIX_List_GetItem
   799                         (pkixLoggers,
   800                         i,
   801                         (PKIX_PL_Object **) &logger,
   802                         plContext),
   803                         PKIX_LISTGETITEMFAILED);
   805             PKIX_CHECK(pkix_Logger_Duplicate
   806                         ((PKIX_PL_Object *)logger,
   807                         (PKIX_PL_Object **)&dupLogger,
   808                         plContext),
   809                         PKIX_LOGGERDUPLICATEFAILED);
   811             PKIX_CHECK(PKIX_List_AppendItem
   812                         (list,
   813                         (PKIX_PL_Object *) dupLogger,
   814                         plContext),
   815                         PKIX_LISTAPPENDITEMFAILED);
   817             PKIX_DECREF(logger);
   818             PKIX_DECREF(dupLogger);
   819         }
   821         /* Set the list to be immutable */
   822         PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
   823                         PKIX_LISTSETIMMUTABLEFAILED);
   825         *pLoggers = list;
   827 cleanup:
   829         PKIX_DECREF(logger);
   831         /* Restore logging capability */
   832         pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   833         pkixLoggersErrors = savedPkixLoggersErrors;
   835         if (locked) {
   836                 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
   837                         PKIX_MONITORLOCKEXITFAILED);
   838         }
   840         PKIX_RETURN(LOGGER);
   841 }
   843 /*
   844  * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
   845  */
   846 PKIX_Error *
   847 PKIX_SetLoggers(
   848         PKIX_List *loggers,  /* list of PKIX_Logger */
   849         void *plContext)
   850 {
   851         PKIX_List *list = NULL;
   852         PKIX_List *savedPkixLoggersErrors = NULL;
   853         PKIX_List *savedPkixLoggersDebugTrace = NULL;
   854         PKIX_Logger *logger = NULL;
   855         PKIX_Logger *dupLogger = NULL;
   856         PKIX_Boolean locked = PKIX_FALSE;
   857         PKIX_UInt32 i, length;
   859         PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
   861         PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   862                 PKIX_MONITORLOCKENTERFAILED);
   863         locked = PKIX_TRUE;
   865         /* Disable tracing, etc. to avoid recursion and deadlock */
   866         savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   867         pkixLoggersDebugTrace = NULL;
   868         savedPkixLoggersErrors = pkixLoggersErrors;
   869         pkixLoggersErrors = NULL;
   871         /* discard any prior loggers */
   872         PKIX_DECREF(pkixLoggers);
   873         PKIX_DECREF(savedPkixLoggersErrors);
   874         PKIX_DECREF(savedPkixLoggersDebugTrace);
   876         if (loggers != NULL) {
   878                 PKIX_CHECK(PKIX_List_Create(&list, plContext),
   879                     PKIX_LISTCREATEFAILED);
   881                 PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
   882                     PKIX_LISTGETLENGTHFAILED);
   884                 for (i = 0; i < length; i++) {
   886                     PKIX_CHECK(PKIX_List_GetItem
   887                         (loggers,
   888                         i,
   889                         (PKIX_PL_Object **) &logger,
   890                         plContext),
   891                         PKIX_LISTGETITEMFAILED);
   893                     PKIX_CHECK(pkix_Logger_Duplicate
   894                         ((PKIX_PL_Object *)logger,
   895                         (PKIX_PL_Object **)&dupLogger,
   896                         plContext),
   897                         PKIX_LOGGERDUPLICATEFAILED);
   899                     PKIX_CHECK(PKIX_List_AppendItem
   900                         (list,
   901                         (PKIX_PL_Object *) dupLogger,
   902                         plContext),
   903                         PKIX_LISTAPPENDITEMFAILED);
   905                     /* Make two lists */
   907                     /* Put in pkixLoggersErrors in any case*/
   909                     if (savedPkixLoggersErrors == NULL) {
   911                         PKIX_CHECK(PKIX_List_Create
   912                                 (&savedPkixLoggersErrors,
   913                                 plContext),
   914                                 PKIX_LISTCREATEFAILED);
   915                     }
   917                     PKIX_CHECK(PKIX_List_AppendItem
   918                             (savedPkixLoggersErrors,
   919                             (PKIX_PL_Object *) dupLogger,
   920                             plContext),
   921                             PKIX_LISTAPPENDITEMFAILED);
   923                     if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
   925                         /* Put in pkixLoggersDebugTrace */
   927                         if (savedPkixLoggersDebugTrace == NULL) {
   929                             PKIX_CHECK(PKIX_List_Create
   930                                     (&savedPkixLoggersDebugTrace,
   931                                     plContext),
   932                                     PKIX_LISTCREATEFAILED);
   933                         }
   935                         PKIX_CHECK(PKIX_List_AppendItem
   936                                 (savedPkixLoggersDebugTrace,
   937                                 (PKIX_PL_Object *) dupLogger,
   938                                 plContext),
   939                                 PKIX_LISTAPPENDITEMFAILED);
   940                     }
   941                     PKIX_DECREF(logger);
   942                     PKIX_DECREF(dupLogger);
   944                 }
   946                 pkixLoggers = list;
   947         }
   949 cleanup:
   951         if (PKIX_ERROR_RECEIVED){
   952                 PKIX_DECREF(list);
   953                 PKIX_DECREF(savedPkixLoggersErrors);
   954                 PKIX_DECREF(savedPkixLoggersDebugTrace);
   955                 pkixLoggers = NULL;
   956         }
   958         PKIX_DECREF(logger);
   960         /* Reenable logging capability with new lists */
   961         pkixLoggersErrors = savedPkixLoggersErrors;
   962         pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   964         if (locked) {
   965                 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
   966                         PKIX_MONITORLOCKEXITFAILED);
   967         }
   969         PKIX_RETURN(LOGGER);
   970 }
   972 /*
   973  * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
   974  */
   975 PKIX_Error *
   976 PKIX_AddLogger(
   977         PKIX_Logger *logger,
   978         void *plContext)
   979 {
   980         PKIX_Logger *dupLogger = NULL;
   981         PKIX_Logger *addLogger = NULL;
   982         PKIX_List *savedPkixLoggersErrors = NULL;
   983         PKIX_List *savedPkixLoggersDebugTrace = NULL;
   984         PKIX_Boolean locked = PKIX_FALSE;
   985         PKIX_UInt32 i, length;
   987         PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
   988         PKIX_NULLCHECK_ONE(logger);
   990         PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   991                 PKIX_MONITORLOCKENTERFAILED);
   992         locked = PKIX_TRUE;
   994         savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   995         pkixLoggersDebugTrace = NULL;
   996         savedPkixLoggersErrors = pkixLoggersErrors;
   997         pkixLoggersErrors = NULL;
   999         PKIX_DECREF(savedPkixLoggersErrors);
  1000         PKIX_DECREF(savedPkixLoggersDebugTrace);
  1002         if (pkixLoggers == NULL) {
  1004             PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
  1005                     PKIX_LISTCREATEFAILED);
  1008         PKIX_CHECK(pkix_Logger_Duplicate
  1009                     ((PKIX_PL_Object *)logger,
  1010                     (PKIX_PL_Object **)&dupLogger,
  1011                     plContext),
  1012                     PKIX_LOGGERDUPLICATEFAILED);
  1014         PKIX_CHECK(PKIX_List_AppendItem
  1015                     (pkixLoggers,
  1016                     (PKIX_PL_Object *) dupLogger,
  1017                     plContext),
  1018                     PKIX_LISTAPPENDITEMFAILED);
  1020         PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
  1021                     PKIX_LISTGETLENGTHFAILED);
  1023         /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
  1024         for (i = 0; i < length; i++) {
  1026                 PKIX_CHECK(PKIX_List_GetItem
  1027                         (pkixLoggers,
  1028                         i,
  1029                         (PKIX_PL_Object **) &addLogger,
  1030                         plContext),
  1031                         PKIX_LISTGETITEMFAILED);
  1034                 /* Put in pkixLoggersErrors */
  1036                 if (savedPkixLoggersErrors == NULL) {
  1038                         PKIX_CHECK(PKIX_List_Create
  1039                                     (&savedPkixLoggersErrors,
  1040                                     plContext),
  1041                                     PKIX_LISTCREATEFAILED);
  1044                 PKIX_CHECK(PKIX_List_AppendItem
  1045                         (savedPkixLoggersErrors,
  1046                         (PKIX_PL_Object *) addLogger,
  1047                         plContext),
  1048                         PKIX_LISTAPPENDITEMFAILED);
  1050                 if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
  1052                         /* Put in pkixLoggersDebugTrace */
  1054                         if (savedPkixLoggersDebugTrace == NULL) {
  1056                             PKIX_CHECK(PKIX_List_Create
  1057                                     (&savedPkixLoggersDebugTrace,
  1058                                     plContext),
  1059                                     PKIX_LISTCREATEFAILED);
  1062                         PKIX_CHECK(PKIX_List_AppendItem
  1063                                 (savedPkixLoggersDebugTrace,
  1064                                 (PKIX_PL_Object *) addLogger,
  1065                                 plContext),
  1066                                 PKIX_LISTAPPENDITEMFAILED);
  1069                 PKIX_DECREF(addLogger);
  1073 cleanup:
  1075         PKIX_DECREF(dupLogger);
  1076         PKIX_DECREF(addLogger);
  1078         /* Restore logging capability */
  1079         pkixLoggersErrors = savedPkixLoggersErrors;
  1080         pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  1082         if (locked) {
  1083                 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
  1084                         PKIX_MONITORLOCKEXITFAILED);
  1087        PKIX_RETURN(LOGGER);

mercurial