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"
41 static const size_t TIMESTAMP_STR_LEN = 32;
46 enum ast_security_event_severity severity;
47 #define MAX_SECURITY_IES 12
48 struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
49 struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
50 #undef MAX_SECURITY_IES
51 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
53 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
55 [AST_SECURITY_EVENT_FAILED_ACL] = {
57 .version = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
58 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
60 { AST_EVENT_IE_EVENT_TV, 0 },
61 { AST_EVENT_IE_SEVERITY, 0 },
62 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
63 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
64 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
65 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
66 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
67 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
68 { AST_EVENT_IE_END, 0 }
71 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
72 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
73 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
74 { AST_EVENT_IE_END, 0 }
78 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
79 .name = "InvalidAccountID",
80 .version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
81 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
83 { AST_EVENT_IE_EVENT_TV, 0 },
84 { AST_EVENT_IE_SEVERITY, 0 },
85 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
86 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
87 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
88 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
89 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
90 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
91 { AST_EVENT_IE_END, 0 }
94 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
95 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
96 { AST_EVENT_IE_END, 0 }
100 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
101 .name = "SessionLimit",
102 .version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
103 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
105 { AST_EVENT_IE_EVENT_TV, 0 },
106 { AST_EVENT_IE_SEVERITY, 0 },
107 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
108 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
109 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
110 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
111 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
112 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
113 { AST_EVENT_IE_END, 0 }
116 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
117 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
118 { AST_EVENT_IE_END, 0 }
122 [AST_SECURITY_EVENT_MEM_LIMIT] = {
123 .name = "MemoryLimit",
124 .version = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
125 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
127 { AST_EVENT_IE_EVENT_TV, 0 },
128 { AST_EVENT_IE_SEVERITY, 0 },
129 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
130 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
131 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
132 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
133 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
134 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
135 { AST_EVENT_IE_END, 0 }
138 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
139 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
140 { AST_EVENT_IE_END, 0 }
144 [AST_SECURITY_EVENT_LOAD_AVG] = {
145 .name = "LoadAverageLimit",
146 .version = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
147 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
149 { AST_EVENT_IE_EVENT_TV, 0 },
150 { AST_EVENT_IE_SEVERITY, 0 },
151 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
152 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
153 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
154 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
155 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
156 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
157 { AST_EVENT_IE_END, 0 }
160 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
161 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
162 { AST_EVENT_IE_END, 0 }
166 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
167 .name = "RequestNotSupported",
168 .version = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
169 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
171 { AST_EVENT_IE_EVENT_TV, 0 },
172 { AST_EVENT_IE_SEVERITY, 0 },
173 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
174 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
175 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
176 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
177 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
178 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
179 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
180 { AST_EVENT_IE_END, 0 }
183 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
184 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
185 { AST_EVENT_IE_END, 0 }
189 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
190 .name = "RequestNotAllowed",
191 .version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
192 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
194 { AST_EVENT_IE_EVENT_TV, 0 },
195 { AST_EVENT_IE_SEVERITY, 0 },
196 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
197 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
198 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
199 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
200 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
201 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
202 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
203 { AST_EVENT_IE_END, 0 }
206 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
207 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
208 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
209 { AST_EVENT_IE_END, 0 }
213 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
214 .name = "AuthMethodNotAllowed",
215 .version = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
216 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
218 { AST_EVENT_IE_EVENT_TV, 0 },
219 { AST_EVENT_IE_SEVERITY, 0 },
220 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
221 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
222 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
223 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
224 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
225 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
226 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
227 { AST_EVENT_IE_END, 0 }
230 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
231 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
232 { AST_EVENT_IE_END, 0 }
236 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
237 .name = "RequestBadFormat",
238 .version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
239 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
241 { AST_EVENT_IE_EVENT_TV, 0 },
242 { AST_EVENT_IE_SEVERITY, 0 },
243 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
244 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
245 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
246 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
247 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
248 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
249 { AST_EVENT_IE_END, 0 }
252 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
253 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
254 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
255 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
256 { AST_EVENT_IE_END, 0 }
260 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
261 .name = "SuccessfulAuth",
262 .version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
263 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
265 { AST_EVENT_IE_EVENT_TV, 0 },
266 { AST_EVENT_IE_SEVERITY, 0 },
267 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
268 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
269 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
270 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
271 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
272 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
273 { AST_EVENT_IE_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
274 { AST_EVENT_IE_END, 0 }
277 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
278 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
279 { AST_EVENT_IE_END, 0 }
283 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
284 .name = "UnexpectedAddress",
285 .version = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
286 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
288 { AST_EVENT_IE_EVENT_TV, 0 },
289 { AST_EVENT_IE_SEVERITY, 0 },
290 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
291 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
292 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
293 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
294 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
295 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
296 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
297 { AST_EVENT_IE_END, 0 }
300 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
301 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
302 { AST_EVENT_IE_END, 0 }
306 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
307 .name = "ChallengeResponseFailed",
308 .version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
309 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
311 { AST_EVENT_IE_EVENT_TV, 0 },
312 { AST_EVENT_IE_SEVERITY, 0 },
313 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
314 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
315 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
316 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
317 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
318 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
319 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
320 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
321 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
322 { AST_EVENT_IE_END, 0 }
325 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
326 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
327 { AST_EVENT_IE_END, 0 }
331 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
332 .name = "InvalidPassword",
333 .version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
334 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
336 { AST_EVENT_IE_EVENT_TV, 0 },
337 { AST_EVENT_IE_SEVERITY, 0 },
338 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
339 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
340 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
341 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
342 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
343 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
344 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
345 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
346 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
347 { AST_EVENT_IE_END, 0 }
350 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
351 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
352 { AST_EVENT_IE_END, 0 }
356 [AST_SECURITY_EVENT_CHAL_SENT] = {
357 .name = "ChallengeSent",
358 .version = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
359 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
361 { AST_EVENT_IE_EVENT_TV, 0 },
362 { AST_EVENT_IE_SEVERITY, 0 },
363 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
364 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
365 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
366 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
367 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
368 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
369 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
370 { AST_EVENT_IE_END, 0 }
373 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
374 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
375 { AST_EVENT_IE_END, 0 }
379 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
380 .name = "InvalidTransport",
381 .version = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
382 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
384 { AST_EVENT_IE_EVENT_TV, 0 },
385 { AST_EVENT_IE_SEVERITY, 0 },
386 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
387 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
388 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
389 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
390 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
391 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
392 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
393 { AST_EVENT_IE_END, 0 }
396 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
397 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
398 { AST_EVENT_IE_END, 0 }
406 static const struct {
407 enum ast_security_event_severity severity;
410 { AST_SECURITY_EVENT_SEVERITY_INFO, "Informational" },
411 { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
414 const char *ast_security_event_severity_get_name(
415 const enum ast_security_event_severity severity)
419 for (i = 0; i < ARRAY_LEN(severities); i++) {
420 if (severities[i].severity == severity) {
421 return severities[i].str;
428 static int check_event_type(const enum ast_security_event_type event_type)
430 if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
431 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
438 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
440 if (check_event_type(event_type)) {
444 return sec_events[event_type].name;
447 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
448 const enum ast_security_event_type event_type)
450 if (check_event_type(event_type)) {
454 return sec_events[event_type].required_ies;
457 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
458 const enum ast_security_event_type event_type)
460 if (check_event_type(event_type)) {
464 return sec_events[event_type].optional_ies;
467 static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
469 ast_str_set(str, 0, "%u-%u",
470 (unsigned int) tv->tv_sec,
471 (unsigned int) tv->tv_usec);
474 static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
476 struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
477 struct timeval tv = ast_tvnow();
478 const char *severity_str;
480 if (check_event_type(sec->event_type)) {
484 encode_timestamp(&str, &tv);
487 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
491 return ast_event_new(AST_EVENT_SECURITY,
492 AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
493 AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
494 AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, str->str,
495 AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
496 AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
500 static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
501 const struct timeval *tv)
503 struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
505 encode_timestamp(&str, tv);
507 return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
510 static int add_ip_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
511 const struct ast_security_event_ip_addr *addr)
513 struct ast_str *str = ast_str_alloca(64);
515 ast_str_set(&str, 0, (ast_sockaddr_is_ipv4(addr->addr) || ast_sockaddr_is_ipv4_mapped(addr->addr)) ? "IPV4/" : "IPV6/");
517 switch (addr->transport) {
518 case AST_SECURITY_EVENT_TRANSPORT_UDP:
519 ast_str_append(&str, 0, "UDP/");
521 case AST_SECURITY_EVENT_TRANSPORT_TCP:
522 ast_str_append(&str, 0, "TCP/");
524 case AST_SECURITY_EVENT_TRANSPORT_TLS:
525 ast_str_append(&str, 0, "TLS/");
529 ast_str_append(&str, 0, "%s", ast_sockaddr_stringify_addr(addr->addr));
530 ast_str_append(&str, 0, "/%s", ast_sockaddr_stringify_port(addr->addr));
532 return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
540 static int add_ie(struct ast_event **event, const struct ast_security_event_common *sec,
541 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
545 switch (ie_type->ie_type) {
546 case AST_EVENT_IE_SERVICE:
547 case AST_EVENT_IE_ACCOUNT_ID:
548 case AST_EVENT_IE_SESSION_ID:
549 case AST_EVENT_IE_MODULE:
550 case AST_EVENT_IE_ACL_NAME:
551 case AST_EVENT_IE_REQUEST_TYPE:
552 case AST_EVENT_IE_REQUEST_PARAMS:
553 case AST_EVENT_IE_AUTH_METHOD:
554 case AST_EVENT_IE_CHALLENGE:
555 case AST_EVENT_IE_RESPONSE:
556 case AST_EVENT_IE_EXPECTED_RESPONSE:
557 case AST_EVENT_IE_RECEIVED_CHALLENGE:
558 case AST_EVENT_IE_RECEIVED_HASH:
559 case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
563 str = *((const char **)(((const char *) sec) + ie_type->offset));
566 ast_log(LOG_WARNING, "Required IE '%d' for security event "
567 "type '%d' not present\n", ie_type->ie_type,
573 res = ast_event_append_ie_str(event, ie_type->ie_type, str);
578 case AST_EVENT_IE_EVENT_VERSION:
579 case AST_EVENT_IE_USING_PASSWORD:
582 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
583 res = ast_event_append_ie_uint(event, ie_type->ie_type, val);
586 case AST_EVENT_IE_LOCAL_ADDR:
587 case AST_EVENT_IE_REMOTE_ADDR:
588 case AST_EVENT_IE_EXPECTED_ADDR:
590 const struct ast_security_event_ip_addr *addr;
592 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
594 if (req && !addr->addr) {
595 ast_log(LOG_WARNING, "Required IE '%d' for security event "
596 "type '%d' not present\n", ie_type->ie_type,
602 res = add_ip_ie(event, ie_type->ie_type, addr);
606 case AST_EVENT_IE_SESSION_TV:
608 const struct timeval *tval;
610 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
613 ast_log(LOG_WARNING, "Required IE '%d' for security event "
614 "type '%d' not present\n", ie_type->ie_type,
620 add_timeval_ie(event, ie_type->ie_type, tval);
625 case AST_EVENT_IE_EVENT_TV:
626 case AST_EVENT_IE_SEVERITY:
627 /* Added automatically, nothing to do here. */
630 ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event "
631 "will be missing data.\n", ie_type->ie_type);
638 static int handle_security_event(const struct ast_security_event_common *sec)
640 struct ast_event *event;
641 const struct ast_security_event_ie_type *ies;
644 if (!(event = alloc_event(sec))) {
648 for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
649 ies[i].ie_type != AST_EVENT_IE_END;
651 if (add_ie(&event, sec, ies + i, REQUIRED)) {
656 for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
657 ies[i].ie_type != AST_EVENT_IE_END;
659 if (add_ie(&event, sec, ies + i, NOT_REQUIRED)) {
665 if (ast_event_queue(event)) {
673 ast_event_destroy(event);
679 int ast_security_event_report(const struct ast_security_event_common *sec)
683 if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
684 ast_log(LOG_ERROR, "Invalid security event type\n");
688 if (!sec_events[sec->event_type].name) {
689 ast_log(LOG_WARNING, "Security event type %u not handled\n",
694 if (sec->version != sec_events[sec->event_type].version) {
695 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
700 res = handle_security_event(sec);