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