pkix_logger.c (34076B)
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 */ 10 11 #include "pkix_logger.h" 12 #ifndef PKIX_ERROR_DESCRIPTION 13 #include "prprf.h" 14 #endif 15 16 /* Global variable to keep PKIX_Logger List */ 17 PKIX_List *pkixLoggers = NULL; 18 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; 48 49 /* To ensure atomic update on pkixLoggers lists */ 50 PKIX_PL_MonitorLock *pkixLoggerLock = NULL; 51 52 /* --Private-Functions-------------------------------------------- */ 53 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; 106 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 */ 111 112 if ((pkixLoggersList == NULL) || (message == NULL)) { 113 return(NULL); 114 } 115 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 */ 129 130 error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext); 131 if (error) { return(NULL); } 132 133 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 134 pkixLoggersDebugTrace = NULL; 135 savedPkixLoggersErrors = pkixLoggersErrors; 136 pkixLoggersErrors = NULL; 137 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; } 142 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; } 150 151 } else { 152 error = PKIX_PL_String_Create 153 (PKIX_ESCASCII, "%s", 0, &formatString, plContext); 154 if (error) { goto cleanup; } 155 156 } 157 158 error = PKIX_PL_Sprintf 159 (&msgString, 160 plContext, 161 formatString, 162 messageString, 163 message2String); 164 if (error) { goto cleanup; } 165 166 /* Go through the Logger list */ 167 168 error = PKIX_List_GetLength(pkixLoggersList, &length, plContext); 169 if (error) { goto cleanup; } 170 171 for (i = 0; i < length; i++) { 172 173 error = PKIX_List_GetItem 174 (pkixLoggersList, 175 i, 176 (PKIX_PL_Object **) &logger, 177 plContext); 178 if (error) { goto cleanup; } 179 180 /* Intended logging level less or equal than the max */ 181 needLogging = (currentLevel <= logger->maxLevel); 182 183 if (needLogging && (logger->callback)) { 184 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 } 197 198 if (needLogging) { 199 if (logComponent == logger->logComponent) { 200 needLogging = PKIX_TRUE; 201 } else { 202 needLogging = PKIX_FALSE; 203 } 204 } 205 206 if (needLogging) { 207 error = logger->callback 208 (logger, 209 msgString, 210 currentLevel, 211 logComponent, 212 plContext); 213 if (error) { goto cleanup; } 214 } 215 } 216 217 error = PKIX_PL_Object_DecRef 218 ((PKIX_PL_Object *)logger, plContext); 219 logger = NULL; 220 if (error) { goto cleanup; } 221 222 } 223 224 cleanup: 225 226 if (formatString) { 227 error = PKIX_PL_Object_DecRef 228 ((PKIX_PL_Object *)formatString, plContext); 229 } 230 231 if (messageString) { 232 error = PKIX_PL_Object_DecRef 233 ((PKIX_PL_Object *)messageString, plContext); 234 } 235 236 if (message2String) { 237 error = PKIX_PL_Object_DecRef 238 ((PKIX_PL_Object *)message2String, plContext); 239 } 240 241 if (msgString) { 242 error = PKIX_PL_Object_DecRef 243 ((PKIX_PL_Object *)msgString, plContext); 244 } 245 246 if (logger) { 247 error = PKIX_PL_Object_DecRef 248 ((PKIX_PL_Object *)logger, plContext); 249 } 250 251 if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) { 252 pkixLoggersErrors = savedPkixLoggersErrors; 253 } 254 255 if (pkixLoggersDebugTrace == NULL && 256 savedPkixLoggersDebugTrace != NULL) { 257 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 258 } 259 260 error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext); 261 if (error) { return(NULL); } 262 263 return(NULL); 264 } 265 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; 277 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 */ 285 286 pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString, 287 message2, logComponent, 288 currentLevel, plContext); 289 PKIX_RETURN(LOGGER); 290 } 291 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; 302 303 PKIX_ENTER(LOGGER, "pkix_Logger_Destroy"); 304 PKIX_NULLCHECK_ONE(object); 305 306 /* Check that this object is a logger */ 307 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 308 PKIX_OBJECTNOTLOGGER); 309 310 logger = (PKIX_Logger *)object; 311 312 /* We have a valid logger. DecRef its item and recurse on next */ 313 314 logger->callback = NULL; 315 PKIX_DECREF(logger->context); 316 logger->logComponent = (PKIX_ERRORCLASS)0; 317 318 cleanup: 319 320 PKIX_RETURN(LOGGER); 321 } 322 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; 339 340 PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper"); 341 PKIX_NULLCHECK_TWO(object, pString); 342 343 /* Check that this object is a logger */ 344 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 345 PKIX_OBJECTNOTLOGGER); 346 347 logger = (PKIX_Logger *)object; 348 349 asciiFormat = 350 "[\n" 351 "\tLogger: \n" 352 "\tContext: %s\n" 353 "\tMaximum Level: %d\n" 354 "\tComponent Name: %s\n" 355 "]\n"; 356 357 PKIX_CHECK(PKIX_PL_String_Create 358 (PKIX_ESCASCII, 359 asciiFormat, 360 0, 361 &formatString, 362 plContext), 363 PKIX_STRINGCREATEFAILED); 364 365 PKIX_TOSTRING(logger->context, &contextString, plContext, 366 PKIX_OBJECTTOSTRINGFAILED); 367 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); 375 376 PKIX_CHECK(PKIX_PL_Sprintf 377 (&loggerString, 378 plContext, 379 formatString, 380 contextString, 381 logger->maxLevel, 382 componentString), 383 PKIX_SPRINTFFAILED); 384 385 *pString = loggerString; 386 387 cleanup: 388 389 PKIX_DECREF(formatString); 390 PKIX_DECREF(contextString); 391 PKIX_RETURN(LOGGER); 392 } 393 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; 409 410 PKIX_ENTER(LOGGER, "pkix_Logger_Equals"); 411 PKIX_NULLCHECK_THREE(first, second, pResult); 412 413 /* test that first is a Logger */ 414 PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext), 415 PKIX_FIRSTOBJECTNOTLOGGER); 416 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 } 425 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; 434 435 firstLogger = (PKIX_Logger *)first; 436 secondLogger = (PKIX_Logger *)second; 437 438 cmpResult = PKIX_FALSE; 439 440 if (firstLogger->callback != secondLogger->callback) { 441 goto cleanup; 442 } 443 444 if (firstLogger->logComponent != secondLogger->logComponent) { 445 goto cleanup; 446 } 447 448 PKIX_EQUALS 449 (firstLogger->context, 450 secondLogger->context, 451 &cmpResult, 452 plContext, 453 PKIX_OBJECTEQUALSFAILED); 454 455 if (cmpResult == PKIX_FALSE) { 456 goto cleanup; 457 } 458 459 if (firstLogger->maxLevel != secondLogger->maxLevel) { 460 goto cleanup; 461 } 462 463 *pResult = cmpResult; 464 465 cleanup: 466 467 PKIX_RETURN(LOGGER); 468 } 469 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; 483 484 PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode"); 485 PKIX_NULLCHECK_TWO(object, pHashcode); 486 487 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext), 488 PKIX_OBJECTNOTLOGGER); 489 490 logger = (PKIX_Logger *)object; 491 492 PKIX_HASHCODE(logger->context, &tempHash, plContext, 493 PKIX_OBJECTHASHCODEFAILED); 494 495 hash = (((((PKIX_UInt32)((char *)logger->callback - (char *)NULL) + tempHash) << 7) + 496 logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent; 497 498 *pHashcode = hash; 499 500 cleanup: 501 502 PKIX_RETURN(LOGGER); 503 } 504 505 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; 518 519 PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate"); 520 PKIX_NULLCHECK_TWO(object, pNewObject); 521 522 PKIX_CHECK(pkix_CheckType 523 ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext), 524 PKIX_OBJECTNOTLOGGER); 525 526 logger = (PKIX_Logger *) object; 527 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); 534 535 dupLogger->callback = logger->callback; 536 dupLogger->maxLevel = logger->maxLevel; 537 538 PKIX_DUPLICATE 539 (logger->context, 540 &dupLogger->context, 541 plContext, 542 PKIX_OBJECTDUPLICATEFAILED); 543 544 dupLogger->logComponent = logger->logComponent; 545 546 *pNewObject = (PKIX_PL_Object *) dupLogger; 547 548 cleanup: 549 550 if (PKIX_ERROR_RECEIVED){ 551 PKIX_DECREF(dupLogger); 552 } 553 554 PKIX_RETURN(LOGGER); 555 } 556 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; 573 574 PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf"); 575 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; 585 586 systemClasses[PKIX_LOGGER_TYPE] = entry; 587 588 PKIX_RETURN(LOGGER); 589 } 590 591 /* --Public-Logger-Functions--------------------------------------------- */ 592 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; 604 605 PKIX_ENTER(LOGGER, "PKIX_Logger_Create"); 606 PKIX_NULLCHECK_ONE(pLogger); 607 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); 614 615 logger->callback = callback; 616 logger->maxLevel = 0; 617 logger->logComponent = (PKIX_ERRORCLASS)0; 618 619 PKIX_INCREF(loggerContext); 620 logger->context = loggerContext; 621 622 *pLogger = logger; 623 logger = NULL; 624 625 cleanup: 626 627 PKIX_DECREF(logger); 628 629 PKIX_RETURN(LOGGER); 630 } 631 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); 643 644 *pCallback = logger->callback; 645 646 PKIX_RETURN(LOGGER); 647 } 648 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); 660 661 PKIX_INCREF(logger->context); 662 *pLoggerContext = logger->context; 663 664 cleanup: 665 PKIX_RETURN(LOGGER); 666 } 667 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); 679 680 *pLevel = logger->maxLevel; 681 682 PKIX_RETURN(LOGGER); 683 } 684 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); 696 697 if (level > PKIX_LOGGER_LEVEL_MAX) { 698 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM); 699 } else { 700 logger->maxLevel = level; 701 } 702 703 cleanup: 704 705 PKIX_RETURN(LOGGER); 706 } 707 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); 719 720 *pComponent = logger->logComponent; 721 722 PKIX_RETURN(LOGGER); 723 } 724 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); 736 737 logger->logComponent = component; 738 739 PKIX_RETURN(LOGGER); 740 } 741 742 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 */ 748 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; 764 765 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers"); 766 PKIX_NULLCHECK_ONE(pLoggers); 767 768 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 769 PKIX_MONITORLOCKENTERFAILED); 770 locked = PKIX_TRUE; 771 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; 783 784 if (pkixLoggers == NULL) { 785 length = 0; 786 } else { 787 PKIX_CHECK(PKIX_List_GetLength 788 (pkixLoggers, &length, plContext), 789 PKIX_LISTGETLENGTHFAILED); 790 } 791 792 /* Create a list and copy the pkixLoggers item to the list */ 793 PKIX_CHECK(PKIX_List_Create(&list, plContext), 794 PKIX_LISTCREATEFAILED); 795 796 for (i = 0; i < length; i++) { 797 798 PKIX_CHECK(PKIX_List_GetItem 799 (pkixLoggers, 800 i, 801 (PKIX_PL_Object **) &logger, 802 plContext), 803 PKIX_LISTGETITEMFAILED); 804 805 PKIX_CHECK(pkix_Logger_Duplicate 806 ((PKIX_PL_Object *)logger, 807 (PKIX_PL_Object **)&dupLogger, 808 plContext), 809 PKIX_LOGGERDUPLICATEFAILED); 810 811 PKIX_CHECK(PKIX_List_AppendItem 812 (list, 813 (PKIX_PL_Object *) dupLogger, 814 plContext), 815 PKIX_LISTAPPENDITEMFAILED); 816 817 PKIX_DECREF(logger); 818 PKIX_DECREF(dupLogger); 819 } 820 821 /* Set the list to be immutable */ 822 PKIX_CHECK(PKIX_List_SetImmutable(list, plContext), 823 PKIX_LISTSETIMMUTABLEFAILED); 824 825 *pLoggers = list; 826 827 cleanup: 828 829 PKIX_DECREF(logger); 830 831 /* Restore logging capability */ 832 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 833 pkixLoggersErrors = savedPkixLoggersErrors; 834 835 if (locked) { 836 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 837 PKIX_MONITORLOCKEXITFAILED); 838 } 839 840 PKIX_RETURN(LOGGER); 841 } 842 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; 858 859 PKIX_ENTER(LOGGER, "PKIX_SetLoggers"); 860 861 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 862 PKIX_MONITORLOCKENTERFAILED); 863 locked = PKIX_TRUE; 864 865 /* Disable tracing, etc. to avoid recursion and deadlock */ 866 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 867 pkixLoggersDebugTrace = NULL; 868 savedPkixLoggersErrors = pkixLoggersErrors; 869 pkixLoggersErrors = NULL; 870 871 /* discard any prior loggers */ 872 PKIX_DECREF(pkixLoggers); 873 PKIX_DECREF(savedPkixLoggersErrors); 874 PKIX_DECREF(savedPkixLoggersDebugTrace); 875 876 if (loggers != NULL) { 877 878 PKIX_CHECK(PKIX_List_Create(&list, plContext), 879 PKIX_LISTCREATEFAILED); 880 881 PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext), 882 PKIX_LISTGETLENGTHFAILED); 883 884 for (i = 0; i < length; i++) { 885 886 PKIX_CHECK(PKIX_List_GetItem 887 (loggers, 888 i, 889 (PKIX_PL_Object **) &logger, 890 plContext), 891 PKIX_LISTGETITEMFAILED); 892 893 PKIX_CHECK(pkix_Logger_Duplicate 894 ((PKIX_PL_Object *)logger, 895 (PKIX_PL_Object **)&dupLogger, 896 plContext), 897 PKIX_LOGGERDUPLICATEFAILED); 898 899 PKIX_CHECK(PKIX_List_AppendItem 900 (list, 901 (PKIX_PL_Object *) dupLogger, 902 plContext), 903 PKIX_LISTAPPENDITEMFAILED); 904 905 /* Make two lists */ 906 907 /* Put in pkixLoggersErrors in any case*/ 908 909 if (savedPkixLoggersErrors == NULL) { 910 911 PKIX_CHECK(PKIX_List_Create 912 (&savedPkixLoggersErrors, 913 plContext), 914 PKIX_LISTCREATEFAILED); 915 } 916 917 PKIX_CHECK(PKIX_List_AppendItem 918 (savedPkixLoggersErrors, 919 (PKIX_PL_Object *) dupLogger, 920 plContext), 921 PKIX_LISTAPPENDITEMFAILED); 922 923 if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { 924 925 /* Put in pkixLoggersDebugTrace */ 926 927 if (savedPkixLoggersDebugTrace == NULL) { 928 929 PKIX_CHECK(PKIX_List_Create 930 (&savedPkixLoggersDebugTrace, 931 plContext), 932 PKIX_LISTCREATEFAILED); 933 } 934 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); 943 944 } 945 946 pkixLoggers = list; 947 } 948 949 cleanup: 950 951 if (PKIX_ERROR_RECEIVED){ 952 PKIX_DECREF(list); 953 PKIX_DECREF(savedPkixLoggersErrors); 954 PKIX_DECREF(savedPkixLoggersDebugTrace); 955 pkixLoggers = NULL; 956 } 957 958 PKIX_DECREF(logger); 959 960 /* Reenable logging capability with new lists */ 961 pkixLoggersErrors = savedPkixLoggersErrors; 962 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 963 964 if (locked) { 965 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 966 PKIX_MONITORLOCKEXITFAILED); 967 } 968 969 PKIX_RETURN(LOGGER); 970 } 971 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; 986 987 PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger"); 988 PKIX_NULLCHECK_ONE(logger); 989 990 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext), 991 PKIX_MONITORLOCKENTERFAILED); 992 locked = PKIX_TRUE; 993 994 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace; 995 pkixLoggersDebugTrace = NULL; 996 savedPkixLoggersErrors = pkixLoggersErrors; 997 pkixLoggersErrors = NULL; 998 999 PKIX_DECREF(savedPkixLoggersErrors); 1000 PKIX_DECREF(savedPkixLoggersDebugTrace); 1001 1002 if (pkixLoggers == NULL) { 1003 1004 PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext), 1005 PKIX_LISTCREATEFAILED); 1006 } 1007 1008 PKIX_CHECK(pkix_Logger_Duplicate 1009 ((PKIX_PL_Object *)logger, 1010 (PKIX_PL_Object **)&dupLogger, 1011 plContext), 1012 PKIX_LOGGERDUPLICATEFAILED); 1013 1014 PKIX_CHECK(PKIX_List_AppendItem 1015 (pkixLoggers, 1016 (PKIX_PL_Object *) dupLogger, 1017 plContext), 1018 PKIX_LISTAPPENDITEMFAILED); 1019 1020 PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext), 1021 PKIX_LISTGETLENGTHFAILED); 1022 1023 /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */ 1024 for (i = 0; i < length; i++) { 1025 1026 PKIX_CHECK(PKIX_List_GetItem 1027 (pkixLoggers, 1028 i, 1029 (PKIX_PL_Object **) &addLogger, 1030 plContext), 1031 PKIX_LISTGETITEMFAILED); 1032 1033 1034 /* Put in pkixLoggersErrors */ 1035 1036 if (savedPkixLoggersErrors == NULL) { 1037 1038 PKIX_CHECK(PKIX_List_Create 1039 (&savedPkixLoggersErrors, 1040 plContext), 1041 PKIX_LISTCREATEFAILED); 1042 } 1043 1044 PKIX_CHECK(PKIX_List_AppendItem 1045 (savedPkixLoggersErrors, 1046 (PKIX_PL_Object *) addLogger, 1047 plContext), 1048 PKIX_LISTAPPENDITEMFAILED); 1049 1050 if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) { 1051 1052 /* Put in pkixLoggersDebugTrace */ 1053 1054 if (savedPkixLoggersDebugTrace == NULL) { 1055 1056 PKIX_CHECK(PKIX_List_Create 1057 (&savedPkixLoggersDebugTrace, 1058 plContext), 1059 PKIX_LISTCREATEFAILED); 1060 } 1061 1062 PKIX_CHECK(PKIX_List_AppendItem 1063 (savedPkixLoggersDebugTrace, 1064 (PKIX_PL_Object *) addLogger, 1065 plContext), 1066 PKIX_LISTAPPENDITEMFAILED); 1067 } 1068 1069 PKIX_DECREF(addLogger); 1070 1071 } 1072 1073 cleanup: 1074 1075 PKIX_DECREF(dupLogger); 1076 PKIX_DECREF(addLogger); 1077 1078 /* Restore logging capability */ 1079 pkixLoggersErrors = savedPkixLoggersErrors; 1080 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace; 1081 1082 if (locked) { 1083 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext), 1084 PKIX_MONITORLOCKEXITFAILED); 1085 } 1086 1087 PKIX_RETURN(LOGGER); 1088 }