summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2013-05-17 17:36:10 +0000
committerJonathan Rose <jrose@digium.com>2013-05-17 17:36:10 +0000
commitb90bba7a303bf57c3c874a1c8f506d39d4e78a9c (patch)
tree56e6ca0d885b1e9e11856a6be44b4b92582f5606 /main
parent15945a7185187a3d79c7c7247a297bf92b49c139 (diff)
Stasis: Update security events to use Stasis
Also moves ACL messages to the security topic and gets rid of the ACL topic (closes issue ASTERISK-21103) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2496/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@388975 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/asterisk.c7
-rw-r--r--main/json.c44
-rw-r--r--main/manager.c8
-rw-r--r--main/named_acl.c20
-rw-r--r--main/security_events.c231
5 files changed, 211 insertions, 99 deletions
diff --git a/main/asterisk.c b/main/asterisk.c
index 9308230fb..933aae63d 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -242,6 +242,7 @@ int daemon(int, int); /* defined in libresolv of all places */
#include "asterisk/sorcery.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
+#include "asterisk/security_events.h"
#include "asterisk/stasis_endpoints.h"
#include "../defaults.h"
@@ -4263,6 +4264,12 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (ast_security_stasis_init()) { /* Initialize Security Stasis Topic and Events */
+ ast_security_stasis_cleanup();
+ printf("%s", term_quit());
+ exit(1);
+ }
+
if (ast_named_acl_init()) { /* Initialize the Named ACL system */
printf("%s", term_quit());
exit(1);
diff --git a/main/json.c b/main/json.c
index 87971f04a..5b69ccbaa 100644
--- a/main/json.c
+++ b/main/json.c
@@ -527,6 +527,50 @@ struct ast_json *ast_json_timeval(const struct timeval tv, const char *zone)
return ast_json_string_create(buf);
}
+struct ast_json *ast_json_ipaddr(const struct ast_sockaddr *addr, enum ast_transport transport_type)
+{
+ struct ast_str *string = ast_str_alloca(64);
+
+ if (!string) {
+ return NULL;
+ }
+
+ ast_str_set(&string, 0, (ast_sockaddr_is_ipv4(addr) ||
+ ast_sockaddr_is_ipv4_mapped(addr)) ? "IPV4/" : "IPV6/");
+
+ if (transport_type) {
+ char *transport_string = NULL;
+
+ /* NOTE: None will be applied if multiple transport types are specified in transport_type */
+ switch(transport_type) {
+ case AST_TRANSPORT_UDP:
+ transport_string = "UDP";
+ break;
+ case AST_TRANSPORT_TCP:
+ transport_string = "TCP";
+ break;
+ case AST_TRANSPORT_TLS:
+ transport_string = "TLS";
+ break;
+ case AST_TRANSPORT_WS:
+ transport_string = "WS";
+ break;
+ case AST_TRANSPORT_WSS:
+ transport_string = "WSS";
+ break;
+ }
+
+ if (transport_string) {
+ ast_str_append(&string, 0, "%s/", transport_string);
+ }
+ }
+
+ ast_str_append(&string, 0, "%s", ast_sockaddr_stringify_addr(addr));
+ ast_str_append(&string, 0, "/%s", ast_sockaddr_stringify_port(addr));
+
+ return ast_json_string_create(ast_str_buffer(string));
+}
+
void ast_json_init(void)
{
/* Setup to use Asterisk custom allocators */
diff --git a/main/manager.c b/main/manager.c
index 6e7ea1e20..4d2923eb5 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -1070,7 +1070,7 @@ static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, st
static void acl_change_stasis_subscribe(void)
{
if (!acl_change_sub) {
- acl_change_sub = stasis_subscribe(ast_acl_topic(),
+ acl_change_sub = stasis_subscribe(ast_security_topic(),
acl_change_stasis_cb, NULL);
}
}
@@ -2361,10 +2361,10 @@ static int set_eventmask(struct mansession *s, const char *eventmask)
return maskint;
}
-static enum ast_security_event_transport_type mansession_get_transport(const struct mansession *s)
+static enum ast_transport mansession_get_transport(const struct mansession *s)
{
- return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS :
- AST_SECURITY_EVENT_TRANSPORT_TCP;
+ return s->tcptls_session->parent->tls_cfg ? AST_TRANSPORT_TLS :
+ AST_TRANSPORT_TCP;
}
static void report_invalid_user(const struct mansession *s, const char *username)
diff --git a/main/named_acl.c b/main/named_acl.c
index afcd0692f..092aa94a6 100644
--- a/main/named_acl.c
+++ b/main/named_acl.c
@@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/paths.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
+#include "asterisk/security_events.h"
#define NACL_CONFIG "acl.conf"
#define ACL_FAMILY "acls"
@@ -356,16 +357,11 @@ struct ast_ha *ast_named_acl_find(const char *name, int *is_realtime, int *is_un
return ha;
}
-/*! \brief Topic for ACLs */
-static struct stasis_topic *acl_topic;
-
/*! \brief Message type for named ACL changes */
STASIS_MESSAGE_TYPE_DEFN(ast_named_acl_change_type);
static void acl_stasis_shutdown(void)
{
- ao2_cleanup(acl_topic);
- acl_topic = NULL;
STASIS_MESSAGE_TYPE_CLEANUP(ast_named_acl_change_type);
}
@@ -376,22 +372,16 @@ static void acl_stasis_shutdown(void)
static void ast_acl_stasis_init(void)
{
ast_register_atexit(acl_stasis_shutdown);
- acl_topic = stasis_topic_create("ast_acl");
STASIS_MESSAGE_TYPE_INIT(ast_named_acl_change_type);
}
-struct stasis_topic *ast_acl_topic(void)
-{
- return acl_topic;
-}
-
/*!
* \internal
* \brief Sends a stasis message corresponding to a given named ACL that has changed or
* that all ACLs have been updated and old copies must be refreshed. Consumers of
- * named ACLs should subscribe to the ast_acl_topic and respond to messages of the
- * ast_named_acl_change_type stasis message type in order to be able to accomodate
- * changes to named ACLs.
+ * named ACLs should subscribe to the ast_security_topic and respond to messages
+ * of the ast_named_acl_change_type stasis message type in order to be able to
+ * accommodate changes to named ACLs.
*
* \param name Name of the ACL that has changed. May be an empty string (but not NULL)
* If name is an empty string, then all ACLs must be refreshed.
@@ -423,7 +413,7 @@ static int publish_acl_change(const char *name)
goto publish_failure;
}
- stasis_publish(ast_acl_topic(), msg);
+ stasis_publish(ast_security_topic(), msg);
return 0;
diff --git a/main/security_events.c b/main/security_events.c
index bdb9b21c8..d42bea64a 100644
--- a/main/security_events.c
+++ b/main/security_events.c
@@ -37,9 +37,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/network.h"
#include "asterisk/security_events.h"
#include "asterisk/netsock2.h"
+#include "asterisk/stasis.h"
+#include "asterisk/json.h"
+#include "asterisk/astobj2.h"
static const size_t TIMESTAMP_STR_LEN = 32;
+/*! \brief Security Topic */
+static struct stasis_topic *security_topic;
+
+struct stasis_topic *ast_security_topic(void)
+{
+ return security_topic;
+}
+
+/*! \brief Message type for security events */
+STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type);
+
+int ast_security_stasis_init(void)
+{
+ security_topic = stasis_topic_create("ast_security");
+ if (!security_topic) {
+ return -1;
+ }
+
+ if (STASIS_MESSAGE_TYPE_INIT(ast_security_event_type)) {
+ return -1;
+ }
+
+ if (ast_register_atexit(ast_security_stasis_cleanup)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void ast_security_stasis_cleanup(void)
+{
+ STASIS_MESSAGE_TYPE_CLEANUP(ast_security_event_type);
+
+ ao2_cleanup(security_topic);
+ security_topic = NULL;
+}
+
static const struct {
const char *name;
uint32_t version;
@@ -464,72 +504,17 @@ const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
return sec_events[event_type].optional_ies;
}
-static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
-{
- ast_str_set(str, 0, "%u-%u",
- (unsigned int) tv->tv_sec,
- (unsigned int) tv->tv_usec);
-}
-
-static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
-{
- struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
- struct timeval tv = ast_tvnow();
- const char *severity_str;
-
- if (check_event_type(sec->event_type)) {
- return NULL;
- }
-
- encode_timestamp(&str, &tv);
-
- severity_str = S_OR(
- ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
- "Unknown"
- );
-
- return ast_event_new(AST_EVENT_SECURITY,
- AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
- AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
- AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, ast_str_buffer(str),
- AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
- AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
- AST_EVENT_IE_END);
-}
-
-static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
- const struct timeval *tv)
-{
- struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
-
- encode_timestamp(&str, tv);
-
- return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
-}
-
-static int add_ip_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
+static int add_ip_json_object(struct ast_json *json, enum ast_event_ie_type ie_type,
const struct ast_security_event_ip_addr *addr)
{
- struct ast_str *str = ast_str_alloca(64);
+ struct ast_json *json_ip;
- ast_str_set(&str, 0, (ast_sockaddr_is_ipv4(addr->addr) || ast_sockaddr_is_ipv4_mapped(addr->addr)) ? "IPV4/" : "IPV6/");
-
- switch (addr->transport) {
- case AST_SECURITY_EVENT_TRANSPORT_UDP:
- ast_str_append(&str, 0, "UDP/");
- break;
- case AST_SECURITY_EVENT_TRANSPORT_TCP:
- ast_str_append(&str, 0, "TCP/");
- break;
- case AST_SECURITY_EVENT_TRANSPORT_TLS:
- ast_str_append(&str, 0, "TLS/");
- break;
+ json_ip = ast_json_ipaddr(addr->addr, addr->transport);
+ if (!json_ip) {
+ return -1;
}
- ast_str_append(&str, 0, "%s", ast_sockaddr_stringify_addr(addr->addr));
- ast_str_append(&str, 0, "/%s", ast_sockaddr_stringify_port(addr->addr));
-
- return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
+ return ast_json_object_set(json, ast_event_get_ie_type_name(ie_type), json_ip);
}
enum ie_required {
@@ -537,7 +522,7 @@ enum ie_required {
REQUIRED
};
-static int add_ie(struct ast_event **event, const struct ast_security_event_common *sec,
+static int add_json_object(struct ast_json *json, const struct ast_security_event_common *sec,
const struct ast_security_event_ie_type *ie_type, enum ie_required req)
{
int res = 0;
@@ -559,6 +544,7 @@ static int add_ie(struct ast_event **event, const struct ast_security_event_comm
case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
{
const char *str;
+ struct ast_json *json_string;
str = *((const char **)(((const char *) sec) + ie_type->offset));
@@ -567,20 +553,36 @@ static int add_ie(struct ast_event **event, const struct ast_security_event_comm
"type '%d' not present\n", ie_type->ie_type,
sec->event_type);
res = -1;
+ break;
}
- if (str) {
- res = ast_event_append_ie_str(event, ie_type->ie_type, str);
+ if (!str) {
+ break;
}
+ json_string = ast_json_string_create(str);
+ if (!json_string) {
+ res = -1;
+ break;
+ }
+
+ res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
break;
}
case AST_EVENT_IE_EVENT_VERSION:
case AST_EVENT_IE_USING_PASSWORD:
{
+ struct ast_json *json_string;
uint32_t val;
val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
- res = ast_event_append_ie_uint(event, ie_type->ie_type, val);
+
+ json_string = ast_json_stringf("%d", val);
+ if (!json_string) {
+ res = -1;
+ break;
+ }
+
+ res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
break;
}
case AST_EVENT_IE_LOCAL_ADDR:
@@ -599,8 +601,9 @@ static int add_ie(struct ast_event **event, const struct ast_security_event_comm
}
if (addr->addr) {
- res = add_ip_ie(event, ie_type->ie_type, addr);
+ res = add_ip_json_object(json, ie_type->ie_type, addr);
}
+
break;
}
case AST_EVENT_IE_SESSION_TV:
@@ -617,7 +620,12 @@ static int add_ie(struct ast_event **event, const struct ast_security_event_comm
}
if (tval) {
- add_timeval_ie(event, ie_type->ie_type, tval);
+ struct ast_json *json_tval = ast_json_timeval(*tval, NULL);
+ if (!json_tval) {
+ res = -1;
+ break;
+ }
+ res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_tval);
}
break;
@@ -635,20 +643,78 @@ static int add_ie(struct ast_event **event, const struct ast_security_event_comm
return res;
}
+static struct ast_json *alloc_security_event_json_object(const struct ast_security_event_common *sec)
+{
+ struct timeval tv = ast_tvnow();
+ const char *severity_str;
+ struct ast_json *json_temp;
+ RAII_VAR(struct ast_json *, json_object, ast_json_object_create(), ast_json_unref);
+
+ if (!json_object) {
+ return NULL;
+ }
+
+ /* NOTE: Every time ast_json_object_set is used, json_temp becomes a stale pointer since the reference is taken.
+ * This is true even if ast_json_object_set fails.
+ */
+
+ /* AST_EVENT_IE_SECURITY_EVENT */
+ json_temp = ast_json_integer_create(sec->event_type);
+ if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SECURITY_EVENT), json_temp)) {
+ return NULL;
+ }
+
+ /* AST_EVENT_IE_EVENT_VERSION */
+ json_temp = ast_json_stringf("%d", sec->version);
+ if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_VERSION), json_temp)) {
+ return NULL;
+ }
+
+ /* AST_EVENT_IE_EVENT_TV */
+ json_temp = ast_json_timeval(tv, NULL);
+ if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_TV), json_temp)) {
+ return NULL;
+ }
+
+ /* AST_EVENT_IE_SERVICE */
+ json_temp = ast_json_string_create(sec->service);
+ if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SERVICE), json_temp)) {
+ return NULL;
+ }
+
+ /* AST_EVENT_IE_SEVERITY */
+ severity_str = S_OR(
+ ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
+ "Unknown"
+ );
+
+ json_temp = ast_json_string_create(severity_str);
+ if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SEVERITY), json_temp)) {
+ return NULL;
+ }
+
+ return ast_json_ref(json_object);
+}
+
static int handle_security_event(const struct ast_security_event_common *sec)
{
- struct ast_event *event;
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
+
const struct ast_security_event_ie_type *ies;
unsigned int i;
- if (!(event = alloc_event(sec))) {
+ json_object = alloc_security_event_json_object(sec);
+
+ if (!json_object) {
return -1;
}
for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
ies[i].ie_type != AST_EVENT_IE_END;
i++) {
- if (add_ie(&event, sec, ies + i, REQUIRED)) {
+ if (add_json_object(json_object, sec, ies + i, REQUIRED)) {
goto return_error;
}
}
@@ -656,30 +722,32 @@ static int handle_security_event(const struct ast_security_event_common *sec)
for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
ies[i].ie_type != AST_EVENT_IE_END;
i++) {
- if (add_ie(&event, sec, ies + i, NOT_REQUIRED)) {
+ if (add_json_object(json_object, sec, ies + i, NOT_REQUIRED)) {
goto return_error;
}
}
+ /* The json blob is ready. Throw it in the payload and send it out over stasis. */
+ if (!(json_payload = ast_json_payload_create(json_object))) {
+ goto return_error;
+ }
+
+ msg = stasis_message_create(ast_security_event_type(), json_payload);
- if (ast_event_queue(event)) {
+ if (!msg) {
goto return_error;
}
+ stasis_publish(ast_security_topic(), msg);
+
return 0;
return_error:
- if (event) {
- ast_event_destroy(event);
- }
-
return -1;
}
int ast_security_event_report(const struct ast_security_event_common *sec)
{
- int res;
-
if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
ast_log(LOG_ERROR, "Invalid security event type\n");
return -1;
@@ -697,9 +765,12 @@ int ast_security_event_report(const struct ast_security_event_common *sec)
return -1;
}
- res = handle_security_event(sec);
+ if (handle_security_event(sec)) {
+ ast_log(LOG_ERROR, "Failed to issue security event of type %s.\n",
+ ast_security_event_get_name(sec->event_type));
+ }
- return res;
+ return 0;
}