res_security_log.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Digium, Inc.
  5. *
  6. * Russell Bryant <russell@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. *
  21. * \author Russell Bryant <russell@digium.com>
  22. *
  23. * \brief Security Event Logging
  24. *
  25. * \todo Make informational security events optional
  26. * \todo Escape quotes in string payload IE contents
  27. */
  28. /*** MODULEINFO
  29. <support_level>core</support_level>
  30. ***/
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
  33. #include "asterisk/module.h"
  34. #include "asterisk/logger.h"
  35. #include "asterisk/threadstorage.h"
  36. #include "asterisk/strings.h"
  37. #include "asterisk/security_events.h"
  38. #include "asterisk/stasis.h"
  39. #include "asterisk/json.h"
  40. static const char LOG_SECURITY_NAME[] = "SECURITY";
  41. static int LOG_SECURITY;
  42. static struct stasis_subscription *security_stasis_sub;
  43. AST_THREADSTORAGE(security_event_buf);
  44. static const size_t SECURITY_EVENT_BUF_INIT_LEN = 256;
  45. enum ie_required {
  46. NOT_REQUIRED,
  47. REQUIRED
  48. };
  49. static void append_json_single(struct ast_str **str, struct ast_json *json,
  50. const enum ast_event_ie_type ie_type, enum ie_required required)
  51. {
  52. const char *ie_type_key = ast_event_get_ie_type_name(ie_type);
  53. struct ast_json *json_string;
  54. json_string = ast_json_object_get(json, ie_type_key);
  55. if (!required && !json_string) {
  56. /* Optional IE isn't present. Ignore. */
  57. return;
  58. }
  59. /* At this point, it _better_ be there! */
  60. ast_assert(json_string != NULL);
  61. ast_str_append(str, 0, ",%s=\"%s\"",
  62. ie_type_key,
  63. ast_json_string_get(json_string));
  64. }
  65. static void append_json(struct ast_str **str, struct ast_json *json,
  66. const struct ast_security_event_ie_type *ies, enum ie_required required)
  67. {
  68. unsigned int i;
  69. for (i = 0; ies[i].ie_type != AST_EVENT_IE_END; i++) {
  70. append_json_single(str, json, ies[i].ie_type, required);
  71. }
  72. }
  73. static void security_event_stasis_cb(struct ast_json *json)
  74. {
  75. struct ast_str *str;
  76. struct ast_json *event_type_json;
  77. enum ast_security_event_type event_type;
  78. event_type_json = ast_json_object_get(json, "SecurityEvent");
  79. event_type = ast_json_integer_get(event_type_json);
  80. ast_assert((unsigned int)event_type < AST_SECURITY_EVENT_NUM_TYPES);
  81. if (!(str = ast_str_thread_get(&security_event_buf,
  82. SECURITY_EVENT_BUF_INIT_LEN))) {
  83. return;
  84. }
  85. ast_str_set(&str, 0, "SecurityEvent=\"%s\"",
  86. ast_security_event_get_name(event_type));
  87. append_json(&str, json,
  88. ast_security_event_get_required_ies(event_type), REQUIRED);
  89. append_json(&str, json,
  90. ast_security_event_get_optional_ies(event_type), NOT_REQUIRED);
  91. ast_log_dynamic_level(LOG_SECURITY, "%s\n", ast_str_buffer(str));
  92. }
  93. static void security_stasis_cb(void *data, struct stasis_subscription *sub,
  94. struct stasis_message *message)
  95. {
  96. struct ast_json_payload *payload = stasis_message_data(message);
  97. if (stasis_message_type(message) != ast_security_event_type()) {
  98. return;
  99. }
  100. if (!payload) {
  101. return;
  102. }
  103. security_event_stasis_cb(payload->json);
  104. }
  105. static int load_module(void)
  106. {
  107. if ((LOG_SECURITY = ast_logger_register_level(LOG_SECURITY_NAME)) == -1) {
  108. return AST_MODULE_LOAD_DECLINE;
  109. }
  110. if (!(security_stasis_sub = stasis_subscribe(ast_security_topic(), security_stasis_cb, NULL))) {
  111. ast_logger_unregister_level(LOG_SECURITY_NAME);
  112. LOG_SECURITY = -1;
  113. return AST_MODULE_LOAD_DECLINE;
  114. }
  115. stasis_subscription_accept_message_type(security_stasis_sub, ast_security_event_type());
  116. stasis_subscription_set_filter(security_stasis_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
  117. ast_verb(3, "Security Logging Enabled\n");
  118. return AST_MODULE_LOAD_SUCCESS;
  119. }
  120. static int unload_module(void)
  121. {
  122. if (security_stasis_sub) {
  123. security_stasis_sub = stasis_unsubscribe_and_join(security_stasis_sub);
  124. }
  125. ast_logger_unregister_level(LOG_SECURITY_NAME);
  126. ast_verb(3, "Security Logging Disabled\n");
  127. return 0;
  128. }
  129. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Security Event Logging");