ast_json_pack(): Use safer json ref mechanism.
[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 #include "asterisk/utils.h"
366 #include "asterisk/strings.h"
367 #include "asterisk/network.h"
368 #include "asterisk/event.h"
369 #include "asterisk/security_events.h"
370 #include "asterisk/netsock2.h"
371 #include "asterisk/stasis.h"
372 #include "asterisk/json.h"
373 #include "asterisk/astobj2.h"
374
375 static const size_t SECURITY_EVENT_BUF_INIT_LEN = 256;
376
377 /*! \brief Security Topic */
378 static struct stasis_topic *security_topic;
379
380 struct stasis_topic *ast_security_topic(void)
381 {
382         return security_topic;
383 }
384
385 static int append_event_str_single(struct ast_str **str, struct ast_json *json,
386                 const enum ast_event_ie_type ie_type)
387 {
388         const char *ie_type_key = ast_event_get_ie_type_name(ie_type);
389         struct ast_json *json_string = ast_json_object_get(json, ie_type_key);
390
391         if (!json_string) {
392                 return 0;
393         }
394
395         if (ast_str_append(str, 0, "%s: %s\r\n", ie_type_key, S_OR(ast_json_string_get(json_string), "")) == -1) {
396                 return -1;
397         }
398
399         return 0;
400 }
401
402 static int append_event_str_from_json(struct ast_str **str, struct ast_json *json,
403                 const struct ast_security_event_ie_type *ies)
404 {
405         unsigned int i;
406
407         if (!ies) {
408                 return 0;
409         }
410
411         for (i = 0; ies[i].ie_type != AST_EVENT_IE_END; i++) {
412                 if (append_event_str_single(str, json, ies[i].ie_type)) {
413                         return -1;
414                 }
415         }
416
417         return 0;
418 }
419
420 static struct ast_manager_event_blob *security_event_to_ami_blob(struct ast_json *json)
421 {
422         RAII_VAR(struct ast_str *, str, NULL, ast_free);
423         struct ast_json *event_type_json;
424         enum ast_security_event_type event_type;
425
426         event_type_json = ast_json_object_get(json, "SecurityEvent");
427         event_type = ast_json_integer_get(event_type_json);
428
429         ast_assert((unsigned int)event_type < AST_SECURITY_EVENT_NUM_TYPES);
430
431         if (!(str = ast_str_create(SECURITY_EVENT_BUF_INIT_LEN))) {
432                 return NULL;
433         }
434
435         if (append_event_str_from_json(&str, json,
436                         ast_security_event_get_required_ies(event_type))) {
437                 ast_log(AST_LOG_ERROR, "Failed to issue a security event to AMI: "
438                         "error occurred when adding required event fields.\n");
439                 return NULL;
440         }
441
442         if (append_event_str_from_json(&str, json,
443                         ast_security_event_get_optional_ies(event_type))) {
444                 ast_log(AST_LOG_ERROR, "Failed to issue a security event to AMI: "
445                         "error occurred when adding optional event fields.\n");
446                 return NULL;
447         }
448
449         return ast_manager_event_blob_create(EVENT_FLAG_SECURITY,
450                 ast_security_event_get_name(event_type),
451                 "%s",
452                 ast_str_buffer(str));
453 }
454
455 static struct ast_manager_event_blob *security_event_to_ami(struct stasis_message *message)
456 {
457         struct ast_json_payload *payload = stasis_message_data(message);
458
459         if (stasis_message_type(message) != ast_security_event_type()) {
460                 return NULL;
461         }
462
463         if (!payload) {
464                 return NULL;
465         }
466
467         return security_event_to_ami_blob(payload->json);
468 }
469
470 /*! \brief Message type for security events */
471 STASIS_MESSAGE_TYPE_DEFN(ast_security_event_type,
472         .to_ami = security_event_to_ami,
473         );
474
475 static void security_stasis_cleanup(void)
476 {
477         ao2_cleanup(security_topic);
478         security_topic = NULL;
479
480         STASIS_MESSAGE_TYPE_CLEANUP(ast_security_event_type);
481 }
482
483 int ast_security_stasis_init(void)
484 {
485         ast_register_cleanup(security_stasis_cleanup);
486
487         security_topic = stasis_topic_create("ast_security");
488         if (!security_topic) {
489                 return -1;
490         }
491
492         if (STASIS_MESSAGE_TYPE_INIT(ast_security_event_type)) {
493                 return -1;
494         }
495
496
497         return 0;
498 }
499
500 static const struct {
501         const char *name;
502         uint32_t version;
503         enum ast_security_event_severity severity;
504 #define MAX_SECURITY_IES 12
505         struct ast_security_event_ie_type required_ies[MAX_SECURITY_IES];
506         struct ast_security_event_ie_type optional_ies[MAX_SECURITY_IES];
507 #undef MAX_SECURITY_IES
508 } sec_events[AST_SECURITY_EVENT_NUM_TYPES] = {
509
510 #define SEC_EVT_FIELD(e, field) (offsetof(struct ast_security_event_##e, field))
511
512 [AST_SECURITY_EVENT_FAILED_ACL] = {
513         .name     = "FailedACL",
514         .version  = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
515         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
516         .required_ies = {
517                 { AST_EVENT_IE_EVENT_TV, 0 },
518                 { AST_EVENT_IE_SEVERITY, 0 },
519                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
520                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
521                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
522                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
523                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
524                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
525                 { AST_EVENT_IE_END, 0 }
526         },
527         .optional_ies = {
528                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
529                 { AST_EVENT_IE_ACL_NAME, SEC_EVT_FIELD(failed_acl, acl_name) },
530                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
531                 { AST_EVENT_IE_END, 0 }
532         },
533 },
534
535 [AST_SECURITY_EVENT_INVAL_ACCT_ID] = {
536         .name     = "InvalidAccountID",
537         .version  = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
538         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
539         .required_ies = {
540                 { AST_EVENT_IE_EVENT_TV, 0 },
541                 { AST_EVENT_IE_SEVERITY, 0 },
542                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
543                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
544                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
545                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
546                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
547                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
548                 { AST_EVENT_IE_END, 0 }
549         },
550         .optional_ies = {
551                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
552                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
553                 { AST_EVENT_IE_END, 0 }
554         },
555 },
556
557 [AST_SECURITY_EVENT_SESSION_LIMIT] = {
558         .name     = "SessionLimit",
559         .version  = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
560         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
561         .required_ies = {
562                 { AST_EVENT_IE_EVENT_TV, 0 },
563                 { AST_EVENT_IE_SEVERITY, 0 },
564                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
565                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
566                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
567                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
568                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
569                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
570                 { AST_EVENT_IE_END, 0 }
571         },
572         .optional_ies = {
573                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
574                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
575                 { AST_EVENT_IE_END, 0 }
576         },
577 },
578
579 [AST_SECURITY_EVENT_MEM_LIMIT] = {
580         .name     = "MemoryLimit",
581         .version  = AST_SECURITY_EVENT_MEM_LIMIT_VERSION,
582         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
583         .required_ies = {
584                 { AST_EVENT_IE_EVENT_TV, 0 },
585                 { AST_EVENT_IE_SEVERITY, 0 },
586                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
587                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
588                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
589                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
590                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
591                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
592                 { AST_EVENT_IE_END, 0 }
593         },
594         .optional_ies = {
595                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
596                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
597                 { AST_EVENT_IE_END, 0 }
598         },
599 },
600
601 [AST_SECURITY_EVENT_LOAD_AVG] = {
602         .name     = "LoadAverageLimit",
603         .version  = AST_SECURITY_EVENT_LOAD_AVG_VERSION,
604         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
605         .required_ies = {
606                 { AST_EVENT_IE_EVENT_TV, 0 },
607                 { AST_EVENT_IE_SEVERITY, 0 },
608                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
609                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
610                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
611                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
612                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
613                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
614                 { AST_EVENT_IE_END, 0 }
615         },
616         .optional_ies = {
617                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
618                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
619                 { AST_EVENT_IE_END, 0 }
620         },
621 },
622
623 [AST_SECURITY_EVENT_REQ_NO_SUPPORT] = {
624         .name     = "RequestNotSupported",
625         .version  = AST_SECURITY_EVENT_REQ_NO_SUPPORT_VERSION,
626         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
627         .required_ies = {
628                 { AST_EVENT_IE_EVENT_TV, 0 },
629                 { AST_EVENT_IE_SEVERITY, 0 },
630                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
631                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
632                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
633                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
634                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
635                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
636                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_no_support, request_type) },
637                 { AST_EVENT_IE_END, 0 }
638         },
639         .optional_ies = {
640                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
641                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
642                 { AST_EVENT_IE_END, 0 }
643         },
644 },
645
646 [AST_SECURITY_EVENT_REQ_NOT_ALLOWED] = {
647         .name     = "RequestNotAllowed",
648         .version  = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
649         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
650         .required_ies = {
651                 { AST_EVENT_IE_EVENT_TV, 0 },
652                 { AST_EVENT_IE_SEVERITY, 0 },
653                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
654                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
655                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
656                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
657                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
658                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
659                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_not_allowed, request_type) },
660                 { AST_EVENT_IE_END, 0 }
661         },
662         .optional_ies = {
663                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
664                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
665                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_not_allowed, request_params) },
666                 { AST_EVENT_IE_END, 0 }
667         },
668 },
669
670 [AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED] = {
671         .name     = "AuthMethodNotAllowed",
672         .version  = AST_SECURITY_EVENT_AUTH_METHOD_NOT_ALLOWED_VERSION,
673         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
674         .required_ies = {
675                 { AST_EVENT_IE_EVENT_TV, 0 },
676                 { AST_EVENT_IE_SEVERITY, 0 },
677                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
678                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
679                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
680                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
681                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
682                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
683                 { AST_EVENT_IE_AUTH_METHOD, SEC_EVT_FIELD(auth_method_not_allowed, auth_method) },
684                 { AST_EVENT_IE_END, 0 }
685         },
686         .optional_ies = {
687                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
688                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
689                 { AST_EVENT_IE_END, 0 }
690         },
691 },
692
693 [AST_SECURITY_EVENT_REQ_BAD_FORMAT] = {
694         .name     = "RequestBadFormat",
695         .version  = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
696         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
697         .required_ies = {
698                 { AST_EVENT_IE_EVENT_TV, 0 },
699                 { AST_EVENT_IE_SEVERITY, 0 },
700                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
701                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
702                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
703                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
704                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
705                 { AST_EVENT_IE_REQUEST_TYPE, SEC_EVT_FIELD(req_bad_format, request_type) },
706                 { AST_EVENT_IE_END, 0 }
707         },
708         .optional_ies = {
709                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
710                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
711                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
712                 { AST_EVENT_IE_REQUEST_PARAMS, SEC_EVT_FIELD(req_bad_format, request_params) },
713                 { AST_EVENT_IE_END, 0 }
714         },
715 },
716
717 [AST_SECURITY_EVENT_SUCCESSFUL_AUTH] = {
718         .name     = "SuccessfulAuth",
719         .version  = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
720         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
721         .required_ies = {
722                 { AST_EVENT_IE_EVENT_TV, 0 },
723                 { AST_EVENT_IE_SEVERITY, 0 },
724                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
725                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
726                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
727                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
728                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
729                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
730                 { AST_EVENT_IE_USING_PASSWORD, SEC_EVT_FIELD(successful_auth, using_password) },
731                 { AST_EVENT_IE_END, 0 }
732         },
733         .optional_ies = {
734                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
735                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
736                 { AST_EVENT_IE_END, 0 }
737         },
738 },
739
740 [AST_SECURITY_EVENT_UNEXPECTED_ADDR] = {
741         .name     = "UnexpectedAddress",
742         .version  = AST_SECURITY_EVENT_UNEXPECTED_ADDR_VERSION,
743         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
744         .required_ies = {
745                 { AST_EVENT_IE_EVENT_TV, 0 },
746                 { AST_EVENT_IE_SEVERITY, 0 },
747                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
748                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
749                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
750                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
751                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
752                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
753                 { AST_EVENT_IE_EXPECTED_ADDR, SEC_EVT_FIELD(unexpected_addr, expected_addr) },
754                 { AST_EVENT_IE_END, 0 }
755         },
756         .optional_ies = {
757                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
758                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
759                 { AST_EVENT_IE_END, 0 }
760         },
761 },
762
763 [AST_SECURITY_EVENT_CHAL_RESP_FAILED] = {
764         .name     = "ChallengeResponseFailed",
765         .version  = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
766         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
767         .required_ies = {
768                 { AST_EVENT_IE_EVENT_TV, 0 },
769                 { AST_EVENT_IE_SEVERITY, 0 },
770                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
771                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
772                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
773                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
774                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
775                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
776                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_resp_failed, challenge) },
777                 { AST_EVENT_IE_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, response) },
778                 { AST_EVENT_IE_EXPECTED_RESPONSE, SEC_EVT_FIELD(chal_resp_failed, expected_response) },
779                 { AST_EVENT_IE_END, 0 }
780         },
781         .optional_ies = {
782                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
783                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
784                 { AST_EVENT_IE_END, 0 }
785         },
786 },
787
788 [AST_SECURITY_EVENT_INVAL_PASSWORD] = {
789         .name     = "InvalidPassword",
790         .version  = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
791         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
792         .required_ies = {
793                 { AST_EVENT_IE_EVENT_TV, 0 },
794                 { AST_EVENT_IE_SEVERITY, 0 },
795                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
796                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
797                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
798                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
799                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
800                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
801                 { AST_EVENT_IE_END, 0 }
802         },
803         .optional_ies = {
804                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
805                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
806                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(inval_password, challenge) },
807                 { AST_EVENT_IE_RECEIVED_CHALLENGE, SEC_EVT_FIELD(inval_password, received_challenge) },
808                 { AST_EVENT_IE_RECEIVED_HASH, SEC_EVT_FIELD(inval_password, received_hash) },
809                 { AST_EVENT_IE_END, 0 }
810         },
811 },
812
813 [AST_SECURITY_EVENT_CHAL_SENT] = {
814         .name     = "ChallengeSent",
815         .version  = AST_SECURITY_EVENT_CHAL_SENT_VERSION,
816         .severity = AST_SECURITY_EVENT_SEVERITY_INFO,
817         .required_ies = {
818                 { AST_EVENT_IE_EVENT_TV, 0 },
819                 { AST_EVENT_IE_SEVERITY, 0 },
820                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
821                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
822                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
823                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
824                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
825                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
826                 { AST_EVENT_IE_CHALLENGE, SEC_EVT_FIELD(chal_sent, challenge) },
827                 { AST_EVENT_IE_END, 0 }
828         },
829         .optional_ies = {
830                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
831                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
832                 { AST_EVENT_IE_END, 0 }
833         },
834 },
835
836 [AST_SECURITY_EVENT_INVAL_TRANSPORT] = {
837         .name     = "InvalidTransport",
838         .version  = AST_SECURITY_EVENT_INVAL_TRANSPORT_VERSION,
839         .severity = AST_SECURITY_EVENT_SEVERITY_ERROR,
840         .required_ies = {
841                 { AST_EVENT_IE_EVENT_TV, 0 },
842                 { AST_EVENT_IE_SEVERITY, 0 },
843                 { AST_EVENT_IE_SERVICE, SEC_EVT_FIELD(common, service) },
844                 { AST_EVENT_IE_EVENT_VERSION, SEC_EVT_FIELD(common, version) },
845                 { AST_EVENT_IE_ACCOUNT_ID, SEC_EVT_FIELD(common, account_id) },
846                 { AST_EVENT_IE_SESSION_ID, SEC_EVT_FIELD(common, session_id) },
847                 { AST_EVENT_IE_LOCAL_ADDR, SEC_EVT_FIELD(common, local_addr) },
848                 { AST_EVENT_IE_REMOTE_ADDR, SEC_EVT_FIELD(common, remote_addr) },
849                 { AST_EVENT_IE_ATTEMPTED_TRANSPORT, SEC_EVT_FIELD(inval_transport, transport) },
850                 { AST_EVENT_IE_END, 0 }
851         },
852         .optional_ies = {
853                 { AST_EVENT_IE_MODULE, SEC_EVT_FIELD(common, module) },
854                 { AST_EVENT_IE_SESSION_TV, SEC_EVT_FIELD(common, session_tv) },
855                 { AST_EVENT_IE_END, 0 }
856         },
857 },
858
859 #undef SEC_EVT_FIELD
860
861 };
862
863 static const struct {
864         enum ast_security_event_severity severity;
865         const char *str;
866 } severities[] = {
867         { AST_SECURITY_EVENT_SEVERITY_INFO,  "Informational" },
868         { AST_SECURITY_EVENT_SEVERITY_ERROR, "Error" },
869 };
870
871 const char *ast_security_event_severity_get_name(
872                 const enum ast_security_event_severity severity)
873 {
874         unsigned int i;
875
876         for (i = 0; i < ARRAY_LEN(severities); i++) {
877                 if (severities[i].severity == severity) {
878                         return severities[i].str;
879                 }
880         }
881
882         return NULL;
883 }
884
885 static int check_event_type(const enum ast_security_event_type event_type)
886 {
887         if ((unsigned int)event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
888                 ast_log(LOG_ERROR, "Invalid security event type %u\n", event_type);
889                 return -1;
890         }
891
892         return 0;
893 }
894
895 const char *ast_security_event_get_name(const enum ast_security_event_type event_type)
896 {
897         if (check_event_type(event_type)) {
898                 return NULL;
899         }
900
901         return sec_events[event_type].name;
902 }
903
904 const struct ast_security_event_ie_type *ast_security_event_get_required_ies(
905                 const enum ast_security_event_type event_type)
906 {
907         if (check_event_type(event_type)) {
908                 return NULL;
909         }
910
911         return sec_events[event_type].required_ies;
912 }
913
914 const struct ast_security_event_ie_type *ast_security_event_get_optional_ies(
915                 const enum ast_security_event_type event_type)
916 {
917         if (check_event_type(event_type)) {
918                 return NULL;
919         }
920
921         return sec_events[event_type].optional_ies;
922 }
923
924 static int add_ip_json_object(struct ast_json *json, enum ast_event_ie_type ie_type,
925                 const struct ast_security_event_ip_addr *addr)
926 {
927         struct ast_json *json_ip;
928
929         json_ip = ast_json_ipaddr(addr->addr, addr->transport);
930         if (!json_ip) {
931                 return -1;
932         }
933
934         return ast_json_object_set(json, ast_event_get_ie_type_name(ie_type), json_ip);
935 }
936
937 enum ie_required {
938         NOT_REQUIRED,
939         REQUIRED
940 };
941
942 static int add_json_object(struct ast_json *json, const struct ast_security_event_common *sec,
943                 const struct ast_security_event_ie_type *ie_type, enum ie_required req)
944 {
945         int res = 0;
946
947         switch (ie_type->ie_type) {
948         case AST_EVENT_IE_SERVICE:
949         case AST_EVENT_IE_ACCOUNT_ID:
950         case AST_EVENT_IE_SESSION_ID:
951         case AST_EVENT_IE_MODULE:
952         case AST_EVENT_IE_ACL_NAME:
953         case AST_EVENT_IE_REQUEST_TYPE:
954         case AST_EVENT_IE_REQUEST_PARAMS:
955         case AST_EVENT_IE_AUTH_METHOD:
956         case AST_EVENT_IE_CHALLENGE:
957         case AST_EVENT_IE_RESPONSE:
958         case AST_EVENT_IE_EXPECTED_RESPONSE:
959         case AST_EVENT_IE_RECEIVED_CHALLENGE:
960         case AST_EVENT_IE_RECEIVED_HASH:
961         case AST_EVENT_IE_ATTEMPTED_TRANSPORT:
962         {
963                 const char *str;
964                 struct ast_json *json_string;
965
966                 str = *((const char **)(((const char *) sec) + ie_type->offset));
967
968                 if (req && !str) {
969                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
970                                         "type '%u' (%s) not present\n", ie_type->ie_type,
971                                         ast_event_get_ie_type_name(ie_type->ie_type),
972                                         sec->event_type, ast_security_event_get_name(sec->event_type));
973                         res = -1;
974                         break;
975                 }
976
977                 if (!str) {
978                         break;
979                 }
980
981                 json_string = ast_json_string_create(str);
982                 if (!json_string) {
983                         res = -1;
984                         break;
985                 }
986
987                 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
988                 break;
989         }
990         case AST_EVENT_IE_EVENT_VERSION:
991         case AST_EVENT_IE_USING_PASSWORD:
992         {
993                 struct ast_json *json_string;
994                 uint32_t val;
995                 val = *((const uint32_t *)(((const char *) sec) + ie_type->offset));
996
997                 json_string = ast_json_stringf("%u", val);
998                 if (!json_string) {
999                         res = -1;
1000                         break;
1001                 }
1002
1003                 res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_string);
1004                 break;
1005         }
1006         case AST_EVENT_IE_LOCAL_ADDR:
1007         case AST_EVENT_IE_REMOTE_ADDR:
1008         case AST_EVENT_IE_EXPECTED_ADDR:
1009         {
1010                 const struct ast_security_event_ip_addr *addr;
1011
1012                 addr = (const struct ast_security_event_ip_addr *)(((const char *) sec) + ie_type->offset);
1013
1014                 if (req && !addr->addr) {
1015                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
1016                                         "type '%u' (%s) not present\n", ie_type->ie_type,
1017                                         ast_event_get_ie_type_name(ie_type->ie_type),
1018                                         sec->event_type, ast_security_event_get_name(sec->event_type));
1019                         res = -1;
1020                 }
1021
1022                 if (addr->addr) {
1023                         res = add_ip_json_object(json, ie_type->ie_type, addr);
1024                 }
1025
1026                 break;
1027         }
1028         case AST_EVENT_IE_SESSION_TV:
1029         {
1030                 const struct timeval *tval;
1031
1032                 tval = *((const struct timeval **)(((const char *) sec) + ie_type->offset));
1033
1034                 if (req && !tval) {
1035                         ast_log(LOG_WARNING, "Required IE '%d' (%s) for security event "
1036                                         "type '%u' (%s) not present\n", ie_type->ie_type,
1037                                         ast_event_get_ie_type_name(ie_type->ie_type),
1038                                         sec->event_type, ast_security_event_get_name(sec->event_type));
1039                         res = -1;
1040                 }
1041
1042                 if (tval) {
1043                         struct ast_json *json_tval = ast_json_timeval(*tval, NULL);
1044                         if (!json_tval) {
1045                                 res = -1;
1046                                 break;
1047                         }
1048                         res = ast_json_object_set(json, ast_event_get_ie_type_name(ie_type->ie_type), json_tval);
1049                 }
1050
1051                 break;
1052         }
1053         case AST_EVENT_IE_EVENT_TV:
1054         case AST_EVENT_IE_SEVERITY:
1055                 /* Added automatically, nothing to do here. */
1056                 break;
1057         default:
1058                 ast_log(LOG_WARNING, "Unhandled IE type '%d' (%s), this security event "
1059                                 "will be missing data.\n", ie_type->ie_type,
1060                                 ast_event_get_ie_type_name(ie_type->ie_type));
1061                 break;
1062         }
1063
1064         return res;
1065 }
1066
1067 static struct ast_json *alloc_security_event_json_object(const struct ast_security_event_common *sec)
1068 {
1069         struct timeval tv = ast_tvnow();
1070         const char *severity_str;
1071         struct ast_json *json_temp;
1072         RAII_VAR(struct ast_json *, json_object, ast_json_object_create(), ast_json_unref);
1073
1074         if (!json_object) {
1075                 return NULL;
1076         }
1077
1078         /* NOTE: Every time ast_json_object_set is used, json_temp becomes a stale pointer since the reference is taken.
1079          *       This is true even if ast_json_object_set fails.
1080          */
1081
1082         json_temp = ast_json_integer_create(sec->event_type);
1083         if (!json_temp || ast_json_object_set(json_object, "SecurityEvent", json_temp)) {
1084                 return NULL;
1085         }
1086
1087         json_temp = ast_json_stringf("%u", sec->version);
1088         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_VERSION), json_temp)) {
1089                 return NULL;
1090         }
1091
1092         /* AST_EVENT_IE_EVENT_TV */
1093         json_temp  = ast_json_timeval(tv, NULL);
1094         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_EVENT_TV), json_temp)) {
1095                 return NULL;
1096         }
1097
1098         /* AST_EVENT_IE_SERVICE */
1099         json_temp = ast_json_string_create(sec->service);
1100         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SERVICE), json_temp)) {
1101                 return NULL;
1102         }
1103
1104         /* AST_EVENT_IE_SEVERITY */
1105         severity_str = S_OR(
1106                 ast_security_event_severity_get_name(sec_events[sec->event_type].severity),
1107                 "Unknown"
1108         );
1109
1110         json_temp = ast_json_string_create(severity_str);
1111         if (!json_temp || ast_json_object_set(json_object, ast_event_get_ie_type_name(AST_EVENT_IE_SEVERITY), json_temp)) {
1112                 return NULL;
1113         }
1114
1115         return ast_json_ref(json_object);
1116 }
1117
1118 static int handle_security_event(const struct ast_security_event_common *sec)
1119 {
1120         RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1121         RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
1122         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1123
1124         const struct ast_security_event_ie_type *ies;
1125         unsigned int i;
1126
1127         if (!ast_security_event_type()) {
1128                 return -1;
1129         }
1130
1131         json_object = alloc_security_event_json_object(sec);
1132         if (!json_object) {
1133                 return -1;
1134         }
1135
1136         for (ies = ast_security_event_get_required_ies(sec->event_type), i = 0;
1137                         ies[i].ie_type != AST_EVENT_IE_END;
1138                         i++) {
1139                 if (add_json_object(json_object, sec, ies + i, REQUIRED)) {
1140                         goto return_error;
1141                 }
1142         }
1143
1144         for (ies = ast_security_event_get_optional_ies(sec->event_type), i = 0;
1145                         ies[i].ie_type != AST_EVENT_IE_END;
1146                         i++) {
1147                 if (add_json_object(json_object, sec, ies + i, NOT_REQUIRED)) {
1148                         goto return_error;
1149                 }
1150         }
1151
1152         /* The json blob is ready.  Throw it in the payload and send it out over stasis. */
1153         if (!(json_payload = ast_json_payload_create(json_object))) {
1154                 goto return_error;
1155         }
1156
1157         msg = stasis_message_create(ast_security_event_type(), json_payload);
1158
1159         if (!msg) {
1160                 goto return_error;
1161         }
1162
1163         stasis_publish(ast_security_topic(), msg);
1164
1165         return 0;
1166
1167 return_error:
1168         return -1;
1169 }
1170
1171 int ast_security_event_report(const struct ast_security_event_common *sec)
1172 {
1173         if ((unsigned int)sec->event_type >= AST_SECURITY_EVENT_NUM_TYPES) {
1174                 ast_log(LOG_ERROR, "Invalid security event type\n");
1175                 return -1;
1176         }
1177
1178         if (!sec_events[sec->event_type].name) {
1179                 ast_log(LOG_WARNING, "Security event type %u not handled\n",
1180                                 sec->event_type);
1181                 return -1;
1182         }
1183
1184         if (sec->version != sec_events[sec->event_type].version) {
1185                 ast_log(LOG_WARNING, "Security event %u version mismatch\n",
1186                                 sec->event_type);
1187                 return -1;
1188         }
1189
1190         if (handle_security_event(sec)) {
1191                 ast_log(LOG_ERROR, "Failed to issue security event of type %s.\n",
1192                                 ast_security_event_get_name(sec->event_type));
1193         }
1194
1195         return 0;
1196 }
1197
1198