Replace most uses of ast_register_atexit with ast_register_cleanup.
[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 /*** DOCUMENTATION
32         <managerEvent language="en_US" name="FailedACL">
33                 <managerEventInstance class="EVENT_FLAG_SECURITY">
34                         <synopsis>Raised when a request violates an ACL check.</synopsis>
35                         <syntax>
36                                 <parameter name="EventTV">
37                                         <para>The time the event was detected.</para>
38                                 </parameter>
39                                 <parameter name="Severity">
40                                         <para>A relative severity of the security event.</para>
41                                         <enumlist>
42                                                 <enum name="Informational"/>
43                                                 <enum name="Error"/>
44                                         </enumlist>
45                                 </parameter>
46                                 <parameter name="Service">
47                                         <para>The Asterisk service that raised the security event.</para>
48                                 </parameter>
49                                 <parameter name="EventVersion">
50                                         <para>The version of this event.</para>
51                                 </parameter>
52                                 <parameter name="AccountID">
53                                         <para>The Service account associated with the security event
54                                         notification.</para>
55                                 </parameter>
56                                 <parameter name="SessionID">
57                                         <para>A unique identifier for the session in the service
58                                         that raised the event.</para>
59                                 </parameter>
60                                 <parameter name="LocalAddress">
61                                         <para>The address of the Asterisk service that raised the
62                                         security event.</para>
63                                 </parameter>
64                                 <parameter name="RemoteAddress">
65                                         <para>The remote address of the entity that caused the
66                                         security event to be raised.</para>
67                                 </parameter>
68                                 <parameter name="Module" required="false">
69                                         <para>If available, the name of the module that raised the event.</para>
70                                 </parameter>
71                                 <parameter name="ACLName" required="false">
72                                         <para>If available, the name of the ACL that failed.</para>
73                                 </parameter>
74                                 <parameter name="SessionTV" required="false">
75                                         <para>The timestamp reported by the session.</para>
76                                 </parameter>
77                         </syntax>
78                 </managerEventInstance>
79         </managerEvent>
80         <managerEvent language="en_US" name="InvalidAccountID">
81                 <managerEventInstance class="EVENT_FLAG_SECURITY">
82                         <synopsis>Raised when a request fails an authentication check due to an invalid account ID.</synopsis>
83                         <syntax>
84                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
85                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
86                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
87                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
88                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
89                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
90                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
91                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
92                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
93                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
94                         </syntax>
95                 </managerEventInstance>
96         </managerEvent>
97         <managerEvent language="en_US" name="SessionLimit">
98                 <managerEventInstance class="EVENT_FLAG_SECURITY">
99                         <synopsis>Raised when a request fails due to exceeding the number of allowed concurrent sessions for that service.</synopsis>
100                         <syntax>
101                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
102                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
103                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
104                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
105                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
106                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
107                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
108                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
109                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
110                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
111                         </syntax>
112                 </managerEventInstance>
113         </managerEvent>
114         <managerEvent language="en_US" name="MemoryLimit">
115                 <managerEventInstance class="EVENT_FLAG_SECURITY">
116                         <synopsis>Raised when a request fails due to an internal memory allocation failure.</synopsis>
117                         <syntax>
118                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
119                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
120                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
121                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
122                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
123                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
124                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
125                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
126                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
127                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
128                         </syntax>
129                 </managerEventInstance>
130         </managerEvent>
131         <managerEvent language="en_US" name="LoadAverageLimit">
132                 <managerEventInstance class="EVENT_FLAG_SECURITY">
133                         <synopsis>Raised when a request fails because a configured load average limit has been reached.</synopsis>
134                         <syntax>
135                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
136                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
137                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
138                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
139                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
140                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
141                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
142                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
143                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
144                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
145                         </syntax>
146                 </managerEventInstance>
147         </managerEvent>
148         <managerEvent language="en_US" name="RequestNotSupported">
149                 <managerEventInstance class="EVENT_FLAG_SECURITY">
150                         <synopsis>Raised when a request fails due to some aspect of the requested item not being supported by the service.</synopsis>
151                         <syntax>
152                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
153                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
154                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
155                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
156                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
157                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
158                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
159                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
160                                 <parameter name="RequestType">
161                                         <para>The type of request attempted.</para>
162                                 </parameter>
163                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
164                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
165                         </syntax>
166                 </managerEventInstance>
167         </managerEvent>
168         <managerEvent language="en_US" name="RequestNotAllowed">
169                 <managerEventInstance class="EVENT_FLAG_SECURITY">
170                         <synopsis>Raised when a request is not allowed by the service.</synopsis>
171                         <syntax>
172                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
173                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
174                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
175                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
176                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
177                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
178                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
179                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
180                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RequestNotSupported']/managerEventInstance/syntax/parameter[@name='RequestType'])" />
181                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
182                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
183                                 <parameter name="RequestParams" required="false">
184                                         <para>Parameters provided to the rejected request.</para>
185                                 </parameter>
186                         </syntax>
187                 </managerEventInstance>
188         </managerEvent>
189         <managerEvent language="en_US" name="AuthMethodNotAllowed">
190                 <managerEventInstance class="EVENT_FLAG_SECURITY">
191                         <synopsis>Raised when a request used an authentication method not allowed by the service.</synopsis>
192                         <syntax>
193                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
194                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
195                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
196                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
197                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
198                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
199                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
200                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
201                                 <parameter name="AuthMethod">
202                                         <para>The authentication method attempted.</para>
203                                 </parameter>
204                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
205                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
206                         </syntax>
207                 </managerEventInstance>
208         </managerEvent>
209         <managerEvent language="en_US" name="RequestBadFormat">
210                 <managerEventInstance class="EVENT_FLAG_SECURITY">
211                         <synopsis>Raised when a request is received with bad formatting.</synopsis>
212                         <syntax>
213                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
214                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
215                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
216                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
217                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
218                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
219                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
220                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
221                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RequestNotSupported']/managerEventInstance/syntax/parameter[@name='RequestType'])" />
222                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
223                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
224                                 <parameter name="AccountID" required="false">
225                                         <para>The account ID associated with the rejected request.</para>
226                                 </parameter>
227                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='RequestNotAllowed']/managerEventInstance/syntax/parameter[@name='RequestParams'])" />
228                         </syntax>
229                 </managerEventInstance>
230         </managerEvent>
231         <managerEvent language="en_US" name="SuccessfulAuth">
232                 <managerEventInstance class="EVENT_FLAG_SECURITY">
233                         <synopsis>Raised when a request successfully authenticates with a service.</synopsis>
234                         <syntax>
235                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
236                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
237                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
238                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
239                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
240                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
241                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
242                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
243                                 <parameter name="UsingPassword">
244                                         <para>Whether or not the authentication attempt included a password.</para>
245                                 </parameter>
246                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
247                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
248                         </syntax>
249                 </managerEventInstance>
250         </managerEvent>
251         <managerEvent language="en_US" name="UnexpectedAddress">
252                 <managerEventInstance class="EVENT_FLAG_SECURITY">
253                         <synopsis>Raised when a request has a different source address then what is expected for a session already in progress with a service.</synopsis>
254                         <syntax>
255                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
256                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
257                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
258                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
259                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
260                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
261                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
262                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
263                                 <parameter name="ExpectedAddress">
264                                         <para>The address that the request was expected to use.</para>
265                                 </parameter>
266                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
267                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
268                         </syntax>
269                 </managerEventInstance>
270         </managerEvent>
271         <managerEvent language="en_US" name="ChallengeResponseFailed">
272                 <managerEventInstance class="EVENT_FLAG_SECURITY">
273                         <synopsis>Raised when a request's attempt to authenticate has been challenged, and the request failed the authentication challenge.</synopsis>
274                         <syntax>
275                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
276                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
277                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
278                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
279                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
280                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
281                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
282                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
283                                 <parameter name="Challenge">
284                                         <para>The challenge that was sent.</para>
285                                 </parameter>
286                                 <parameter name="Response">
287                                         <para>The response that was received.</para>
288                                 </parameter>
289                                 <parameter name="ExpectedResponse">
290                                         <para>The expected response to the challenge.</para>
291                                 </parameter>
292                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
293                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
294                         </syntax>
295                 </managerEventInstance>
296         </managerEvent>
297         <managerEvent language="en_US" name="InvalidPassword">
298                 <managerEventInstance class="EVENT_FLAG_SECURITY">
299                         <synopsis>Raised when a request provides an invalid password during an authentication attempt.</synopsis>
300                         <syntax>
301                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
302                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
303                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
304                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
305                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
306                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
307                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
308                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
309                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
310                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
311                                 <parameter name="Challenge" required="false">
312                                         <para>The challenge that was sent.</para>
313                                 </parameter>
314                                 <parameter name="ReceivedChallenge" required="false">
315                                         <para>The challenge that was received.</para>
316                                 </parameter>
317                                 <parameter name="RecievedHash" required="false">
318                                         <para>The hash that was received.</para>
319                                 </parameter>
320                         </syntax>
321                 </managerEventInstance>
322         </managerEvent>
323         <managerEvent language="en_US" name="ChallengeSent">
324                 <managerEventInstance class="EVENT_FLAG_SECURITY">
325                         <synopsis>Raised when an Asterisk service sends an authentication challenge to a request.</synopsis>
326                         <syntax>
327                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
328                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
329                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
330                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
331                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
332                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
333                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
334                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
335                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='ChallengeResponseFailed']/managerEventInstance/syntax/parameter[@name='Challenge'])" />
336                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
337                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
338                         </syntax>
339                 </managerEventInstance>
340         </managerEvent>
341         <managerEvent language="en_US" name="InvalidTransport">
342                 <managerEventInstance class="EVENT_FLAG_SECURITY">
343                         <synopsis>Raised when a request attempts to use a transport not allowed by the Asterisk service.</synopsis>
344                         <syntax>
345                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventTV'])" />
346                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Severity'])" />
347                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Service'])" />
348                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='EventVersion'])" />
349                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='AccountID'])" />
350                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionID'])" />
351                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='LocalAddress'])" />
352                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='RemoteAddress'])" />
353                                 <parameter name="AttemptedTransport">
354                                         <para>The transport type that the request attempted to use.</para>
355                                 </parameter>
356                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='Module'])" />
357                                 <xi:include xpointer="xpointer(/docs/managerEvent[@name='FailedACL']/managerEventInstance/syntax/parameter[@name='SessionTV'])" />
358                         </syntax>
359                 </managerEventInstance>
360         </managerEvent>
361  ***/
362
363 #include "asterisk.h"
364
365 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
366
367 #include "asterisk/utils.h"
368 #include "asterisk/strings.h"
369 #include "asterisk/network.h"
370 #include "asterisk/event.h"
371 #include "asterisk/security_events.h"
372 #include "asterisk/netsock2.h"
373 #include "asterisk/stasis.h"
374 #include "asterisk/json.h"
375 #include "asterisk/astobj2.h"
376
377 static const size_t TIMESTAMP_STR_LEN = 32;
378 static const size_t SECURITY_EVENT_BUF_INIT_LEN = 256;
379
380 /*! \brief Security Topic */
381 static struct stasis_topic *security_topic;
382
383 struct stasis_topic *ast_security_topic(void)
384 {
385         return security_topic;
386 }
387
388 static int append_event_str_single(struct ast_str **str, struct ast_json *json,
389                 const enum ast_event_ie_type ie_type)
390 {
391         const char *ie_type_key = ast_event_get_ie_type_name(ie_type);
392         struct ast_json *json_string = ast_json_object_get(json, ie_type_key);
393
394         if (!json_string) {
395                 return 0;
396         }
397
398         if (ast_str_append(str, 0, "%s: %s\r\n", ie_type_key, S_OR(ast_json_string_get(json_string), "")) == -1) {
399                 return -1;
400         }
401
402         return 0;
403 }
404
405 static int append_event_str_from_json(struct ast_str **str, struct ast_json *json,
406                 const struct ast_security_event_ie_type *ies)
407 {
408         unsigned int i;
409
410         if (!ies) {
411                 return 0;
412         }
413
414         for (i = 0; ies[i].ie_type != AST_EVENT_IE_END; i++) {
415                 if (append_event_str_single(str, json, ies[i].ie_type)) {
416                         return -1;
417                 }
418         }
419
420         return 0;
421 }
422
423 static struct ast_manager_event_blob *security_event_to_ami_blob(struct ast_json *json)
424 {
425         RAII_VAR(struct ast_str *, str, NULL, ast_free);
426         struct ast_json *event_type_json;
427         enum ast_security_event_type event_type;
428
429         event_type_json = ast_json_object_get(json, "SecurityEvent");
430         event_type = ast_json_integer_get(event_type_json);
431
432         ast_assert(event_type >= 0 && event_type < AST_SECURITY_EVENT_NUM_TYPES);
433
434         if (!(str = ast_str_create(SECURITY_EVENT_BUF_INIT_LEN))) {
435                 return NULL;
436         }
437
438         if (append_event_str_from_json(&str, json,
439                         ast_security_event_get_required_ies(event_type))) {
440                 ast_log(AST_LOG_ERROR, "Failed to issue a security event to AMI: "
441                         "error occurred when adding required event fields.\n");
442                 return NULL;
443         }
444
445         if (append_event_str_from_json(&str, json,
446                         ast_security_event_get_optional_ies(event_type))) {
447                 ast_log(AST_LOG_ERROR, "Failed to issue a security event to AMI: "
448                         "error occurred when adding optional event fields.\n");
449                 return NULL;
450         }
451
452         return ast_manager_event_blob_create(EVENT_FLAG_SECURITY,
453                 ast_security_event_get_name(event_type),
454                 "%s",
455                 ast_str_buffer(str));
456 }
457
458 static struct ast_manager_event_blob *security_event_to_ami(struct stasis_message *message)
459 {
460         struct ast_json_payload *payload = stasis_message_data(message);
461
462         if (stasis_message_type(message) != ast_security_event_type()) {
463                 return NULL;
464         }
465
466         if (!payload) {
467                 return NULL;
468         }
469
470         return security_event_to_ami_blob(payload->json);
471 }
472
473 /*! \brief Message type for security events */
474 STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type,
475         .to_ami = security_event_to_ami,
476         );
477
478 static void security_stasis_cleanup(void)
479 {
480         ao2_cleanup(security_topic);
481         security_topic = NULL;
482
483         STASIS_MESSAGE_TYPE_CLEANUP(ast_security_event_type);
484 }
485
486 int ast_security_stasis_init(void)
487 {
488         ast_register_cleanup(security_stasis_cleanup);
489
490         security_topic = stasis_topic_create("ast_security");
491         if (!security_topic) {
492                 return -1;
493         }
494
495         if (STASIS_MESSAGE_TYPE_INIT(ast_security_event_type)) {
496                 return -1;
497         }
498
499
500         return 0;
501 }
502
503 static const struct {
504         const char *name;
505         uint32_t version;
506         enum ast_security_event_severity severity;
507 #define MAX_SECURITY_IES 12
508         struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
509         struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
510 #undef MAX_SECURITY_IES
511 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
512
513 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
514
515 [AST_SECURITY_EVENT_FAILED_ACL] = {
516         .name     = "FailedACL",
517         .version  = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
518         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
519         .required_ies = {
520                 { AST_EVENT_IE_EVENT_TV, 0 },
521                 { AST_EVENT_IE_SEVERITY, 0 },
522                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
523                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
524                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
525                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
526                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
527                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
528                 { AST_EVENT_IE_END, 0 }
529         },
530         .optional_ies = {
531                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
532                 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
533                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
534                 { AST_EVENT_IE_END, 0 }
535         },
536 },
537
538 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
539         .name     = "InvalidAccountID",
540         .version  = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
541         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
542         .required_ies = {
543                 { AST_EVENT_IE_EVENT_TV, 0 },
544                 { AST_EVENT_IE_SEVERITY, 0 },
545                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
546                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
547                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
548                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
549                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
550                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
551                 { AST_EVENT_IE_END, 0 }
552         },
553         .optional_ies = {
554                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
555                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
556                 { AST_EVENT_IE_END, 0 }
557         },
558 },
559
560 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
561         .name     = "SessionLimit",
562         .version  = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
563         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
564         .required_ies = {
565                 { AST_EVENT_IE_EVENT_TV, 0 },
566                 { AST_EVENT_IE_SEVERITY, 0 },
567                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
568                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
569                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
570                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
571                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
572                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
573                 { AST_EVENT_IE_END, 0 }
574         },
575         .optional_ies = {
576                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
577                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
578                 { AST_EVENT_IE_END, 0 }
579         },
580 },
581
582 [AST_SECURITY_EVENT_MEM_LIMIT] = {
583         .name     = "MemoryLimit",
584         .version  = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
585         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
586         .required_ies = {
587                 { AST_EVENT_IE_EVENT_TV, 0 },
588                 { AST_EVENT_IE_SEVERITY, 0 },
589                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
590                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
591                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
592                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
593                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
594                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
595                 { AST_EVENT_IE_END, 0 }
596         },
597         .optional_ies = {
598                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
599                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
600                 { AST_EVENT_IE_END, 0 }
601         },
602 },
603
604 [AST_SECURITY_EVENT_LOAD_AVG] = {
605         .name     = "LoadAverageLimit",
606         .version  = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
607         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
608         .required_ies = {
609                 { AST_EVENT_IE_EVENT_TV, 0 },
610                 { AST_EVENT_IE_SEVERITY, 0 },
611                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
612                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
613                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
614                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
615                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
616                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
617                 { AST_EVENT_IE_END, 0 }
618         },
619         .optional_ies = {
620                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
621                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
622                 { AST_EVENT_IE_END, 0 }
623         },
624 },
625
626 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
627         .name     = "RequestNotSupported",
628         .version  = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
629         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
630         .required_ies = {
631                 { AST_EVENT_IE_EVENT_TV, 0 },
632                 { AST_EVENT_IE_SEVERITY, 0 },
633                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
634                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
635                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
636                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
637                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
638                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
639                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
640                 { AST_EVENT_IE_END, 0 }
641         },
642         .optional_ies = {
643                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
644                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
645                 { AST_EVENT_IE_END, 0 }
646         },
647 },
648
649 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
650         .name     = "RequestNotAllowed",
651         .version  = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
652         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
653         .required_ies = {
654                 { AST_EVENT_IE_EVENT_TV, 0 },
655                 { AST_EVENT_IE_SEVERITY, 0 },
656                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
657                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
658                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
659                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
660                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
661                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
662                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
663                 { AST_EVENT_IE_END, 0 }
664         },
665         .optional_ies = {
666                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
667                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
668                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
669                 { AST_EVENT_IE_END, 0 }
670         },
671 },
672
673 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
674         .name     = "AuthMethodNotAllowed",
675         .version  = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
676         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
677         .required_ies = {
678                 { AST_EVENT_IE_EVENT_TV, 0 },
679                 { AST_EVENT_IE_SEVERITY, 0 },
680                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
681                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
682                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
683                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
684                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
685                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
686                 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
687                 { AST_EVENT_IE_END, 0 }
688         },
689         .optional_ies = {
690                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
691                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
692                 { AST_EVENT_IE_END, 0 }
693         },
694 },
695
696 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
697         .name     = "RequestBadFormat",
698         .version  = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
699         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
700         .required_ies = {
701                 { AST_EVENT_IE_EVENT_TV, 0 },
702                 { AST_EVENT_IE_SEVERITY, 0 },
703                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
704                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
705                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
706                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
707                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
708                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
709                 { AST_EVENT_IE_END, 0 }
710         },
711         .optional_ies = {
712                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
713                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
714                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
715                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
716                 { AST_EVENT_IE_END, 0 }
717         },
718 },
719
720 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
721         .name     = "SuccessfulAuth",
722         .version  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
723         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
724         .required_ies = {
725                 { AST_EVENT_IE_EVENT_TV, 0 },
726                 { AST_EVENT_IE_SEVERITY, 0 },
727                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
728                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
729                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
730                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
731                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
732                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
733                 { AST_EVENT_IE_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
734                 { AST_EVENT_IE_END, 0 }
735         },
736         .optional_ies = {
737                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
738                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
739                 { AST_EVENT_IE_END, 0 }
740         },
741 },
742
743 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
744         .name     = "UnexpectedAddress",
745         .version  = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
746         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
747         .required_ies = {
748                 { AST_EVENT_IE_EVENT_TV, 0 },
749                 { AST_EVENT_IE_SEVERITY, 0 },
750                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
751                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
752                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
753                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
754                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
755                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
756                 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
757                 { AST_EVENT_IE_END, 0 }
758         },
759         .optional_ies = {
760                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
761                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
762                 { AST_EVENT_IE_END, 0 }
763         },
764 },
765
766 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
767         .name     = "ChallengeResponseFailed",
768         .version  = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
769         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
770         .required_ies = {
771                 { AST_EVENT_IE_EVENT_TV, 0 },
772                 { AST_EVENT_IE_SEVERITY, 0 },
773                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
774                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
775                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
776                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
777                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
778                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
779                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
780                 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
781                 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
782                 { AST_EVENT_IE_END, 0 }
783         },
784         .optional_ies = {
785                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
786                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
787                 { AST_EVENT_IE_END, 0 }
788         },
789 },
790
791 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
792         .name     = "InvalidPassword",
793         .version  = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
794         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
795         .required_ies = {
796                 { AST_EVENT_IE_EVENT_TV, 0 },
797                 { AST_EVENT_IE_SEVERITY, 0 },
798                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
799                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
800                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
801                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
802                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
803                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
804                 { AST_EVENT_IE_END, 0 }
805         },
806         .optional_ies = {
807                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
808                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
809                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
810                 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
811                 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
812                 { AST_EVENT_IE_END, 0 }
813         },
814 },
815
816 [AST_SECURITY_EVENT_CHAL_SENT] = {
817         .name     = "ChallengeSent",
818         .version  = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
819         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
820         .required_ies = {
821                 { AST_EVENT_IE_EVENT_TV, 0 },
822                 { AST_EVENT_IE_SEVERITY, 0 },
823                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
824                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
825                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
826                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
827                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
828                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
829                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
830                 { AST_EVENT_IE_END, 0 }
831         },
832         .optional_ies = {
833                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
834                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
835                 { AST_EVENT_IE_END, 0 }
836         },
837 },
838
839 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
840         .name     = "InvalidTransport",
841         .version  = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
842         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
843         .required_ies = {
844                 { AST_EVENT_IE_EVENT_TV, 0 },
845                 { AST_EVENT_IE_SEVERITY, 0 },
846                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
847                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
848                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
849                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
850                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
851                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
852                 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
853                 { AST_EVENT_IE_END, 0 }
854         },
855         .optional_ies = {
856                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
857                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
858                 { AST_EVENT_IE_END, 0 }
859         },
860 },
861
862 #undef SEC_EVT_FIELD
863
864 };
865
866 static const struct {
867         enum ast_security_event_severity severity;
868         const char *str;
869 } severities[] = {
870         { AST_SECURITY_EVENT_SEVERITY_INFO,  "Informational" },
871         { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
872 };
873
874 const char *ast_security_event_severity_get_name(
875                 const enum ast_security_event_severity severity)
876 {
877         unsigned int i;
878
879         for (i = 0; i < ARRAY_LEN(severities); i++) {
880                 if (severities[i].severity == severity) {
881                         return severities[i].str;
882                 }
883         }
884
885         return NULL;
886 }
887
888 static int check_event_type(const enum ast_security_event_type event_type)
889 {
890         if (event_type < 0 || event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
891                 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
892                 return -1;
893         }
894
895         return 0;
896 }
897
898 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
899 {
900         if (check_event_type(event_type)) {
901                 return NULL;
902         }
903
904         return sec_events[event_type].name;
905 }
906
907 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
908                 const enum ast_security_event_type event_type)
909 {
910         if (check_event_type(event_type)) {
911                 return NULL;
912         }
913
914         return sec_events[event_type].required_ies;
915 }
916
917 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
918                 const enum ast_security_event_type event_type)
919 {
920         if (check_event_type(event_type)) {
921                 return NULL;
922         }
923
924         return sec_events[event_type].optional_ies;
925 }
926
927 static int add_ip_json_object(struct ast_json *json, enum ast_event_ie_type ie_type,
928                 const struct ast_security_event_ip_addr *addr)
929 {
930         struct ast_json *json_ip;
931
932         json_ip = ast_json_ipaddr(addr->addr, addr->transport);
933         if (!json_ip) {
934                 return -1;
935         }
936
937         return ast_json_object_set(json, ast_event_get_ie_type_name(ie_type), json_ip);
938 }
939
940 enum ie_required {
941         NOT_REQUIRED,
942         REQUIRED
943 };
944
945 static int add_json_object(struct ast_json *json, const struct ast_security_event_common *sec,
946                 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
947 {
948         int res = 0;
949
950         switch (ie_type->ie_type) {
951         case AST_EVENT_IE_SERVICE:
952         case AST_EVENT_IE_ACCOUNT_ID:
953         case AST_EVENT_IE_SESSION_ID:
954         case AST_EVENT_IE_MODULE:
955         case AST_EVENT_IE_ACL_NAME:
956         case AST_EVENT_IE_REQUEST_TYPE:
957         case AST_EVENT_IE_REQUEST_PARAMS:
958         case AST_EVENT_IE_AUTH_METHOD:
959         case AST_EVENT_IE_CHALLENGE:
960         case AST_EVENT_IE_RESPONSE:
961         case AST_EVENT_IE_EXPECTED_RESPONSE:
962         case AST_EVENT_IE_RECEIVED_CHALLENGE:
963         case AST_EVENT_IE_RECEIVED_HASH:
964         case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
965         {
966                 const char *str;
967                 struct ast_json *json_string;
968
969                 str = *((const char **)(((const char *) sec) + ie_type->offset));
970
971                 if (req && !str) {
972                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
973                                         "type '%u' (%s) not present\n", ie_type->ie_type,
974                                         ast_event_get_ie_type_name(ie_type->ie_type),
975                                         sec->event_type, ast_security_event_get_name(sec->event_type));
976                         res = -1;
977                         break;
978                 }
979
980                 if (!str) {
981                         break;
982                 }
983
984                 json_string = ast_json_string_create(str);
985                 if (!json_string) {
986                         res = -1;
987                         break;
988                 }
989
990                 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
991                 break;
992         }
993         case AST_EVENT_IE_EVENT_VERSION:
994         case AST_EVENT_IE_USING_PASSWORD:
995         {
996                 struct ast_json *json_string;
997                 uint32_t val;
998                 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
999
1000                 json_string = ast_json_stringf("%u", val);
1001                 if (!json_string) {
1002                         res = -1;
1003                         break;
1004                 }
1005
1006                 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
1007                 break;
1008         }
1009         case AST_EVENT_IE_LOCAL_ADDR:
1010         case AST_EVENT_IE_REMOTE_ADDR:
1011         case AST_EVENT_IE_EXPECTED_ADDR:
1012         {
1013                 const struct ast_security_event_ip_addr *addr;
1014
1015                 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
1016
1017                 if (req && !addr->addr) {
1018                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
1019                                         "type '%u' (%s) not present\n", ie_type->ie_type,
1020                                         ast_event_get_ie_type_name(ie_type->ie_type),
1021                                         sec->event_type, ast_security_event_get_name(sec->event_type));
1022                         res = -1;
1023                 }
1024
1025                 if (addr->addr) {
1026                         res = add_ip_json_object(json, ie_type->ie_type, addr);
1027                 }
1028
1029                 break;
1030         }
1031         case AST_EVENT_IE_SESSION_TV:
1032         {
1033                 const struct timeval *tval;
1034
1035                 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
1036
1037                 if (req && !tval) {
1038                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
1039                                         "type '%u' (%s) not present\n", ie_type->ie_type,
1040                                         ast_event_get_ie_type_name(ie_type->ie_type),
1041                                         sec->event_type, ast_security_event_get_name(sec->event_type));
1042                         res = -1;
1043                 }
1044
1045                 if (tval) {
1046                         struct ast_json *json_tval = ast_json_timeval(*tval, NULL);
1047                         if (!json_tval) {
1048                                 res = -1;
1049                                 break;
1050                         }
1051                         res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_tval);
1052                 }
1053
1054                 break;
1055         }
1056         case AST_EVENT_IE_EVENT_TV:
1057         case AST_EVENT_IE_SEVERITY:
1058                 /* Added automatically, nothing to do here. */
1059                 break;
1060         default:
1061                 ast_log(LOG_WARNING, "Unhandled IE type '%d' (%s), this security event "
1062                                 "will be missing data.\n", ie_type->ie_type,
1063                                 ast_event_get_ie_type_name(ie_type->ie_type));
1064                 break;
1065         }
1066
1067         return res;
1068 }
1069
1070 static struct ast_json *alloc_security_event_json_object(const struct ast_security_event_common *sec)
1071 {
1072         struct timeval tv = ast_tvnow();
1073         const char *severity_str;
1074         struct ast_json *json_temp;
1075         RAII_VAR(struct ast_json *, json_object, ast_json_object_create(), ast_json_unref);
1076
1077         if (!json_object) {
1078                 return NULL;
1079         }
1080
1081         /* NOTE: Every time ast_json_object_set is used, json_temp becomes a stale pointer since the reference is taken.
1082          *       This is true even if ast_json_object_set fails.
1083          */
1084
1085         json_temp = ast_json_integer_create(sec->event_type);
1086         if (!json_temp || ast_json_object_set(json_object, "SecurityEvent", json_temp)) {
1087                 return NULL;
1088         }
1089
1090         json_temp = ast_json_stringf("%u", sec->version);
1091         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_VERSION), json_temp)) {
1092                 return NULL;
1093         }
1094
1095         /* AST_EVENT_IE_EVENT_TV */
1096         json_temp  = ast_json_timeval(tv, NULL);
1097         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_TV), json_temp)) {
1098                 return NULL;
1099         }
1100
1101         /* AST_EVENT_IE_SERVICE */
1102         json_temp = ast_json_string_create(sec->service);
1103         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SERVICE), json_temp)) {
1104                 return NULL;
1105         }
1106
1107         /* AST_EVENT_IE_SEVERITY */
1108         severity_str = S_OR(
1109                 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
1110                 "Unknown"
1111         );
1112
1113         json_temp = ast_json_string_create(severity_str);
1114         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SEVERITY), json_temp)) {
1115                 return NULL;
1116         }
1117
1118         return ast_json_ref(json_object);
1119 }
1120
1121 static int handle_security_event(const struct ast_security_event_common *sec)
1122 {
1123         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1124         RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
1125         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1126
1127         const struct ast_security_event_ie_type *ies;
1128         unsigned int i;
1129
1130         if (!ast_security_event_type()) {
1131                 return -1;
1132         }
1133
1134         json_object = alloc_security_event_json_object(sec);
1135         if (!json_object) {
1136                 return -1;
1137         }
1138
1139         for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
1140                         ies[i].ie_type != AST_EVENT_IE_END;
1141                         i++) {
1142                 if (add_json_object(json_object, sec, ies + i, REQUIRED)) {
1143                         goto return_error;
1144                 }
1145         }
1146
1147         for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
1148                         ies[i].ie_type != AST_EVENT_IE_END;
1149                         i++) {
1150                 if (add_json_object(json_object, sec, ies + i, NOT_REQUIRED)) {
1151                         goto return_error;
1152                 }
1153         }
1154
1155         /* The json blob is ready.  Throw it in the payload and send it out over stasis. */
1156         if (!(json_payload = ast_json_payload_create(json_object))) {
1157                 goto return_error;
1158         }
1159
1160         msg = stasis_message_create(ast_security_event_type(), json_payload);
1161
1162         if (!msg) {
1163                 goto return_error;
1164         }
1165
1166         stasis_publish(ast_security_topic(), msg);
1167
1168         return 0;
1169
1170 return_error:
1171         return -1;
1172 }
1173
1174 int ast_security_event_report(const struct ast_security_event_common *sec)
1175 {
1176         if (sec->event_type < 0 || sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
1177                 ast_log(LOG_ERROR, "Invalid security event type\n");
1178                 return -1;
1179         }
1180
1181         if (!sec_events[sec->event_type].name) {
1182                 ast_log(LOG_WARNING, "Security event type %u not handled\n",
1183                                 sec->event_type);
1184                 return -1;
1185         }
1186
1187         if (sec->version != sec_events[sec->event_type].version) {
1188                 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
1189                                 sec->event_type);
1190                 return -1;
1191         }
1192
1193         if (handle_security_event(sec)) {
1194                 ast_log(LOG_ERROR, "Failed to issue security event of type %s.\n",
1195                                 ast_security_event_get_name(sec->event_type));
1196         }
1197
1198         return 0;
1199 }
1200
1201