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>
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31 #include "asterisk/utils.h"
32 #include "asterisk/strings.h"
33 #include "asterisk/network.h"
34 #include "asterisk/security_events.h"
35 #include "asterisk/netsock2.h"
37 static const size_t TIMESTAMP_STR_LEN = 32;
42 enum ast_security_event_severity severity;
43 #define MAX_SECURITY_IES 12
44 struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
45 struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
46 #undef MAX_SECURITY_IES
47 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
49 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
51 [AST_SECURITY_EVENT_FAILED_ACL] = {
53 .version = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
54 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
56 { AST_EVENT_IE_EVENT_TV, 0 },
57 { AST_EVENT_IE_SEVERITY, 0 },
58 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
59 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
60 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
61 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
62 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
63 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
64 { AST_EVENT_IE_END, 0 }
67 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
68 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
69 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
70 { AST_EVENT_IE_END, 0 }
74 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
75 .name = "InvalidAccountID",
76 .version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
77 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
79 { AST_EVENT_IE_EVENT_TV, 0 },
80 { AST_EVENT_IE_SEVERITY, 0 },
81 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
82 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
83 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
84 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
85 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
86 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
87 { AST_EVENT_IE_END, 0 }
90 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
91 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
92 { AST_EVENT_IE_END, 0 }
96 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
97 .name = "SessionLimit",
98 .version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
99 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
101 { AST_EVENT_IE_EVENT_TV, 0 },
102 { AST_EVENT_IE_SEVERITY, 0 },
103 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
104 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
105 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
106 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
107 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
108 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
109 { AST_EVENT_IE_END, 0 }
112 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
113 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
114 { AST_EVENT_IE_END, 0 }
118 [AST_SECURITY_EVENT_MEM_LIMIT] = {
119 .name = "MemoryLimit",
120 .version = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
121 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
123 { AST_EVENT_IE_EVENT_TV, 0 },
124 { AST_EVENT_IE_SEVERITY, 0 },
125 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
126 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
127 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
128 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
129 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
130 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
131 { AST_EVENT_IE_END, 0 }
134 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
135 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
136 { AST_EVENT_IE_END, 0 }
140 [AST_SECURITY_EVENT_LOAD_AVG] = {
141 .name = "LoadAverageLimit",
142 .version = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
143 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
145 { AST_EVENT_IE_EVENT_TV, 0 },
146 { AST_EVENT_IE_SEVERITY, 0 },
147 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
148 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
149 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
150 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
151 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
152 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
153 { AST_EVENT_IE_END, 0 }
156 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
157 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
158 { AST_EVENT_IE_END, 0 }
162 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
163 .name = "RequestNotSupported",
164 .version = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
165 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
167 { AST_EVENT_IE_EVENT_TV, 0 },
168 { AST_EVENT_IE_SEVERITY, 0 },
169 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
170 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
171 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
172 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
173 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
174 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
175 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
176 { AST_EVENT_IE_END, 0 }
179 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
180 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
181 { AST_EVENT_IE_END, 0 }
185 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
186 .name = "RequestNotAllowed",
187 .version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
188 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
190 { AST_EVENT_IE_EVENT_TV, 0 },
191 { AST_EVENT_IE_SEVERITY, 0 },
192 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
193 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
194 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
195 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
196 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
197 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
198 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
199 { AST_EVENT_IE_END, 0 }
202 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
203 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
204 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
205 { AST_EVENT_IE_END, 0 }
209 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
210 .name = "AuthMethodNotAllowed",
211 .version = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
212 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
214 { AST_EVENT_IE_EVENT_TV, 0 },
215 { AST_EVENT_IE_SEVERITY, 0 },
216 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
217 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
218 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
219 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
220 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
221 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
222 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
223 { AST_EVENT_IE_END, 0 }
226 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
227 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
228 { AST_EVENT_IE_END, 0 }
232 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
233 .name = "RequestBadFormat",
234 .version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
235 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
237 { AST_EVENT_IE_EVENT_TV, 0 },
238 { AST_EVENT_IE_SEVERITY, 0 },
239 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
240 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
241 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
242 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
243 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
244 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
245 { AST_EVENT_IE_END, 0 }
248 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
249 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
250 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
251 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
252 { AST_EVENT_IE_END, 0 }
256 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
257 .name = "SuccessfulAuth",
258 .version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
259 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
261 { AST_EVENT_IE_EVENT_TV, 0 },
262 { AST_EVENT_IE_SEVERITY, 0 },
263 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
264 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
265 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
266 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
267 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
268 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
269 { AST_EVENT_IE_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
270 { AST_EVENT_IE_END, 0 }
273 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
274 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
275 { AST_EVENT_IE_END, 0 }
279 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
280 .name = "UnexpectedAddress",
281 .version = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
282 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
284 { AST_EVENT_IE_EVENT_TV, 0 },
285 { AST_EVENT_IE_SEVERITY, 0 },
286 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
287 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
288 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
289 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
290 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
291 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
292 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
293 { AST_EVENT_IE_END, 0 }
296 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
297 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
298 { AST_EVENT_IE_END, 0 }
302 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
303 .name = "ChallengeResponseFailed",
304 .version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
305 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
307 { AST_EVENT_IE_EVENT_TV, 0 },
308 { AST_EVENT_IE_SEVERITY, 0 },
309 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
310 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
311 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
312 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
313 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
314 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
315 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
316 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
317 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
318 { AST_EVENT_IE_END, 0 }
321 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
322 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
323 { AST_EVENT_IE_END, 0 }
327 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
328 .name = "InvalidPassword",
329 .version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
330 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
332 { AST_EVENT_IE_EVENT_TV, 0 },
333 { AST_EVENT_IE_SEVERITY, 0 },
334 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
335 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
336 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
337 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
338 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
339 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
340 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
341 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
342 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
343 { AST_EVENT_IE_END, 0 }
346 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
347 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
348 { AST_EVENT_IE_END, 0 }
352 [AST_SECURITY_EVENT_CHAL_SENT] = {
353 .name = "ChallengeSent",
354 .version = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
355 .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
357 { AST_EVENT_IE_EVENT_TV, 0 },
358 { AST_EVENT_IE_SEVERITY, 0 },
359 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
360 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
361 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
362 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
363 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
364 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
365 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
366 { AST_EVENT_IE_END, 0 }
369 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
370 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
371 { AST_EVENT_IE_END, 0 }
375 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
376 .name = "InvalidTransport",
377 .version = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
378 .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
380 { AST_EVENT_IE_EVENT_TV, 0 },
381 { AST_EVENT_IE_SEVERITY, 0 },
382 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
383 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
384 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
385 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
386 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
387 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
388 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
389 { AST_EVENT_IE_END, 0 }
392 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
393 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
394 { AST_EVENT_IE_END, 0 }
402 static const struct {
403 enum ast_security_event_severity severity;
406 { AST_SECURITY_EVENT_SEVERITY_INFO, "Informational" },
407 { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
410 const char *ast_security_event_severity_get_name(
411 const enum ast_security_event_severity severity)
415 for (i = 0; i < ARRAY_LEN(severities); i++) {
416 if (severities[i].severity == severity) {
417 return severities[i].str;
424 static int check_event_type(const enum ast_security_event_type event_type)
426 if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
427 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
434 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
436 if (check_event_type(event_type)) {
440 return sec_events[event_type].name;
443 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
444 const enum ast_security_event_type event_type)
446 if (check_event_type(event_type)) {
450 return sec_events[event_type].required_ies;
453 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
454 const enum ast_security_event_type event_type)
456 if (check_event_type(event_type)) {
460 return sec_events[event_type].optional_ies;
463 static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
465 ast_str_set(str, 0, "%u-%u",
466 (unsigned int) tv->tv_sec,
467 (unsigned int) tv->tv_usec);
470 static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
472 struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
473 struct timeval tv = ast_tvnow();
474 const char *severity_str;
476 if (check_event_type(sec->event_type)) {
480 encode_timestamp(&str, &tv);
483 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
487 return ast_event_new(AST_EVENT_SECURITY,
488 AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
489 AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
490 AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, str->str,
491 AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
492 AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
496 static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
497 const struct timeval *tv)
499 struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
501 encode_timestamp(&str, tv);
503 return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
506 static int add_ip_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
507 const struct ast_security_event_ip_addr *addr)
509 struct ast_str *str = ast_str_alloca(64);
511 ast_str_set(&str, 0, (ast_sockaddr_is_ipv4(addr->addr) || ast_sockaddr_is_ipv4_mapped(addr->addr)) ? "IPV4/" : "IPV6/");
513 switch (addr->transport) {
514 case AST_SECURITY_EVENT_TRANSPORT_UDP:
515 ast_str_append(&str, 0, "UDP/");
517 case AST_SECURITY_EVENT_TRANSPORT_TCP:
518 ast_str_append(&str, 0, "TCP/");
520 case AST_SECURITY_EVENT_TRANSPORT_TLS:
521 ast_str_append(&str, 0, "TLS/");
525 ast_str_append(&str, 0, "%s", ast_sockaddr_stringify_addr(addr->addr));
526 ast_str_append(&str, 0, "/%s", ast_sockaddr_stringify_port(addr->addr));
528 return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
536 static int add_ie(struct ast_event **event, const struct ast_security_event_common *sec,
537 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
541 switch (ie_type->ie_type) {
542 case AST_EVENT_IE_SERVICE:
543 case AST_EVENT_IE_ACCOUNT_ID:
544 case AST_EVENT_IE_SESSION_ID:
545 case AST_EVENT_IE_MODULE:
546 case AST_EVENT_IE_ACL_NAME:
547 case AST_EVENT_IE_REQUEST_TYPE:
548 case AST_EVENT_IE_REQUEST_PARAMS:
549 case AST_EVENT_IE_AUTH_METHOD:
550 case AST_EVENT_IE_CHALLENGE:
551 case AST_EVENT_IE_RESPONSE:
552 case AST_EVENT_IE_EXPECTED_RESPONSE:
553 case AST_EVENT_IE_RECEIVED_CHALLENGE:
554 case AST_EVENT_IE_RECEIVED_HASH:
555 case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
559 str = *((const char **)(((const char *) sec) + ie_type->offset));
562 ast_log(LOG_WARNING, "Required IE '%d' for security event "
563 "type '%d' not present\n", ie_type->ie_type,
569 res = ast_event_append_ie_str(event, ie_type->ie_type, str);
574 case AST_EVENT_IE_EVENT_VERSION:
575 case AST_EVENT_IE_USING_PASSWORD:
578 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
579 res = ast_event_append_ie_uint(event, ie_type->ie_type, val);
582 case AST_EVENT_IE_LOCAL_ADDR:
583 case AST_EVENT_IE_REMOTE_ADDR:
584 case AST_EVENT_IE_EXPECTED_ADDR:
586 const struct ast_security_event_ip_addr *addr;
588 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
590 if (req && !addr->addr) {
591 ast_log(LOG_WARNING, "Required IE '%d' for security event "
592 "type '%d' not present\n", ie_type->ie_type,
598 res = add_ip_ie(event, ie_type->ie_type, addr);
602 case AST_EVENT_IE_SESSION_TV:
604 const struct timeval *tval;
606 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
609 ast_log(LOG_WARNING, "Required IE '%d' for security event "
610 "type '%d' not present\n", ie_type->ie_type,
616 add_timeval_ie(event, ie_type->ie_type, tval);
621 case AST_EVENT_IE_EVENT_TV:
622 case AST_EVENT_IE_SEVERITY:
623 /* Added automatically, nothing to do here. */
626 ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event "
627 "will be missing data.\n", ie_type->ie_type);
634 static int handle_security_event(const struct ast_security_event_common *sec)
636 struct ast_event *event;
637 const struct ast_security_event_ie_type *ies;
640 if (!(event = alloc_event(sec))) {
644 for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
645 ies[i].ie_type != AST_EVENT_IE_END;
647 if (add_ie(&event, sec, ies + i, REQUIRED)) {
652 for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
653 ies[i].ie_type != AST_EVENT_IE_END;
655 if (add_ie(&event, sec, ies + i, NOT_REQUIRED)) {
661 if (ast_event_queue(event)) {
669 ast_event_destroy(event);
675 int ast_security_event_report(const struct ast_security_event_common *sec)
679 if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
680 ast_log(LOG_ERROR, "Invalid security event type\n");
684 if (!sec_events[sec->event_type].name) {
685 ast_log(LOG_WARNING, "Security event type %u not handled\n",
690 if (sec->version != sec_events[sec->event_type].version) {
691 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
696 res = handle_security_event(sec);