2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2012, Digium, Inc.
6 * Russell Bryant <russell@digium.com>
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.
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.
22 * \brief Security Event Reporting Helpers
24 * \author Russell Bryant <russell@digium.com>
28 <support_level>core</support_level>
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
35 #include "asterisk/utils.h"
36 #include "asterisk/strings.h"
37 #include "asterisk/network.h"
38 #include "asterisk/security_events.h"
39 #include "asterisk/netsock2.h"
40 #include "asterisk/stasis.h"
41 #include "asterisk/json.h"
42 #include "asterisk/astobj2.h"
44 static const size_t TIMESTAMP_STR_LEN = 32;
46 /*! \brief Security Topic */
47 static struct stasis_topic *security_topic;
49 struct stasis_topic *ast_security_topic(void)
51 return security_topic;
54 /*! \brief Message type for security events */
55 STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type);
57 static void security_stasis_cleanup(void)
59 ao2_cleanup(security_topic);
60 security_topic = NULL;
62 STASIS_MESSAGE_TYPE_CLEANUP(ast_security_event_type);
65 int ast_security_stasis_init(void)
67 ast_register_cleanup(security_stasis_cleanup);
69 security_topic = stasis_topic_create("ast_security");
70 if (!security_topic) {
74 if (STASIS_MESSAGE_TYPE_INIT(ast_security_event_type)) {
85 enum ast_security_event_severity severity;
86 #define MAX_SECURITY_IES 12
87 struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
88 struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
89 #undef MAX_SECURITY_IES
90 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
92 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
94 [AST_SECURITY_EVENT_FAILED_ACL] = {
96 .version = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
97 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
99 { AST_EVENT_IE_EVENT_TV, 0 },
100 { AST_EVENT_IE_SEVERITY, 0 },
101 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
102 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
103 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
104 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
105 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
106 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
107 { AST_EVENT_IE_END, 0 }
110 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
111 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
112 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
113 { AST_EVENT_IE_END, 0 }
117 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
118 .name = "InvalidAccountID",
119 .version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
120 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
122 { AST_EVENT_IE_EVENT_TV, 0 },
123 { AST_EVENT_IE_SEVERITY, 0 },
124 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
125 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
126 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
127 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
128 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
129 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
130 { AST_EVENT_IE_END, 0 }
133 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
134 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
135 { AST_EVENT_IE_END, 0 }
139 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
140 .name = "SessionLimit",
141 .version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
142 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
144 { AST_EVENT_IE_EVENT_TV, 0 },
145 { AST_EVENT_IE_SEVERITY, 0 },
146 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
147 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
148 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
149 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
150 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
151 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
152 { AST_EVENT_IE_END, 0 }
155 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
156 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
157 { AST_EVENT_IE_END, 0 }
161 [AST_SECURITY_EVENT_MEM_LIMIT] = {
162 .name = "MemoryLimit",
163 .version = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
164 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
166 { AST_EVENT_IE_EVENT_TV, 0 },
167 { AST_EVENT_IE_SEVERITY, 0 },
168 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
169 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
170 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
171 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
172 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
173 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
174 { AST_EVENT_IE_END, 0 }
177 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
178 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
179 { AST_EVENT_IE_END, 0 }
183 [AST_SECURITY_EVENT_LOAD_AVG] = {
184 .name = "LoadAverageLimit",
185 .version = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
186 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
188 { AST_EVENT_IE_EVENT_TV, 0 },
189 { AST_EVENT_IE_SEVERITY, 0 },
190 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
191 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
192 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
193 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
194 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
195 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
196 { AST_EVENT_IE_END, 0 }
199 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
200 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
201 { AST_EVENT_IE_END, 0 }
205 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
206 .name = "RequestNotSupported",
207 .version = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
208 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
210 { AST_EVENT_IE_EVENT_TV, 0 },
211 { AST_EVENT_IE_SEVERITY, 0 },
212 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
213 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
214 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
215 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
216 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
217 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
218 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
219 { AST_EVENT_IE_END, 0 }
222 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
223 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
224 { AST_EVENT_IE_END, 0 }
228 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
229 .name = "RequestNotAllowed",
230 .version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
231 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
233 { AST_EVENT_IE_EVENT_TV, 0 },
234 { AST_EVENT_IE_SEVERITY, 0 },
235 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
236 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
237 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
238 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
239 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
240 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
241 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
242 { AST_EVENT_IE_END, 0 }
245 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
246 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
247 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
248 { AST_EVENT_IE_END, 0 }
252 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
253 .name = "AuthMethodNotAllowed",
254 .version = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
255 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
257 { AST_EVENT_IE_EVENT_TV, 0 },
258 { AST_EVENT_IE_SEVERITY, 0 },
259 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
260 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
261 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
262 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
263 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
264 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
265 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
266 { AST_EVENT_IE_END, 0 }
269 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
270 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
271 { AST_EVENT_IE_END, 0 }
275 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
276 .name = "RequestBadFormat",
277 .version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
278 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
280 { AST_EVENT_IE_EVENT_TV, 0 },
281 { AST_EVENT_IE_SEVERITY, 0 },
282 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
283 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
284 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
285 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
286 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
287 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
288 { AST_EVENT_IE_END, 0 }
291 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
292 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
293 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
294 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
295 { AST_EVENT_IE_END, 0 }
299 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
300 .name = "SuccessfulAuth",
301 .version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
302 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
304 { AST_EVENT_IE_EVENT_TV, 0 },
305 { AST_EVENT_IE_SEVERITY, 0 },
306 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
307 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
308 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
309 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
310 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
311 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
312 { AST_EVENT_IE_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
313 { AST_EVENT_IE_END, 0 }
316 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
317 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
318 { AST_EVENT_IE_END, 0 }
322 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
323 .name = "UnexpectedAddress",
324 .version = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
325 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
327 { AST_EVENT_IE_EVENT_TV, 0 },
328 { AST_EVENT_IE_SEVERITY, 0 },
329 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
330 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
331 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
332 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
333 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
334 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
335 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
336 { AST_EVENT_IE_END, 0 }
339 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
340 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
341 { AST_EVENT_IE_END, 0 }
345 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
346 .name = "ChallengeResponseFailed",
347 .version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
348 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
350 { AST_EVENT_IE_EVENT_TV, 0 },
351 { AST_EVENT_IE_SEVERITY, 0 },
352 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
353 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
354 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
355 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
356 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
357 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
358 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
359 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
360 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
361 { AST_EVENT_IE_END, 0 }
364 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
365 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
366 { AST_EVENT_IE_END, 0 }
370 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
371 .name = "InvalidPassword",
372 .version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
373 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
375 { AST_EVENT_IE_EVENT_TV, 0 },
376 { AST_EVENT_IE_SEVERITY, 0 },
377 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
378 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
379 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
380 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
381 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
382 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
383 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
384 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
385 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
386 { AST_EVENT_IE_END, 0 }
389 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
390 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
391 { AST_EVENT_IE_END, 0 }
395 [AST_SECURITY_EVENT_CHAL_SENT] = {
396 .name = "ChallengeSent",
397 .version = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
398 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
400 { AST_EVENT_IE_EVENT_TV, 0 },
401 { AST_EVENT_IE_SEVERITY, 0 },
402 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
403 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
404 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
405 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
406 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
407 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
408 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
409 { AST_EVENT_IE_END, 0 }
412 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
413 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
414 { AST_EVENT_IE_END, 0 }
418 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
419 .name = "InvalidTransport",
420 .version = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
421 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
423 { AST_EVENT_IE_EVENT_TV, 0 },
424 { AST_EVENT_IE_SEVERITY, 0 },
425 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
426 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
427 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
428 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
429 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
430 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
431 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
432 { AST_EVENT_IE_END, 0 }
435 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
436 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
437 { AST_EVENT_IE_END, 0 }
445 static const struct {
446 enum ast_security_event_severity severity;
449 { AST_SECURITY_EVENT_SEVERITY_INFO, "Informational" },
450 { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
453 const char *ast_security_event_severity_get_name(
454 const enum ast_security_event_severity severity)
458 for (i = 0; i < ARRAY_LEN(severities); i++) {
459 if (severities[i].severity == severity) {
460 return severities[i].str;
467 static int check_event_type(const enum ast_security_event_type event_type)
469 if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
470 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
477 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
479 if (check_event_type(event_type)) {
483 return sec_events[event_type].name;
486 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
487 const enum ast_security_event_type event_type)
489 if (check_event_type(event_type)) {
493 return sec_events[event_type].required_ies;
496 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
497 const enum ast_security_event_type event_type)
499 if (check_event_type(event_type)) {
503 return sec_events[event_type].optional_ies;
506 static int add_ip_json_object(struct ast_json *json, enum ast_event_ie_type ie_type,
507 const struct ast_security_event_ip_addr *addr)
509 struct ast_json *json_ip;
511 json_ip = ast_json_ipaddr(addr->addr, addr->transport);
516 return ast_json_object_set(json, ast_event_get_ie_type_name(ie_type), json_ip);
524 static int add_json_object(struct ast_json *json, const struct ast_security_event_common *sec,
525 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
529 switch (ie_type->ie_type) {
530 case AST_EVENT_IE_SERVICE:
531 case AST_EVENT_IE_ACCOUNT_ID:
532 case AST_EVENT_IE_SESSION_ID:
533 case AST_EVENT_IE_MODULE:
534 case AST_EVENT_IE_ACL_NAME:
535 case AST_EVENT_IE_REQUEST_TYPE:
536 case AST_EVENT_IE_REQUEST_PARAMS:
537 case AST_EVENT_IE_AUTH_METHOD:
538 case AST_EVENT_IE_CHALLENGE:
539 case AST_EVENT_IE_RESPONSE:
540 case AST_EVENT_IE_EXPECTED_RESPONSE:
541 case AST_EVENT_IE_RECEIVED_CHALLENGE:
542 case AST_EVENT_IE_RECEIVED_HASH:
543 case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
546 struct ast_json *json_string;
548 str = *((const char **)(((const char *) sec) + ie_type->offset));
551 ast_log(LOG_WARNING, "Required IE '%d' for security event "
552 "type '%d' not present\n", ie_type->ie_type,
562 json_string = ast_json_string_create(str);
568 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
571 case AST_EVENT_IE_EVENT_VERSION:
572 case AST_EVENT_IE_USING_PASSWORD:
574 struct ast_json *json_string;
576 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
578 json_string = ast_json_stringf("%d", val);
584 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
587 case AST_EVENT_IE_LOCAL_ADDR:
588 case AST_EVENT_IE_REMOTE_ADDR:
589 case AST_EVENT_IE_EXPECTED_ADDR:
591 const struct ast_security_event_ip_addr *addr;
593 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
595 if (req && !addr->addr) {
596 ast_log(LOG_WARNING, "Required IE '%d' for security event "
597 "type '%d' not present\n", ie_type->ie_type,
603 res = add_ip_json_object(json, ie_type->ie_type, addr);
608 case AST_EVENT_IE_SESSION_TV:
610 const struct timeval *tval;
612 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
615 ast_log(LOG_WARNING, "Required IE '%d' for security event "
616 "type '%d' not present\n", ie_type->ie_type,
622 struct ast_json *json_tval = ast_json_timeval(*tval, NULL);
627 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_tval);
632 case AST_EVENT_IE_EVENT_TV:
633 case AST_EVENT_IE_SEVERITY:
634 /* Added automatically, nothing to do here. */
637 ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event "
638 "will be missing data.\n", ie_type->ie_type);
645 static struct ast_json *alloc_security_event_json_object(const struct ast_security_event_common *sec)
647 struct timeval tv = ast_tvnow();
648 const char *severity_str;
649 struct ast_json *json_temp;
650 RAII_VAR(struct ast_json *, json_object, ast_json_object_create(), ast_json_unref);
656 /* NOTE: Every time ast_json_object_set is used, json_temp becomes a stale pointer since the reference is taken.
657 * This is true even if ast_json_object_set fails.
660 /* AST_EVENT_IE_SECURITY_EVENT */
661 json_temp = ast_json_integer_create(sec->event_type);
662 if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SECURITY_EVENT), json_temp)) {
666 /* AST_EVENT_IE_EVENT_VERSION */
667 json_temp = ast_json_stringf("%d", sec->version);
668 if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_VERSION), json_temp)) {
672 /* AST_EVENT_IE_EVENT_TV */
673 json_temp = ast_json_timeval(tv, NULL);
674 if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_TV), json_temp)) {
678 /* AST_EVENT_IE_SERVICE */
679 json_temp = ast_json_string_create(sec->service);
680 if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SERVICE), json_temp)) {
684 /* AST_EVENT_IE_SEVERITY */
686 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
690 json_temp = ast_json_string_create(severity_str);
691 if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SEVERITY), json_temp)) {
695 return ast_json_ref(json_object);
698 static int handle_security_event(const struct ast_security_event_common *sec)
700 RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
701 RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
702 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
704 const struct ast_security_event_ie_type *ies;
707 json_object = alloc_security_event_json_object(sec);
713 for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
714 ies[i].ie_type != AST_EVENT_IE_END;
716 if (add_json_object(json_object, sec, ies + i, REQUIRED)) {
721 for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
722 ies[i].ie_type != AST_EVENT_IE_END;
724 if (add_json_object(json_object, sec, ies + i, NOT_REQUIRED)) {
729 /* The json blob is ready. Throw it in the payload and send it out over stasis. */
730 if (!(json_payload = ast_json_payload_create(json_object))) {
734 msg = stasis_message_create(ast_security_event_type(), json_payload);
740 stasis_publish(ast_security_topic(), msg);
748 int ast_security_event_report(const struct ast_security_event_common *sec)
750 if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
751 ast_log(LOG_ERROR, "Invalid security event type\n");
755 if (!sec_events[sec->event_type].name) {
756 ast_log(LOG_WARNING, "Security event type %u not handled\n",
761 if (sec->version != sec_events[sec->event_type].version) {
762 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
767 if (handle_security_event(sec)) {
768 ast_log(LOG_ERROR, "Failed to issue security event of type %s.\n",
769 ast_security_event_get_name(sec->event_type));