/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 2009, Digium, Inc. * * Russell Bryant * * 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 * * \brief Security Event Reporting Helpers * * \author Russell Bryant */ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/utils.h" #include "asterisk/strings.h" #include "asterisk/network.h" #include "asterisk/security_events.h" static const size_t TIMESTAMP_STR_LEN = 32; static const struct { const char *name; uint32_t version; enum ast_security_event_severity severity; #define MAX_SECURITY_IES 12 struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES]; struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES]; #undef MAX_SECURITY_IES } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = { #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field)) [AST_SECURITY_EVENT_FAILED_ACL] = { .name = "FailedACL", .version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_INVAL_ACCT_ID] = { .name = "InvalidAccountID", .version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_SESSION_LIMIT] = { .name = "SessionLimit", .version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_MEM_LIMIT] = { .name = "MemoryLimit", .version = AST_SECURITY_EVENT_MEM_LIMIT_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_LOAD_AVG] = { .name = "LoadAverageLimit", .version = AST_SECURITY_EVENT_LOAD_AVG_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = { .name = "RequestNotSupported", .version = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = { .name = "RequestNotAllowed", .version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = { .name = "AuthMethodNotAllowed", .version = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = { .name = "RequestBadFormat", .version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = { .name = "SuccessfulAuth", .version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_INFO, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = { .name = "UnexpectedAddress", .version = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = { .name = "ChallengeResponseFailed", .version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) }, { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) }, { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, [AST_SECURITY_EVENT_INVAL_PASSWORD] = { .name = "InvalidPassword", .version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, .severity = AST_SECURITY_EVENT_SEVERITY_ERROR, .required_ies = { { AST_EVENT_IE_EVENT_TV, 0 }, { AST_EVENT_IE_SEVERITY, 0 }, { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) }, { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) }, { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) }, { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) }, { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) }, { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) }, { AST_EVENT_IE_END, 0 } }, .optional_ies = { { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) }, { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) }, { AST_EVENT_IE_END, 0 } }, }, #undef SEC_EVT_FIELD }; static const struct { enum ast_security_event_severity severity; const char *str; } severities[] = { { AST_SECURITY_EVENT_SEVERITY_INFO, "Informational" }, { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" }, }; const char *ast_security_event_severity_get_name( const enum ast_security_event_severity severity) { unsigned int i; for (i = 0; i < ARRAY_LEN(severities); i++) { if (severities[i].severity == severity) { return severities[i].str; } } return NULL; } static int check_event_type(const enum ast_security_event_type event_type) { if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) { ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type); return -1; } return 0; } const char *ast_security_event_get_name(const enum ast_security_event_type event_type) { if (check_event_type(event_type)) { return NULL; } return sec_events[event_type].name; } const struct ast_security_event_ie_type *ast_security_event_get_required_ies( const enum ast_security_event_type event_type) { if (check_event_type(event_type)) { return NULL; } return sec_events[event_type].required_ies; } const struct ast_security_event_ie_type *ast_security_event_get_optional_ies( const enum ast_security_event_type event_type) { if (check_event_type(event_type)) { return NULL; } 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, str->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_ipv4_ie(struct ast_event **event, enum ast_event_ie_type ie_type, const struct ast_security_event_ipv4_addr *addr) { struct ast_str *str = ast_str_alloca(64); ast_str_set(&str, 0, "IPV4/"); 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; } ast_str_append(&str, 0, "%s/%hu", ast_inet_ntoa(addr->sin->sin_addr), ntohs(addr->sin->sin_port)); return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str)); } enum ie_required { NOT_REQUIRED, REQUIRED }; static int add_ie(struct ast_event **event, const struct ast_security_event_common *sec, const struct ast_security_event_ie_type *ie_type, enum ie_required req) { int res = 0; switch (ie_type->ie_type) { case AST_EVENT_IE_SERVICE: case AST_EVENT_IE_ACCOUNT_ID: case AST_EVENT_IE_SESSION_ID: case AST_EVENT_IE_MODULE: case AST_EVENT_IE_ACL_NAME: case AST_EVENT_IE_REQUEST_TYPE: case AST_EVENT_IE_REQUEST_PARAMS: case AST_EVENT_IE_AUTH_METHOD: case AST_EVENT_IE_CHALLENGE: case AST_EVENT_IE_RESPONSE: case AST_EVENT_IE_EXPECTED_RESPONSE: { const char *str; str = *((const char **)(((const char *) sec) + ie_type->offset)); if (req && !str) { ast_log(LOG_WARNING, "Required IE '%d' for security event " "type '%d' not present\n", ie_type->ie_type, sec->event_type); res = -1; } if (str) { res = ast_event_append_ie_str(event, ie_type->ie_type, str); } break; } case AST_EVENT_IE_EVENT_VERSION: { 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); break; } case AST_EVENT_IE_LOCAL_ADDR: case AST_EVENT_IE_REMOTE_ADDR: case AST_EVENT_IE_EXPECTED_ADDR: { const struct ast_security_event_ipv4_addr *addr; addr = (const struct ast_security_event_ipv4_addr *)(((const char *) sec) + ie_type->offset); if (req && !addr->sin) { ast_log(LOG_WARNING, "Required IE '%d' for security event " "type '%d' not present\n", ie_type->ie_type, sec->event_type); res = -1; } if (addr->sin) { res = add_ipv4_ie(event, ie_type->ie_type, addr); } break; } case AST_EVENT_IE_SESSION_TV: { const struct timeval *tval; tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset)); if (req && !tval) { ast_log(LOG_WARNING, "Required IE '%d' for security event " "type '%d' not present\n", ie_type->ie_type, sec->event_type); res = -1; } if (tval) { add_timeval_ie(event, ie_type->ie_type, tval); } break; } case AST_EVENT_IE_EVENT_TV: case AST_EVENT_IE_SEVERITY: /* Added automatically, nothing to do here. */ break; default: ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event " "will be missing data.\n", ie_type->ie_type); break; } return res; } static int handle_security_event(const struct ast_security_event_common *sec) { struct ast_event *event; const struct ast_security_event_ie_type *ies; unsigned int i; if (!(event = alloc_event(sec))) { 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)) { goto return_error; } } 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)) { goto return_error; } } if (ast_event_queue(event)) { goto return_error; } 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; } if (!sec_events[sec->event_type].name) { ast_log(LOG_WARNING, "Security event type %u not handled\n", sec->event_type); return -1; } if (sec->version != sec_events[sec->event_type].version) { ast_log(LOG_WARNING, "Security event %u version mismatch\n", sec->event_type); return -1; } res = handle_security_event(sec); return res; }