1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1088 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * pkix_logger.c 1.9 + * 1.10 + * Logger Object Functions 1.11 + * 1.12 + */ 1.13 + 1.14 +#include "pkix_logger.h" 1.15 +#ifndef PKIX_ERROR_DESCRIPTION 1.16 +#include "prprf.h" 1.17 +#endif 1.18 + 1.19 +/* Global variable to keep PKIX_Logger List */ 1.20 +PKIX_List *pkixLoggers = NULL; 1.21 + 1.22 +/* 1.23 + * Once the Logger has been set, for any logging related operations, we have 1.24 + * to go through the List to find a match, and if found, issue the 1.25 + * corresponding callback. The overhead to check for DEBUG and TRACE in each 1.26 + * PKIX function entering and exiting is very expensive (400X), and redundant 1.27 + * if they are not the interest of the Logger. Therefore, the PKIX_Logger List 1.28 + * pkixLoggers is separated into two lists based on its Loggers' trace level. 1.29 + * 1.30 + * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or 1.31 + * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors 1.32 + * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and 1.33 + * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to 1.34 + * pkixLoggersDebugTrace. 1.35 + * 1.36 + * Currently we provide five logging levels and the default setting are by: 1.37 + * 1.38 + * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level 1.39 + * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level 1.40 + * WARNING is not invoked as default 1.41 + * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs 1.42 + * compilation -DPKIX_<component>DEBUG flag to turn on 1.43 + * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE 1.44 + * level. TRACE provides duplicate information of DEBUG, but needs no 1.45 + * recompilation and cannot choose component. To allow application 1.46 + * to use DEBUG level, TRACE is put as last. 1.47 + * 1.48 + */ 1.49 +PKIX_List *pkixLoggersErrors = NULL; 1.50 +PKIX_List *pkixLoggersDebugTrace = NULL; 1.51 + 1.52 +/* To ensure atomic update on pkixLoggers lists */ 1.53 +PKIX_PL_MonitorLock *pkixLoggerLock = NULL; 1.54 + 1.55 +/* --Private-Functions-------------------------------------------- */ 1.56 + 1.57 +/* 1.58 + * FUNCTION: pkix_Logger_CheckErrors 1.59 + * DESCRIPTION: 1.60 + * 1.61 + * This function goes through each PKIX_Logger at "pkixLoggersList" and 1.62 + * checks if "maxLevel" and "logComponent" satisfies what is specified in the 1.63 + * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and 1.64 + * passes a PKIX_PL_String that is the concatenation of "message" and 1.65 + * "message2" to the application for processing. 1.66 + * Since this call is inserted into a handful of PKIX macros, no macros are 1.67 + * applied in this function, to avoid infinite recursion. 1.68 + * If an error occurs, this call is aborted. 1.69 + * 1.70 + * PARAMETERS: 1.71 + * "pkixLoggersList" 1.72 + * A list of PKIX_Loggers to be examined for invoking callback. Must be 1.73 + * non-NULL. 1.74 + * "message" 1.75 + * Address of "message" to be logged. Must be non-NULL. 1.76 + * "message2" 1.77 + * Address of "message2" to be concatenated and logged. May be NULL. 1.78 + * "logComponent" 1.79 + * A PKIX_UInt32 that indicates the component the message is from. 1.80 + * "maxLevel" 1.81 + * A PKIX_UInt32 that represents the level of severity of the message. 1.82 + * "plContext" 1.83 + * Platform-specific context pointer. 1.84 + * THREAD SAFETY: 1.85 + * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 1.86 + * RETURNS: 1.87 + * Returns NULL if the function succeeds 1.88 + * Returns a Fatal Error if the function fails in an unrecoverable way 1.89 + */ 1.90 +PKIX_Error * 1.91 +pkix_Logger_Check( 1.92 + PKIX_List *pkixLoggersList, 1.93 + const char *message, 1.94 + const char *message2, 1.95 + PKIX_ERRORCLASS logComponent, 1.96 + PKIX_UInt32 currentLevel, 1.97 + void *plContext) 1.98 +{ 1.99 + PKIX_Logger *logger = NULL; 1.100 + PKIX_List *savedPkixLoggersErrors = NULL; 1.101 + PKIX_List *savedPkixLoggersDebugTrace = NULL; 1.102 + PKIX_PL_String *formatString = NULL; 1.103 + PKIX_PL_String *messageString = NULL; 1.104 + PKIX_PL_String *message2String = NULL; 1.105 + PKIX_PL_String *msgString = NULL; 1.106 + PKIX_Error *error = NULL; 1.107 + PKIX_Boolean needLogging = PKIX_FALSE; 1.108 + PKIX_UInt32 i, length; 1.109 + 1.110 + /* 1.111 + * We cannot use any the PKIX_ macros here, since this function is 1.112 + * called from some of these macros. It can create infinite recursion. 1.113 + */ 1.114 + 1.115 + if ((pkixLoggersList == NULL) || (message == NULL)) { 1.116 + return(NULL); 1.117 + } 1.118 + 1.119 + /* 1.120 + * Disable all subsequent loggings to avoid recursion. The result is 1.121 + * if other thread is calling this function at the same time, there 1.122 + * won't be any logging because the pkixLoggersErrors and 1.123 + * pkixLoggersDebugTrace are set to null. 1.124 + * It would be nice if we provide control per thread (e.g. make 1.125 + * plContext threadable) then we can avoid the recursion by setting 1.126 + * flag at plContext. Then other thread's logging won't be affected. 1.127 + * 1.128 + * Also we need to use a reentrant Lock. Although we avoid recursion 1.129 + * for TRACE. When there is an ERROR occurs in subsequent call, this 1.130 + * function will be called. 1.131 + */ 1.132 + 1.133 + error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext); 1.134 + if (error) { return(NULL); } 1.135 + 1.136 + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 1.137 + pkixLoggersDebugTrace = NULL; 1.138 + savedPkixLoggersErrors = pkixLoggersErrors; 1.139 + pkixLoggersErrors = NULL; 1.140 + 1.141 + /* Convert message and message2 to String */ 1.142 + error = PKIX_PL_String_Create 1.143 + (PKIX_ESCASCII, message, 0, &messageString, plContext); 1.144 + if (error) { goto cleanup; } 1.145 + 1.146 + if (message2) { 1.147 + error = PKIX_PL_String_Create 1.148 + (PKIX_ESCASCII, message2, 0, &message2String, plContext); 1.149 + if (error) { goto cleanup; } 1.150 + error = PKIX_PL_String_Create 1.151 + (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext); 1.152 + if (error) { goto cleanup; } 1.153 + 1.154 + } else { 1.155 + error = PKIX_PL_String_Create 1.156 + (PKIX_ESCASCII, "%s", 0, &formatString, plContext); 1.157 + if (error) { goto cleanup; } 1.158 + 1.159 + } 1.160 + 1.161 + error = PKIX_PL_Sprintf 1.162 + (&msgString, 1.163 + plContext, 1.164 + formatString, 1.165 + messageString, 1.166 + message2String); 1.167 + if (error) { goto cleanup; } 1.168 + 1.169 + /* Go through the Logger list */ 1.170 + 1.171 + error = PKIX_List_GetLength(pkixLoggersList, &length, plContext); 1.172 + if (error) { goto cleanup; } 1.173 + 1.174 + for (i = 0; i < length; i++) { 1.175 + 1.176 + error = PKIX_List_GetItem 1.177 + (pkixLoggersList, 1.178 + i, 1.179 + (PKIX_PL_Object **) &logger, 1.180 + plContext); 1.181 + if (error) { goto cleanup; } 1.182 + 1.183 + /* Intended logging level less or equal than the max */ 1.184 + needLogging = (currentLevel <= logger->maxLevel); 1.185 + 1.186 + if (needLogging && (logger->callback)) { 1.187 + 1.188 + /* 1.189 + * We separate Logger into two lists based on log level 1.190 + * but log level is not modified. We need to check here to 1.191 + * avoid logging the higher log level (lower value) twice. 1.192 + */ 1.193 + if (pkixLoggersList == pkixLoggersErrors) { 1.194 + needLogging = needLogging && 1.195 + (currentLevel <= PKIX_LOGGER_LEVEL_WARNING); 1.196 + } else if (pkixLoggersList == pkixLoggersDebugTrace) { 1.197 + needLogging = needLogging && 1.198 + (currentLevel > PKIX_LOGGER_LEVEL_WARNING); 1.199 + } 1.200 + 1.201 + if (needLogging) { 1.202 + if (logComponent == logger->logComponent) { 1.203 + needLogging = PKIX_TRUE; 1.204 + } else { 1.205 + needLogging = PKIX_FALSE; 1.206 + } 1.207 + } 1.208 + 1.209 + if (needLogging) { 1.210 + error = logger->callback 1.211 + (logger, 1.212 + msgString, 1.213 + currentLevel, 1.214 + logComponent, 1.215 + plContext); 1.216 + if (error) { goto cleanup; } 1.217 + } 1.218 + } 1.219 + 1.220 + error = PKIX_PL_Object_DecRef 1.221 + ((PKIX_PL_Object *)logger, plContext); 1.222 + logger = NULL; 1.223 + if (error) { goto cleanup; } 1.224 + 1.225 + } 1.226 + 1.227 +cleanup: 1.228 + 1.229 + if (formatString) { 1.230 + error = PKIX_PL_Object_DecRef 1.231 + ((PKIX_PL_Object *)formatString, plContext); 1.232 + } 1.233 + 1.234 + if (messageString) { 1.235 + error = PKIX_PL_Object_DecRef 1.236 + ((PKIX_PL_Object *)messageString, plContext); 1.237 + } 1.238 + 1.239 + if (message2String) { 1.240 + error = PKIX_PL_Object_DecRef 1.241 + ((PKIX_PL_Object *)message2String, plContext); 1.242 + } 1.243 + 1.244 + if (msgString) { 1.245 + error = PKIX_PL_Object_DecRef 1.246 + ((PKIX_PL_Object *)msgString, plContext); 1.247 + } 1.248 + 1.249 + if (logger) { 1.250 + error = PKIX_PL_Object_DecRef 1.251 + ((PKIX_PL_Object *)logger, plContext); 1.252 + } 1.253 + 1.254 + if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) { 1.255 + pkixLoggersErrors = savedPkixLoggersErrors; 1.256 + } 1.257 + 1.258 + if (pkixLoggersDebugTrace == NULL && 1.259 + savedPkixLoggersDebugTrace != NULL) { 1.260 + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 1.261 + } 1.262 + 1.263 + error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext); 1.264 + if (error) { return(NULL); } 1.265 + 1.266 + return(NULL); 1.267 +} 1.268 + 1.269 +PKIX_Error * 1.270 +pkix_Logger_CheckWithCode( 1.271 + PKIX_List *pkixLoggersList, 1.272 + PKIX_UInt32 errorCode, 1.273 + const char *message2, 1.274 + PKIX_ERRORCLASS logComponent, 1.275 + PKIX_UInt32 currentLevel, 1.276 + void *plContext) 1.277 +{ 1.278 + char error[32]; 1.279 + char *errorString = NULL; 1.280 + 1.281 + PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode"); 1.282 +#if defined PKIX_ERROR_DESCRIPTION 1.283 + errorString = PKIX_ErrorText[errorCode]; 1.284 +#else 1.285 + PR_snprintf(error, 32, "Error code: %d", errorCode); 1.286 + errorString = error; 1.287 +#endif /* PKIX_ERROR_DESCRIPTION */ 1.288 + 1.289 + pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString, 1.290 + message2, logComponent, 1.291 + currentLevel, plContext); 1.292 + PKIX_RETURN(LOGGER); 1.293 +} 1.294 + 1.295 +/* 1.296 + * FUNCTION: pkix_Logger_Destroy 1.297 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 1.298 + */ 1.299 +static PKIX_Error * 1.300 +pkix_Logger_Destroy( 1.301 + PKIX_PL_Object *object, 1.302 + void *plContext) 1.303 +{ 1.304 + PKIX_Logger *logger = NULL; 1.305 + 1.306 + PKIX_ENTER(LOGGER, "pkix_Logger_Destroy"); 1.307 + PKIX_NULLCHECK_ONE(object); 1.308 + 1.309 + /* Check that this object is a logger */ 1.310 + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 1.311 + PKIX_OBJECTNOTLOGGER); 1.312 + 1.313 + logger = (PKIX_Logger *)object; 1.314 + 1.315 + /* We have a valid logger. DecRef its item and recurse on next */ 1.316 + 1.317 + logger->callback = NULL; 1.318 + PKIX_DECREF(logger->context); 1.319 + logger->logComponent = (PKIX_ERRORCLASS)NULL; 1.320 + 1.321 +cleanup: 1.322 + 1.323 + PKIX_RETURN(LOGGER); 1.324 +} 1.325 + 1.326 +/* 1.327 + * FUNCTION: pkix_Logger_ToString 1.328 + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) 1.329 + */ 1.330 +static PKIX_Error * 1.331 +pkix_Logger_ToString( 1.332 + PKIX_PL_Object *object, 1.333 + PKIX_PL_String **pString, 1.334 + void *plContext) 1.335 +{ 1.336 + PKIX_Logger *logger = NULL; 1.337 + char *asciiFormat = NULL; 1.338 + PKIX_PL_String *formatString = NULL; 1.339 + PKIX_PL_String *contextString = NULL; 1.340 + PKIX_PL_String *componentString = NULL; 1.341 + PKIX_PL_String *loggerString = NULL; 1.342 + 1.343 + PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper"); 1.344 + PKIX_NULLCHECK_TWO(object, pString); 1.345 + 1.346 + /* Check that this object is a logger */ 1.347 + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 1.348 + PKIX_OBJECTNOTLOGGER); 1.349 + 1.350 + logger = (PKIX_Logger *)object; 1.351 + 1.352 + asciiFormat = 1.353 + "[\n" 1.354 + "\tLogger: \n" 1.355 + "\tContext: %s\n" 1.356 + "\tMaximum Level: %d\n" 1.357 + "\tComponent Name: %s\n" 1.358 + "]\n"; 1.359 + 1.360 + PKIX_CHECK(PKIX_PL_String_Create 1.361 + (PKIX_ESCASCII, 1.362 + asciiFormat, 1.363 + 0, 1.364 + &formatString, 1.365 + plContext), 1.366 + PKIX_STRINGCREATEFAILED); 1.367 + 1.368 + PKIX_TOSTRING(logger->context, &contextString, plContext, 1.369 + PKIX_OBJECTTOSTRINGFAILED); 1.370 + 1.371 + PKIX_CHECK(PKIX_PL_String_Create 1.372 + (PKIX_ESCASCII, 1.373 + (void *)PKIX_ERRORCLASSNAMES[logger->logComponent], 1.374 + 0, 1.375 + &componentString, 1.376 + plContext), 1.377 + PKIX_STRINGCREATEFAILED); 1.378 + 1.379 + PKIX_CHECK(PKIX_PL_Sprintf 1.380 + (&loggerString, 1.381 + plContext, 1.382 + formatString, 1.383 + contextString, 1.384 + logger->maxLevel, 1.385 + componentString), 1.386 + PKIX_SPRINTFFAILED); 1.387 + 1.388 + *pString = loggerString; 1.389 + 1.390 +cleanup: 1.391 + 1.392 + PKIX_DECREF(formatString); 1.393 + PKIX_DECREF(contextString); 1.394 + PKIX_RETURN(LOGGER); 1.395 +} 1.396 + 1.397 +/* 1.398 + * FUNCTION: pkix_Logger_Equals 1.399 + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) 1.400 + */ 1.401 +static PKIX_Error * 1.402 +pkix_Logger_Equals( 1.403 + PKIX_PL_Object *first, 1.404 + PKIX_PL_Object *second, 1.405 + PKIX_Boolean *pResult, 1.406 + void *plContext) 1.407 +{ 1.408 + PKIX_UInt32 secondType; 1.409 + PKIX_Boolean cmpResult; 1.410 + PKIX_Logger *firstLogger = NULL; 1.411 + PKIX_Logger *secondLogger = NULL; 1.412 + 1.413 + PKIX_ENTER(LOGGER, "pkix_Logger_Equals"); 1.414 + PKIX_NULLCHECK_THREE(first, second, pResult); 1.415 + 1.416 + /* test that first is a Logger */ 1.417 + PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext), 1.418 + PKIX_FIRSTOBJECTNOTLOGGER); 1.419 + 1.420 + /* 1.421 + * Since we know first is a Logger, if both references are 1.422 + * identical, they must be equal 1.423 + */ 1.424 + if (first == second){ 1.425 + *pResult = PKIX_TRUE; 1.426 + goto cleanup; 1.427 + } 1.428 + 1.429 + /* 1.430 + * If second isn't a Logger, we don't throw an error. 1.431 + * We simply return a Boolean result of FALSE 1.432 + */ 1.433 + *pResult = PKIX_FALSE; 1.434 + PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), 1.435 + PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); 1.436 + if (secondType != PKIX_LOGGER_TYPE) goto cleanup; 1.437 + 1.438 + firstLogger = (PKIX_Logger *)first; 1.439 + secondLogger = (PKIX_Logger *)second; 1.440 + 1.441 + cmpResult = PKIX_FALSE; 1.442 + 1.443 + if (firstLogger->callback != secondLogger->callback) { 1.444 + goto cleanup; 1.445 + } 1.446 + 1.447 + if (firstLogger->logComponent != secondLogger->logComponent) { 1.448 + goto cleanup; 1.449 + } 1.450 + 1.451 + PKIX_EQUALS 1.452 + (firstLogger->context, 1.453 + secondLogger->context, 1.454 + &cmpResult, 1.455 + plContext, 1.456 + PKIX_OBJECTEQUALSFAILED); 1.457 + 1.458 + if (cmpResult == PKIX_FALSE) { 1.459 + goto cleanup; 1.460 + } 1.461 + 1.462 + if (firstLogger->maxLevel != secondLogger->maxLevel) { 1.463 + goto cleanup; 1.464 + } 1.465 + 1.466 + *pResult = cmpResult; 1.467 + 1.468 +cleanup: 1.469 + 1.470 + PKIX_RETURN(LOGGER); 1.471 +} 1.472 + 1.473 +/* 1.474 + * FUNCTION: pkix_Logger_Hashcode 1.475 + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 1.476 + */ 1.477 +static PKIX_Error * 1.478 +pkix_Logger_Hashcode( 1.479 + PKIX_PL_Object *object, 1.480 + PKIX_UInt32 *pHashcode, 1.481 + void *plContext) 1.482 +{ 1.483 + PKIX_Logger *logger = NULL; 1.484 + PKIX_UInt32 hash = 0; 1.485 + PKIX_UInt32 tempHash = 0; 1.486 + 1.487 + PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode"); 1.488 + PKIX_NULLCHECK_TWO(object, pHashcode); 1.489 + 1.490 + PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 1.491 + PKIX_OBJECTNOTLOGGER); 1.492 + 1.493 + logger = (PKIX_Logger *)object; 1.494 + 1.495 + PKIX_HASHCODE(logger->context, &tempHash, plContext, 1.496 + PKIX_OBJECTHASHCODEFAILED); 1.497 + 1.498 + hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) + 1.499 + logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent; 1.500 + 1.501 + *pHashcode = hash; 1.502 + 1.503 +cleanup: 1.504 + 1.505 + PKIX_RETURN(LOGGER); 1.506 +} 1.507 + 1.508 + 1.509 +/* 1.510 + * FUNCTION: pkix_Logger_Duplicate 1.511 + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) 1.512 + */ 1.513 +static PKIX_Error * 1.514 +pkix_Logger_Duplicate( 1.515 + PKIX_PL_Object *object, 1.516 + PKIX_PL_Object **pNewObject, 1.517 + void *plContext) 1.518 +{ 1.519 + PKIX_Logger *logger = NULL; 1.520 + PKIX_Logger *dupLogger = NULL; 1.521 + 1.522 + PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate"); 1.523 + PKIX_NULLCHECK_TWO(object, pNewObject); 1.524 + 1.525 + PKIX_CHECK(pkix_CheckType 1.526 + ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext), 1.527 + PKIX_OBJECTNOTLOGGER); 1.528 + 1.529 + logger = (PKIX_Logger *) object; 1.530 + 1.531 + PKIX_CHECK(PKIX_PL_Object_Alloc 1.532 + (PKIX_LOGGER_TYPE, 1.533 + sizeof (PKIX_Logger), 1.534 + (PKIX_PL_Object **)&dupLogger, 1.535 + plContext), 1.536 + PKIX_COULDNOTCREATELOGGEROBJECT); 1.537 + 1.538 + dupLogger->callback = logger->callback; 1.539 + dupLogger->maxLevel = logger->maxLevel; 1.540 + 1.541 + PKIX_DUPLICATE 1.542 + (logger->context, 1.543 + &dupLogger->context, 1.544 + plContext, 1.545 + PKIX_OBJECTDUPLICATEFAILED); 1.546 + 1.547 + dupLogger->logComponent = logger->logComponent; 1.548 + 1.549 + *pNewObject = (PKIX_PL_Object *) dupLogger; 1.550 + 1.551 +cleanup: 1.552 + 1.553 + if (PKIX_ERROR_RECEIVED){ 1.554 + PKIX_DECREF(dupLogger); 1.555 + } 1.556 + 1.557 + PKIX_RETURN(LOGGER); 1.558 +} 1.559 + 1.560 +/* 1.561 + * FUNCTION: pkix_Logger_RegisterSelf 1.562 + * DESCRIPTION: 1.563 + * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[] 1.564 + * THREAD SAFETY: 1.565 + * Not Thread Safe - for performance and complexity reasons 1.566 + * 1.567 + * Since this function is only called by PKIX_PL_Initialize, which should 1.568 + * only be called once, it is acceptable that this function is not 1.569 + * thread-safe. 1.570 + */ 1.571 +PKIX_Error * 1.572 +pkix_Logger_RegisterSelf(void *plContext) 1.573 +{ 1.574 + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 1.575 + pkix_ClassTable_Entry entry; 1.576 + 1.577 + PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf"); 1.578 + 1.579 + entry.description = "Logger"; 1.580 + entry.objCounter = 0; 1.581 + entry.typeObjectSize = sizeof(PKIX_Logger); 1.582 + entry.destructor = pkix_Logger_Destroy; 1.583 + entry.equalsFunction = pkix_Logger_Equals; 1.584 + entry.hashcodeFunction = pkix_Logger_Hashcode; 1.585 + entry.toStringFunction = pkix_Logger_ToString; 1.586 + entry.comparator = NULL; 1.587 + entry.duplicateFunction = pkix_Logger_Duplicate; 1.588 + 1.589 + systemClasses[PKIX_LOGGER_TYPE] = entry; 1.590 + 1.591 + PKIX_RETURN(LOGGER); 1.592 +} 1.593 + 1.594 +/* --Public-Logger-Functions--------------------------------------------- */ 1.595 + 1.596 +/* 1.597 + * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h) 1.598 + */ 1.599 +PKIX_Error * 1.600 +PKIX_Logger_Create( 1.601 + PKIX_Logger_LogCallback callback, 1.602 + PKIX_PL_Object *loggerContext, 1.603 + PKIX_Logger **pLogger, 1.604 + void *plContext) 1.605 +{ 1.606 + PKIX_Logger *logger = NULL; 1.607 + 1.608 + PKIX_ENTER(LOGGER, "PKIX_Logger_Create"); 1.609 + PKIX_NULLCHECK_ONE(pLogger); 1.610 + 1.611 + PKIX_CHECK(PKIX_PL_Object_Alloc 1.612 + (PKIX_LOGGER_TYPE, 1.613 + sizeof (PKIX_Logger), 1.614 + (PKIX_PL_Object **)&logger, 1.615 + plContext), 1.616 + PKIX_COULDNOTCREATELOGGEROBJECT); 1.617 + 1.618 + logger->callback = callback; 1.619 + logger->maxLevel = 0; 1.620 + logger->logComponent = (PKIX_ERRORCLASS)NULL; 1.621 + 1.622 + PKIX_INCREF(loggerContext); 1.623 + logger->context = loggerContext; 1.624 + 1.625 + *pLogger = logger; 1.626 + logger = NULL; 1.627 + 1.628 +cleanup: 1.629 + 1.630 + PKIX_DECREF(logger); 1.631 + 1.632 + PKIX_RETURN(LOGGER); 1.633 +} 1.634 + 1.635 +/* 1.636 + * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h) 1.637 + */ 1.638 +PKIX_Error * 1.639 +PKIX_Logger_GetLogCallback( 1.640 + PKIX_Logger *logger, 1.641 + PKIX_Logger_LogCallback *pCallback, 1.642 + void *plContext) 1.643 +{ 1.644 + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback"); 1.645 + PKIX_NULLCHECK_TWO(logger, pCallback); 1.646 + 1.647 + *pCallback = logger->callback; 1.648 + 1.649 + PKIX_RETURN(LOGGER); 1.650 +} 1.651 + 1.652 +/* 1.653 + * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h) 1.654 + */ 1.655 +PKIX_Error * 1.656 +PKIX_Logger_GetLoggerContext( 1.657 + PKIX_Logger *logger, 1.658 + PKIX_PL_Object **pLoggerContext, 1.659 + void *plContext) 1.660 +{ 1.661 + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex"); 1.662 + PKIX_NULLCHECK_TWO(logger, pLoggerContext); 1.663 + 1.664 + PKIX_INCREF(logger->context); 1.665 + *pLoggerContext = logger->context; 1.666 + 1.667 +cleanup: 1.668 + PKIX_RETURN(LOGGER); 1.669 +} 1.670 + 1.671 +/* 1.672 + * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h) 1.673 + */ 1.674 +PKIX_Error * 1.675 +PKIX_Logger_GetMaxLoggingLevel( 1.676 + PKIX_Logger *logger, 1.677 + PKIX_UInt32 *pLevel, 1.678 + void *plContext) 1.679 +{ 1.680 + PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel"); 1.681 + PKIX_NULLCHECK_TWO(logger, pLevel); 1.682 + 1.683 + *pLevel = logger->maxLevel; 1.684 + 1.685 + PKIX_RETURN(LOGGER); 1.686 +} 1.687 + 1.688 +/* 1.689 + * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h) 1.690 + */ 1.691 +PKIX_Error * 1.692 +PKIX_Logger_SetMaxLoggingLevel( 1.693 + PKIX_Logger *logger, 1.694 + PKIX_UInt32 level, 1.695 + void *plContext) 1.696 +{ 1.697 + PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel"); 1.698 + PKIX_NULLCHECK_ONE(logger); 1.699 + 1.700 + if (level > PKIX_LOGGER_LEVEL_MAX) { 1.701 + PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM); 1.702 + } else { 1.703 + logger->maxLevel = level; 1.704 + } 1.705 + 1.706 +cleanup: 1.707 + 1.708 + PKIX_RETURN(LOGGER); 1.709 +} 1.710 + 1.711 +/* 1.712 + * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h) 1.713 + */ 1.714 +PKIX_Error * 1.715 +PKIX_Logger_GetLoggingComponent( 1.716 + PKIX_Logger *logger, 1.717 + PKIX_ERRORCLASS *pComponent, 1.718 + void *plContext) 1.719 +{ 1.720 + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent"); 1.721 + PKIX_NULLCHECK_TWO(logger, pComponent); 1.722 + 1.723 + *pComponent = logger->logComponent; 1.724 + 1.725 + PKIX_RETURN(LOGGER); 1.726 +} 1.727 + 1.728 +/* 1.729 + * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h) 1.730 + */ 1.731 +PKIX_Error * 1.732 +PKIX_Logger_SetLoggingComponent( 1.733 + PKIX_Logger *logger, 1.734 + PKIX_ERRORCLASS component, 1.735 + void *plContext) 1.736 +{ 1.737 + PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent"); 1.738 + PKIX_NULLCHECK_ONE(logger); 1.739 + 1.740 + logger->logComponent = component; 1.741 + 1.742 + PKIX_RETURN(LOGGER); 1.743 +} 1.744 + 1.745 + 1.746 +/* 1.747 + * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are 1.748 + * documented as not thread-safe. However they are thread-safe now. We need 1.749 + * the lock when accessing the logger lists. 1.750 + */ 1.751 + 1.752 +/* 1.753 + * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h) 1.754 + */ 1.755 +PKIX_Error * 1.756 +PKIX_GetLoggers( 1.757 + PKIX_List **pLoggers, /* list of PKIX_Logger */ 1.758 + void *plContext) 1.759 +{ 1.760 + PKIX_List *list = NULL; 1.761 + PKIX_List *savedPkixLoggersDebugTrace = NULL; 1.762 + PKIX_List *savedPkixLoggersErrors = NULL; 1.763 + PKIX_Logger *logger = NULL; 1.764 + PKIX_Logger *dupLogger = NULL; 1.765 + PKIX_UInt32 i, length; 1.766 + PKIX_Boolean locked = PKIX_FALSE; 1.767 + 1.768 + PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); 1.769 + PKIX_NULLCHECK_ONE(pLoggers); 1.770 + 1.771 + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 1.772 + PKIX_MONITORLOCKENTERFAILED); 1.773 + locked = PKIX_TRUE; 1.774 + 1.775 + /* 1.776 + * Temporarily disable DEBUG/TRACE Logging to avoid possible 1.777 + * deadlock: 1.778 + * When the Logger List is being accessed, e.g. by PKIX_ENTER or 1.779 + * PKIX_DECREF, pkix_Logger_Check may check whether logging 1.780 + * is requested, creating a deadlock situation. 1.781 + */ 1.782 + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 1.783 + pkixLoggersDebugTrace = NULL; 1.784 + savedPkixLoggersErrors = pkixLoggersErrors; 1.785 + pkixLoggersErrors = NULL; 1.786 + 1.787 + if (pkixLoggers == NULL) { 1.788 + length = 0; 1.789 + } else { 1.790 + PKIX_CHECK(PKIX_List_GetLength 1.791 + (pkixLoggers, &length, plContext), 1.792 + PKIX_LISTGETLENGTHFAILED); 1.793 + } 1.794 + 1.795 + /* Create a list and copy the pkixLoggers item to the list */ 1.796 + PKIX_CHECK(PKIX_List_Create(&list, plContext), 1.797 + PKIX_LISTCREATEFAILED); 1.798 + 1.799 + for (i = 0; i < length; i++) { 1.800 + 1.801 + PKIX_CHECK(PKIX_List_GetItem 1.802 + (pkixLoggers, 1.803 + i, 1.804 + (PKIX_PL_Object **) &logger, 1.805 + plContext), 1.806 + PKIX_LISTGETITEMFAILED); 1.807 + 1.808 + PKIX_CHECK(pkix_Logger_Duplicate 1.809 + ((PKIX_PL_Object *)logger, 1.810 + (PKIX_PL_Object **)&dupLogger, 1.811 + plContext), 1.812 + PKIX_LOGGERDUPLICATEFAILED); 1.813 + 1.814 + PKIX_CHECK(PKIX_List_AppendItem 1.815 + (list, 1.816 + (PKIX_PL_Object *) dupLogger, 1.817 + plContext), 1.818 + PKIX_LISTAPPENDITEMFAILED); 1.819 + 1.820 + PKIX_DECREF(logger); 1.821 + PKIX_DECREF(dupLogger); 1.822 + } 1.823 + 1.824 + /* Set the list to be immutable */ 1.825 + PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), 1.826 + PKIX_LISTSETIMMUTABLEFAILED); 1.827 + 1.828 + *pLoggers = list; 1.829 + 1.830 +cleanup: 1.831 + 1.832 + PKIX_DECREF(logger); 1.833 + 1.834 + /* Restore logging capability */ 1.835 + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 1.836 + pkixLoggersErrors = savedPkixLoggersErrors; 1.837 + 1.838 + if (locked) { 1.839 + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 1.840 + PKIX_MONITORLOCKEXITFAILED); 1.841 + } 1.842 + 1.843 + PKIX_RETURN(LOGGER); 1.844 +} 1.845 + 1.846 +/* 1.847 + * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h) 1.848 + */ 1.849 +PKIX_Error * 1.850 +PKIX_SetLoggers( 1.851 + PKIX_List *loggers, /* list of PKIX_Logger */ 1.852 + void *plContext) 1.853 +{ 1.854 + PKIX_List *list = NULL; 1.855 + PKIX_List *savedPkixLoggersErrors = NULL; 1.856 + PKIX_List *savedPkixLoggersDebugTrace = NULL; 1.857 + PKIX_Logger *logger = NULL; 1.858 + PKIX_Logger *dupLogger = NULL; 1.859 + PKIX_Boolean locked = PKIX_FALSE; 1.860 + PKIX_UInt32 i, length; 1.861 + 1.862 + PKIX_ENTER(LOGGER, "PKIX_SetLoggers"); 1.863 + 1.864 + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 1.865 + PKIX_MONITORLOCKENTERFAILED); 1.866 + locked = PKIX_TRUE; 1.867 + 1.868 + /* Disable tracing, etc. to avoid recursion and deadlock */ 1.869 + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 1.870 + pkixLoggersDebugTrace = NULL; 1.871 + savedPkixLoggersErrors = pkixLoggersErrors; 1.872 + pkixLoggersErrors = NULL; 1.873 + 1.874 + /* discard any prior loggers */ 1.875 + PKIX_DECREF(pkixLoggers); 1.876 + PKIX_DECREF(savedPkixLoggersErrors); 1.877 + PKIX_DECREF(savedPkixLoggersDebugTrace); 1.878 + 1.879 + if (loggers != NULL) { 1.880 + 1.881 + PKIX_CHECK(PKIX_List_Create(&list, plContext), 1.882 + PKIX_LISTCREATEFAILED); 1.883 + 1.884 + PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext), 1.885 + PKIX_LISTGETLENGTHFAILED); 1.886 + 1.887 + for (i = 0; i < length; i++) { 1.888 + 1.889 + PKIX_CHECK(PKIX_List_GetItem 1.890 + (loggers, 1.891 + i, 1.892 + (PKIX_PL_Object **) &logger, 1.893 + plContext), 1.894 + PKIX_LISTGETITEMFAILED); 1.895 + 1.896 + PKIX_CHECK(pkix_Logger_Duplicate 1.897 + ((PKIX_PL_Object *)logger, 1.898 + (PKIX_PL_Object **)&dupLogger, 1.899 + plContext), 1.900 + PKIX_LOGGERDUPLICATEFAILED); 1.901 + 1.902 + PKIX_CHECK(PKIX_List_AppendItem 1.903 + (list, 1.904 + (PKIX_PL_Object *) dupLogger, 1.905 + plContext), 1.906 + PKIX_LISTAPPENDITEMFAILED); 1.907 + 1.908 + /* Make two lists */ 1.909 + 1.910 + /* Put in pkixLoggersErrors in any case*/ 1.911 + 1.912 + if (savedPkixLoggersErrors == NULL) { 1.913 + 1.914 + PKIX_CHECK(PKIX_List_Create 1.915 + (&savedPkixLoggersErrors, 1.916 + plContext), 1.917 + PKIX_LISTCREATEFAILED); 1.918 + } 1.919 + 1.920 + PKIX_CHECK(PKIX_List_AppendItem 1.921 + (savedPkixLoggersErrors, 1.922 + (PKIX_PL_Object *) dupLogger, 1.923 + plContext), 1.924 + PKIX_LISTAPPENDITEMFAILED); 1.925 + 1.926 + if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { 1.927 + 1.928 + /* Put in pkixLoggersDebugTrace */ 1.929 + 1.930 + if (savedPkixLoggersDebugTrace == NULL) { 1.931 + 1.932 + PKIX_CHECK(PKIX_List_Create 1.933 + (&savedPkixLoggersDebugTrace, 1.934 + plContext), 1.935 + PKIX_LISTCREATEFAILED); 1.936 + } 1.937 + 1.938 + PKIX_CHECK(PKIX_List_AppendItem 1.939 + (savedPkixLoggersDebugTrace, 1.940 + (PKIX_PL_Object *) dupLogger, 1.941 + plContext), 1.942 + PKIX_LISTAPPENDITEMFAILED); 1.943 + } 1.944 + PKIX_DECREF(logger); 1.945 + PKIX_DECREF(dupLogger); 1.946 + 1.947 + } 1.948 + 1.949 + pkixLoggers = list; 1.950 + } 1.951 + 1.952 +cleanup: 1.953 + 1.954 + if (PKIX_ERROR_RECEIVED){ 1.955 + PKIX_DECREF(list); 1.956 + PKIX_DECREF(savedPkixLoggersErrors); 1.957 + PKIX_DECREF(savedPkixLoggersDebugTrace); 1.958 + pkixLoggers = NULL; 1.959 + } 1.960 + 1.961 + PKIX_DECREF(logger); 1.962 + 1.963 + /* Reenable logging capability with new lists */ 1.964 + pkixLoggersErrors = savedPkixLoggersErrors; 1.965 + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 1.966 + 1.967 + if (locked) { 1.968 + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 1.969 + PKIX_MONITORLOCKEXITFAILED); 1.970 + } 1.971 + 1.972 + PKIX_RETURN(LOGGER); 1.973 +} 1.974 + 1.975 +/* 1.976 + * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h) 1.977 + */ 1.978 +PKIX_Error * 1.979 +PKIX_AddLogger( 1.980 + PKIX_Logger *logger, 1.981 + void *plContext) 1.982 +{ 1.983 + PKIX_Logger *dupLogger = NULL; 1.984 + PKIX_Logger *addLogger = NULL; 1.985 + PKIX_List *savedPkixLoggersErrors = NULL; 1.986 + PKIX_List *savedPkixLoggersDebugTrace = NULL; 1.987 + PKIX_Boolean locked = PKIX_FALSE; 1.988 + PKIX_UInt32 i, length; 1.989 + 1.990 + PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); 1.991 + PKIX_NULLCHECK_ONE(logger); 1.992 + 1.993 + PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 1.994 + PKIX_MONITORLOCKENTERFAILED); 1.995 + locked = PKIX_TRUE; 1.996 + 1.997 + savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 1.998 + pkixLoggersDebugTrace = NULL; 1.999 + savedPkixLoggersErrors = pkixLoggersErrors; 1.1000 + pkixLoggersErrors = NULL; 1.1001 + 1.1002 + PKIX_DECREF(savedPkixLoggersErrors); 1.1003 + PKIX_DECREF(savedPkixLoggersDebugTrace); 1.1004 + 1.1005 + if (pkixLoggers == NULL) { 1.1006 + 1.1007 + PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), 1.1008 + PKIX_LISTCREATEFAILED); 1.1009 + } 1.1010 + 1.1011 + PKIX_CHECK(pkix_Logger_Duplicate 1.1012 + ((PKIX_PL_Object *)logger, 1.1013 + (PKIX_PL_Object **)&dupLogger, 1.1014 + plContext), 1.1015 + PKIX_LOGGERDUPLICATEFAILED); 1.1016 + 1.1017 + PKIX_CHECK(PKIX_List_AppendItem 1.1018 + (pkixLoggers, 1.1019 + (PKIX_PL_Object *) dupLogger, 1.1020 + plContext), 1.1021 + PKIX_LISTAPPENDITEMFAILED); 1.1022 + 1.1023 + PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), 1.1024 + PKIX_LISTGETLENGTHFAILED); 1.1025 + 1.1026 + /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ 1.1027 + for (i = 0; i < length; i++) { 1.1028 + 1.1029 + PKIX_CHECK(PKIX_List_GetItem 1.1030 + (pkixLoggers, 1.1031 + i, 1.1032 + (PKIX_PL_Object **) &addLogger, 1.1033 + plContext), 1.1034 + PKIX_LISTGETITEMFAILED); 1.1035 + 1.1036 + 1.1037 + /* Put in pkixLoggersErrors */ 1.1038 + 1.1039 + if (savedPkixLoggersErrors == NULL) { 1.1040 + 1.1041 + PKIX_CHECK(PKIX_List_Create 1.1042 + (&savedPkixLoggersErrors, 1.1043 + plContext), 1.1044 + PKIX_LISTCREATEFAILED); 1.1045 + } 1.1046 + 1.1047 + PKIX_CHECK(PKIX_List_AppendItem 1.1048 + (savedPkixLoggersErrors, 1.1049 + (PKIX_PL_Object *) addLogger, 1.1050 + plContext), 1.1051 + PKIX_LISTAPPENDITEMFAILED); 1.1052 + 1.1053 + if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { 1.1054 + 1.1055 + /* Put in pkixLoggersDebugTrace */ 1.1056 + 1.1057 + if (savedPkixLoggersDebugTrace == NULL) { 1.1058 + 1.1059 + PKIX_CHECK(PKIX_List_Create 1.1060 + (&savedPkixLoggersDebugTrace, 1.1061 + plContext), 1.1062 + PKIX_LISTCREATEFAILED); 1.1063 + } 1.1064 + 1.1065 + PKIX_CHECK(PKIX_List_AppendItem 1.1066 + (savedPkixLoggersDebugTrace, 1.1067 + (PKIX_PL_Object *) addLogger, 1.1068 + plContext), 1.1069 + PKIX_LISTAPPENDITEMFAILED); 1.1070 + } 1.1071 + 1.1072 + PKIX_DECREF(addLogger); 1.1073 + 1.1074 + } 1.1075 + 1.1076 +cleanup: 1.1077 + 1.1078 + PKIX_DECREF(dupLogger); 1.1079 + PKIX_DECREF(addLogger); 1.1080 + 1.1081 + /* Restore logging capability */ 1.1082 + pkixLoggersErrors = savedPkixLoggersErrors; 1.1083 + pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 1.1084 + 1.1085 + if (locked) { 1.1086 + PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 1.1087 + PKIX_MONITORLOCKEXITFAILED); 1.1088 + } 1.1089 + 1.1090 + PKIX_RETURN(LOGGER); 1.1091 +}