From bf5492abd2f0bc4edf386bf06d8728843f5eb3d3 Mon Sep 17 00:00:00 2001 From: Jonathan Rose Date: Fri, 8 Nov 2013 19:33:48 +0000 Subject: [PATCH] security_events: Push out security events over AMI events Security Events will now be written to any listener of the new 'security' class Review: https://reviewboard.asterisk.org/r/2998/ ........ Merged revisions 402584 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@402585 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 3 ++ configs/manager.conf.sample | 1 + include/asterisk/manager.h | 39 +++++++++---------- main/manager.c | 11 ++++++ main/security_events.c | 76 ++++++++++++++++++++++++++++++++++++- 5 files changed, 110 insertions(+), 20 deletions(-) diff --git a/CHANGES b/CHANGES index 423ffb640e..381de61bb8 100644 --- a/CHANGES +++ b/CHANGES @@ -579,6 +579,9 @@ AMI (Asterisk Manager Interface) They contain information about the transfer that just completed, including the location of the transfered channel. + * Added a 'security' class to AMI which outputs the required fields for + security messages similar to the log messages from res_security_log + CDR (Call Detail Records) ------------------ * Significant changes have been made to the behavior of CDRs. The CDR engine diff --git a/configs/manager.conf.sample b/configs/manager.conf.sample index 54f6928c86..13076ce8d5 100644 --- a/configs/manager.conf.sample +++ b/configs/manager.conf.sample @@ -147,6 +147,7 @@ bindaddr = 0.0.0.0 ; test - Ability to read TestEvent notifications sent to the Asterisk Test ; Suite. Note that this is only enabled when the TEST_FRAMEWORK ; compiler flag is defined. +; security - Security Events. Read-only. ; message - Permissions to send out of call messages. Write-only ; ;read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h index dad7c49174..6d0be4c0d6 100644 --- a/include/asterisk/manager.h +++ b/include/asterisk/manager.h @@ -68,26 +68,27 @@ /*! \name Manager event classes */ /*@{ */ -#define EVENT_FLAG_SYSTEM (1 << 0) /* System events such as module load/unload */ -#define EVENT_FLAG_CALL (1 << 1) /* Call event, such as state change, etc */ -#define EVENT_FLAG_LOG (1 << 2) /* Log events */ -#define EVENT_FLAG_VERBOSE (1 << 3) /* Verbose messages */ -#define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */ -#define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */ -#define EVENT_FLAG_USER (1 << 6) /* Ability to read/set user info */ -#define EVENT_FLAG_CONFIG (1 << 7) /* Ability to modify configurations */ -#define EVENT_FLAG_DTMF (1 << 8) /* Ability to read DTMF events */ -#define EVENT_FLAG_REPORTING (1 << 9) /* Reporting events such as rtcp sent */ -#define EVENT_FLAG_CDR (1 << 10) /* CDR events */ -#define EVENT_FLAG_DIALPLAN (1 << 11) /* Dialplan events (VarSet, NewExten) */ -#define EVENT_FLAG_ORIGINATE (1 << 12) /* Originate a call to an extension */ -#define EVENT_FLAG_AGI (1 << 13) /* AGI events */ -#define EVENT_FLAG_HOOKRESPONSE (1 << 14) /* Hook Response */ -#define EVENT_FLAG_CC (1 << 15) /* Call Completion events */ -#define EVENT_FLAG_AOC (1 << 16) /* Advice Of Charge events */ -#define EVENT_FLAG_TEST (1 << 17) /* Test event used to signal the Asterisk Test Suite */ +#define EVENT_FLAG_SYSTEM (1 << 0) /* System events such as module load/unload */ +#define EVENT_FLAG_CALL (1 << 1) /* Call event, such as state change, etc */ +#define EVENT_FLAG_LOG (1 << 2) /* Log events */ +#define EVENT_FLAG_VERBOSE (1 << 3) /* Verbose messages */ +#define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */ +#define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */ +#define EVENT_FLAG_USER (1 << 6) /* Ability to read/set user info */ +#define EVENT_FLAG_CONFIG (1 << 7) /* Ability to modify configurations */ +#define EVENT_FLAG_DTMF (1 << 8) /* Ability to read DTMF events */ +#define EVENT_FLAG_REPORTING (1 << 9) /* Reporting events such as rtcp sent */ +#define EVENT_FLAG_CDR (1 << 10) /* CDR events */ +#define EVENT_FLAG_DIALPLAN (1 << 11) /* Dialplan events (VarSet, NewExten) */ +#define EVENT_FLAG_ORIGINATE (1 << 12) /* Originate a call to an extension */ +#define EVENT_FLAG_AGI (1 << 13) /* AGI events */ +#define EVENT_FLAG_HOOKRESPONSE (1 << 14) /* Hook Response */ +#define EVENT_FLAG_CC (1 << 15) /* Call Completion events */ +#define EVENT_FLAG_AOC (1 << 16) /* Advice Of Charge events */ +#define EVENT_FLAG_TEST (1 << 17) /* Test event used to signal the Asterisk Test Suite */ +#define EVENT_FLAG_SECURITY (1 << 18) /* Security Message as AMI Event */ /*XXX Why shifted by 30? XXX */ -#define EVENT_FLAG_MESSAGE (1 << 30) /* MESSAGE events. */ +#define EVENT_FLAG_MESSAGE (1 << 30) /* MESSAGE events. */ /*@} */ /*! \brief Export manager structures */ diff --git a/main/manager.c b/main/manager.c index 01cc75474c..f2590b1bb8 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1129,6 +1129,9 @@ static struct stasis_message_router *stasis_router; /*! \brief The \ref stasis_subscription for forwarding the RTP topic to the AMI topic */ static struct stasis_forward *rtp_topic_forwarder; +/*! \brief The \ref stasis_subscription for forwarding the Security topic to the AMI topic */ +static struct stasis_forward *security_topic_forwarder; + #define MGR_SHOW_TERMINAL_WIDTH 80 #define MAX_VARS 128 @@ -1593,6 +1596,7 @@ static const struct permalias { { EVENT_FLAG_CC, "cc" }, { EVENT_FLAG_AOC, "aoc" }, { EVENT_FLAG_TEST, "test" }, + { EVENT_FLAG_SECURITY, "security" }, { EVENT_FLAG_MESSAGE, "message" }, { INT_MAX, "all" }, { 0, "none" }, @@ -7774,6 +7778,8 @@ static void manager_shutdown(void) } stasis_forward_cancel(rtp_topic_forwarder); rtp_topic_forwarder = NULL; + stasis_forward_cancel(security_topic_forwarder); + security_topic_forwarder = NULL; ao2_cleanup(manager_topic); manager_topic = NULL; STASIS_MESSAGE_TYPE_CLEANUP(ast_manager_get_generic_type); @@ -7817,6 +7823,11 @@ static int manager_subscriptions_init(void) return -1; } + security_topic_forwarder = stasis_forward_all(ast_security_topic(), manager_topic); + if (!security_topic_forwarder) { + return -1; + } + stasis_router = stasis_message_router_create(manager_topic); if (!stasis_router) { return -1; diff --git a/main/security_events.c b/main/security_events.c index d10338984a..42ebc59fea 100644 --- a/main/security_events.c +++ b/main/security_events.c @@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/astobj2.h" static const size_t TIMESTAMP_STR_LEN = 32; +static const size_t SECURITY_EVENT_BUF_INIT_LEN = 256; /*! \brief Security Topic */ static struct stasis_topic *security_topic; @@ -51,8 +52,81 @@ struct stasis_topic *ast_security_topic(void) return security_topic; } +static int append_event_str_single(struct ast_str **str, struct ast_json *json, + const enum ast_event_ie_type ie_type) +{ + const char *ie_type_key = ast_event_get_ie_type_name(ie_type); + struct ast_json *json_string = ast_json_object_get(json, ie_type_key); + + ast_assert(json_string != NULL); + + if (ast_str_append(str, 0, "%s: %s\r\n", ie_type_key, ast_json_string_get(json_string)) == -1) { + return -1; + } + + return 0; +} + +static int append_event_str_from_json(struct ast_str **str, struct ast_json *json, + const struct ast_security_event_ie_type *ies) +{ + unsigned int i; + + for (i = 0; ies[i].ie_type != AST_EVENT_IE_END; i++) { + if (append_event_str_single(str, json, ies[i].ie_type)) { + return -1; + } + } + + return 0; +} + +static struct ast_manager_event_blob *security_event_to_ami_blob(struct ast_json *json) +{ + RAII_VAR(struct ast_str *, str, NULL, ast_free); + struct ast_json *event_type_json; + enum ast_security_event_type event_type; + + event_type_json = ast_json_object_get(json, "SecurityEvent"); + event_type = ast_json_integer_get(event_type_json); + + ast_assert(event_type >= 0 && event_type < AST_SECURITY_EVENT_NUM_TYPES); + + if (!(str = ast_str_create(SECURITY_EVENT_BUF_INIT_LEN))) { + return NULL; + } + + if (append_event_str_from_json(&str, json, + ast_security_event_get_required_ies(event_type))) { + ast_log(LOG_ERROR, "Failed to issue a security event to AMI.\n"); + return NULL; + } + + return ast_manager_event_blob_create(EVENT_FLAG_SECURITY, + ast_security_event_get_name(event_type), + "%s", + ast_str_buffer(str)); +} + +static struct ast_manager_event_blob *security_event_to_ami(struct stasis_message *message) +{ + struct ast_json_payload *payload = stasis_message_data(message); + + if (stasis_message_type(message) != ast_security_event_type()) { + return NULL; + } + + if (!payload) { + return NULL; + } + + return security_event_to_ami_blob(payload->json); +} + /*! \brief Message type for security events */ -STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type); +STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type, + .to_ami = security_event_to_ami, + ); static void security_stasis_cleanup(void) {