Add an API for reporting security events, and a security event logging module.
[asterisk/asterisk.git] / tests / test_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 /*! \file
20  *
21  * \brief Test security event generation
22  *
23  * \author Russell Bryant <russell@digium.com>
24  */
25
26 /*** MODULEINFO
27         <defaultenabled>no</defaultenabled>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/module.h"
35 #include "asterisk/cli.h"
36 #include "asterisk/utils.h"
37 #include "asterisk/security_events.h"
38
39 static void evt_gen_failed_acl(void);
40 static void evt_gen_inval_acct_id(void);
41 static void evt_gen_session_limit(void);
42 static void evt_gen_mem_limit(void);
43 static void evt_gen_load_avg(void);
44 static void evt_gen_req_no_support(void);
45 static void evt_gen_req_not_allowed(void);
46 static void evt_gen_auth_method_not_allowed(void);
47 static void evt_gen_req_bad_format(void);
48 static void evt_gen_successful_auth(void);
49 static void evt_gen_unexpected_addr(void);
50 static void evt_gen_chal_resp_failed(void);
51 static void evt_gen_inval_password(void);
52
53 typedef void (*evt_generator)(void);
54 static const evt_generator evt_generators[AST_SECURITY_EVENT_NUM_TYPES] = {
55         [AST_SECURITY_EVENT_FAILED_ACL]              = evt_gen_failed_acl,
56         [AST_SECURITY_EVENT_INVAL_ACCT_ID]           = evt_gen_inval_acct_id,
57         [AST_SECURITY_EVENT_SESSION_LIMIT]           = evt_gen_session_limit,
58         [AST_SECURITY_EVENT_MEM_LIMIT]               = evt_gen_mem_limit,
59         [AST_SECURITY_EVENT_LOAD_AVG]                = evt_gen_load_avg,
60         [AST_SECURITY_EVENT_REQ_NO_SUPPORT]          = evt_gen_req_no_support,
61         [AST_SECURITY_EVENT_REQ_NOT_ALLOWED]         = evt_gen_req_not_allowed,
62         [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = evt_gen_auth_method_not_allowed,
63         [AST_SECURITY_EVENT_REQ_BAD_FORMAT]          = evt_gen_req_bad_format,
64         [AST_SECURITY_EVENT_SUCCESSFUL_AUTH]         = evt_gen_successful_auth,
65         [AST_SECURITY_EVENT_UNEXPECTED_ADDR]         = evt_gen_unexpected_addr,
66         [AST_SECURITY_EVENT_CHAL_RESP_FAILED]        = evt_gen_chal_resp_failed,
67         [AST_SECURITY_EVENT_INVAL_PASSWORD]          = evt_gen_inval_password,
68 };
69
70 static void evt_gen_failed_acl(void)
71 {
72         struct sockaddr_in sin_local = {
73                 .sin_family = AF_INET
74         };
75         struct sockaddr_in sin_remote = {
76                 .sin_family = AF_INET
77         };
78         struct timeval session_tv = ast_tvnow();
79         struct ast_security_event_failed_acl failed_acl_event = {
80                 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
81                 .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
82                 .common.service    = "TEST",
83                 .common.module     = AST_MODULE,
84                 .common.account_id = "Username",
85                 .common.session_id = "Session123",
86                 .common.session_tv = &session_tv,
87                 .common.local_addr = {
88                         .sin  = &sin_local,
89                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
90                 },
91                 .common.remote_addr = {
92                         .sin = &sin_remote,
93                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
94                 },
95
96                 .acl_name   = "TEST_ACL",
97         };
98
99         inet_aton("192.168.1.1", &sin_local.sin_addr);
100         sin_local.sin_port = htons(12121);
101
102         inet_aton("192.168.1.2", &sin_remote.sin_addr);
103         sin_remote.sin_port = htons(12345);
104
105         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
106 }
107
108 static void evt_gen_inval_acct_id(void)
109 {
110         struct sockaddr_in sin_local = {
111                 .sin_family = AF_INET
112         };
113         struct sockaddr_in sin_remote = {
114                 .sin_family = AF_INET
115         };
116         struct timeval session_tv = ast_tvnow();
117         struct ast_security_event_inval_acct_id inval_acct_id = {
118                 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
119                 .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
120                 .common.service    = "TEST",
121                 .common.module     = AST_MODULE,
122                 .common.account_id = "FakeUser",
123                 .common.session_id = "Session456",
124                 .common.session_tv = &session_tv,
125                 .common.local_addr = {
126                         .sin  = &sin_local,
127                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
128                 },
129                 .common.remote_addr = {
130                         .sin = &sin_remote,
131                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
132                 },
133         };
134
135         inet_aton("10.1.2.3", &sin_local.sin_addr);
136         sin_local.sin_port = htons(4321);
137
138         inet_aton("10.1.2.4", &sin_remote.sin_addr);
139         sin_remote.sin_port = htons(1234);
140
141         ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
142 }
143
144 static void evt_gen_session_limit(void)
145 {
146         struct sockaddr_in sin_local = {
147                 .sin_family = AF_INET
148         };
149         struct sockaddr_in sin_remote = {
150                 .sin_family = AF_INET
151         };
152         struct timeval session_tv = ast_tvnow();
153         struct ast_security_event_session_limit session_limit = {
154                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
155                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
156                 .common.service    = "TEST",
157                 .common.module     = AST_MODULE,
158                 .common.account_id = "Jenny",
159                 .common.session_id = "8675309",
160                 .common.session_tv = &session_tv,
161                 .common.local_addr = {
162                         .sin  = &sin_local,
163                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TLS,
164                 },
165                 .common.remote_addr = {
166                         .sin = &sin_remote,
167                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TLS,
168                 },
169         };
170
171         inet_aton("10.5.4.3", &sin_local.sin_addr);
172         sin_local.sin_port = htons(4444);
173
174         inet_aton("10.5.4.2", &sin_remote.sin_addr);
175         sin_remote.sin_port = htons(3333);
176
177         ast_security_event_report(AST_SEC_EVT(&session_limit));
178 }
179
180 static void evt_gen_mem_limit(void)
181 {
182         struct sockaddr_in sin_local = {
183                 .sin_family = AF_INET
184         };
185         struct sockaddr_in sin_remote = {
186                 .sin_family = AF_INET
187         };
188         struct timeval session_tv = ast_tvnow();
189         struct ast_security_event_mem_limit mem_limit = {
190                 .common.event_type = AST_SECURITY_EVENT_MEM_LIMIT,
191                 .common.version    = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
192                 .common.service    = "TEST",
193                 .common.module     = AST_MODULE,
194                 .common.account_id = "Felix",
195                 .common.session_id = "Session2604",
196                 .common.session_tv = &session_tv,
197                 .common.local_addr = {
198                         .sin  = &sin_local,
199                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
200                 },
201                 .common.remote_addr = {
202                         .sin = &sin_remote,
203                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
204                 },
205         };
206
207         inet_aton("10.10.10.10", &sin_local.sin_addr);
208         sin_local.sin_port = htons(555);
209
210         inet_aton("10.10.10.12", &sin_remote.sin_addr);
211         sin_remote.sin_port = htons(5656);
212
213         ast_security_event_report(AST_SEC_EVT(&mem_limit));
214 }
215
216 static void evt_gen_load_avg(void)
217 {
218         struct sockaddr_in sin_local = {
219                 .sin_family = AF_INET
220         };
221         struct sockaddr_in sin_remote = {
222                 .sin_family = AF_INET
223         };
224         struct timeval session_tv = ast_tvnow();
225         struct ast_security_event_load_avg load_avg = {
226                 .common.event_type = AST_SECURITY_EVENT_LOAD_AVG,
227                 .common.version    = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
228                 .common.service    = "TEST",
229                 .common.module     = AST_MODULE,
230                 .common.account_id = "GuestAccount",
231                 .common.session_id = "XYZ123",
232                 .common.session_tv = &session_tv,
233                 .common.local_addr = {
234                         .sin  = &sin_local,
235                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
236                 },
237                 .common.remote_addr = {
238                         .sin = &sin_remote,
239                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
240                 },
241         };
242
243         inet_aton("10.11.12.13", &sin_local.sin_addr);
244         sin_local.sin_port = htons(9876);
245
246         inet_aton("10.12.11.10", &sin_remote.sin_addr);
247         sin_remote.sin_port = htons(9825);
248
249         ast_security_event_report(AST_SEC_EVT(&load_avg));
250 }
251
252 static void evt_gen_req_no_support(void)
253 {
254         struct sockaddr_in sin_local = {
255                 .sin_family = AF_INET
256         };
257         struct sockaddr_in sin_remote = {
258                 .sin_family = AF_INET
259         };
260         struct timeval session_tv = ast_tvnow();
261         struct ast_security_event_req_no_support req_no_support = {
262                 .common.event_type = AST_SECURITY_EVENT_REQ_NO_SUPPORT,
263                 .common.version    = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
264                 .common.service    = "TEST",
265                 .common.module     = AST_MODULE,
266                 .common.account_id = "George",
267                 .common.session_id = "asdkl23478289lasdkf",
268                 .common.session_tv = &session_tv,
269                 .common.local_addr = {
270                         .sin  = &sin_local,
271                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
272                 },
273                 .common.remote_addr = {
274                         .sin = &sin_remote,
275                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
276                 },
277
278                 .request_type = "MakeMeDinner",
279         };
280
281         inet_aton("10.110.120.130", &sin_local.sin_addr);
282         sin_local.sin_port = htons(9888);
283
284         inet_aton("10.120.110.100", &sin_remote.sin_addr);
285         sin_remote.sin_port = htons(9777);
286
287         ast_security_event_report(AST_SEC_EVT(&req_no_support));
288 }
289
290 static void evt_gen_req_not_allowed(void)
291 {
292         struct sockaddr_in sin_local = {
293                 .sin_family = AF_INET
294         };
295         struct sockaddr_in sin_remote = {
296                 .sin_family = AF_INET
297         };
298         struct timeval session_tv = ast_tvnow();
299         struct ast_security_event_req_not_allowed req_not_allowed = {
300                 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
301                 .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
302                 .common.service    = "TEST",
303                 .common.module     = AST_MODULE,
304                 .common.account_id = "George",
305                 .common.session_id = "alksdjf023423h4lka0df",
306                 .common.session_tv = &session_tv,
307                 .common.local_addr = {
308                         .sin  = &sin_local,
309                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
310                 },
311                 .common.remote_addr = {
312                         .sin = &sin_remote,
313                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
314                 },
315
316                 .request_type = "MakeMeBreakfast",
317                 .request_params = "BACONNNN!",
318         };
319
320         inet_aton("10.110.120.130", &sin_local.sin_addr);
321         sin_local.sin_port = htons(9888);
322
323         inet_aton("10.120.110.100", &sin_remote.sin_addr);
324         sin_remote.sin_port = htons(9777);
325
326         ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
327 }
328
329 static void evt_gen_auth_method_not_allowed(void)
330 {
331         struct sockaddr_in sin_local = {
332                 .sin_family = AF_INET
333         };
334         struct sockaddr_in sin_remote = {
335                 .sin_family = AF_INET
336         };
337         struct timeval session_tv = ast_tvnow();
338         struct ast_security_event_auth_method_not_allowed auth_method_not_allowed = {
339                 .common.event_type = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED,
340                 .common.version    = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
341                 .common.service    = "TEST",
342                 .common.module     = AST_MODULE,
343                 .common.account_id = "Bob",
344                 .common.session_id = "010101010101",
345                 .common.session_tv = &session_tv,
346                 .common.local_addr = {
347                         .sin  = &sin_local,
348                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
349                 },
350                 .common.remote_addr = {
351                         .sin = &sin_remote,
352                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
353                 },
354
355                 .auth_method = "PlainText"
356         };
357
358         inet_aton("10.110.120.135", &sin_local.sin_addr);
359         sin_local.sin_port = htons(8754);
360
361         inet_aton("10.120.110.105", &sin_remote.sin_addr);
362         sin_remote.sin_port = htons(8745);
363
364         ast_security_event_report(AST_SEC_EVT(&auth_method_not_allowed));
365 }
366
367 static void evt_gen_req_bad_format(void)
368 {
369         struct sockaddr_in sin_local = {
370                 .sin_family = AF_INET
371         };
372         struct sockaddr_in sin_remote = {
373                 .sin_family = AF_INET
374         };
375         struct timeval session_tv = ast_tvnow();
376         struct ast_security_event_req_bad_format req_bad_format = {
377                 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
378                 .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
379                 .common.service    = "TEST",
380                 .common.module     = AST_MODULE,
381                 .common.account_id = "Larry",
382                 .common.session_id = "838383fhfhf83hf8h3f8h",
383                 .common.session_tv = &session_tv,
384                 .common.local_addr = {
385                         .sin  = &sin_local,
386                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
387                 },
388                 .common.remote_addr = {
389                         .sin = &sin_remote,
390                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
391                 },
392
393                 .request_type = "CheeseBurger",
394                 .request_params = "Onions,Swiss,MotorOil",
395         };
396
397         inet_aton("10.110.220.230", &sin_local.sin_addr);
398         sin_local.sin_port = htons(1212);
399
400         inet_aton("10.120.210.200", &sin_remote.sin_addr);
401         sin_remote.sin_port = htons(2121);
402
403         ast_security_event_report(AST_SEC_EVT(&req_bad_format));
404 }
405
406 static void evt_gen_successful_auth(void)
407 {
408         struct sockaddr_in sin_local = {
409                 .sin_family = AF_INET
410         };
411         struct sockaddr_in sin_remote = {
412                 .sin_family = AF_INET
413         };
414         struct timeval session_tv = ast_tvnow();
415         struct ast_security_event_successful_auth successful_auth = {
416                 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
417                 .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
418                 .common.service    = "TEST",
419                 .common.module     = AST_MODULE,
420                 .common.account_id = "ValidUser",
421                 .common.session_id = "Session456",
422                 .common.session_tv = &session_tv,
423                 .common.local_addr = {
424                         .sin  = &sin_local,
425                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
426                 },
427                 .common.remote_addr = {
428                         .sin = &sin_remote,
429                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
430                 },
431         };
432
433         inet_aton("10.1.2.3", &sin_local.sin_addr);
434         sin_local.sin_port = htons(4321);
435
436         inet_aton("10.1.2.4", &sin_remote.sin_addr);
437         sin_remote.sin_port = htons(1234);
438
439         ast_security_event_report(AST_SEC_EVT(&successful_auth));
440 }
441
442 static void evt_gen_unexpected_addr(void)
443 {
444         struct sockaddr_in sin_local = {
445                 .sin_family = AF_INET
446         };
447         struct sockaddr_in sin_remote = {
448                 .sin_family = AF_INET
449         };
450         struct sockaddr_in sin_expected = {
451                 .sin_family = AF_INET
452         };
453         struct timeval session_tv = ast_tvnow();
454         struct ast_security_event_unexpected_addr unexpected_addr = {
455                 .common.event_type = AST_SECURITY_EVENT_UNEXPECTED_ADDR,
456                 .common.version    = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
457                 .common.service    = "TEST",
458                 .common.module     = AST_MODULE,
459                 .common.account_id = "CoolUser",
460                 .common.session_id = "Session789",
461                 .common.session_tv = &session_tv,
462                 .common.local_addr = {
463                         .sin  = &sin_local,
464                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
465                 },
466                 .common.remote_addr = {
467                         .sin = &sin_remote,
468                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
469                 },
470
471                 .expected_addr = {
472                         .sin = &sin_expected,
473                         .transport  = AST_SECURITY_EVENT_TRANSPORT_UDP,
474                 },
475         };
476
477         inet_aton("10.1.2.3", &sin_local.sin_addr);
478         sin_local.sin_port = htons(4321);
479
480         inet_aton("10.1.2.4", &sin_remote.sin_addr);
481         sin_remote.sin_port = htons(1234);
482
483         inet_aton("10.1.2.5", &sin_expected.sin_addr);
484         sin_expected.sin_port = htons(2343);
485
486         ast_security_event_report(AST_SEC_EVT(&unexpected_addr));
487 }
488
489 static void evt_gen_chal_resp_failed(void)
490 {
491         struct sockaddr_in sin_local = {
492                 .sin_family = AF_INET
493         };
494         struct sockaddr_in sin_remote = {
495                 .sin_family = AF_INET
496         };
497         struct timeval session_tv = ast_tvnow();
498         struct ast_security_event_chal_resp_failed chal_resp_failed = {
499                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
500                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
501                 .common.service    = "TEST",
502                 .common.module     = AST_MODULE,
503                 .common.account_id = "SuperDuperUser",
504                 .common.session_id = "Session1231231231",
505                 .common.session_tv = &session_tv,
506                 .common.local_addr = {
507                         .sin  = &sin_local,
508                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
509                 },
510                 .common.remote_addr = {
511                         .sin = &sin_remote,
512                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
513                 },
514
515                 .challenge         = "8adf8a9sd8fas9df23ljk4",
516                 .response          = "9u3jlaksdjflakjsdfoi23",
517                 .expected_response = "oiafaljhadf9834luahk3k",
518         };
519
520         inet_aton("10.1.2.3", &sin_local.sin_addr);
521         sin_local.sin_port = htons(4321);
522
523         inet_aton("10.1.2.4", &sin_remote.sin_addr);
524         sin_remote.sin_port = htons(1234);
525
526         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
527 }
528
529 static void evt_gen_inval_password(void)
530 {
531         struct sockaddr_in sin_local = {
532                 .sin_family = AF_INET
533         };
534         struct sockaddr_in sin_remote = {
535                 .sin_family = AF_INET
536         };
537         struct timeval session_tv = ast_tvnow();
538         struct ast_security_event_inval_password inval_password = {
539                 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
540                 .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
541                 .common.service    = "TEST",
542                 .common.module     = AST_MODULE,
543                 .common.account_id = "AccountIDGoesHere",
544                 .common.session_id = "SessionIDGoesHere",
545                 .common.session_tv = &session_tv,
546                 .common.local_addr = {
547                         .sin  = &sin_local,
548                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
549                 },
550                 .common.remote_addr = {
551                         .sin = &sin_remote,
552                         .transport  = AST_SECURITY_EVENT_TRANSPORT_TCP,
553                 },
554         };
555
556         inet_aton("10.200.100.30", &sin_local.sin_addr);
557         sin_local.sin_port = htons(4321);
558
559         inet_aton("10.200.100.40", &sin_remote.sin_addr);
560         sin_remote.sin_port = htons(1234);
561
562         ast_security_event_report(AST_SEC_EVT(&inval_password));
563 }
564
565 static void gen_events(struct ast_cli_args *a)
566 {
567         unsigned int i;
568
569         ast_cli(a->fd, "Generating some security events ...\n");
570
571         for (i = 0; i < ARRAY_LEN(evt_generators); i++) {
572                 const char *event_type = ast_security_event_get_name(i);
573
574                 if (!evt_generators[i]) {
575                         ast_cli(a->fd, "*** No event generator for event type '%s' ***\n",
576                                         event_type);
577                         continue;
578                 }
579
580                 ast_cli(a->fd, "Generating a '%s' security event ...\n", event_type);
581
582                 evt_generators[i]();
583         }
584
585         ast_cli(a->fd, "Security event generation complete.\n");
586 }
587
588 static char *handle_cli_sec_evt_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
589 {
590         switch (cmd) {
591         case CLI_INIT:
592                 e->command = "securityevents test generation";
593                 e->usage = ""
594                         "Usage: securityevents test generation"
595                         "";
596                 return NULL;
597         case CLI_GENERATE:
598                 return NULL;
599         case CLI_HANDLER:
600                 gen_events(a);
601                 return CLI_SUCCESS;
602         }
603
604         return CLI_FAILURE;
605 }
606
607 static struct ast_cli_entry cli_sec_evt[] = {
608         AST_CLI_DEFINE(handle_cli_sec_evt_test, "Test security event generation"),
609 };
610
611 static int unload_module(void)
612 {
613         return ast_cli_unregister_multiple(cli_sec_evt, ARRAY_LEN(cli_sec_evt));
614 }
615
616 static int load_module(void)
617 {
618         int res;
619
620         res = ast_cli_register_multiple(cli_sec_evt, ARRAY_LEN(cli_sec_evt));
621
622         return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
623 }
624
625 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Test Security Event Generation");