summaryrefslogtreecommitdiff
path: root/res/res_security_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_security_log.c')
-rw-r--r--res/res_security_log.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/res/res_security_log.c b/res/res_security_log.c
new file mode 100644
index 000000000..2e3d4af52
--- /dev/null
+++ b/res/res_security_log.c
@@ -0,0 +1,163 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2009, Digium, Inc.
+ *
+ * Russell Bryant <russell@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ *
+ * \author Russell Bryant <russell@digium.com>
+ *
+ * \brief Security Event Logging
+ *
+ * \todo Make informational security events optional
+ * \todo Escape quotes in string payload IE contents
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
+
+#include "asterisk/module.h"
+#include "asterisk/logger.h"
+#include "asterisk/event.h"
+#include "asterisk/threadstorage.h"
+#include "asterisk/strings.h"
+#include "asterisk/security_events.h"
+
+static const char LOG_SECURITY_NAME[] = "SECURITY";
+
+static int LOG_SECURITY;
+
+static struct ast_event_sub *security_event_sub;
+
+AST_THREADSTORAGE(security_event_buf);
+static const size_t SECURITY_EVENT_BUF_INIT_LEN = 256;
+
+enum ie_required {
+ NOT_REQUIRED,
+ REQUIRED
+};
+
+static int ie_is_present(const struct ast_event *event,
+ const enum ast_event_ie_type ie_type)
+{
+ return (ast_event_get_ie_raw(event, ie_type) != NULL);
+}
+
+static void append_ie(struct ast_str **str, const struct ast_event *event,
+ const enum ast_event_ie_type ie_type, enum ie_required required)
+{
+ if (!required && !ie_is_present(event, ie_type)) {
+ /* Optional IE isn't present. Ignore. */
+ return;
+ }
+
+ /* At this point, it _better_ be there! */
+ ast_assert(ie_is_present(event, ie_type));
+
+ switch (ast_event_get_ie_pltype(ie_type)) {
+ case AST_EVENT_IE_PLTYPE_UINT:
+ ast_str_append(str, 0, ",%s=\"%u\"",
+ ast_event_get_ie_type_name(ie_type),
+ ast_event_get_ie_uint(event, ie_type));
+ break;
+ case AST_EVENT_IE_PLTYPE_STR:
+ ast_str_append(str, 0, ",%s=\"%s\"",
+ ast_event_get_ie_type_name(ie_type),
+ ast_event_get_ie_str(event, ie_type));
+ break;
+ case AST_EVENT_IE_PLTYPE_BITFLAGS:
+ ast_str_append(str, 0, ",%s=\"%u\"",
+ ast_event_get_ie_type_name(ie_type),
+ ast_event_get_ie_bitflags(event, ie_type));
+ break;
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ case AST_EVENT_IE_PLTYPE_RAW:
+ ast_log(LOG_WARNING, "Unexpected payload type for IE '%s'\n",
+ ast_event_get_ie_type_name(ie_type));
+ break;
+ }
+}
+
+static void append_ies(struct ast_str **str, const struct ast_event *event,
+ const struct ast_security_event_ie_type *ies, enum ie_required required)
+{
+ unsigned int i;
+
+ for (i = 0; ies[i].ie_type != AST_EVENT_IE_END; i++) {
+ append_ie(str, event, ies[i].ie_type, required);
+ }
+}
+
+static void security_event_cb(const struct ast_event *event, void *data)
+{
+ struct ast_str *str;
+ enum ast_security_event_type event_type;
+
+ if (!(str = ast_str_thread_get(&security_event_buf,
+ SECURITY_EVENT_BUF_INIT_LEN))) {
+ return;
+ }
+
+ /* Note that the event type is guaranteed to be valid here. */
+ event_type = ast_event_get_ie_uint(event, AST_EVENT_IE_SECURITY_EVENT);
+ ast_assert(event_type >= 0 && event_type < AST_SECURITY_EVENT_NUM_TYPES);
+
+ ast_str_set(&str, 0, "%s=\"%s\"",
+ ast_event_get_ie_type_name(AST_EVENT_IE_SECURITY_EVENT),
+ ast_security_event_get_name(event_type));
+
+ append_ies(&str, event,
+ ast_security_event_get_required_ies(event_type), REQUIRED);
+ append_ies(&str, event,
+ ast_security_event_get_optional_ies(event_type), NOT_REQUIRED);
+
+ ast_log_dynamic_level(LOG_SECURITY, "%s\n", ast_str_buffer(str));
+}
+
+static int load_module(void)
+{
+ if ((LOG_SECURITY = ast_logger_register_level(LOG_SECURITY_NAME)) == -1) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ if (!(security_event_sub = ast_event_subscribe(AST_EVENT_SECURITY,
+ security_event_cb, "Security Event Logger",
+ NULL, AST_EVENT_IE_END))) {
+ ast_logger_unregister_level(LOG_SECURITY_NAME);
+ LOG_SECURITY = -1;
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ ast_verb(3, "Security Logging Enabled\n");
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+ if (security_event_sub) {
+ security_event_sub = ast_event_unsubscribe(security_event_sub);
+ }
+
+ ast_verb(3, "Security Logging Disabled\n");
+
+ return 0;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Security Event Logging");