Add IPv6 address support to security events framework.
[asterisk/asterisk.git] / main / security_events.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, 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 #include "asterisk/netsock2.h"
36
37 static const size_t TIMESTAMP_STR_LEN = 32;
38
39 static const struct {
40         const char *name;
41         uint32_t version;
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] = {
48
49 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
50
51 [AST_SECURITY_EVENT_FAILED_ACL] = {
52         .name     = "FailedACL",
53         .version  = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
54         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
55         .required_ies = {
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 }
65         },
66         .optional_ies = {
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 }
71         },
72 },
73
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,
78         .required_ies = {
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 }
88         },
89         .optional_ies = {
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 }
93         },
94 },
95
96 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
97         .name     = "SessionLimit",
98         .version  = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
99         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
100         .required_ies = {
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 }
110         },
111         .optional_ies = {
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 }
115         },
116 },
117
118 [AST_SECURITY_EVENT_MEM_LIMIT] = {
119         .name     = "MemoryLimit",
120         .version  = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
121         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
122         .required_ies = {
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 }
132         },
133         .optional_ies = {
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 }
137         },
138 },
139
140 [AST_SECURITY_EVENT_LOAD_AVG] = {
141         .name     = "LoadAverageLimit",
142         .version  = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
143         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
144         .required_ies = {
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 }
154         },
155         .optional_ies = {
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 }
159         },
160 },
161
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,
166         .required_ies = {
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 }
177         },
178         .optional_ies = {
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 }
182         },
183 },
184
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,
189         .required_ies = {
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 }
200         },
201         .optional_ies = {
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 }
206         },
207 },
208
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,
213         .required_ies = {
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 }
224         },
225         .optional_ies = {
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 }
229         },
230 },
231
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,
236         .required_ies = {
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 }
246         },
247         .optional_ies = {
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 }
253         },
254 },
255
256 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
257         .name     = "SuccessfulAuth",
258         .version  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
259         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
260         .required_ies = {
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 }
271         },
272         .optional_ies = {
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 }
276         },
277 },
278
279 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
280         .name     = "UnexpectedAddress",
281         .version  = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
282         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
283         .required_ies = {
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 }
294         },
295         .optional_ies = {
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 }
299         },
300 },
301
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,
306         .required_ies = {
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 }
319         },
320         .optional_ies = {
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 }
324         },
325 },
326
327 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
328         .name     = "InvalidPassword",
329         .version  = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
330         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
331         .required_ies = {
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 }
344         },
345         .optional_ies = {
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 }
349         },
350 },
351
352 [AST_SECURITY_EVENT_CHAL_SENT] = {
353         .name     = "ChallengeSent",
354         .version  = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
355         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
356         .required_ies = {
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 }
367         },
368         .optional_ies = {
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 }
372         },
373 },
374
375 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
376         .name     = "InvalidTransport",
377         .version  = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
378         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
379         .required_ies = {
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 }
390         },
391         .optional_ies = {
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 }
395         },
396 },
397
398 #undef SEC_EVT_FIELD
399
400 };
401
402 static const struct {
403         enum ast_security_event_severity severity;
404         const char *str;
405 } severities[] = {
406         { AST_SECURITY_EVENT_SEVERITY_INFO,  "Informational" },
407         { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
408 };
409
410 const char *ast_security_event_severity_get_name(
411                 const enum ast_security_event_severity severity)
412 {
413         unsigned int i;
414
415         for (i = 0; i < ARRAY_LEN(severities); i++) {
416                 if (severities[i].severity == severity) {
417                         return severities[i].str;
418                 }
419         }
420
421         return NULL;
422 }
423
424 static int check_event_type(const enum ast_security_event_type event_type)
425 {
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);
428                 return -1;
429         }
430
431         return 0;
432 }
433
434 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
435 {
436         if (check_event_type(event_type)) {
437                 return NULL;
438         }
439
440         return sec_events[event_type].name;
441 }
442
443 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
444                 const enum ast_security_event_type event_type)
445 {
446         if (check_event_type(event_type)) {
447                 return NULL;
448         }
449
450         return sec_events[event_type].required_ies;
451 }
452
453 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
454                 const enum ast_security_event_type event_type)
455 {
456         if (check_event_type(event_type)) {
457                 return NULL;
458         }
459
460         return sec_events[event_type].optional_ies;
461 }
462
463 static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
464 {
465         ast_str_set(str, 0, "%u-%u",
466                         (unsigned int) tv->tv_sec,
467                         (unsigned int) tv->tv_usec);
468 }
469
470 static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
471 {
472         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
473         struct timeval tv = ast_tvnow();
474         const char *severity_str;
475
476         if (check_event_type(sec->event_type)) {
477                 return NULL;
478         }
479
480         encode_timestamp(&str, &tv);
481
482         severity_str = S_OR(
483                 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
484                 "Unknown"
485         );
486
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,
493                 AST_EVENT_IE_END);
494 }
495
496 static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
497                 const struct timeval *tv)
498 {
499         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
500
501         encode_timestamp(&str, tv);
502
503         return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
504 }
505
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)
508 {
509         struct ast_str *str = ast_str_alloca(64);
510
511         ast_str_set(&str, 0, (ast_sockaddr_is_ipv4(addr->addr) || ast_sockaddr_is_ipv4_mapped(addr->addr)) ? "IPV4/" : "IPV6/");
512
513         switch (addr->transport) {
514         case AST_SECURITY_EVENT_TRANSPORT_UDP:
515                 ast_str_append(&str, 0, "UDP/");
516                 break;
517         case AST_SECURITY_EVENT_TRANSPORT_TCP:
518                 ast_str_append(&str, 0, "TCP/");
519                 break;
520         case AST_SECURITY_EVENT_TRANSPORT_TLS:
521                 ast_str_append(&str, 0, "TLS/");
522                 break;
523         }
524
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));
527
528         return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
529 }
530
531 enum ie_required {
532         NOT_REQUIRED,
533         REQUIRED
534 };
535
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)
538 {
539         int res = 0;
540
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:
556         {
557                 const char *str;
558
559                 str = *((const char **)(((const char *) sec) + ie_type->offset));
560
561                 if (req && !str) {
562                         ast_log(LOG_WARNING, "Required IE '%d' for security event "
563                                         "type '%d' not present\n", ie_type->ie_type,
564                                         sec->event_type);
565                         res = -1;
566                 }
567
568                 if (str) {
569                         res = ast_event_append_ie_str(event, ie_type->ie_type, str);
570                 }
571
572                 break;
573         }
574         case AST_EVENT_IE_EVENT_VERSION:
575         case AST_EVENT_IE_USING_PASSWORD:
576         {
577                 uint32_t val;
578                 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
579                 res = ast_event_append_ie_uint(event, ie_type->ie_type, val);
580                 break;
581         }
582         case AST_EVENT_IE_LOCAL_ADDR:
583         case AST_EVENT_IE_REMOTE_ADDR:
584         case AST_EVENT_IE_EXPECTED_ADDR:
585         {
586                 const struct ast_security_event_ip_addr *addr;
587
588                 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
589
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,
593                                         sec->event_type);
594                         res = -1;
595                 }
596
597                 if (addr->addr) {
598                         res = add_ip_ie(event, ie_type->ie_type, addr);
599                 }
600                 break;
601         }
602         case AST_EVENT_IE_SESSION_TV:
603         {
604                 const struct timeval *tval;
605
606                 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
607
608                 if (req && !tval) {
609                         ast_log(LOG_WARNING, "Required IE '%d' for security event "
610                                         "type '%d' not present\n", ie_type->ie_type,
611                                         sec->event_type);
612                         res = -1;
613                 }
614
615                 if (tval) {
616                         add_timeval_ie(event, ie_type->ie_type, tval);
617                 }
618
619                 break;
620         }
621         case AST_EVENT_IE_EVENT_TV:
622         case AST_EVENT_IE_SEVERITY:
623                 /* Added automatically, nothing to do here. */
624                 break;
625         default:
626                 ast_log(LOG_WARNING, "Unhandled IE type '%d', this security event "
627                                 "will be missing data.\n", ie_type->ie_type);
628                 break;
629         }
630
631         return res;
632 }
633
634 static int handle_security_event(const struct ast_security_event_common *sec)
635 {
636         struct ast_event *event;
637         const struct ast_security_event_ie_type *ies;
638         unsigned int i;
639
640         if (!(event = alloc_event(sec))) {
641                 return -1;
642         }
643
644         for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
645                         ies[i].ie_type != AST_EVENT_IE_END;
646                         i++) {
647                 if (add_ie(&event, sec, ies + i, REQUIRED)) {
648                         goto return_error;
649                 }
650         }
651
652         for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
653                         ies[i].ie_type != AST_EVENT_IE_END;
654                         i++) {
655                 if (add_ie(&event, sec, ies + i, NOT_REQUIRED)) {
656                         goto return_error;
657                 }
658         }
659
660
661         if (ast_event_queue(event)) {
662                 goto return_error;
663         }
664
665         return 0;
666
667 return_error:
668         if (event) {
669                 ast_event_destroy(event);
670         }
671
672         return -1;
673 }
674
675 int ast_security_event_report(const struct ast_security_event_common *sec)
676 {
677         int res;
678
679         if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
680                 ast_log(LOG_ERROR, "Invalid security event type\n");
681                 return -1;
682         }
683
684         if (!sec_events[sec->event_type].name) {
685                 ast_log(LOG_WARNING, "Security event type %u not handled\n",
686                                 sec->event_type);
687                 return -1;
688         }
689
690         if (sec->version != sec_events[sec->event_type].version) {
691                 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
692                                 sec->event_type);
693                 return -1;
694         }
695
696         res = handle_security_event(sec);
697
698         return res;
699 }
700
701