d1e2ac0ccd3e96a33e667ffe4d13264187f3c38d
[asterisk/asterisk.git] / main / security_events.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*!
20  * \file
21  *
22  * \brief Security Event Reporting Helpers
23  *
24  * \author Russell Bryant <russell@digium.com>
25  */
26
27 #include "asterisk.h"
28
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
30
31 #include "asterisk/utils.h"
32 #include "asterisk/strings.h"
33 #include "asterisk/network.h"
34 #include "asterisk/security_events.h"
35
36 static const size_t TIMESTAMP_STR_LEN = 32;
37
38 static const struct {
39         const char *name;
40         uint32_t version;
41         enum ast_security_event_severity severity;
42 #define MAX_SECURITY_IES 12
43         struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
44         struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
45 #undef MAX_SECURITY_IES
46 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
47
48 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
49
50 [AST_SECURITY_EVENT_FAILED_ACL] = {
51         .name     = "FailedACL",
52         .version  = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
53         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
54         .required_ies = {
55                 { AST_EVENT_IE_EVENT_TV, 0 },
56                 { AST_EVENT_IE_SEVERITY, 0 },
57                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
58                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
59                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
60                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
61                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
62                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
63                 { AST_EVENT_IE_END, 0 }
64         },
65         .optional_ies = {
66                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
67                 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
68                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
69                 { AST_EVENT_IE_END, 0 }
70         },
71 },
72
73 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
74         .name     = "InvalidAccountID",
75         .version  = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
76         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
77         .required_ies = {
78                 { AST_EVENT_IE_EVENT_TV, 0 },
79                 { AST_EVENT_IE_SEVERITY, 0 },
80                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
81                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
82                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
83                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
84                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
85                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
86                 { AST_EVENT_IE_END, 0 }
87         },
88         .optional_ies = {
89                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
90                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
91                 { AST_EVENT_IE_END, 0 }
92         },
93 },
94
95 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
96         .name     = "SessionLimit",
97         .version  = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
98         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
99         .required_ies = {
100                 { AST_EVENT_IE_EVENT_TV, 0 },
101                 { AST_EVENT_IE_SEVERITY, 0 },
102                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
103                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
104                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
105                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
106                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
107                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
108                 { AST_EVENT_IE_END, 0 }
109         },
110         .optional_ies = {
111                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
112                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
113                 { AST_EVENT_IE_END, 0 }
114         },
115 },
116
117 [AST_SECURITY_EVENT_MEM_LIMIT] = {
118         .name     = "MemoryLimit",
119         .version  = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
120         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
121         .required_ies = {
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 }
131         },
132         .optional_ies = {
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 }
136         },
137 },
138
139 [AST_SECURITY_EVENT_LOAD_AVG] = {
140         .name     = "LoadAverageLimit",
141         .version  = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
142         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
143         .required_ies = {
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 }
153         },
154         .optional_ies = {
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 }
158         },
159 },
160
161 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
162         .name     = "RequestNotSupported",
163         .version  = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
164         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
165         .required_ies = {
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_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
175                 { AST_EVENT_IE_END, 0 }
176         },
177         .optional_ies = {
178                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
179                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
180                 { AST_EVENT_IE_END, 0 }
181         },
182 },
183
184 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
185         .name     = "RequestNotAllowed",
186         .version  = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
187         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
188         .required_ies = {
189                 { AST_EVENT_IE_EVENT_TV, 0 },
190                 { AST_EVENT_IE_SEVERITY, 0 },
191                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
192                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
193                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
194                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
195                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
196                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
197                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
198                 { AST_EVENT_IE_END, 0 }
199         },
200         .optional_ies = {
201                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
202                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
203                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
204                 { AST_EVENT_IE_END, 0 }
205         },
206 },
207
208 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
209         .name     = "AuthMethodNotAllowed",
210         .version  = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
211         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
212         .required_ies = {
213                 { AST_EVENT_IE_EVENT_TV, 0 },
214                 { AST_EVENT_IE_SEVERITY, 0 },
215                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
216                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
217                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
218                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
219                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
220                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
221                 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
222                 { AST_EVENT_IE_END, 0 }
223         },
224         .optional_ies = {
225                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
226                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
227                 { AST_EVENT_IE_END, 0 }
228         },
229 },
230
231 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
232         .name     = "RequestBadFormat",
233         .version  = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
234         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
235         .required_ies = {
236                 { AST_EVENT_IE_EVENT_TV, 0 },
237                 { AST_EVENT_IE_SEVERITY, 0 },
238                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
239                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
240                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
241                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
242                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
243                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
244                 { AST_EVENT_IE_END, 0 }
245         },
246         .optional_ies = {
247                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
248                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
249                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
250                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
251                 { AST_EVENT_IE_END, 0 }
252         },
253 },
254
255 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
256         .name     = "SuccessfulAuth",
257         .version  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
258         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
259         .required_ies = {
260                 { AST_EVENT_IE_EVENT_TV, 0 },
261                 { AST_EVENT_IE_SEVERITY, 0 },
262                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
263                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
264                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
265                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
266                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
267                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
268                 { AST_EVENT_IE_END, 0 }
269         },
270         .optional_ies = {
271                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
272                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
273                 { AST_EVENT_IE_END, 0 }
274         },
275 },
276
277 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
278         .name     = "UnexpectedAddress",
279         .version  = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
280         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
281         .required_ies = {
282                 { AST_EVENT_IE_EVENT_TV, 0 },
283                 { AST_EVENT_IE_SEVERITY, 0 },
284                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
285                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
286                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
287                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
288                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
289                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
290                 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
291                 { AST_EVENT_IE_END, 0 }
292         },
293         .optional_ies = {
294                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
295                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
296                 { AST_EVENT_IE_END, 0 }
297         },
298 },
299
300 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
301         .name     = "ChallengeResponseFailed",
302         .version  = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
303         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
304         .required_ies = {
305                 { AST_EVENT_IE_EVENT_TV, 0 },
306                 { AST_EVENT_IE_SEVERITY, 0 },
307                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
308                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
309                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
310                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
311                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
312                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
313                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
314                 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
315                 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
316                 { AST_EVENT_IE_END, 0 }
317         },
318         .optional_ies = {
319                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
320                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
321                 { AST_EVENT_IE_END, 0 }
322         },
323 },
324
325 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
326         .name     = "InvalidPassword",
327         .version  = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
328         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
329         .required_ies = {
330                 { AST_EVENT_IE_EVENT_TV, 0 },
331                 { AST_EVENT_IE_SEVERITY, 0 },
332                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
333                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
334                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
335                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
336                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
337                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
338                 { AST_EVENT_IE_END, 0 }
339         },
340         .optional_ies = {
341                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
342                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
343                 { AST_EVENT_IE_END, 0 }
344         },
345 },
346
347 #undef SEC_EVT_FIELD
348
349 };
350
351 static const struct {
352         enum ast_security_event_severity severity;
353         const char *str;
354 } severities[] = {
355         { AST_SECURITY_EVENT_SEVERITY_INFO,  "Informational" },
356         { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
357 };
358
359 const char *ast_security_event_severity_get_name(
360                 const enum ast_security_event_severity severity)
361 {
362         unsigned int i;
363
364         for (i = 0; i < ARRAY_LEN(severities); i++) {
365                 if (severities[i].severity == severity) {
366                         return severities[i].str;
367                 }
368         }
369
370         return NULL;
371 }
372
373 static int check_event_type(const enum ast_security_event_type event_type)
374 {
375         if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
376                 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
377                 return -1;
378         }
379
380         return 0;
381 }
382
383 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
384 {
385         if (check_event_type(event_type)) {
386                 return NULL;
387         }
388
389         return sec_events[event_type].name;
390 }
391
392 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
393                 const enum ast_security_event_type event_type)
394 {
395         if (check_event_type(event_type)) {
396                 return NULL;
397         }
398
399         return sec_events[event_type].required_ies;
400 }
401
402 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
403                 const enum ast_security_event_type event_type)
404 {
405         if (check_event_type(event_type)) {
406                 return NULL;
407         }
408
409         return sec_events[event_type].optional_ies;
410 }
411
412 static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
413 {
414         ast_str_set(str, 0, "%u-%u",
415                         (unsigned int) tv->tv_sec,
416                         (unsigned int) tv->tv_usec);
417 }
418
419 static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
420 {
421         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
422         struct timeval tv = ast_tvnow();
423         const char *severity_str;
424
425         if (check_event_type(sec->event_type)) {
426                 return NULL;
427         }
428
429         encode_timestamp(&str, &tv);
430
431         severity_str = S_OR(
432                 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
433                 "Unknown"
434         );
435
436         return ast_event_new(AST_EVENT_SECURITY,
437                 AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
438                 AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
439                 AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, str->str,
440                 AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
441                 AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
442                 AST_EVENT_IE_END);
443 }
444
445 static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
446                 const struct timeval *tv)
447 {
448         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
449
450         encode_timestamp(&str, tv);
451
452         return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
453 }
454
455 static int add_ipv4_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
456                 const struct ast_security_event_ipv4_addr *addr)
457 {
458         struct ast_str *str = ast_str_alloca(64);
459
460         ast_str_set(&str, 0, "IPV4/");
461
462         switch (addr->transport) {
463         case AST_SECURITY_EVENT_TRANSPORT_UDP:
464                 ast_str_append(&str, 0, "UDP/");
465                 break;
466         case AST_SECURITY_EVENT_TRANSPORT_TCP:
467                 ast_str_append(&str, 0, "TCP/");
468                 break;
469         case AST_SECURITY_EVENT_TRANSPORT_TLS:
470                 ast_str_append(&str, 0, "TLS/");
471                 break;
472         }
473
474         ast_str_append(&str, 0, "%s/%hu",
475                         ast_inet_ntoa(addr->sin->sin_addr),
476                         ntohs(addr->sin->sin_port));
477
478         return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
479 }
480
481 enum ie_required {
482         NOT_REQUIRED,
483         REQUIRED
484 };
485
486 static int add_ie(struct ast_event **event, const struct ast_security_event_common *sec,
487                 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
488 {
489         int res = 0;
490
491         switch (ie_type->ie_type) {
492         case AST_EVENT_IE_SERVICE:
493         case AST_EVENT_IE_ACCOUNT_ID:
494         case AST_EVENT_IE_SESSION_ID:
495         case AST_EVENT_IE_MODULE:
496         case AST_EVENT_IE_ACL_NAME:
497         case AST_EVENT_IE_REQUEST_TYPE:
498         case AST_EVENT_IE_REQUEST_PARAMS:
499         case AST_EVENT_IE_AUTH_METHOD:
500         case AST_EVENT_IE_CHALLENGE:
501         case AST_EVENT_IE_RESPONSE:
502         case AST_EVENT_IE_EXPECTED_RESPONSE:
503         {
504                 const char *str;
505
506                 str = *((const char **)(((const char *) sec) + ie_type->offset));
507
508                 if (req && !str) {
509                         ast_log(LOG_WARNING, "Required IE '%d' for security event "
510                                         "type '%d' not present\n", ie_type->ie_type,
511                                         sec->event_type);
512                         res = -1;
513                 }
514
515                 if (str) {
516                         res = ast_event_append_ie_str(event, ie_type->ie_type, str);
517                 }
518
519                 break;
520         }
521         case AST_EVENT_IE_EVENT_VERSION:
522         {
523                 uint32_t val;
524                 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
525                 res = ast_event_append_ie_uint(event, ie_type->ie_type, val);
526                 break;
527         }
528         case AST_EVENT_IE_LOCAL_ADDR:
529         case AST_EVENT_IE_REMOTE_ADDR:
530         case AST_EVENT_IE_EXPECTED_ADDR:
531         {
532                 const struct ast_security_event_ipv4_addr *addr;
533
534                 addr = (const struct ast_security_event_ipv4_addr *)(((const char *) sec) + ie_type->offset);
535
536                 if (req && !addr->sin) {
537                         ast_log(LOG_WARNING, "Required IE '%d' for security event "
538                                         "type '%d' not present\n", ie_type->ie_type,
539                                         sec->event_type);
540                         res = -1;
541                 }
542
543                 if (addr->sin) {
544                         res = add_ipv4_ie(event, ie_type->ie_type, addr);
545                 }
546                 break;
547         }
548         case AST_EVENT_IE_SESSION_TV:
549         {
550                 const struct timeval *tval;
551
552                 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
553
554                 if (req && !tval) {
555                         ast_log(LOG_WARNING, "Required IE '%d' for security event "
556                                         "type '%d' not present\n", ie_type->ie_type,
557                                         sec->event_type);
558                         res = -1;
559                 }
560
561                 if (tval) {
562                         add_timeval_ie(event, ie_type->ie_type, tval);
563                 }
564
565                 break;
566         }
567         case AST_EVENT_IE_EVENT_TV:
568         case AST_EVENT_IE_SEVERITY:
569                 /* Added automatically, nothing to do here. */
570                 break;
571         default:
572                 ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event "
573                                 "will be missing data.\n", ie_type->ie_type);
574                 break;
575         }
576
577         return res;
578 }
579
580 static int handle_security_event(const struct ast_security_event_common *sec)
581 {
582         struct ast_event *event;
583         const struct ast_security_event_ie_type *ies;
584         unsigned int i;
585
586         if (!(event = alloc_event(sec))) {
587                 return -1;
588         }
589
590         for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
591                         ies[i].ie_type != AST_EVENT_IE_END;
592                         i++) {
593                 if (add_ie(&event, sec, ies + i, REQUIRED)) {
594                         goto return_error;
595                 }
596         }
597
598         for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
599                         ies[i].ie_type != AST_EVENT_IE_END;
600                         i++) {
601                 if (add_ie(&event, sec, ies + i, NOT_REQUIRED)) {
602                         goto return_error;
603                 }
604         }
605
606
607         if (ast_event_queue(event)) {
608                 goto return_error;
609         }
610
611         return 0;
612
613 return_error:
614         if (event) {
615                 ast_event_destroy(event);
616         }
617
618         return -1;
619 }
620
621 int ast_security_event_report(const struct ast_security_event_common *sec)
622 {
623         int res;
624
625         if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
626                 ast_log(LOG_ERROR, "Invalid security event type\n");
627                 return -1;
628         }
629
630         if (!sec_events[sec->event_type].name) {
631                 ast_log(LOG_WARNING, "Security event type %u not handled\n",
632                                 sec->event_type);
633                 return -1;
634         }
635
636         if (sec->version != sec_events[sec->event_type].version) {
637                 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
638                                 sec->event_type);
639                 return -1;
640         }
641
642         res = handle_security_event(sec);
643
644         return res;
645 }
646
647