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

http://github.com/zpao/v8monkey · C · 1121 lines · 682 code · 210 blank · 229 comment · 84 complexity · db90ca76d87662ffcb48f4139dcdfe66 MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the PKIX-C library.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Sun Microsystems, Inc.
  18. * Portions created by the Initial Developer are
  19. * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Sun Microsystems, Inc.
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * pkix_logger.c
  39. *
  40. * Logger Object Functions
  41. *
  42. */
  43. #include "pkix_logger.h"
  44. #ifndef PKIX_ERROR_DESCRIPTION
  45. #include "prprf.h"
  46. #endif
  47. /* Global variable to keep PKIX_Logger List */
  48. PKIX_List *pkixLoggers = NULL;
  49. /*
  50. * Once the Logger has been set, for any logging related operations, we have
  51. * to go through the List to find a match, and if found, issue the
  52. * corresponding callback. The overhead to check for DEBUG and TRACE in each
  53. * PKIX function entering and exiting is very expensive (400X), and redundant
  54. * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
  55. * pkixLoggers is separated into two lists based on its Loggers' trace level.
  56. *
  57. * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
  58. * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
  59. * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
  60. * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
  61. * pkixLoggersDebugTrace.
  62. *
  63. * Currently we provide five logging levels and the default setting are by:
  64. *
  65. * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
  66. * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
  67. * WARNING is not invoked as default
  68. * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
  69. * compilation -DPKIX_<component>DEBUG flag to turn on
  70. * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
  71. * level. TRACE provides duplicate information of DEBUG, but needs no
  72. * recompilation and cannot choose component. To allow application
  73. * to use DEBUG level, TRACE is put as last.
  74. *
  75. */
  76. PKIX_List *pkixLoggersErrors = NULL;
  77. PKIX_List *pkixLoggersDebugTrace = NULL;
  78. /* To ensure atomic update on pkixLoggers lists */
  79. PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
  80. /* --Private-Functions-------------------------------------------- */
  81. /*
  82. * FUNCTION: pkix_Logger_CheckErrors
  83. * DESCRIPTION:
  84. *
  85. * This function goes through each PKIX_Logger at "pkixLoggersList" and
  86. * checks if "maxLevel" and "logComponent" satisfies what is specified in the
  87. * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
  88. * passes a PKIX_PL_String that is the concatenation of "message" and
  89. * "message2" to the application for processing.
  90. * Since this call is inserted into a handful of PKIX macros, no macros are
  91. * applied in this function, to avoid infinite recursion.
  92. * If an error occurs, this call is aborted.
  93. *
  94. * PARAMETERS:
  95. * "pkixLoggersList"
  96. * A list of PKIX_Loggers to be examined for invoking callback. Must be
  97. * non-NULL.
  98. * "message"
  99. * Address of "message" to be logged. Must be non-NULL.
  100. * "message2"
  101. * Address of "message2" to be concatenated and logged. May be NULL.
  102. * "logComponent"
  103. * A PKIX_UInt32 that indicates the component the message is from.
  104. * "maxLevel"
  105. * A PKIX_UInt32 that represents the level of severity of the message.
  106. * "plContext"
  107. * Platform-specific context pointer.
  108. * THREAD SAFETY:
  109. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  110. * RETURNS:
  111. * Returns NULL if the function succeeds
  112. * Returns a Fatal Error if the function fails in an unrecoverable way
  113. */
  114. PKIX_Error *
  115. pkix_Logger_Check(
  116. PKIX_List *pkixLoggersList,
  117. const char *message,
  118. const char *message2,
  119. PKIX_ERRORCLASS logComponent,
  120. PKIX_UInt32 currentLevel,
  121. void *plContext)
  122. {
  123. PKIX_Logger *logger = NULL;
  124. PKIX_List *savedPkixLoggersErrors = NULL;
  125. PKIX_List *savedPkixLoggersDebugTrace = NULL;
  126. PKIX_PL_String *formatString = NULL;
  127. PKIX_PL_String *messageString = NULL;
  128. PKIX_PL_String *message2String = NULL;
  129. PKIX_PL_String *msgString = NULL;
  130. PKIX_Error *error = NULL;
  131. PKIX_Boolean needLogging = PKIX_FALSE;
  132. PKIX_UInt32 i, length;
  133. /*
  134. * We cannot use any the PKIX_ macros here, since this function is
  135. * called from some of these macros. It can create infinite recursion.
  136. */
  137. if ((pkixLoggersList == NULL) || (message == NULL)) {
  138. return(NULL);
  139. }
  140. /*
  141. * Disable all subsequent loggings to avoid recursion. The result is
  142. * if other thread is calling this function at the same time, there
  143. * won't be any logging because the pkixLoggersErrors and
  144. * pkixLoggersDebugTrace are set to null.
  145. * It would be nice if we provide control per thread (e.g. make
  146. * plContext threadable) then we can avoid the recursion by setting
  147. * flag at plContext. Then other thread's logging won't be affected.
  148. *
  149. * Also we need to use a reentrant Lock. Although we avoid recursion
  150. * for TRACE. When there is an ERROR occurs in subsequent call, this
  151. * function will be called.
  152. */
  153. error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
  154. if (error) { return(NULL); }
  155. savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
  156. pkixLoggersDebugTrace = NULL;
  157. savedPkixLoggersErrors = pkixLoggersErrors;
  158. pkixLoggersErrors = NULL;
  159. /* Convert message and message2 to String */
  160. error = PKIX_PL_String_Create
  161. (PKIX_ESCASCII, message, 0, &messageString, plContext);
  162. if (error) { goto cleanup; }
  163. if (message2) {
  164. error = PKIX_PL_String_Create
  165. (PKIX_ESCASCII, message2, 0, &message2String, plContext);
  166. if (error) { goto cleanup; }
  167. error = PKIX_PL_String_Create
  168. (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
  169. if (error) { goto cleanup; }
  170. } else {
  171. error = PKIX_PL_String_Create
  172. (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
  173. if (error) { goto cleanup; }
  174. }
  175. error = PKIX_PL_Sprintf
  176. (&msgString,
  177. plContext,
  178. formatString,
  179. messageString,
  180. message2String);
  181. if (error) { goto cleanup; }
  182. /* Go through the Logger list */
  183. error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
  184. if (error) { goto cleanup; }
  185. for (i = 0; i < length; i++) {
  186. error = PKIX_List_GetItem
  187. (pkixLoggersList,
  188. i,
  189. (PKIX_PL_Object **) &logger,
  190. plContext);
  191. if (error) { goto cleanup; }
  192. /* Intended logging level less or equal than the max */
  193. needLogging = (currentLevel <= logger->maxLevel);
  194. if (needLogging && (logger->callback)) {
  195. /*
  196. * We separate Logger into two lists based on log level
  197. * but log level is not modified. We need to check here to
  198. * avoid logging the higher log level (lower value) twice.
  199. */
  200. if (pkixLoggersList == pkixLoggersErrors) {
  201. needLogging = needLogging &&
  202. (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
  203. } else if (pkixLoggersList == pkixLoggersDebugTrace) {
  204. needLogging = needLogging &&
  205. (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
  206. }
  207. if (needLogging) {
  208. if (logComponent == logger->logComponent) {
  209. needLogging = PKIX_TRUE;
  210. } else {
  211. needLogging = PKIX_FALSE;
  212. }
  213. }
  214. if (needLogging) {
  215. error = logger->callback
  216. (logger,
  217. msgString,
  218. currentLevel,
  219. logComponent,
  220. plContext);
  221. if (error) { goto cleanup; }
  222. }
  223. }
  224. error = PKIX_PL_Object_DecRef
  225. ((PKIX_PL_Object *)logger, plContext);
  226. logger = NULL;
  227. if (error) { goto cleanup; }
  228. }
  229. cleanup:
  230. if (formatString) {
  231. error = PKIX_PL_Object_DecRef
  232. ((PKIX_PL_Object *)formatString, plContext);
  233. }
  234. if (messageString) {
  235. error = PKIX_PL_Object_DecRef
  236. ((PKIX_PL_Object *)messageString, plContext);
  237. }
  238. if (message2String) {
  239. error = PKIX_PL_Object_DecRef
  240. ((PKIX_PL_Object *)message2String, plContext);
  241. }
  242. if (msgString) {
  243. error = PKIX_PL_Object_DecRef
  244. ((PKIX_PL_Object *)msgString, plContext);
  245. }
  246. if (logger) {
  247. error = PKIX_PL_Object_DecRef
  248. ((PKIX_PL_Object *)logger, plContext);
  249. }
  250. if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
  251. pkixLoggersErrors = savedPkixLoggersErrors;
  252. }
  253. if (pkixLoggersDebugTrace == NULL &&
  254. savedPkixLoggersDebugTrace != NULL) {
  255. pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  256. }
  257. error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
  258. if (error) { return(NULL); }
  259. return(NULL);
  260. }
  261. PKIX_Error *
  262. pkix_Logger_CheckWithCode(
  263. PKIX_List *pkixLoggersList,
  264. PKIX_UInt32 errorCode,
  265. const char *message2,
  266. PKIX_ERRORCLASS logComponent,
  267. PKIX_UInt32 currentLevel,
  268. void *plContext)
  269. {
  270. char error[32];
  271. char *errorString = NULL;
  272. PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
  273. #if defined PKIX_ERROR_DESCRIPTION
  274. errorString = PKIX_ErrorText[errorCode];
  275. #else
  276. PR_snprintf(error, 32, "Error code: %d", errorCode);
  277. errorString = error;
  278. #endif /* PKIX_ERROR_DESCRIPTION */
  279. pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
  280. message2, logComponent,
  281. currentLevel, plContext);
  282. PKIX_RETURN(LOGGER);
  283. }
  284. /*
  285. * FUNCTION: pkix_Logger_Destroy
  286. * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
  287. */
  288. static PKIX_Error *
  289. pkix_Logger_Destroy(
  290. PKIX_PL_Object *object,
  291. void *plContext)
  292. {
  293. PKIX_Logger *logger = NULL;
  294. PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
  295. PKIX_NULLCHECK_ONE(object);
  296. /* Check that this object is a logger */
  297. PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
  298. PKIX_OBJECTNOTLOGGER);
  299. logger = (PKIX_Logger *)object;
  300. /* We have a valid logger. DecRef its item and recurse on next */
  301. logger->callback = NULL;
  302. PKIX_DECREF(logger->context);
  303. logger->logComponent = (PKIX_ERRORCLASS)NULL;
  304. cleanup:
  305. PKIX_RETURN(LOGGER);
  306. }
  307. /*
  308. * FUNCTION: pkix_Logger_ToString
  309. * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
  310. */
  311. static PKIX_Error *
  312. pkix_Logger_ToString(
  313. PKIX_PL_Object *object,
  314. PKIX_PL_String **pString,
  315. void *plContext)
  316. {
  317. PKIX_Logger *logger = NULL;
  318. char *asciiFormat = NULL;
  319. PKIX_PL_String *formatString = NULL;
  320. PKIX_PL_String *contextString = NULL;
  321. PKIX_PL_String *componentString = NULL;
  322. PKIX_PL_String *loggerString = NULL;
  323. PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
  324. PKIX_NULLCHECK_TWO(object, pString);
  325. /* Check that this object is a logger */
  326. PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
  327. PKIX_OBJECTNOTLOGGER);
  328. logger = (PKIX_Logger *)object;
  329. asciiFormat =
  330. "[\n"
  331. "\tLogger: \n"
  332. "\tContext: %s\n"
  333. "\tMaximum Level: %d\n"
  334. "\tComponent Name: %s\n"
  335. "]\n";
  336. PKIX_CHECK(PKIX_PL_String_Create
  337. (PKIX_ESCASCII,
  338. asciiFormat,
  339. 0,
  340. &formatString,
  341. plContext),
  342. PKIX_STRINGCREATEFAILED);
  343. PKIX_TOSTRING(logger->context, &contextString, plContext,
  344. PKIX_OBJECTTOSTRINGFAILED);
  345. PKIX_CHECK(PKIX_PL_String_Create
  346. (PKIX_ESCASCII,
  347. (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
  348. 0,
  349. &componentString,
  350. plContext),
  351. PKIX_STRINGCREATEFAILED);
  352. PKIX_CHECK(PKIX_PL_Sprintf
  353. (&loggerString,
  354. plContext,
  355. formatString,
  356. contextString,
  357. logger->maxLevel,
  358. componentString),
  359. PKIX_SPRINTFFAILED);
  360. *pString = loggerString;
  361. cleanup:
  362. PKIX_DECREF(formatString);
  363. PKIX_DECREF(contextString);
  364. PKIX_RETURN(LOGGER);
  365. }
  366. /*
  367. * FUNCTION: pkix_Logger_Equals
  368. * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
  369. */
  370. static PKIX_Error *
  371. pkix_Logger_Equals(
  372. PKIX_PL_Object *first,
  373. PKIX_PL_Object *second,
  374. PKIX_Boolean *pResult,
  375. void *plContext)
  376. {
  377. PKIX_UInt32 secondType;
  378. PKIX_Boolean cmpResult;
  379. PKIX_Logger *firstLogger = NULL;
  380. PKIX_Logger *secondLogger = NULL;
  381. PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
  382. PKIX_NULLCHECK_THREE(first, second, pResult);
  383. /* test that first is a Logger */
  384. PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
  385. PKIX_FIRSTOBJECTNOTLOGGER);
  386. /*
  387. * Since we know first is a Logger, if both references are
  388. * identical, they must be equal
  389. */
  390. if (first == second){
  391. *pResult = PKIX_TRUE;
  392. goto cleanup;
  393. }
  394. /*
  395. * If second isn't a Logger, we don't throw an error.
  396. * We simply return a Boolean result of FALSE
  397. */
  398. *pResult = PKIX_FALSE;
  399. PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
  400. PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
  401. if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
  402. firstLogger = (PKIX_Logger *)first;
  403. secondLogger = (PKIX_Logger *)second;
  404. cmpResult = PKIX_FALSE;
  405. if (firstLogger->callback != secondLogger->callback) {
  406. goto cleanup;
  407. }
  408. if (firstLogger->logComponent != secondLogger->logComponent) {
  409. goto cleanup;
  410. }
  411. PKIX_EQUALS
  412. (firstLogger->context,
  413. secondLogger->context,
  414. &cmpResult,
  415. plContext,
  416. PKIX_OBJECTEQUALSFAILED);
  417. if (cmpResult == PKIX_FALSE) {
  418. goto cleanup;
  419. }
  420. if (firstLogger->maxLevel != secondLogger->maxLevel) {
  421. goto cleanup;
  422. }
  423. *pResult = cmpResult;
  424. cleanup:
  425. PKIX_RETURN(LOGGER);
  426. }
  427. /*
  428. * FUNCTION: pkix_Logger_Hashcode
  429. * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
  430. */
  431. static PKIX_Error *
  432. pkix_Logger_Hashcode(
  433. PKIX_PL_Object *object,
  434. PKIX_UInt32 *pHashcode,
  435. void *plContext)
  436. {
  437. PKIX_Logger *logger = NULL;
  438. PKIX_UInt32 hash = 0;
  439. PKIX_UInt32 tempHash = 0;
  440. PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
  441. PKIX_NULLCHECK_TWO(object, pHashcode);
  442. PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
  443. PKIX_OBJECTNOTLOGGER);
  444. logger = (PKIX_Logger *)object;
  445. PKIX_HASHCODE(logger->context, &tempHash, plContext,
  446. PKIX_OBJECTHASHCODEFAILED);
  447. hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) +
  448. logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
  449. *pHashcode = hash;
  450. cleanup:
  451. PKIX_RETURN(LOGGER);
  452. }
  453. /*
  454. * FUNCTION: pkix_Logger_Duplicate
  455. * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
  456. */
  457. static PKIX_Error *
  458. pkix_Logger_Duplicate(
  459. PKIX_PL_Object *object,
  460. PKIX_PL_Object **pNewObject,
  461. void *plContext)
  462. {
  463. PKIX_Logger *logger = NULL;
  464. PKIX_Logger *dupLogger = NULL;
  465. PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
  466. PKIX_NULLCHECK_TWO(object, pNewObject);
  467. PKIX_CHECK(pkix_CheckType
  468. ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
  469. PKIX_OBJECTNOTLOGGER);
  470. logger = (PKIX_Logger *) object;
  471. PKIX_CHECK(PKIX_PL_Object_Alloc
  472. (PKIX_LOGGER_TYPE,
  473. sizeof (PKIX_Logger),
  474. (PKIX_PL_Object **)&dupLogger,
  475. plContext),
  476. PKIX_COULDNOTCREATELOGGEROBJECT);
  477. dupLogger->callback = logger->callback;
  478. dupLogger->maxLevel = logger->maxLevel;
  479. PKIX_DUPLICATE
  480. (logger->context,
  481. &dupLogger->context,
  482. plContext,
  483. PKIX_OBJECTDUPLICATEFAILED);
  484. dupLogger->logComponent = logger->logComponent;
  485. *pNewObject = (PKIX_PL_Object *) dupLogger;
  486. cleanup:
  487. if (PKIX_ERROR_RECEIVED){
  488. PKIX_DECREF(dupLogger);
  489. }
  490. PKIX_RETURN(LOGGER);
  491. }
  492. /*
  493. * FUNCTION: pkix_Logger_RegisterSelf
  494. * DESCRIPTION:
  495. * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
  496. * THREAD SAFETY:
  497. * Not Thread Safe - for performance and complexity reasons
  498. *
  499. * Since this function is only called by PKIX_PL_Initialize, which should
  500. * only be called once, it is acceptable that this function is not
  501. * thread-safe.
  502. */
  503. PKIX_Error *
  504. pkix_Logger_RegisterSelf(void *plContext)
  505. {
  506. extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
  507. pkix_ClassTable_Entry entry;
  508. PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
  509. entry.description = "Logger";
  510. entry.objCounter = 0;
  511. entry.typeObjectSize = sizeof(PKIX_Logger);
  512. entry.destructor = pkix_Logger_Destroy;
  513. entry.equalsFunction = pkix_Logger_Equals;
  514. entry.hashcodeFunction = pkix_Logger_Hashcode;
  515. entry.toStringFunction = pkix_Logger_ToString;
  516. entry.comparator = NULL;
  517. entry.duplicateFunction = pkix_Logger_Duplicate;
  518. systemClasses[PKIX_LOGGER_TYPE] = entry;
  519. PKIX_RETURN(LOGGER);
  520. }
  521. /* --Public-Logger-Functions--------------------------------------------- */
  522. /*
  523. * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
  524. */
  525. PKIX_Error *
  526. PKIX_Logger_Create(
  527. PKIX_Logger_LogCallback callback,
  528. PKIX_PL_Object *loggerContext,
  529. PKIX_Logger **pLogger,
  530. void *plContext)
  531. {
  532. PKIX_Logger *logger = NULL;
  533. PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
  534. PKIX_NULLCHECK_ONE(pLogger);
  535. PKIX_CHECK(PKIX_PL_Object_Alloc
  536. (PKIX_LOGGER_TYPE,
  537. sizeof (PKIX_Logger),
  538. (PKIX_PL_Object **)&logger,
  539. plContext),
  540. PKIX_COULDNOTCREATELOGGEROBJECT);
  541. logger->callback = callback;
  542. logger->maxLevel = 0;
  543. logger->logComponent = (PKIX_ERRORCLASS)NULL;
  544. PKIX_INCREF(loggerContext);
  545. logger->context = loggerContext;
  546. *pLogger = logger;
  547. logger = NULL;
  548. cleanup:
  549. PKIX_DECREF(logger);
  550. PKIX_RETURN(LOGGER);
  551. }
  552. /*
  553. * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
  554. */
  555. PKIX_Error *
  556. PKIX_Logger_GetLogCallback(
  557. PKIX_Logger *logger,
  558. PKIX_Logger_LogCallback *pCallback,
  559. void *plContext)
  560. {
  561. PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
  562. PKIX_NULLCHECK_TWO(logger, pCallback);
  563. *pCallback = logger->callback;
  564. PKIX_RETURN(LOGGER);
  565. }
  566. /*
  567. * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
  568. */
  569. PKIX_Error *
  570. PKIX_Logger_GetLoggerContext(
  571. PKIX_Logger *logger,
  572. PKIX_PL_Object **pLoggerContext,
  573. void *plContext)
  574. {
  575. PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
  576. PKIX_NULLCHECK_TWO(logger, pLoggerContext);
  577. PKIX_INCREF(logger->context);
  578. *pLoggerContext = logger->context;
  579. cleanup:
  580. PKIX_RETURN(LOGGER);
  581. }
  582. /*
  583. * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
  584. */
  585. PKIX_Error *
  586. PKIX_Logger_GetMaxLoggingLevel(
  587. PKIX_Logger *logger,
  588. PKIX_UInt32 *pLevel,
  589. void *plContext)
  590. {
  591. PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
  592. PKIX_NULLCHECK_TWO(logger, pLevel);
  593. *pLevel = logger->maxLevel;
  594. PKIX_RETURN(LOGGER);
  595. }
  596. /*
  597. * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
  598. */
  599. PKIX_Error *
  600. PKIX_Logger_SetMaxLoggingLevel(
  601. PKIX_Logger *logger,
  602. PKIX_UInt32 level,
  603. void *plContext)
  604. {
  605. PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
  606. PKIX_NULLCHECK_ONE(logger);
  607. if (level > PKIX_LOGGER_LEVEL_MAX) {
  608. PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
  609. } else {
  610. logger->maxLevel = level;
  611. }
  612. cleanup:
  613. PKIX_RETURN(LOGGER);
  614. }
  615. /*
  616. * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
  617. */
  618. PKIX_Error *
  619. PKIX_Logger_GetLoggingComponent(
  620. PKIX_Logger *logger,
  621. PKIX_ERRORCLASS *pComponent,
  622. void *plContext)
  623. {
  624. PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
  625. PKIX_NULLCHECK_TWO(logger, pComponent);
  626. *pComponent = logger->logComponent;
  627. PKIX_RETURN(LOGGER);
  628. }
  629. /*
  630. * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
  631. */
  632. PKIX_Error *
  633. PKIX_Logger_SetLoggingComponent(
  634. PKIX_Logger *logger,
  635. PKIX_ERRORCLASS component,
  636. void *plContext)
  637. {
  638. PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
  639. PKIX_NULLCHECK_ONE(logger);
  640. logger->logComponent = component;
  641. PKIX_RETURN(LOGGER);
  642. }
  643. /*
  644. * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
  645. * documented as not thread-safe. However they are thread-safe now. We need
  646. * the lock when accessing the logger lists.
  647. */
  648. /*
  649. * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
  650. */
  651. PKIX_Error *
  652. PKIX_GetLoggers(
  653. PKIX_List **pLoggers, /* list of PKIX_Logger */
  654. void *plContext)
  655. {
  656. PKIX_List *list = NULL;
  657. PKIX_List *savedPkixLoggersDebugTrace = NULL;
  658. PKIX_List *savedPkixLoggersErrors = NULL;
  659. PKIX_Logger *logger = NULL;
  660. PKIX_Logger *dupLogger = NULL;
  661. PKIX_UInt32 i, length;
  662. PKIX_Boolean locked = PKIX_FALSE;
  663. PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
  664. PKIX_NULLCHECK_ONE(pLoggers);
  665. PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
  666. PKIX_MONITORLOCKENTERFAILED);
  667. locked = PKIX_TRUE;
  668. /*
  669. * Temporarily disable DEBUG/TRACE Logging to avoid possible
  670. * deadlock:
  671. * When the Logger List is being accessed, e.g. by PKIX_ENTER or
  672. * PKIX_DECREF, pkix_Logger_Check may check whether logging
  673. * is requested, creating a deadlock situation.
  674. */
  675. savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
  676. pkixLoggersDebugTrace = NULL;
  677. savedPkixLoggersErrors = pkixLoggersErrors;
  678. pkixLoggersErrors = NULL;
  679. if (pkixLoggers == NULL) {
  680. length = 0;
  681. } else {
  682. PKIX_CHECK(PKIX_List_GetLength
  683. (pkixLoggers, &length, plContext),
  684. PKIX_LISTGETLENGTHFAILED);
  685. }
  686. /* Create a list and copy the pkixLoggers item to the list */
  687. PKIX_CHECK(PKIX_List_Create(&list, plContext),
  688. PKIX_LISTCREATEFAILED);
  689. for (i = 0; i < length; i++) {
  690. PKIX_CHECK(PKIX_List_GetItem
  691. (pkixLoggers,
  692. i,
  693. (PKIX_PL_Object **) &logger,
  694. plContext),
  695. PKIX_LISTGETITEMFAILED);
  696. PKIX_CHECK(pkix_Logger_Duplicate
  697. ((PKIX_PL_Object *)logger,
  698. (PKIX_PL_Object **)&dupLogger,
  699. plContext),
  700. PKIX_LOGGERDUPLICATEFAILED);
  701. PKIX_CHECK(PKIX_List_AppendItem
  702. (list,
  703. (PKIX_PL_Object *) dupLogger,
  704. plContext),
  705. PKIX_LISTAPPENDITEMFAILED);
  706. PKIX_DECREF(logger);
  707. PKIX_DECREF(dupLogger);
  708. }
  709. /* Set the list to be immutable */
  710. PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
  711. PKIX_LISTSETIMMUTABLEFAILED);
  712. *pLoggers = list;
  713. cleanup:
  714. PKIX_DECREF(logger);
  715. /* Restore logging capability */
  716. pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  717. pkixLoggersErrors = savedPkixLoggersErrors;
  718. if (locked) {
  719. PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
  720. PKIX_MONITORLOCKEXITFAILED);
  721. }
  722. PKIX_RETURN(LOGGER);
  723. }
  724. /*
  725. * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
  726. */
  727. PKIX_Error *
  728. PKIX_SetLoggers(
  729. PKIX_List *loggers, /* list of PKIX_Logger */
  730. void *plContext)
  731. {
  732. PKIX_List *list = NULL;
  733. PKIX_List *savedPkixLoggersErrors = NULL;
  734. PKIX_List *savedPkixLoggersDebugTrace = NULL;
  735. PKIX_Logger *logger = NULL;
  736. PKIX_Logger *dupLogger = NULL;
  737. PKIX_Boolean locked = PKIX_FALSE;
  738. PKIX_UInt32 i, length;
  739. PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
  740. PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
  741. PKIX_MONITORLOCKENTERFAILED);
  742. locked = PKIX_TRUE;
  743. /* Disable tracing, etc. to avoid recursion and deadlock */
  744. savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
  745. pkixLoggersDebugTrace = NULL;
  746. savedPkixLoggersErrors = pkixLoggersErrors;
  747. pkixLoggersErrors = NULL;
  748. /* discard any prior loggers */
  749. PKIX_DECREF(pkixLoggers);
  750. PKIX_DECREF(savedPkixLoggersErrors);
  751. PKIX_DECREF(savedPkixLoggersDebugTrace);
  752. if (loggers != NULL) {
  753. PKIX_CHECK(PKIX_List_Create(&list, plContext),
  754. PKIX_LISTCREATEFAILED);
  755. PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
  756. PKIX_LISTGETLENGTHFAILED);
  757. for (i = 0; i < length; i++) {
  758. PKIX_CHECK(PKIX_List_GetItem
  759. (loggers,
  760. i,
  761. (PKIX_PL_Object **) &logger,
  762. plContext),
  763. PKIX_LISTGETITEMFAILED);
  764. PKIX_CHECK(pkix_Logger_Duplicate
  765. ((PKIX_PL_Object *)logger,
  766. (PKIX_PL_Object **)&dupLogger,
  767. plContext),
  768. PKIX_LOGGERDUPLICATEFAILED);
  769. PKIX_CHECK(PKIX_List_AppendItem
  770. (list,
  771. (PKIX_PL_Object *) dupLogger,
  772. plContext),
  773. PKIX_LISTAPPENDITEMFAILED);
  774. /* Make two lists */
  775. /* Put in pkixLoggersErrors in any case*/
  776. if (savedPkixLoggersErrors == NULL) {
  777. PKIX_CHECK(PKIX_List_Create
  778. (&savedPkixLoggersErrors,
  779. plContext),
  780. PKIX_LISTCREATEFAILED);
  781. }
  782. PKIX_CHECK(PKIX_List_AppendItem
  783. (savedPkixLoggersErrors,
  784. (PKIX_PL_Object *) dupLogger,
  785. plContext),
  786. PKIX_LISTAPPENDITEMFAILED);
  787. if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
  788. /* Put in pkixLoggersDebugTrace */
  789. if (savedPkixLoggersDebugTrace == NULL) {
  790. PKIX_CHECK(PKIX_List_Create
  791. (&savedPkixLoggersDebugTrace,
  792. plContext),
  793. PKIX_LISTCREATEFAILED);
  794. }
  795. PKIX_CHECK(PKIX_List_AppendItem
  796. (savedPkixLoggersDebugTrace,
  797. (PKIX_PL_Object *) dupLogger,
  798. plContext),
  799. PKIX_LISTAPPENDITEMFAILED);
  800. }
  801. PKIX_DECREF(logger);
  802. PKIX_DECREF(dupLogger);
  803. }
  804. pkixLoggers = list;
  805. }
  806. cleanup:
  807. if (PKIX_ERROR_RECEIVED){
  808. PKIX_DECREF(list);
  809. PKIX_DECREF(savedPkixLoggersErrors);
  810. PKIX_DECREF(savedPkixLoggersDebugTrace);
  811. pkixLoggers = NULL;
  812. }
  813. PKIX_DECREF(logger);
  814. /* Reenable logging capability with new lists */
  815. pkixLoggersErrors = savedPkixLoggersErrors;
  816. pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  817. if (locked) {
  818. PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
  819. PKIX_MONITORLOCKEXITFAILED);
  820. }
  821. PKIX_RETURN(LOGGER);
  822. }
  823. /*
  824. * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
  825. */
  826. PKIX_Error *
  827. PKIX_AddLogger(
  828. PKIX_Logger *logger,
  829. void *plContext)
  830. {
  831. PKIX_Logger *dupLogger = NULL;
  832. PKIX_Logger *addLogger = NULL;
  833. PKIX_List *savedPkixLoggersErrors = NULL;
  834. PKIX_List *savedPkixLoggersDebugTrace = NULL;
  835. PKIX_Boolean locked = PKIX_FALSE;
  836. PKIX_UInt32 i, length;
  837. PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
  838. PKIX_NULLCHECK_ONE(logger);
  839. PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
  840. PKIX_MONITORLOCKENTERFAILED);
  841. locked = PKIX_TRUE;
  842. savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
  843. pkixLoggersDebugTrace = NULL;
  844. savedPkixLoggersErrors = pkixLoggersErrors;
  845. pkixLoggersErrors = NULL;
  846. PKIX_DECREF(savedPkixLoggersErrors);
  847. PKIX_DECREF(savedPkixLoggersDebugTrace);
  848. if (pkixLoggers == NULL) {
  849. PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
  850. PKIX_LISTCREATEFAILED);
  851. }
  852. PKIX_CHECK(pkix_Logger_Duplicate
  853. ((PKIX_PL_Object *)logger,
  854. (PKIX_PL_Object **)&dupLogger,
  855. plContext),
  856. PKIX_LOGGERDUPLICATEFAILED);
  857. PKIX_CHECK(PKIX_List_AppendItem
  858. (pkixLoggers,
  859. (PKIX_PL_Object *) dupLogger,
  860. plContext),
  861. PKIX_LISTAPPENDITEMFAILED);
  862. PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
  863. PKIX_LISTGETLENGTHFAILED);
  864. /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
  865. for (i = 0; i < length; i++) {
  866. PKIX_CHECK(PKIX_List_GetItem
  867. (pkixLoggers,
  868. i,
  869. (PKIX_PL_Object **) &addLogger,
  870. plContext),
  871. PKIX_LISTGETITEMFAILED);
  872. /* Put in pkixLoggersErrors */
  873. if (savedPkixLoggersErrors == NULL) {
  874. PKIX_CHECK(PKIX_List_Create
  875. (&savedPkixLoggersErrors,
  876. plContext),
  877. PKIX_LISTCREATEFAILED);
  878. }
  879. PKIX_CHECK(PKIX_List_AppendItem
  880. (savedPkixLoggersErrors,
  881. (PKIX_PL_Object *) addLogger,
  882. plContext),
  883. PKIX_LISTAPPENDITEMFAILED);
  884. if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
  885. /* Put in pkixLoggersDebugTrace */
  886. if (savedPkixLoggersDebugTrace == NULL) {
  887. PKIX_CHECK(PKIX_List_Create
  888. (&savedPkixLoggersDebugTrace,
  889. plContext),
  890. PKIX_LISTCREATEFAILED);
  891. }
  892. PKIX_CHECK(PKIX_List_AppendItem
  893. (savedPkixLoggersDebugTrace,
  894. (PKIX_PL_Object *) addLogger,
  895. plContext),
  896. PKIX_LISTAPPENDITEMFAILED);
  897. }
  898. PKIX_DECREF(addLogger);
  899. }
  900. cleanup:
  901. PKIX_DECREF(dupLogger);
  902. PKIX_DECREF(addLogger);
  903. /* Restore logging capability */
  904. pkixLoggersErrors = savedPkixLoggersErrors;
  905. pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  906. if (locked) {
  907. PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
  908. PKIX_MONITORLOCKEXITFAILED);
  909. }
  910. PKIX_RETURN(LOGGER);
  911. }