Merged revisions 337595,337597 via svnmerge from
[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_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
269                 { AST_EVENT_IE_END, 0 }
270         },
271         .optional_ies = {
272                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
273                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
274                 { AST_EVENT_IE_END, 0 }
275         },
276 },
277
278 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
279         .name     = "UnexpectedAddress",
280         .version  = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
281         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
282         .required_ies = {
283                 { AST_EVENT_IE_EVENT_TV, 0 },
284                 { AST_EVENT_IE_SEVERITY, 0 },
285                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
286                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
287                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
288                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
289                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
290                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
291                 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
292                 { AST_EVENT_IE_END, 0 }
293         },
294         .optional_ies = {
295                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
296                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
297                 { AST_EVENT_IE_END, 0 }
298         },
299 },
300
301 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
302         .name     = "ChallengeResponseFailed",
303         .version  = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
304         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
305         .required_ies = {
306                 { AST_EVENT_IE_EVENT_TV, 0 },
307                 { AST_EVENT_IE_SEVERITY, 0 },
308                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
309                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
310                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
311                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
312                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
313                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
314                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
315                 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
316                 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
317                 { AST_EVENT_IE_END, 0 }
318         },
319         .optional_ies = {
320                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
321                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
322                 { AST_EVENT_IE_END, 0 }
323         },
324 },
325
326 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
327         .name     = "InvalidPassword",
328         .version  = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
329         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
330         .required_ies = {
331                 { AST_EVENT_IE_EVENT_TV, 0 },
332                 { AST_EVENT_IE_SEVERITY, 0 },
333                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
334                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
335                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
336                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
337                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
338                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
339                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
340                 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
341                 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
342                 { AST_EVENT_IE_END, 0 }
343         },
344         .optional_ies = {
345                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
346                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
347                 { AST_EVENT_IE_END, 0 }
348         },
349 },
350
351 [AST_SECURITY_EVENT_CHAL_SENT] = {
352         .name     = "ChallengeSent",
353         .version  = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
354         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
355         .required_ies = {
356                 { AST_EVENT_IE_EVENT_TV, 0 },
357                 { AST_EVENT_IE_SEVERITY, 0 },
358                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
359                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
360                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
361                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
362                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
363                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
364                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
365                 { AST_EVENT_IE_END, 0 }
366         },
367         .optional_ies = {
368                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
369                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
370                 { AST_EVENT_IE_END, 0 }
371         },
372 },
373
374 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
375         .name     = "InvalidTransport",
376         .version  = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
377         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
378         .required_ies = {
379                 { AST_EVENT_IE_EVENT_TV, 0 },
380                 { AST_EVENT_IE_SEVERITY, 0 },
381                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
382                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
383                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
384                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
385                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
386                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
387                 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
388                 { AST_EVENT_IE_END, 0 }
389         },
390         .optional_ies = {
391                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
392                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
393                 { AST_EVENT_IE_END, 0 }
394         },
395 },
396
397 #undef SEC_EVT_FIELD
398
399 };
400
401 static const struct {
402         enum ast_security_event_severity severity;
403         const char *str;
404 } severities[] = {
405         { AST_SECURITY_EVENT_SEVERITY_INFO,  "Informational" },
406         { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
407 };
408
409 const char *ast_security_event_severity_get_name(
410                 const enum ast_security_event_severity severity)
411 {
412         unsigned int i;
413
414         for (i = 0; i < ARRAY_LEN(severities); i++) {
415                 if (severities[i].severity == severity) {
416                         return severities[i].str;
417                 }
418         }
419
420         return NULL;
421 }
422
423 static int check_event_type(const enum ast_security_event_type event_type)
424 {
425         if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
426                 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
427                 return -1;
428         }
429
430         return 0;
431 }
432
433 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
434 {
435         if (check_event_type(event_type)) {
436                 return NULL;
437         }
438
439         return sec_events[event_type].name;
440 }
441
442 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
443                 const enum ast_security_event_type event_type)
444 {
445         if (check_event_type(event_type)) {
446                 return NULL;
447         }
448
449         return sec_events[event_type].required_ies;
450 }
451
452 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
453                 const enum ast_security_event_type event_type)
454 {
455         if (check_event_type(event_type)) {
456                 return NULL;
457         }
458
459         return sec_events[event_type].optional_ies;
460 }
461
462 static void encode_timestamp(struct ast_str **str, const struct timeval *tv)
463 {
464         ast_str_set(str, 0, "%u-%u",
465                         (unsigned int) tv->tv_sec,
466                         (unsigned int) tv->tv_usec);
467 }
468
469 static struct ast_event *alloc_event(const struct ast_security_event_common *sec)
470 {
471         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
472         struct timeval tv = ast_tvnow();
473         const char *severity_str;
474
475         if (check_event_type(sec->event_type)) {
476                 return NULL;
477         }
478
479         encode_timestamp(&str, &tv);
480
481         severity_str = S_OR(
482                 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
483                 "Unknown"
484         );
485
486         return ast_event_new(AST_EVENT_SECURITY,
487                 AST_EVENT_IE_SECURITY_EVENT, AST_EVENT_IE_PLTYPE_UINT, sec->event_type,
488                 AST_EVENT_IE_EVENT_VERSION, AST_EVENT_IE_PLTYPE_UINT, sec->version,
489                 AST_EVENT_IE_EVENT_TV, AST_EVENT_IE_PLTYPE_STR, str->str,
490                 AST_EVENT_IE_SERVICE, AST_EVENT_IE_PLTYPE_STR, sec->service,
491                 AST_EVENT_IE_SEVERITY, AST_EVENT_IE_PLTYPE_STR, severity_str,
492                 AST_EVENT_IE_END);
493 }
494
495 static int add_timeval_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
496                 const struct timeval *tv)
497 {
498         struct ast_str *str = ast_str_alloca(TIMESTAMP_STR_LEN);
499
500         encode_timestamp(&str, tv);
501
502         return ast_event_append_ie_str(event, ie_type, ast_str_buffer(str));
503 }
504
505 static int add_ipv4_ie(struct ast_event **event, enum ast_event_ie_type ie_type,
506                 const struct ast_security_event_ipv4_addr *addr)
507 {
508         struct ast_str *str = ast_str_alloca(64);
509
510         ast_str_set(&str, 0, "IPV4/");
511
512         switch (addr->transport) {
513         case AST_SECURITY_EVENT_TRANSPORT_UDP:
514                 ast_str_append(&str, 0, "UDP/");
515                 break;
516         case AST_SECURITY_EVENT_TRANSPORT_TCP:
517                 ast_str_append(&str, 0, "TCP/");
518                 break;
519         case AST_SECURITY_EVENT_TRANSPORT_TLS:
520                 ast_str_append(&str, 0, "TLS/");
521                 break;
522         }
523
524         ast_str_append(&str, 0, "%s/%hu",
525                         ast_inet_ntoa(addr->sin->sin_addr),
526                         ntohs(addr->sin->sin_port));
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_ipv4_addr *addr;
587
588                 addr = (const struct ast_security_event_ipv4_addr *)(((const char *) sec) + ie_type->offset);
589
590                 if (req && !addr->sin) {
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->sin) {
598                         res = add_ipv4_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