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