9e500e8defd3cf341ce61681ebf54c38e0773e01
[asterisk/asterisk.git] / main / manager.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief The Asterisk Management Interface - AMI
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * OpenSSL http://www.openssl.org - for AMI/SSL
26  *
27  * At the moment this file contains a number of functions, namely:
28  *
29  * - data structures storing AMI state
30  * - AMI-related API functions, used by internal asterisk components
31  * - handlers for AMI-related CLI functions
32  * - handlers for AMI functions (available through the AMI socket)
33  * - the code for the main AMI listener thread and individual session threads
34  * - the http handlers invoked for AMI-over-HTTP by the threads in main/http.c
35  *
36  * \ref amiconf
37  */
38
39 /*! \li \ref manager.c uses the configuration file \ref manager.conf and \ref users.conf
40  * \addtogroup configuration_file
41  */
42
43 /*! \page manager.conf manager.conf
44  * \verbinclude manager.conf.sample
45  */
46
47 /*! \page users.conf users.conf
48  * \verbinclude users.conf.sample
49  */
50
51 /*** MODULEINFO
52         <support_level>core</support_level>
53  ***/
54
55 #include "asterisk.h"
56
57 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
58
59 #include "asterisk/_private.h"
60 #include "asterisk/paths.h"     /* use various ast_config_AST_* */
61 #include <ctype.h>
62 #include <sys/time.h>
63 #include <signal.h>
64 #include <sys/mman.h>
65 #include <sys/types.h>
66 #include <regex.h>
67
68 #include "asterisk/channel.h"
69 #include "asterisk/file.h"
70 #include "asterisk/manager.h"
71 #include "asterisk/module.h"
72 #include "asterisk/config.h"
73 #include "asterisk/callerid.h"
74 #include "asterisk/lock.h"
75 #include "asterisk/cli.h"
76 #include "asterisk/app.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/md5.h"
79 #include "asterisk/acl.h"
80 #include "asterisk/utils.h"
81 #include "asterisk/tcptls.h"
82 #include "asterisk/http.h"
83 #include "asterisk/ast_version.h"
84 #include "asterisk/threadstorage.h"
85 #include "asterisk/linkedlists.h"
86 #include "asterisk/term.h"
87 #include "asterisk/astobj2.h"
88 #include "asterisk/features.h"
89 #include "asterisk/security_events.h"
90 #include "asterisk/event.h"
91 #include "asterisk/aoc.h"
92 #include "asterisk/stringfields.h"
93 #include "asterisk/presencestate.h"
94 #include "asterisk/stasis.h"
95 #include "asterisk/test.h"
96 #include "asterisk/json.h"
97
98 /*** DOCUMENTATION
99         <manager name="Ping" language="en_US">
100                 <synopsis>
101                         Keepalive command.
102                 </synopsis>
103                 <syntax>
104                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
105                 </syntax>
106                 <description>
107                         <para>A 'Ping' action will ellicit a 'Pong' response. Used to keep the
108                         manager connection open.</para>
109                 </description>
110         </manager>
111         <manager name="Events" language="en_US">
112                 <synopsis>
113                         Control Event Flow.
114                 </synopsis>
115                 <syntax>
116                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
117                         <parameter name="EventMask" required="true">
118                                 <enumlist>
119                                         <enum name="on">
120                                                 <para>If all events should be sent.</para>
121                                         </enum>
122                                         <enum name="off">
123                                                 <para>If no events should be sent.</para>
124                                         </enum>
125                                         <enum name="system,call,log,...">
126                                                 <para>To select which flags events should have to be sent.</para>
127                                         </enum>
128                                 </enumlist>
129                         </parameter>
130                 </syntax>
131                 <description>
132                         <para>Enable/Disable sending of events to this manager client.</para>
133                 </description>
134         </manager>
135         <manager name="Logoff" language="en_US">
136                 <synopsis>
137                         Logoff Manager.
138                 </synopsis>
139                 <syntax>
140                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
141                 </syntax>
142                 <description>
143                         <para>Logoff the current manager session.</para>
144                 </description>
145         </manager>
146         <manager name="Login" language="en_US">
147                 <synopsis>
148                         Login Manager.
149                 </synopsis>
150                 <syntax>
151                         <parameter name="ActionID">
152                                 <para>ActionID for this transaction. Will be returned.</para>
153                         </parameter>
154                         <parameter name="Username" required="true">
155                                 <para>Username to login with as specified in manager.conf.</para>
156                         </parameter>
157                         <parameter name="Secret">
158                                 <para>Secret to login with as specified in manager.conf.</para>
159                         </parameter>
160                 </syntax>
161                 <description>
162                         <para>Login Manager.</para>
163                 </description>
164         </manager>
165         <manager name="Challenge" language="en_US">
166                 <synopsis>
167                         Generate Challenge for MD5 Auth.
168                 </synopsis>
169                 <syntax>
170                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
171                         <parameter name="AuthType" required="true">
172                                 <para>Digest algorithm to use in the challenge. Valid values are:</para>
173                                 <enumlist>
174                                         <enum name="MD5" />
175                                 </enumlist>
176                         </parameter>
177                 </syntax>
178                 <description>
179                         <para>Generate a challenge for MD5 authentication.</para>
180                 </description>
181         </manager>
182         <manager name="Hangup" language="en_US">
183                 <synopsis>
184                         Hangup channel.
185                 </synopsis>
186                 <syntax>
187                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
188                         <parameter name="Channel" required="true">
189                                 <para>The exact channel name to be hungup, or to use a regular expression, set this parameter to: /regex/</para>
190                                 <para>Example exact channel: SIP/provider-0000012a</para>
191                                 <para>Example regular expression: /^SIP/provider-.*$/</para>
192                         </parameter>
193                         <parameter name="Cause">
194                                 <para>Numeric hangup cause.</para>
195                         </parameter>
196                 </syntax>
197                 <description>
198                         <para>Hangup a channel.</para>
199                 </description>
200         </manager>
201         <manager name="Status" language="en_US">
202                 <synopsis>
203                         List channel status.
204                 </synopsis>
205                 <syntax>
206                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
207                         <parameter name="Channel" required="true">
208                                 <para>The name of the channel to query for status.</para>
209                         </parameter>
210                         <parameter name="Variables">
211                                 <para>Comma <literal>,</literal> separated list of variable to include.</para>
212                         </parameter>
213                 </syntax>
214                 <description>
215                         <para>Will return the status information of each channel along with the
216                         value for the specified channel variables.</para>
217                 </description>
218         </manager>
219         <manager name="Setvar" language="en_US">
220                 <synopsis>
221                         Set a channel variable.
222                 </synopsis>
223                 <syntax>
224                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
225                         <parameter name="Channel">
226                                 <para>Channel to set variable for.</para>
227                         </parameter>
228                         <parameter name="Variable" required="true">
229                                 <para>Variable name.</para>
230                         </parameter>
231                         <parameter name="Value" required="true">
232                                 <para>Variable value.</para>
233                         </parameter>
234                 </syntax>
235                 <description>
236                         <para>Set a global or local channel variable.</para>
237                         <note>
238                                 <para>If a channel name is not provided then the variable is global.</para>
239                         </note>
240                 </description>
241         </manager>
242         <manager name="Getvar" language="en_US">
243                 <synopsis>
244                         Gets a channel variable.
245                 </synopsis>
246                 <syntax>
247                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
248                         <parameter name="Channel">
249                                 <para>Channel to read variable from.</para>
250                         </parameter>
251                         <parameter name="Variable" required="true">
252                                 <para>Variable name.</para>
253                         </parameter>
254                 </syntax>
255                 <description>
256                         <para>Get the value of a global or local channel variable.</para>
257                         <note>
258                                 <para>If a channel name is not provided then the variable is global.</para>
259                         </note>
260                 </description>
261         </manager>
262         <manager name="GetConfig" language="en_US">
263                 <synopsis>
264                         Retrieve configuration.
265                 </synopsis>
266                 <syntax>
267                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
268                         <parameter name="Filename" required="true">
269                                 <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
270                         </parameter>
271                         <parameter name="Category">
272                                 <para>Category in configuration file.</para>
273                         </parameter>
274                 </syntax>
275                 <description>
276                         <para>This action will dump the contents of a configuration
277                         file by category and contents or optionally by specified category only.</para>
278                 </description>
279         </manager>
280         <manager name="GetConfigJSON" language="en_US">
281                 <synopsis>
282                         Retrieve configuration (JSON format).
283                 </synopsis>
284                 <syntax>
285                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
286                         <parameter name="Filename" required="true">
287                                 <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
288                         </parameter>
289                 </syntax>
290                 <description>
291                         <para>This action will dump the contents of a configuration file by category
292                         and contents in JSON format. This only makes sense to be used using rawman over
293                         the HTTP interface.</para>
294                 </description>
295         </manager>
296         <manager name="UpdateConfig" language="en_US">
297                 <synopsis>
298                         Update basic configuration.
299                 </synopsis>
300                 <syntax>
301                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
302                         <parameter name="SrcFilename" required="true">
303                                 <para>Configuration filename to read (e.g. <filename>foo.conf</filename>).</para>
304                         </parameter>
305                         <parameter name="DstFilename" required="true">
306                                 <para>Configuration filename to write (e.g. <filename>foo.conf</filename>)</para>
307                         </parameter>
308                         <parameter name="Reload">
309                                 <para>Whether or not a reload should take place (or name of specific module).</para>
310                         </parameter>
311                         <parameter name="Action-XXXXXX">
312                                 <para>Action to take.</para>
313                                 <para>X's represent 6 digit number beginning with 000000.</para>
314                                 <enumlist>
315                                         <enum name="NewCat" />
316                                         <enum name="RenameCat" />
317                                         <enum name="DelCat" />
318                                         <enum name="EmptyCat" />
319                                         <enum name="Update" />
320                                         <enum name="Delete" />
321                                         <enum name="Append" />
322                                         <enum name="Insert" />
323                                 </enumlist>
324                         </parameter>
325                         <parameter name="Cat-XXXXXX">
326                                 <para>Category to operate on.</para>
327                                 <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
328                         </parameter>
329                         <parameter name="Var-XXXXXX">
330                                 <para>Variable to work on.</para>
331                                 <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
332                         </parameter>
333                         <parameter name="Value-XXXXXX">
334                                 <para>Value to work on.</para>
335                                 <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
336                         </parameter>
337                         <parameter name="Match-XXXXXX">
338                                 <para>Extra match required to match line.</para>
339                                 <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
340                         </parameter>
341                         <parameter name="Line-XXXXXX">
342                                 <para>Line in category to operate on (used with delete and insert actions).</para>
343                                 <xi:include xpointer="xpointer(/docs/manager[@name='UpdateConfig']/syntax/parameter[@name='Action-XXXXXX']/para[2])" />
344                         </parameter>
345                 </syntax>
346                 <description>
347                         <para>This action will modify, create, or delete configuration elements
348                         in Asterisk configuration files.</para>
349                 </description>
350         </manager>
351         <manager name="CreateConfig" language="en_US">
352                 <synopsis>
353                         Creates an empty file in the configuration directory.
354                 </synopsis>
355                 <syntax>
356                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
357                         <parameter name="Filename" required="true">
358                                 <para>The configuration filename to create (e.g. <filename>foo.conf</filename>).</para>
359                         </parameter>
360                 </syntax>
361                 <description>
362                         <para>This action will create an empty file in the configuration
363                         directory. This action is intended to be used before an UpdateConfig
364                         action.</para>
365                 </description>
366         </manager>
367         <manager name="ListCategories" language="en_US">
368                 <synopsis>
369                         List categories in configuration file.
370                 </synopsis>
371                 <syntax>
372                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
373                         <parameter name="Filename" required="true">
374                                 <para>Configuration filename (e.g. <filename>foo.conf</filename>).</para>
375                         </parameter>
376                 </syntax>
377                 <description>
378                         <para>This action will dump the categories in a given file.</para>
379                 </description>
380         </manager>
381         <manager name="Redirect" language="en_US">
382                 <synopsis>
383                         Redirect (transfer) a call.
384                 </synopsis>
385                 <syntax>
386                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
387                         <parameter name="Channel" required="true">
388                                 <para>Channel to redirect.</para>
389                         </parameter>
390                         <parameter name="ExtraChannel">
391                                 <para>Second call leg to transfer (optional).</para>
392                         </parameter>
393                         <parameter name="Exten" required="true">
394                                 <para>Extension to transfer to.</para>
395                         </parameter>
396                         <parameter name="ExtraExten">
397                                 <para>Extension to transfer extrachannel to (optional).</para>
398                         </parameter>
399                         <parameter name="Context" required="true">
400                                 <para>Context to transfer to.</para>
401                         </parameter>
402                         <parameter name="ExtraContext">
403                                 <para>Context to transfer extrachannel to (optional).</para>
404                         </parameter>
405                         <parameter name="Priority" required="true">
406                                 <para>Priority to transfer to.</para>
407                         </parameter>
408                         <parameter name="ExtraPriority">
409                                 <para>Priority to transfer extrachannel to (optional).</para>
410                         </parameter>
411                 </syntax>
412                 <description>
413                         <para>Redirect (transfer) a call.</para>
414                 </description>
415         </manager>
416         <manager name="Atxfer" language="en_US">
417                 <synopsis>
418                         Attended transfer.
419                 </synopsis>
420                 <syntax>
421                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
422                         <parameter name="Channel" required="true">
423                                 <para>Transferer's channel.</para>
424                         </parameter>
425                         <parameter name="Exten" required="true">
426                                 <para>Extension to transfer to.</para>
427                         </parameter>
428                         <parameter name="Context" required="true">
429                                 <para>Context to transfer to.</para>
430                         </parameter>
431                         <parameter name="Priority" required="true">
432                                 <para>Priority to transfer to.</para>
433                         </parameter>
434                 </syntax>
435                 <description>
436                         <para>Attended transfer.</para>
437                 </description>
438         </manager>
439         <manager name="Originate" language="en_US">
440                 <synopsis>
441                         Originate a call.
442                 </synopsis>
443                 <syntax>
444                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
445                         <parameter name="Channel" required="true">
446                                 <para>Channel name to call.</para>
447                         </parameter>
448                         <parameter name="Exten">
449                                 <para>Extension to use (requires <literal>Context</literal> and
450                                 <literal>Priority</literal>)</para>
451                         </parameter>
452                         <parameter name="Context">
453                                 <para>Context to use (requires <literal>Exten</literal> and
454                                 <literal>Priority</literal>)</para>
455                         </parameter>
456                         <parameter name="Priority">
457                                 <para>Priority to use (requires <literal>Exten</literal> and
458                                 <literal>Context</literal>)</para>
459                         </parameter>
460                         <parameter name="Application">
461                                 <para>Application to execute.</para>
462                         </parameter>
463                         <parameter name="Data">
464                                 <para>Data to use (requires <literal>Application</literal>).</para>
465                         </parameter>
466                         <parameter name="Timeout" default="30000">
467                                 <para>How long to wait for call to be answered (in ms.).</para>
468                         </parameter>
469                         <parameter name="CallerID">
470                                 <para>Caller ID to be set on the outgoing channel.</para>
471                         </parameter>
472                         <parameter name="Variable">
473                                 <para>Channel variable to set, multiple Variable: headers are allowed.</para>
474                         </parameter>
475                         <parameter name="Account">
476                                 <para>Account code.</para>
477                         </parameter>
478                         <parameter name="EarlyMedia">
479                                 <para>Set to <literal>true</literal> to force call bridge on early media..</para>
480                         </parameter>
481                         <parameter name="Async">
482                                 <para>Set to <literal>true</literal> for fast origination.</para>
483                         </parameter>
484                         <parameter name="Codecs">
485                                 <para>Comma-separated list of codecs to use for this call.</para>
486                         </parameter>
487                 </syntax>
488                 <description>
489                         <para>Generates an outgoing call to a
490                         <replaceable>Extension</replaceable>/<replaceable>Context</replaceable>/<replaceable>Priority</replaceable>
491                         or <replaceable>Application</replaceable>/<replaceable>Data</replaceable></para>
492                 </description>
493                 <see-also>
494                         <ref type="managerEvent">OriginateResponse</ref>
495                 </see-also>
496         </manager>
497         <managerEvent language="en_US" name="OriginateResponse">
498                 <managerEventInstance class="EVENT_FLAG_CALL">
499                         <synopsis>Raised in response to an Originate command.</synopsis>
500                         <syntax>
501                                 <parameter name="ActionID" required="false"/>
502                                 <parameter name="Resonse">
503                                         <enumlist>
504                                                 <enum name="Failure"/>
505                                                 <enum name="Success"/>
506                                         </enumlist>
507                                 </parameter>
508                                 <parameter name="Channel"/>
509                                 <parameter name="Context"/>
510                                 <parameter name="Exten"/>
511                                 <parameter name="Reason"/>
512                                 <parameter name="Uniqueid"/>
513                                 <parameter name="CallerIDNum"/>
514                                 <parameter name="CallerIDName"/>
515                         </syntax>
516                         <see-also>
517                                 <ref type="manager">Originate</ref>
518                         </see-also>
519                 </managerEventInstance>
520         </managerEvent>
521         <manager name="Command" language="en_US">
522                 <synopsis>
523                         Execute Asterisk CLI Command.
524                 </synopsis>
525                 <syntax>
526                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
527                         <parameter name="Command" required="true">
528                                 <para>Asterisk CLI command to run.</para>
529                         </parameter>
530                 </syntax>
531                 <description>
532                         <para>Run a CLI command.</para>
533                 </description>
534         </manager>
535         <manager name="ExtensionState" language="en_US">
536                 <synopsis>
537                         Check Extension Status.
538                 </synopsis>
539                 <syntax>
540                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
541                         <parameter name="Exten" required="true">
542                                 <para>Extension to check state on.</para>
543                         </parameter>
544                         <parameter name="Context" required="true">
545                                 <para>Context for extension.</para>
546                         </parameter>
547                 </syntax>
548                 <description>
549                         <para>Report the extension state for given extension. If the extension has a hint,
550                         will use devicestate to check the status of the device connected to the extension.</para>
551                         <para>Will return an <literal>Extension Status</literal> message. The response will include
552                         the hint for the extension and the status.</para>
553                 </description>
554         </manager>
555         <manager name="PresenceState" language="en_US">
556                 <synopsis>
557                         Check Presence State
558                 </synopsis>
559                 <syntax>
560                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
561                         <parameter name="Provider" required="true">
562                                 <para>Presence Provider to check the state of</para>
563                         </parameter>
564                 </syntax>
565                 <description>
566                         <para>Report the presence state for the given presence provider.</para>
567                         <para>Will return a <literal>Presence State</literal> message. The response will include the
568                         presence state and, if set, a presence subtype and custom message.</para>
569                 </description>
570         </manager>
571         <manager name="AbsoluteTimeout" language="en_US">
572                 <synopsis>
573                         Set absolute timeout.
574                 </synopsis>
575                 <syntax>
576                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
577                         <parameter name="Channel" required="true">
578                                 <para>Channel name to hangup.</para>
579                         </parameter>
580                         <parameter name="Timeout" required="true">
581                                 <para>Maximum duration of the call (sec).</para>
582                         </parameter>
583                 </syntax>
584                 <description>
585                         <para>Hangup a channel after a certain time. Acknowledges set time with
586                         <literal>Timeout Set</literal> message.</para>
587                 </description>
588         </manager>
589         <manager name="MailboxStatus" language="en_US">
590                 <synopsis>
591                         Check mailbox.
592                 </synopsis>
593                 <syntax>
594                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
595                         <parameter name="Mailbox" required="true">
596                                 <para>Full mailbox ID <replaceable>mailbox</replaceable>@<replaceable>vm-context</replaceable>.</para>
597                         </parameter>
598                 </syntax>
599                 <description>
600                         <para>Checks a voicemail account for status.</para>
601                         <para>Returns whether there are messages waiting.</para>
602                         <para>Message: Mailbox Status.</para>
603                         <para>Mailbox: <replaceable>mailboxid</replaceable>.</para>
604                         <para>Waiting: <literal>0</literal> if messages waiting, <literal>1</literal>
605                         if no messages waiting.</para>
606                 </description>
607         </manager>
608         <manager name="MailboxCount" language="en_US">
609                 <synopsis>
610                         Check Mailbox Message Count.
611                 </synopsis>
612                 <syntax>
613                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
614                         <parameter name="Mailbox" required="true">
615                                 <para>Full mailbox ID <replaceable>mailbox</replaceable>@<replaceable>vm-context</replaceable>.</para>
616                         </parameter>
617                 </syntax>
618                 <description>
619                         <para>Checks a voicemail account for new messages.</para>
620                         <para>Returns number of urgent, new and old messages.</para>
621                         <para>Message: Mailbox Message Count</para>
622                         <para>Mailbox: <replaceable>mailboxid</replaceable></para>
623                         <para>UrgentMessages: <replaceable>count</replaceable></para>
624                         <para>NewMessages: <replaceable>count</replaceable></para>
625                         <para>OldMessages: <replaceable>count</replaceable></para>
626                 </description>
627         </manager>
628         <manager name="ListCommands" language="en_US">
629                 <synopsis>
630                         List available manager commands.
631                 </synopsis>
632                 <syntax>
633                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
634                 </syntax>
635                 <description>
636                         <para>Returns the action name and synopsis for every action that
637                         is available to the user.</para>
638                 </description>
639         </manager>
640         <manager name="SendText" language="en_US">
641                 <synopsis>
642                         Send text message to channel.
643                 </synopsis>
644                 <syntax>
645                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
646                         <parameter name="Channel" required="true">
647                                 <para>Channel to send message to.</para>
648                         </parameter>
649                         <parameter name="Message" required="true">
650                                 <para>Message to send.</para>
651                         </parameter>
652                 </syntax>
653                 <description>
654                         <para>Sends A Text Message to a channel while in a call.</para>
655                 </description>
656         </manager>
657         <manager name="UserEvent" language="en_US">
658                 <synopsis>
659                         Send an arbitrary event.
660                 </synopsis>
661                 <syntax>
662                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
663                         <parameter name="UserEvent" required="true">
664                                 <para>Event string to send.</para>
665                         </parameter>
666                         <parameter name="Header1">
667                                 <para>Content1.</para>
668                         </parameter>
669                         <parameter name="HeaderN">
670                                 <para>ContentN.</para>
671                         </parameter>
672                 </syntax>
673                 <description>
674                         <para>Send an event to manager sessions.</para>
675                 </description>
676         </manager>
677         <manager name="WaitEvent" language="en_US">
678                 <synopsis>
679                         Wait for an event to occur.
680                 </synopsis>
681                 <syntax>
682                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
683                         <parameter name="Timeout" required="true">
684                                 <para>Maximum time (in seconds) to wait for events, <literal>-1</literal> means forever.</para>
685                         </parameter>
686                 </syntax>
687                 <description>
688                         <para>This action will ellicit a <literal>Success</literal> response. Whenever
689                         a manager event is queued. Once WaitEvent has been called on an HTTP manager
690                         session, events will be generated and queued.</para>
691                 </description>
692         </manager>
693         <manager name="CoreSettings" language="en_US">
694                 <synopsis>
695                         Show PBX core settings (version etc).
696                 </synopsis>
697                 <syntax>
698                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
699                 </syntax>
700                 <description>
701                         <para>Query for Core PBX settings.</para>
702                 </description>
703         </manager>
704         <manager name="CoreStatus" language="en_US">
705                 <synopsis>
706                         Show PBX core status variables.
707                 </synopsis>
708                 <syntax>
709                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
710                 </syntax>
711                 <description>
712                         <para>Query for Core PBX status.</para>
713                 </description>
714         </manager>
715         <manager name="Reload" language="en_US">
716                 <synopsis>
717                         Send a reload event.
718                 </synopsis>
719                 <syntax>
720                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
721                         <parameter name="Module">
722                                 <para>Name of the module to reload.</para>
723                         </parameter>
724                 </syntax>
725                 <description>
726                         <para>Send a reload event.</para>
727                 </description>
728         </manager>
729         <manager name="CoreShowChannels" language="en_US">
730                 <synopsis>
731                         List currently active channels.
732                 </synopsis>
733                 <syntax>
734                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
735                 </syntax>
736                 <description>
737                         <para>List currently defined channels and some information about them.</para>
738                 </description>
739         </manager>
740         <manager name="ModuleLoad" language="en_US">
741                 <synopsis>
742                         Module management.
743                 </synopsis>
744                 <syntax>
745                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
746                         <parameter name="Module">
747                                 <para>Asterisk module name (including .so extension) or subsystem identifier:</para>
748                                 <enumlist>
749                                         <enum name="cdr" />
750                                         <enum name="dnsmgr" />
751                                         <enum name="extconfig" />
752                                         <enum name="enum" />
753                                         <enum name="acl" />
754                                         <enum name="manager" />
755                                         <enum name="http" />
756                                         <enum name="logger" />
757                                         <enum name="features" />
758                                         <enum name="dsp" />
759                                         <enum name="udptl" />
760                                         <enum name="indications" />
761                                         <enum name="cel" />
762                                         <enum name="plc" />
763                                 </enumlist>
764                         </parameter>
765                         <parameter name="LoadType" required="true">
766                                 <para>The operation to be done on module. Subsystem identifiers may only
767                                 be reloaded.</para>
768                                 <enumlist>
769                                         <enum name="load" />
770                                         <enum name="unload" />
771                                         <enum name="reload" />
772                                 </enumlist>
773                                 <para>If no module is specified for a <literal>reload</literal> loadtype,
774                                 all modules are reloaded.</para>
775                         </parameter>
776                 </syntax>
777                 <description>
778                         <para>Loads, unloads or reloads an Asterisk module in a running system.</para>
779                 </description>
780         </manager>
781         <manager name="ModuleCheck" language="en_US">
782                 <synopsis>
783                         Check if module is loaded.
784                 </synopsis>
785                 <syntax>
786                         <parameter name="Module" required="true">
787                                 <para>Asterisk module name (not including extension).</para>
788                         </parameter>
789                 </syntax>
790                 <description>
791                         <para>Checks if Asterisk module is loaded. Will return Success/Failure.
792                         For success returns, the module revision number is included.</para>
793                 </description>
794         </manager>
795         <manager name="AOCMessage" language="en_US">
796                 <synopsis>
797                         Generate an Advice of Charge message on a channel.
798                 </synopsis>
799                 <syntax>
800                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
801                         <parameter name="Channel" required="true">
802                                 <para>Channel name to generate the AOC message on.</para>
803                         </parameter>
804                         <parameter name="ChannelPrefix">
805                                 <para>Partial channel prefix.  By using this option one can match the beginning part
806                                 of a channel name without having to put the entire name in.  For example
807                                 if a channel name is SIP/snom-00000001 and this value is set to SIP/snom, then
808                                 that channel matches and the message will be sent.  Note however that only
809                                 the first matched channel has the message sent on it. </para>
810                         </parameter>
811                         <parameter name="MsgType" required="true">
812                                 <para>Defines what type of AOC message to create, AOC-D or AOC-E</para>
813                                 <enumlist>
814                                         <enum name="D" />
815                                         <enum name="E" />
816                                 </enumlist>
817                         </parameter>
818                         <parameter name="ChargeType" required="true">
819                                 <para>Defines what kind of charge this message represents.</para>
820                                 <enumlist>
821                                         <enum name="NA" />
822                                         <enum name="FREE" />
823                                         <enum name="Currency" />
824                                         <enum name="Unit" />
825                                 </enumlist>
826                         </parameter>
827                         <parameter name="UnitAmount(0)">
828                                 <para>This represents the amount of units charged. The ETSI AOC standard specifies that
829                                 this value along with the optional UnitType value are entries in a list.  To accommodate this
830                                 these values take an index value starting at 0 which can be used to generate this list of
831                                 unit entries.  For Example, If two unit entires were required this could be achieved by setting the
832                                 paramter UnitAmount(0)=1234 and UnitAmount(1)=5678.  Note that UnitAmount at index 0 is
833                                 required when ChargeType=Unit, all other entries in the list are optional.
834                                 </para>
835                         </parameter>
836                         <parameter name="UnitType(0)">
837                                 <para>Defines the type of unit.  ETSI AOC standard specifies this as an integer
838                                 value between 1 and 16, but this value is left open to accept any positive
839                                 integer.  Like the UnitAmount parameter, this value represents a list entry
840                                 and has an index parameter that starts at 0.
841                                 </para>
842                         </parameter>
843                         <parameter name="CurrencyName">
844                                 <para>Specifies the currency's name.  Note that this value is truncated after 10 characters.</para>
845                         </parameter>
846                         <parameter name="CurrencyAmount">
847                                 <para>Specifies the charge unit amount as a positive integer.  This value is required
848                                 when ChargeType==Currency.</para>
849                         </parameter>
850                         <parameter name="CurrencyMultiplier">
851                                 <para>Specifies the currency multiplier.  This value is required when ChargeType==Currency.</para>
852                                 <enumlist>
853                                         <enum name="OneThousandth" />
854                                         <enum name="OneHundredth" />
855                                         <enum name="OneTenth" />
856                                         <enum name="One" />
857                                         <enum name="Ten" />
858                                         <enum name="Hundred" />
859                                         <enum name="Thousand" />
860                                 </enumlist>
861                         </parameter>
862                         <parameter name="TotalType" default="Total">
863                                 <para>Defines what kind of AOC-D total is represented.</para>
864                                 <enumlist>
865                                         <enum name="Total" />
866                                         <enum name="SubTotal" />
867                                 </enumlist>
868                         </parameter>
869                         <parameter name="AOCBillingId">
870                                 <para>Represents a billing ID associated with an AOC-D or AOC-E message. Note
871                                 that only the first 3 items of the enum are valid AOC-D billing IDs</para>
872                                 <enumlist>
873                                         <enum name="Normal" />
874                                         <enum name="ReverseCharge" />
875                                         <enum name="CreditCard" />
876                                         <enum name="CallFwdUnconditional" />
877                                         <enum name="CallFwdBusy" />
878                                         <enum name="CallFwdNoReply" />
879                                         <enum name="CallDeflection" />
880                                         <enum name="CallTransfer" />
881                                 </enumlist>
882                         </parameter>
883                         <parameter name="ChargingAssociationId">
884                                 <para>Charging association identifier.  This is optional for AOC-E and can be
885                                 set to any value between -32768 and 32767</para>
886                         </parameter>
887                         <parameter name="ChargingAssociationNumber">
888                                 <para>Represents the charging association party number.  This value is optional
889                                 for AOC-E.</para>
890                         </parameter>
891                         <parameter name="ChargingAssociationPlan">
892                                 <para>Integer representing the charging plan associated with the ChargingAssociationNumber.
893                                 The value is bits 7 through 1 of the Q.931 octet containing the type-of-number and
894                                 numbering-plan-identification fields.</para>
895                         </parameter>
896                 </syntax>
897                 <description>
898                         <para>Generates an AOC-D or AOC-E message on a channel.</para>
899                 </description>
900         </manager>
901         <function name="AMI_CLIENT" language="en_US">
902                 <synopsis>
903                         Checks attributes of manager accounts
904                 </synopsis>
905                 <syntax>
906                         <parameter name="loginname" required="true">
907                                 <para>Login name, specified in manager.conf</para>
908                         </parameter>
909                         <parameter name="field" required="true">
910                                 <para>The manager account attribute to return</para>
911                                 <enumlist>
912                                         <enum name="sessions"><para>The number of sessions for this AMI account</para></enum>
913                                 </enumlist>
914                         </parameter>
915                 </syntax>
916                 <description>
917                         <para>
918                                 Currently, the only supported  parameter is "sessions" which will return the current number of
919                                 active sessions for this AMI account.
920                         </para>
921                 </description>
922         </function>
923         <manager name="Filter" language="en_US">
924                 <synopsis>
925                         Dynamically add filters for the current manager session.
926                 </synopsis>
927                 <syntax>
928                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
929                         <parameter name="Operation">
930                                 <enumlist>
931                                         <enum name="Add">
932                                                 <para>Add a filter.</para>
933                                         </enum>
934                                 </enumlist>
935                         </parameter>
936                         <parameter name="Filter">
937                                 <para>Filters can be whitelist or blacklist</para>
938                                 <para>Example whitelist filter: "Event: Newchannel"</para>
939                                 <para>Example blacklist filter: "!Channel: DAHDI.*"</para>
940                                 <para>This filter option is used to whitelist or blacklist events per user to be
941                                 reported with regular expressions and are allowed if both the regex matches
942                                 and the user has read access as defined in manager.conf. Filters are assumed to be for whitelisting
943                                 unless preceeded by an exclamation point, which marks it as being black.
944                                 Evaluation of the filters is as follows:</para>
945                                 <para>- If no filters are configured all events are reported as normal.</para>
946                                 <para>- If there are white filters only: implied black all filter processed first, then white filters.</para>
947                                 <para>- If there are black filters only: implied white all filter processed first, then black filters.</para>
948                                 <para>- If there are both white and black filters: implied black all filter processed first, then white
949                                 filters, and lastly black filters.</para>
950                         </parameter>
951                 </syntax>
952                 <description>
953                         <para>The filters added are only used for the current session.
954                         Once the connection is closed the filters are removed.</para>
955                         <para>This comand requires the system permission because
956                         this command can be used to create filters that may bypass
957                         filters defined in manager.conf</para>
958                 </description>
959         </manager>
960         <manager name="FilterList" language="en_US">
961                 <synopsis>
962                         Show current event filters for this session
963                 </synopsis>
964                 <description>
965                         <para>The filters displayed are for the current session.  Only those filters defined in
966                         manager.conf will be present upon starting a new session.</para>
967                 </description>
968         </manager>
969  ***/
970
971 /*! \addtogroup Group_AMI AMI functions
972 */
973 /*! @{
974  Doxygen group */
975
976 enum error_type {
977         UNKNOWN_ACTION = 1,
978         UNKNOWN_CATEGORY,
979         UNSPECIFIED_CATEGORY,
980         UNSPECIFIED_ARGUMENT,
981         FAILURE_ALLOCATION,
982         FAILURE_NEWCAT,
983         FAILURE_DELCAT,
984         FAILURE_EMPTYCAT,
985         FAILURE_UPDATE,
986         FAILURE_DELETE,
987         FAILURE_APPEND
988 };
989
990 enum add_filter_result {
991         FILTER_SUCCESS,
992         FILTER_ALLOC_FAILED,
993         FILTER_COMPILE_FAIL,
994 };
995
996 /*!
997  * Linked list of events.
998  * Global events are appended to the list by append_event().
999  * The usecount is the number of stored pointers to the element,
1000  * excluding the list pointers. So an element that is only in
1001  * the list has a usecount of 0, not 1.
1002  *
1003  * Clients have a pointer to the last event processed, and for each
1004  * of these clients we track the usecount of the elements.
1005  * If we have a pointer to an entry in the list, it is safe to navigate
1006  * it forward because elements will not be deleted, but only appended.
1007  * The worst that can happen is seeing the pointer still NULL.
1008  *
1009  * When the usecount of an element drops to 0, and the element is the
1010  * first in the list, we can remove it. Removal is done within the
1011  * main thread, which is woken up for the purpose.
1012  *
1013  * For simplicity of implementation, we make sure the list is never empty.
1014  */
1015 struct eventqent {
1016         int usecount;           /*!< # of clients who still need the event */
1017         int category;
1018         unsigned int seq;       /*!< sequence number */
1019         struct timeval tv;  /*!< When event was allocated */
1020         AST_RWLIST_ENTRY(eventqent) eq_next;
1021         char eventdata[1];      /*!< really variable size, allocated by append_event() */
1022 };
1023
1024 static AST_RWLIST_HEAD_STATIC(all_events, eventqent);
1025
1026 static int displayconnects = 1;
1027 static int allowmultiplelogin = 1;
1028 static int timestampevents;
1029 static int httptimeout = 60;
1030 static int broken_events_action = 0;
1031 static int manager_enabled = 0;
1032 static int webmanager_enabled = 0;
1033 static int manager_debug = 0;   /*!< enable some debugging code in the manager */
1034 static int authtimeout;
1035 static int authlimit;
1036 static char *manager_channelvars;
1037
1038 #define DEFAULT_REALM           "asterisk"
1039 static char global_realm[MAXHOSTNAMELEN];       /*!< Default realm */
1040
1041 static int block_sockets;
1042 static int unauth_sessions = 0;
1043 static struct stasis_subscription *acl_change_sub;
1044
1045 #define MGR_SHOW_TERMINAL_WIDTH 80
1046
1047 #define MAX_VARS 128
1048
1049 /*! \brief
1050  * Descriptor for a manager session, either on the AMI socket or over HTTP.
1051  *
1052  * \note
1053  * AMI session have managerid == 0; the entry is created upon a connect,
1054  * and destroyed with the socket.
1055  * HTTP sessions have managerid != 0, the value is used as a search key
1056  * to lookup sessions (using the mansession_id cookie, or nonce key from
1057  * Digest Authentication http header).
1058  */
1059 #define MAX_BLACKLIST_CMD_LEN 2
1060 static const struct {
1061         const char *words[AST_MAX_CMD_LEN];
1062 } command_blacklist[] = {
1063         {{ "module", "load", NULL }},
1064         {{ "module", "unload", NULL }},
1065         {{ "restart", "gracefully", NULL }},
1066 };
1067
1068 static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *message);
1069
1070 static void acl_change_stasis_subscribe(void)
1071 {
1072         if (!acl_change_sub) {
1073                 acl_change_sub = stasis_subscribe(ast_acl_topic(),
1074                         acl_change_stasis_cb, NULL);
1075         }
1076 }
1077
1078 static void acl_change_stasis_unsubscribe(void)
1079 {
1080         if (acl_change_sub) {
1081                 acl_change_sub = stasis_unsubscribe(acl_change_sub);
1082         }
1083 }
1084
1085 /* In order to understand what the heck is going on with the
1086  * mansession_session and mansession structs, we need to have a bit of a history
1087  * lesson.
1088  *
1089  * In the beginning, there was the mansession. The mansession contained data that was
1090  * intrinsic to a manager session, such as the time that it started, the name of the logged-in
1091  * user, etc. In addition to these parameters were the f and fd parameters. For typical manager
1092  * sessions, these were used to represent the TCP socket over which the AMI session was taking
1093  * place. It makes perfect sense for these fields to be a part of the session-specific data since
1094  * the session actually defines this information.
1095  *
1096  * Then came the HTTP AMI sessions. With these, the f and fd fields need to be opened and closed
1097  * for every single action that occurs. Thus the f and fd fields aren't really specific to the session
1098  * but rather to the action that is being executed. Because a single session may execute many commands
1099  * at once, some sort of safety needed to be added in order to be sure that we did not end up with fd
1100  * leaks from one action overwriting the f and fd fields used by a previous action before the previous action
1101  * has had a chance to properly close its handles.
1102  *
1103  * The initial idea to solve this was to use thread synchronization, but this prevented multiple actions
1104  * from being run at the same time in a single session. Some manager actions may block for a long time, thus
1105  * creating a large queue of actions to execute. In addition, this fix did not address the basic architectural
1106  * issue that for HTTP manager sessions, the f and fd variables are not really a part of the session, but are
1107  * part of the action instead.
1108  *
1109  * The new idea was to create a structure on the stack for each HTTP Manager action. This structure would
1110  * contain the action-specific information, such as which file to write to. In order to maintain expectations
1111  * of action handlers and not have to change the public API of the manager code, we would need to name this
1112  * new stacked structure 'mansession' and contain within it the old mansession struct that we used to use.
1113  * We renamed the old mansession struct 'mansession_session' to hopefully convey that what is in this structure
1114  * is session-specific data. The structure that it is wrapped in, called a 'mansession' really contains action-specific
1115  * data.
1116  */
1117 struct mansession_session {
1118                                 /*! \todo XXX need to document which fields it is protecting */
1119         struct ast_sockaddr addr;       /*!< address we are connecting from */
1120         FILE *f;                /*!< fdopen() on the underlying fd */
1121         int fd;                 /*!< descriptor used for output. Either the socket (AMI) or a temporary file (HTTP) */
1122         int inuse;              /*!< number of HTTP sessions using this entry */
1123         int needdestroy;        /*!< Whether an HTTP session should be destroyed */
1124         pthread_t waiting_thread;       /*!< Sleeping thread using this descriptor */
1125         uint32_t managerid;     /*!< Unique manager identifier, 0 for AMI sessions */
1126         time_t sessionstart;    /*!< Session start time */
1127         struct timeval sessionstart_tv; /*!< Session start time */
1128         time_t sessiontimeout;  /*!< Session timeout if HTTP */
1129         char username[80];      /*!< Logged in username */
1130         char challenge[10];     /*!< Authentication challenge */
1131         int authenticated;      /*!< Authentication status */
1132         int readperm;           /*!< Authorization for reading */
1133         int writeperm;          /*!< Authorization for writing */
1134         char inbuf[1025];       /*!< Buffer -  we use the extra byte to add a '\\0' and simplify parsing */
1135         int inlen;              /*!< number of buffered bytes */
1136         struct ao2_container *whitefilters;     /*!< Manager event filters - white list */
1137         struct ao2_container *blackfilters;     /*!< Manager event filters - black list */
1138         struct ast_variable *chanvars;  /*!< Channel variables to set for originate */
1139         int send_events;        /*!<  XXX what ? */
1140         struct eventqent *last_ev;      /*!< last event processed. */
1141         int writetimeout;       /*!< Timeout for ast_carefulwrite() */
1142         time_t authstart;
1143         int pending_event;         /*!< Pending events indicator in case when waiting_thread is NULL */
1144         time_t noncetime;       /*!< Timer for nonce value expiration */
1145         unsigned long oldnonce; /*!< Stale nonce value */
1146         unsigned long nc;       /*!< incremental  nonce counter */
1147         AST_LIST_HEAD_NOLOCK(mansession_datastores, ast_datastore) datastores; /*!< Data stores on the session */
1148         AST_LIST_ENTRY(mansession_session) list;
1149 };
1150
1151 enum mansession_message_parsing {
1152         MESSAGE_OKAY,
1153         MESSAGE_LINE_TOO_LONG
1154 };
1155
1156 /*! \brief In case you didn't read that giant block of text above the mansession_session struct, the
1157  * \ref struct mansession is named this solely to keep the API the same in Asterisk. This structure really
1158  * represents data that is different from Manager action to Manager action. The mansession_session pointer
1159  * contained within points to session-specific data.
1160  */
1161 struct mansession {
1162         struct mansession_session *session;
1163         struct ast_tcptls_session_instance *tcptls_session;
1164         FILE *f;
1165         int fd;
1166         enum mansession_message_parsing parsing;
1167         int write_error:1;
1168         struct manager_custom_hook *hook;
1169         ast_mutex_t lock;
1170 };
1171
1172 static struct ao2_container *sessions = NULL;
1173
1174 /*! \brief user descriptor, as read from the config file.
1175  *
1176  * \note It is still missing some fields -- e.g. we can have multiple permit and deny
1177  * lines which are not supported here, and readperm/writeperm/writetimeout
1178  * are not stored.
1179  */
1180 struct ast_manager_user {
1181         char username[80];
1182         char *secret;                   /*!< Secret for logging in */
1183         int readperm;                   /*!< Authorization for reading */
1184         int writeperm;                  /*!< Authorization for writing */
1185         int writetimeout;               /*!< Per user Timeout for ast_carefulwrite() */
1186         int displayconnects;            /*!< XXX unused */
1187         int keep;                       /*!< mark entries created on a reload */
1188         struct ao2_container *whitefilters; /*!< Manager event filters - white list */
1189         struct ao2_container *blackfilters; /*!< Manager event filters - black list */
1190         struct ast_acl_list *acl;       /*!< ACL setting */
1191         char *a1_hash;                  /*!< precalculated A1 for Digest auth */
1192         struct ast_variable *chanvars;  /*!< Channel variables to set for originate */
1193         AST_RWLIST_ENTRY(ast_manager_user) list;
1194 };
1195
1196 /*! \brief list of users found in the config file */
1197 static AST_RWLIST_HEAD_STATIC(users, ast_manager_user);
1198
1199 /*! \brief list of actions registered */
1200 static AST_RWLIST_HEAD_STATIC(actions, manager_action);
1201
1202 /*! \brief list of hooks registered */
1203 static AST_RWLIST_HEAD_STATIC(manager_hooks, manager_custom_hook);
1204
1205 /*! \brief A container of event documentation nodes */
1206 AO2_GLOBAL_OBJ_STATIC(event_docs);
1207
1208 static enum add_filter_result manager_add_filter(const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters);
1209
1210 /*!
1211  * \internal
1212  * \brief Find a registered action object.
1213  *
1214  * \param name Name of AMI action to find.
1215  *
1216  * \return Reffed action found or NULL
1217  */
1218 static struct manager_action *action_find(const char *name)
1219 {
1220         struct manager_action *act;
1221
1222         AST_RWLIST_RDLOCK(&actions);
1223         AST_RWLIST_TRAVERSE(&actions, act, list) {
1224                 if (!strcasecmp(name, act->action)) {
1225                         ao2_t_ref(act, +1, "found action object");
1226                         break;
1227                 }
1228         }
1229         AST_RWLIST_UNLOCK(&actions);
1230
1231         return act;
1232 }
1233
1234 /*! \brief Add a custom hook to be called when an event is fired */
1235 void ast_manager_register_hook(struct manager_custom_hook *hook)
1236 {
1237         AST_RWLIST_WRLOCK(&manager_hooks);
1238         AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list);
1239         AST_RWLIST_UNLOCK(&manager_hooks);
1240 }
1241
1242 /*! \brief Delete a custom hook to be called when an event is fired */
1243 void ast_manager_unregister_hook(struct manager_custom_hook *hook)
1244 {
1245         AST_RWLIST_WRLOCK(&manager_hooks);
1246         AST_RWLIST_REMOVE(&manager_hooks, hook, list);
1247         AST_RWLIST_UNLOCK(&manager_hooks);
1248 }
1249
1250 int check_manager_enabled(void)
1251 {
1252         return manager_enabled;
1253 }
1254
1255 int check_webmanager_enabled(void)
1256 {
1257         return (webmanager_enabled && manager_enabled);
1258 }
1259
1260 /*!
1261  * Grab a reference to the last event, update usecount as needed.
1262  * Can handle a NULL pointer.
1263  */
1264 static struct eventqent *grab_last(void)
1265 {
1266         struct eventqent *ret;
1267
1268         AST_RWLIST_WRLOCK(&all_events);
1269         ret = AST_RWLIST_LAST(&all_events);
1270         /* the list is never empty now, but may become so when
1271          * we optimize it in the future, so be prepared.
1272          */
1273         if (ret) {
1274                 ast_atomic_fetchadd_int(&ret->usecount, 1);
1275         }
1276         AST_RWLIST_UNLOCK(&all_events);
1277         return ret;
1278 }
1279
1280 /*!
1281  * Purge unused events. Remove elements from the head
1282  * as long as their usecount is 0 and there is a next element.
1283  */
1284 static void purge_events(void)
1285 {
1286         struct eventqent *ev;
1287         struct timeval now = ast_tvnow();
1288
1289         AST_RWLIST_WRLOCK(&all_events);
1290         while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
1291             ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
1292                 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
1293                 ast_free(ev);
1294         }
1295
1296         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
1297                 /* Never release the last event */
1298                 if (!AST_RWLIST_NEXT(ev, eq_next)) {
1299                         break;
1300                 }
1301
1302                 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
1303                 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
1304                         AST_RWLIST_REMOVE_CURRENT(eq_next);
1305                         ast_free(ev);
1306                 }
1307         }
1308         AST_RWLIST_TRAVERSE_SAFE_END;
1309         AST_RWLIST_UNLOCK(&all_events);
1310 }
1311
1312 /*!
1313  * helper functions to convert back and forth between
1314  * string and numeric representation of set of flags
1315  */
1316 static const struct permalias {
1317         int num;
1318         const char *label;
1319 } perms[] = {
1320         { EVENT_FLAG_SYSTEM, "system" },
1321         { EVENT_FLAG_CALL, "call" },
1322         { EVENT_FLAG_LOG, "log" },
1323         { EVENT_FLAG_VERBOSE, "verbose" },
1324         { EVENT_FLAG_COMMAND, "command" },
1325         { EVENT_FLAG_AGENT, "agent" },
1326         { EVENT_FLAG_USER, "user" },
1327         { EVENT_FLAG_CONFIG, "config" },
1328         { EVENT_FLAG_DTMF, "dtmf" },
1329         { EVENT_FLAG_REPORTING, "reporting" },
1330         { EVENT_FLAG_CDR, "cdr" },
1331         { EVENT_FLAG_DIALPLAN, "dialplan" },
1332         { EVENT_FLAG_ORIGINATE, "originate" },
1333         { EVENT_FLAG_AGI, "agi" },
1334         { EVENT_FLAG_CC, "cc" },
1335         { EVENT_FLAG_AOC, "aoc" },
1336         { EVENT_FLAG_TEST, "test" },
1337         { EVENT_FLAG_MESSAGE, "message" },
1338         { INT_MAX, "all" },
1339         { 0, "none" },
1340 };
1341
1342 /*! \brief Checks to see if a string which can be used to evaluate functions should be rejected */
1343 static int function_capable_string_allowed_with_auths(const char *evaluating, int writepermlist)
1344 {
1345         if (!(writepermlist & EVENT_FLAG_SYSTEM)
1346                 && (
1347                         strstr(evaluating, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
1348                         strstr(evaluating, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
1349                 )) {
1350                 return 0;
1351         }
1352         return 1;
1353 }
1354
1355 /*! \brief Convert authority code to a list of options for a user. This will only
1356  * display those authority codes that have an explicit match on authority */
1357 static const char *user_authority_to_str(int authority, struct ast_str **res)
1358 {
1359         int i;
1360         char *sep = "";
1361
1362         ast_str_reset(*res);
1363         for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
1364                 if ((authority & perms[i].num) == perms[i].num) {
1365                         ast_str_append(res, 0, "%s%s", sep, perms[i].label);
1366                         sep = ",";
1367                 }
1368         }
1369
1370         if (ast_str_strlen(*res) == 0)  /* replace empty string with something sensible */
1371                 ast_str_append(res, 0, "<none>");
1372
1373         return ast_str_buffer(*res);
1374 }
1375
1376
1377 /*! \brief Convert authority code to a list of options. Note that the EVENT_FLAG_ALL
1378  * authority will always be returned. */
1379 static const char *authority_to_str(int authority, struct ast_str **res)
1380 {
1381         int i;
1382         char *sep = "";
1383
1384         ast_str_reset(*res);
1385         for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
1386                 if (authority & perms[i].num) {
1387                         ast_str_append(res, 0, "%s%s", sep, perms[i].label);
1388                         sep = ",";
1389                 }
1390         }
1391
1392         if (ast_str_strlen(*res) == 0)  /* replace empty string with something sensible */
1393                 ast_str_append(res, 0, "<none>");
1394
1395         return ast_str_buffer(*res);
1396 }
1397
1398 /*! Tells you if smallstr exists inside bigstr
1399    which is delim by delim and uses no buf or stringsep
1400    ast_instring("this|that|more","this",'|') == 1;
1401
1402    feel free to move this to app.c -anthm */
1403 static int ast_instring(const char *bigstr, const char *smallstr, const char delim)
1404 {
1405         const char *val = bigstr, *next;
1406
1407         do {
1408                 if ((next = strchr(val, delim))) {
1409                         if (!strncmp(val, smallstr, (next - val))) {
1410                                 return 1;
1411                         } else {
1412                                 continue;
1413                         }
1414                 } else {
1415                         return !strcmp(smallstr, val);
1416                 }
1417         } while (*(val = (next + 1)));
1418
1419         return 0;
1420 }
1421
1422 static int get_perm(const char *instr)
1423 {
1424         int x = 0, ret = 0;
1425
1426         if (!instr) {
1427                 return 0;
1428         }
1429
1430         for (x = 0; x < ARRAY_LEN(perms); x++) {
1431                 if (ast_instring(instr, perms[x].label, ',')) {
1432                         ret |= perms[x].num;
1433                 }
1434         }
1435
1436         return ret;
1437 }
1438
1439 /*!
1440  * A number returns itself, false returns 0, true returns all flags,
1441  * other strings return the flags that are set.
1442  */
1443 static int strings_to_mask(const char *string)
1444 {
1445         const char *p;
1446
1447         if (ast_strlen_zero(string)) {
1448                 return -1;
1449         }
1450
1451         for (p = string; *p; p++) {
1452                 if (*p < '0' || *p > '9') {
1453                         break;
1454                 }
1455         }
1456         if (!*p) { /* all digits */
1457                 return atoi(string);
1458         }
1459         if (ast_false(string)) {
1460                 return 0;
1461         }
1462         if (ast_true(string)) { /* all permissions */
1463                 int x, ret = 0;
1464                 for (x = 0; x < ARRAY_LEN(perms); x++) {
1465                         ret |= perms[x].num;
1466                 }
1467                 return ret;
1468         }
1469         return get_perm(string);
1470 }
1471
1472 /*! \brief Unreference manager session object.
1473      If no more references, then go ahead and delete it */
1474 static struct mansession_session *unref_mansession(struct mansession_session *s)
1475 {
1476         int refcount = ao2_ref(s, -1);
1477         if (manager_debug) {
1478                 ast_debug(1, "Mansession: %p refcount now %d\n", s, refcount - 1);
1479         }
1480         return s;
1481 }
1482
1483 static void event_filter_destructor(void *obj)
1484 {
1485         regex_t *regex_filter = obj;
1486         regfree(regex_filter);
1487 }
1488
1489 static void session_destructor(void *obj)
1490 {
1491         struct mansession_session *session = obj;
1492         struct eventqent *eqe = session->last_ev;
1493         struct ast_datastore *datastore;
1494
1495         /* Get rid of each of the data stores on the session */
1496         while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
1497                 /* Free the data store */
1498                 ast_datastore_free(datastore);
1499         }
1500
1501         if (session->f != NULL) {
1502                 fclose(session->f);
1503         }
1504         if (eqe) {
1505                 ast_atomic_fetchadd_int(&eqe->usecount, -1);
1506         }
1507         if (session->chanvars) {
1508                 ast_variables_destroy(session->chanvars);
1509         }
1510
1511         if (session->whitefilters) {
1512                 ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
1513                 ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one");
1514         }
1515
1516         if (session->blackfilters) {
1517                 ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
1518                 ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one");
1519         }
1520 }
1521
1522 /*! \brief Allocate manager session structure and add it to the list of sessions */
1523 static struct mansession_session *build_mansession(const struct ast_sockaddr *addr)
1524 {
1525         struct mansession_session *newsession;
1526
1527         if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
1528                 return NULL;
1529         }
1530
1531         if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
1532                 ao2_ref(newsession, -1);
1533                 return NULL;
1534         }
1535
1536         if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
1537                 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
1538                 return NULL;
1539         }
1540
1541         newsession->fd = -1;
1542         newsession->waiting_thread = AST_PTHREADT_NULL;
1543         newsession->writetimeout = 100;
1544         newsession->send_events = -1;
1545         ast_sockaddr_copy(&newsession->addr, addr);
1546
1547         ao2_link(sessions, newsession);
1548
1549         return newsession;
1550 }
1551
1552 static int mansession_cmp_fn(void *obj, void *arg, int flags)
1553 {
1554         struct mansession_session *s = obj;
1555         char *str = arg;
1556         return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
1557 }
1558
1559 static void session_destroy(struct mansession_session *s)
1560 {
1561         unref_mansession(s);
1562         ao2_unlink(sessions, s);
1563 }
1564
1565
1566 static int check_manager_session_inuse(const char *name)
1567 {
1568         struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
1569         int inuse = 0;
1570
1571         if (session) {
1572                 inuse = 1;
1573                 unref_mansession(session);
1574         }
1575         return inuse;
1576 }
1577
1578
1579 /*!
1580  * lookup an entry in the list of registered users.
1581  * must be called with the list lock held.
1582  */
1583 static struct ast_manager_user *get_manager_by_name_locked(const char *name)
1584 {
1585         struct ast_manager_user *user = NULL;
1586
1587         AST_RWLIST_TRAVERSE(&users, user, list) {
1588                 if (!strcasecmp(user->username, name)) {
1589                         break;
1590                 }
1591         }
1592
1593         return user;
1594 }
1595
1596 /*! \brief Get displayconnects config option.
1597  *  \param session manager session to get parameter from.
1598  *  \return displayconnects config option value.
1599  */
1600 static int manager_displayconnects (struct mansession_session *session)
1601 {
1602         struct ast_manager_user *user = NULL;
1603         int ret = 0;
1604
1605         AST_RWLIST_RDLOCK(&users);
1606         if ((user = get_manager_by_name_locked (session->username))) {
1607                 ret = user->displayconnects;
1608         }
1609         AST_RWLIST_UNLOCK(&users);
1610
1611         return ret;
1612 }
1613
1614 static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1615 {
1616         struct manager_action *cur;
1617         struct ast_str *authority;
1618         int num, l, which;
1619         char *ret = NULL;
1620 #ifdef AST_XML_DOCS
1621         char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64], privilege_title[64];
1622 #endif
1623
1624         switch (cmd) {
1625         case CLI_INIT:
1626                 e->command = "manager show command";
1627                 e->usage =
1628                         "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
1629                         "       Shows the detailed description for a specific Asterisk manager interface command.\n";
1630                 return NULL;
1631         case CLI_GENERATE:
1632                 l = strlen(a->word);
1633                 which = 0;
1634                 AST_RWLIST_RDLOCK(&actions);
1635                 AST_RWLIST_TRAVERSE(&actions, cur, list) {
1636                         if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
1637                                 ret = ast_strdup(cur->action);
1638                                 break;  /* make sure we exit even if ast_strdup() returns NULL */
1639                         }
1640                 }
1641                 AST_RWLIST_UNLOCK(&actions);
1642                 return ret;
1643         }
1644         authority = ast_str_alloca(80);
1645         if (a->argc < 4) {
1646                 return CLI_SHOWUSAGE;
1647         }
1648
1649 #ifdef AST_XML_DOCS
1650         /* setup the titles */
1651         term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1652         term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
1653         term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1654         term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
1655         term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
1656         term_color(privilege_title, "[Privilege]\n", COLOR_MAGENTA, 0, 40);
1657 #endif
1658
1659         AST_RWLIST_RDLOCK(&actions);
1660         AST_RWLIST_TRAVERSE(&actions, cur, list) {
1661                 for (num = 3; num < a->argc; num++) {
1662                         if (!strcasecmp(cur->action, a->argv[num])) {
1663                                 authority_to_str(cur->authority, &authority);
1664
1665 #ifdef AST_XML_DOCS
1666                                 if (cur->docsrc == AST_XML_DOC) {
1667                                         ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
1668                                                 syntax_title,
1669                                                 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
1670                                                 synopsis_title,
1671                                                 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
1672                                                 description_title,
1673                                                 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
1674                                                 arguments_title,
1675                                                 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
1676                                                 seealso_title,
1677                                                 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1),
1678                                                 privilege_title,
1679                                                 ast_xmldoc_printable(S_OR(authority->str, "Not available"), 1));
1680                                 } else
1681 #endif
1682                                 {
1683                                         ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
1684                                                 cur->action, cur->synopsis,
1685                                                 authority->str,
1686                                                 S_OR(cur->description, ""));
1687                                 }
1688                         }
1689                 }
1690         }
1691         AST_RWLIST_UNLOCK(&actions);
1692
1693         return CLI_SUCCESS;
1694 }
1695
1696 static char *handle_mandebug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1697 {
1698         switch (cmd) {
1699         case CLI_INIT:
1700                 e->command = "manager set debug [on|off]";
1701                 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
1702                 return NULL;
1703         case CLI_GENERATE:
1704                 return NULL;
1705         }
1706
1707         if (a->argc == 3) {
1708                 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
1709         } else if (a->argc == 4) {
1710                 if (!strcasecmp(a->argv[3], "on")) {
1711                         manager_debug = 1;
1712                 } else if (!strcasecmp(a->argv[3], "off")) {
1713                         manager_debug = 0;
1714                 } else {
1715                         return CLI_SHOWUSAGE;
1716                 }
1717         }
1718         return CLI_SUCCESS;
1719 }
1720
1721 static char *handle_showmanager(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1722 {
1723         struct ast_manager_user *user = NULL;
1724         int l, which;
1725         char *ret = NULL;
1726         struct ast_str *rauthority = ast_str_alloca(128);
1727         struct ast_str *wauthority = ast_str_alloca(128);
1728         struct ast_variable *v;
1729
1730         switch (cmd) {
1731         case CLI_INIT:
1732                 e->command = "manager show user";
1733                 e->usage =
1734                         " Usage: manager show user <user>\n"
1735                         "        Display all information related to the manager user specified.\n";
1736                 return NULL;
1737         case CLI_GENERATE:
1738                 l = strlen(a->word);
1739                 which = 0;
1740                 if (a->pos != 3) {
1741                         return NULL;
1742                 }
1743                 AST_RWLIST_RDLOCK(&users);
1744                 AST_RWLIST_TRAVERSE(&users, user, list) {
1745                         if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
1746                                 ret = ast_strdup(user->username);
1747                                 break;
1748                         }
1749                 }
1750                 AST_RWLIST_UNLOCK(&users);
1751                 return ret;
1752         }
1753
1754         if (a->argc != 4) {
1755                 return CLI_SHOWUSAGE;
1756         }
1757
1758         AST_RWLIST_RDLOCK(&users);
1759
1760         if (!(user = get_manager_by_name_locked(a->argv[3]))) {
1761                 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
1762                 AST_RWLIST_UNLOCK(&users);
1763                 return CLI_SUCCESS;
1764         }
1765
1766         ast_cli(a->fd, "\n");
1767         ast_cli(a->fd,
1768                 "       username: %s\n"
1769                 "         secret: %s\n"
1770                 "            ACL: %s\n"
1771                 "      read perm: %s\n"
1772                 "     write perm: %s\n"
1773                 "displayconnects: %s\n",
1774                 (user->username ? user->username : "(N/A)"),
1775                 (user->secret ? "<Set>" : "(N/A)"),
1776                 ((user->acl && !ast_acl_list_is_empty(user->acl)) ? "yes" : "no"),
1777                 user_authority_to_str(user->readperm, &rauthority),
1778                 user_authority_to_str(user->writeperm, &wauthority),
1779                 (user->displayconnects ? "yes" : "no"));
1780         ast_cli(a->fd, "      Variables: \n");
1781                 for (v = user->chanvars ; v ; v = v->next) {
1782                         ast_cli(a->fd, "                 %s = %s\n", v->name, v->value);
1783                 }
1784
1785         AST_RWLIST_UNLOCK(&users);
1786
1787         return CLI_SUCCESS;
1788 }
1789
1790 static char *handle_showmanagers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1791 {
1792         struct ast_manager_user *user = NULL;
1793         int count_amu = 0;
1794         switch (cmd) {
1795         case CLI_INIT:
1796                 e->command = "manager show users";
1797                 e->usage =
1798                         "Usage: manager show users\n"
1799                         "       Prints a listing of all managers that are currently configured on that\n"
1800                         " system.\n";
1801                 return NULL;
1802         case CLI_GENERATE:
1803                 return NULL;
1804         }
1805         if (a->argc != 3) {
1806                 return CLI_SHOWUSAGE;
1807         }
1808
1809         AST_RWLIST_RDLOCK(&users);
1810
1811         /* If there are no users, print out something along those lines */
1812         if (AST_RWLIST_EMPTY(&users)) {
1813                 ast_cli(a->fd, "There are no manager users.\n");
1814                 AST_RWLIST_UNLOCK(&users);
1815                 return CLI_SUCCESS;
1816         }
1817
1818         ast_cli(a->fd, "\nusername\n--------\n");
1819
1820         AST_RWLIST_TRAVERSE(&users, user, list) {
1821                 ast_cli(a->fd, "%s\n", user->username);
1822                 count_amu++;
1823         }
1824
1825         AST_RWLIST_UNLOCK(&users);
1826
1827         ast_cli(a->fd,"-------------------\n"
1828                       "%d manager users configured.\n", count_amu);
1829         return CLI_SUCCESS;
1830 }
1831
1832 /*! \brief  CLI command  manager list commands */
1833 static char *handle_showmancmds(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1834 {
1835         struct manager_action *cur;
1836         int name_len = 1;
1837         int space_remaining;
1838 #define HSMC_FORMAT "  %-*.*s  %-.*s\n"
1839         switch (cmd) {
1840         case CLI_INIT:
1841                 e->command = "manager show commands";
1842                 e->usage =
1843                         "Usage: manager show commands\n"
1844                         "       Prints a listing of all the available Asterisk manager interface commands.\n";
1845                 return NULL;
1846         case CLI_GENERATE:
1847                 return NULL;
1848         }
1849
1850         AST_RWLIST_RDLOCK(&actions);
1851         AST_RWLIST_TRAVERSE(&actions, cur, list) {
1852                 int incoming_len = strlen(cur->action);
1853                 if (incoming_len > name_len) {
1854                         name_len = incoming_len;
1855                 }
1856         }
1857
1858         space_remaining = MGR_SHOW_TERMINAL_WIDTH - name_len - 4;
1859         if (space_remaining < 0) {
1860                 space_remaining = 0;
1861         }
1862
1863         ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "Action", space_remaining, "Synopsis");
1864         ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "------", space_remaining, "--------");
1865
1866         AST_RWLIST_TRAVERSE(&actions, cur, list) {
1867                 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, cur->action, space_remaining, cur->synopsis);
1868         }
1869         AST_RWLIST_UNLOCK(&actions);
1870
1871         return CLI_SUCCESS;
1872 }
1873
1874 /*! \brief CLI command manager list connected */
1875 static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1876 {
1877         struct mansession_session *session;
1878         time_t now = time(NULL);
1879 #define HSMCONN_FORMAT1 "  %-15.15s  %-55.55s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
1880 #define HSMCONN_FORMAT2 "  %-15.15s  %-55.55s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
1881         int count = 0;
1882         struct ao2_iterator i;
1883
1884         switch (cmd) {
1885         case CLI_INIT:
1886                 e->command = "manager show connected";
1887                 e->usage =
1888                         "Usage: manager show connected\n"
1889                         "       Prints a listing of the users that are currently connected to the\n"
1890                         "Asterisk manager interface.\n";
1891                 return NULL;
1892         case CLI_GENERATE:
1893                 return NULL;
1894         }
1895
1896         ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
1897
1898         i = ao2_iterator_init(sessions, 0);
1899         while ((session = ao2_iterator_next(&i))) {
1900                 ao2_lock(session);
1901                 ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_sockaddr_stringify_addr(&session->addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
1902                 count++;
1903                 ao2_unlock(session);
1904                 unref_mansession(session);
1905         }
1906         ao2_iterator_destroy(&i);
1907         ast_cli(a->fd, "%d users connected.\n", count);
1908
1909         return CLI_SUCCESS;
1910 }
1911
1912 /*! \brief CLI command manager list eventq */
1913 /* Should change to "manager show connected" */
1914 static char *handle_showmaneventq(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1915 {
1916         struct eventqent *s;
1917         switch (cmd) {
1918         case CLI_INIT:
1919                 e->command = "manager show eventq";
1920                 e->usage =
1921                         "Usage: manager show eventq\n"
1922                         "       Prints a listing of all events pending in the Asterisk manger\n"
1923                         "event queue.\n";
1924                 return NULL;
1925         case CLI_GENERATE:
1926                 return NULL;
1927         }
1928         AST_RWLIST_RDLOCK(&all_events);
1929         AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
1930                 ast_cli(a->fd, "Usecount: %d\n", s->usecount);
1931                 ast_cli(a->fd, "Category: %d\n", s->category);
1932                 ast_cli(a->fd, "Event:\n%s", s->eventdata);
1933         }
1934         AST_RWLIST_UNLOCK(&all_events);
1935
1936         return CLI_SUCCESS;
1937 }
1938
1939 /*! \brief CLI command manager reload */
1940 static char *handle_manager_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1941 {
1942         switch (cmd) {
1943         case CLI_INIT:
1944                 e->command = "manager reload";
1945                 e->usage =
1946                         "Usage: manager reload\n"
1947                         "       Reloads the manager configuration.\n";
1948                 return NULL;
1949         case CLI_GENERATE:
1950                 return NULL;
1951         }
1952         if (a->argc > 2) {
1953                 return CLI_SHOWUSAGE;
1954         }
1955         reload_manager();
1956         return CLI_SUCCESS;
1957 }
1958
1959 static struct eventqent *advance_event(struct eventqent *e)
1960 {
1961         struct eventqent *next;
1962
1963         AST_RWLIST_RDLOCK(&all_events);
1964         if ((next = AST_RWLIST_NEXT(e, eq_next))) {
1965                 ast_atomic_fetchadd_int(&next->usecount, 1);
1966                 ast_atomic_fetchadd_int(&e->usecount, -1);
1967         }
1968         AST_RWLIST_UNLOCK(&all_events);
1969         return next;
1970 }
1971
1972 #define GET_HEADER_FIRST_MATCH  0
1973 #define GET_HEADER_LAST_MATCH   1
1974 #define GET_HEADER_SKIP_EMPTY   2
1975
1976 /*!
1977  * \brief Return a matching header value.
1978  *
1979  * \details
1980  * Generic function to return either the first or the last
1981  * matching header from a list of variables, possibly skipping
1982  * empty strings.
1983  *
1984  * \note At the moment there is only one use of this function in
1985  * this file, so we make it static.
1986  *
1987  * \note Never returns NULL.
1988  */
1989 static const char *__astman_get_header(const struct message *m, char *var, int mode)
1990 {
1991         int x, l = strlen(var);
1992         const char *result = "";
1993
1994         if (!m) {
1995                 return result;
1996         }
1997
1998         for (x = 0; x < m->hdrcount; x++) {
1999                 const char *h = m->headers[x];
2000                 if (!strncasecmp(var, h, l) && h[l] == ':') {
2001                         const char *value = h + l + 1;
2002                         value = ast_skip_blanks(value); /* ignore leading spaces in the value */
2003                         /* found a potential candidate */
2004                         if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
2005                                 continue;       /* not interesting */
2006                         }
2007                         if (mode & GET_HEADER_LAST_MATCH) {
2008                                 result = value; /* record the last match so far */
2009                         } else {
2010                                 return value;
2011                         }
2012                 }
2013         }
2014
2015         return result;
2016 }
2017
2018 /*!
2019  * \brief Return the first matching variable from an array.
2020  *
2021  * \note This is the legacy function and is implemented in
2022  * therms of __astman_get_header().
2023  *
2024  * \note Never returns NULL.
2025  */
2026 const char *astman_get_header(const struct message *m, char *var)
2027 {
2028         return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
2029 }
2030
2031 /*!
2032  * \internal
2033  * \brief Process one "Variable:" header value string.
2034  *
2035  * \param head Current list of AMI variables to get new values added.
2036  * \param hdr_val Header value string to process.
2037  *
2038  * \return New variable list head.
2039  */
2040 static struct ast_variable *man_do_variable_value(struct ast_variable *head, const char *hdr_val)
2041 {
2042         char *parse;
2043         AST_DECLARE_APP_ARGS(args,
2044                 AST_APP_ARG(vars)[64];
2045         );
2046
2047         hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
2048         parse = ast_strdupa(hdr_val);
2049
2050         /* Break the header value string into name=val pair items. */
2051         AST_STANDARD_APP_ARGS(args, parse);
2052         if (args.argc) {
2053                 int y;
2054
2055                 /* Process each name=val pair item. */
2056                 for (y = 0; y < args.argc; y++) {
2057                         struct ast_variable *cur;
2058                         char *var;
2059                         char *val;
2060
2061                         if (!args.vars[y]) {
2062                                 continue;
2063                         }
2064                         var = val = args.vars[y];
2065                         strsep(&val, "=");
2066
2067                         /* XXX We may wish to trim whitespace from the strings. */
2068                         if (!val || ast_strlen_zero(var)) {
2069                                 continue;
2070                         }
2071
2072                         /* Create new variable list node and prepend it to the list. */
2073                         cur = ast_variable_new(var, val, "");
2074                         if (cur) {
2075                                 cur->next = head;
2076                                 head = cur;
2077                         }
2078                 }
2079         }
2080
2081         return head;
2082 }
2083
2084 struct ast_variable *astman_get_variables(const struct message *m)
2085 {
2086         int varlen;
2087         int x;
2088         struct ast_variable *head = NULL;
2089
2090         static const char var_hdr[] = "Variable:";
2091
2092         /* Process all "Variable:" headers. */
2093         varlen = strlen(var_hdr);
2094         for (x = 0; x < m->hdrcount; x++) {
2095                 if (strncasecmp(var_hdr, m->headers[x], varlen)) {
2096                         continue;
2097                 }
2098                 head = man_do_variable_value(head, m->headers[x] + varlen);
2099         }
2100
2101         return head;
2102 }
2103
2104 /*! \brief access for hooks to send action messages to ami */
2105 int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
2106 {
2107         const char *action;
2108         int ret = 0;
2109         struct manager_action *act_found;
2110         struct mansession s = {.session = NULL, };
2111         struct message m = { 0 };
2112         char *dup_str;
2113         char *src;
2114         int x = 0;
2115         int curlen;
2116
2117         if (hook == NULL) {
2118                 return -1;
2119         }
2120
2121         /* Create our own copy of the AMI action msg string. */
2122         src = dup_str = ast_strdup(msg);
2123         if (!dup_str) {
2124                 return -1;
2125         }
2126
2127         /* convert msg string to message struct */
2128         curlen = strlen(src);
2129         for (x = 0; x < curlen; x++) {
2130                 int cr; /* set if we have \r */
2131                 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
2132                         cr = 2; /* Found. Update length to include \r\n */
2133                 else if (src[x] == '\n')
2134                         cr = 1; /* also accept \n only */
2135                 else
2136                         continue;
2137                 /* don't keep empty lines */
2138                 if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
2139                         /* ... but trim \r\n and terminate the header string */
2140                         src[x] = '\0';
2141                         m.headers[m.hdrcount++] = src;
2142                 }
2143                 x += cr;
2144                 curlen -= x;            /* remaining size */
2145                 src += x;               /* update pointer */
2146                 x = -1;                 /* reset loop */
2147         }
2148
2149         action = astman_get_header(&m, "Action");
2150         if (strcasecmp(action, "login")) {
2151                 act_found = action_find(action);
2152                 if (act_found) {
2153                         /*
2154                          * we have to simulate a session for this action request
2155                          * to be able to pass it down for processing
2156                          * This is necessary to meet the previous design of manager.c
2157                          */
2158                         s.hook = hook;
2159                         s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
2160
2161                         ao2_lock(act_found);
2162                         if (act_found->registered && act_found->func) {
2163                                 if (act_found->module) {
2164                                         ast_module_ref(act_found->module);
2165                                 }
2166                                 ao2_unlock(act_found);
2167                                 ret = act_found->func(&s, &m);
2168                                 ao2_lock(act_found);
2169                                 if (act_found->module) {
2170                                         ast_module_unref(act_found->module);
2171                                 }
2172                         } else {
2173                                 ret = -1;
2174                         }
2175                         ao2_unlock(act_found);
2176                         ao2_t_ref(act_found, -1, "done with found action object");
2177                 }
2178         }
2179         ast_free(dup_str);
2180         return ret;
2181 }
2182
2183
2184 /*!
2185  * helper function to send a string to the socket.
2186  * Return -1 on error (e.g. buffer full).
2187  */
2188 static int send_string(struct mansession *s, char *string)
2189 {
2190         int res;
2191         FILE *f = s->f ? s->f : s->session->f;
2192         int fd = s->f ? s->fd : s->session->fd;
2193
2194         /* It's a result from one of the hook's action invocation */
2195         if (s->hook) {
2196                 /*
2197                  * to send responses, we're using the same function
2198                  * as for receiving events. We call the event "HookResponse"
2199                  */
2200                 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
2201                 return 0;
2202         }
2203
2204         if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
2205                 s->write_error = 1;
2206         }
2207
2208         return res;
2209 }
2210
2211 /*!
2212  * \brief thread local buffer for astman_append
2213  *
2214  * \note This can not be defined within the astman_append() function
2215  *       because it declares a couple of functions that get used to
2216  *       initialize the thread local storage key.
2217  */
2218 AST_THREADSTORAGE(astman_append_buf);
2219
2220 AST_THREADSTORAGE(userevent_buf);
2221
2222 /*! \brief initial allocated size for the astman_append_buf and astman_send_*_va */
2223 #define ASTMAN_APPEND_BUF_INITSIZE   256
2224
2225 /*!
2226  * utility functions for creating AMI replies
2227  */
2228 void astman_append(struct mansession *s, const char *fmt, ...)
2229 {
2230         va_list ap;
2231         struct ast_str *buf;
2232
2233         if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
2234                 return;
2235         }
2236
2237         va_start(ap, fmt);
2238         ast_str_set_va(&buf, 0, fmt, ap);
2239         va_end(ap);
2240
2241         if (s->f != NULL || s->session->f != NULL) {
2242                 send_string(s, ast_str_buffer(buf));
2243         } else {
2244                 ast_verbose("fd == -1 in astman_append, should not happen\n");
2245         }
2246 }
2247
2248 /*! \note NOTE: XXX this comment is unclear and possibly wrong.
2249    Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER
2250    hold the session lock _or_ be running in an action callback (in which case s->session->busy will
2251    be non-zero). In either of these cases, there is no need to lock-protect the session's
2252    fd, since no other output will be sent (events will be queued), and no input will
2253    be read until either the current action finishes or get_input() obtains the session
2254    lock.
2255  */
2256
2257 /*! \todo XXX MSG_MOREDATA should go to a header file. */
2258 #define MSG_MOREDATA    ((char *)astman_send_response)
2259
2260 /*! \brief send a response with an optional message,
2261  * and terminate it with an empty line.
2262  * m is used only to grab the 'ActionID' field.
2263  *
2264  * Use the explicit constant MSG_MOREDATA to remove the empty line.
2265  * XXX MSG_MOREDATA should go to a header file.
2266  */
2267 static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
2268 {
2269         const char *id = astman_get_header(m, "ActionID");
2270
2271         astman_append(s, "Response: %s\r\n", resp);
2272         if (!ast_strlen_zero(id)) {
2273                 astman_append(s, "ActionID: %s\r\n", id);
2274         }
2275         if (listflag) {
2276                 astman_append(s, "EventList: %s\r\n", listflag);        /* Start, complete, cancelled */
2277         }
2278         if (msg == MSG_MOREDATA) {
2279                 return;
2280         } else if (msg) {
2281                 astman_append(s, "Message: %s\r\n\r\n", msg);
2282         } else {
2283                 astman_append(s, "\r\n");
2284         }
2285 }
2286
2287 void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
2288 {
2289         astman_send_response_full(s, m, resp, msg, NULL);
2290 }
2291
2292 void astman_send_error(struct mansession *s, const struct message *m, char *error)
2293 {
2294         astman_send_response_full(s, m, "Error", error, NULL);
2295 }
2296
2297 void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt, ...)
2298 {
2299         va_list ap;
2300         struct ast_str *buf;
2301         char *msg;
2302
2303         if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
2304                 return;
2305         }
2306
2307         va_start(ap, fmt);
2308         ast_str_set_va(&buf, 0, fmt, ap);
2309         va_end(ap);
2310
2311         /* astman_append will use the same underlying buffer, so copy the message out
2312          * before sending the response */
2313         msg = ast_str_buffer(buf);
2314         if (msg) {
2315                 msg = ast_strdupa(msg);
2316         }
2317         astman_send_response_full(s, m, "Error", msg, NULL);
2318 }
2319
2320 void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
2321 {
2322         astman_send_response_full(s, m, "Success", msg, NULL);
2323 }
2324
2325 static void astman_start_ack(struct mansession *s, const struct message *m)
2326 {
2327         astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
2328 }
2329
2330 void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
2331 {
2332         astman_send_response_full(s, m, "Success", msg, listflag);
2333 }
2334
2335 /*! \brief Lock the 'mansession' structure. */
2336 static void mansession_lock(struct mansession *s)
2337 {
2338         ast_mutex_lock(&s->lock);
2339 }
2340
2341 /*! \brief Unlock the 'mansession' structure. */
2342 static void mansession_unlock(struct mansession *s)
2343 {
2344         ast_mutex_unlock(&s->lock);
2345 }
2346
2347 /*! \brief
2348    Rather than braindead on,off this now can also accept a specific int mask value
2349    or a ',' delim list of mask strings (the same as manager.conf) -anthm
2350 */
2351 static int set_eventmask(struct mansession *s, const char *eventmask)
2352 {
2353         int maskint = strings_to_mask(eventmask);
2354
2355         ao2_lock(s->session);
2356         if (maskint >= 0) {
2357                 s->session->send_events = maskint;
2358         }
2359         ao2_unlock(s->session);
2360
2361         return maskint;
2362 }
2363
2364 static enum ast_security_event_transport_type mansession_get_transport(const struct mansession *s)
2365 {
2366         return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS :
2367                         AST_SECURITY_EVENT_TRANSPORT_TCP;
2368 }
2369
2370 static void report_invalid_user(const struct mansession *s, const char *username)
2371 {
2372         char session_id[32];
2373         struct ast_security_event_inval_acct_id inval_acct_id = {
2374                 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
2375                 .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
2376                 .common.service    = "AMI",
2377                 .common.account_id = username,
2378                 .common.session_tv = &s->session->sessionstart_tv,
2379                 .common.local_addr = {
2380                         .addr      = &s->tcptls_session->parent->local_address,
2381                         .transport = mansession_get_transport(s),
2382                 },
2383                 .common.remote_addr = {
2384                         .addr      = &s->session->addr,
2385                         .transport = mansession_get_transport(s),
2386                 },
2387                 .common.session_id = session_id,
2388         };
2389
2390         snprintf(session_id, sizeof(session_id), "%p", s);
2391
2392         ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
2393 }
2394
2395 static void report_failed_acl(const struct mansession *s, const char *username)
2396 {
2397         char session_id[32];
2398         struct ast_security_event_failed_acl failed_acl_event = {
2399                 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
2400                 .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
2401                 .common.service    = "AMI",
2402                 .common.account_id = username,
2403                 .common.session_tv = &s->session->sessionstart_tv,
2404                 .common.local_addr = {
2405                         .addr      = &s->tcptls_session->parent->local_address,
2406                         .transport = mansession_get_transport(s),
2407                 },
2408                 .common.remote_addr = {
2409                         .addr      = &s->session->addr,
2410                         .transport = mansession_get_transport(s),
2411                 },
2412                 .common.session_id = session_id,
2413         };
2414
2415         snprintf(session_id, sizeof(session_id), "%p", s->session);
2416
2417         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
2418 }
2419
2420 static void report_inval_password(const struct mansession *s, const char *username)
2421 {
2422         char session_id[32];
2423         struct ast_security_event_inval_password inval_password = {
2424                 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
2425                 .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
2426                 .common.service    = "AMI",
2427                 .common.account_id = username,
2428                 .common.session_tv = &s->session->sessionstart_tv,
2429                 .common.local_addr = {
2430                         .addr      = &s->tcptls_session->parent->local_address,
2431                         .transport = mansession_get_transport(s),
2432                 },
2433                 .common.remote_addr = {
2434                         .addr      = &s->session->addr,
2435                         .transport = mansession_get_transport(s),
2436                 },
2437                 .common.session_id = session_id,
2438         };
2439
2440         snprintf(session_id, sizeof(session_id), "%p", s->session);
2441
2442         ast_security_event_report(AST_SEC_EVT(&inval_password));
2443 }
2444
2445 static void report_auth_success(const struct mansession *s)
2446 {
2447         char session_id[32];
2448         struct ast_security_event_successful_auth successful_auth = {
2449                 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
2450                 .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
2451                 .common.service    = "AMI",
2452                 .common.account_id = s->session->username,
2453                 .common.session_tv = &s->session->sessionstart_tv,
2454                 .common.local_addr = {
2455                         .addr      = &s->tcptls_session->parent->local_address,
2456                         .transport = mansession_get_transport(s),
2457                 },
2458                 .common.remote_addr = {
2459                         .addr      = &s->session->addr,
2460                         .transport = mansession_get_transport(s),
2461                 },
2462                 .common.session_id = session_id,
2463         };
2464
2465         snprintf(session_id, sizeof(session_id), "%p", s->session);
2466
2467         ast_security_event_report(AST_SEC_EVT(&successful_auth));
2468 }
2469
2470 static void report_req_not_allowed(const struct mansession *s, const char *action)
2471 {
2472         char session_id[32];
2473         char request_type[64];
2474         struct ast_security_event_req_not_allowed req_not_allowed = {
2475                 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
2476                 .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
2477                 .common.service    = "AMI",
2478                 .common.account_id = s->session->username,
2479                 .common.session_tv = &s->session->sessionstart_tv,
2480                 .common.local_addr = {
2481                         .addr      = &s->tcptls_session->parent->local_address,
2482                         .transport = mansession_get_transport(s),
2483                 },
2484                 .common.remote_addr = {
2485                         .addr      = &s->session->addr,
2486                         .transport = mansession_get_transport(s),
2487                 },
2488                 .common.session_id = session_id,
2489
2490                 .request_type      = request_type,
2491         };
2492
2493         snprintf(session_id, sizeof(session_id), "%p", s->session);
2494         snprintf(request_type, sizeof(request_type), "Action: %s", action);
2495
2496         ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
2497 }
2498
2499 static void report_req_bad_format(const struct mansession *s, const char *action)
2500 {
2501         char session_id[32];
2502         char request_type[64];
2503         struct ast_security_event_req_bad_format req_bad_format = {
2504                 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
2505                 .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
2506                 .common.service    = "AMI",
2507                 .common.account_id = s->session->username,
2508                 .common.session_tv = &s->session->sessionstart_tv,
2509                 .common.local_addr = {
2510                         .addr      = &s->tcptls_session->parent->local_address,
2511                         .transport = mansession_get_transport(s),
2512                 },
2513                 .common.remote_addr = {
2514                         .addr      = &s->session->addr,
2515                         .transport = mansession_get_transport(s),
2516                 },
2517                 .common.session_id = session_id,
2518
2519                 .request_type      = request_type,
2520         };
2521
2522         snprintf(session_id, sizeof(session_id), "%p", s->session);
2523         snprintf(request_type, sizeof(request_type), "Action: %s", action);
2524
2525         ast_security_event_report(AST_SEC_EVT(&req_bad_format));
2526 }
2527
2528 static void report_failed_challenge_response(const struct mansession *s,
2529                 const char *response, const char *expected_response)
2530 {
2531         char session_id[32];
2532         struct ast_security_event_chal_resp_failed chal_resp_failed = {
2533                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
2534                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
2535                 .common.service    = "AMI",
2536                 .common.account_id = s->session->username,
2537                 .common.session_tv = &s->session->sessionstart_tv,
2538                 .common.local_addr = {
2539                         .addr      = &s->tcptls_session->parent->local_address,
2540                         .transport = mansession_get_transport(s),
2541                 },
2542                 .common.remote_addr = {
2543                         .addr      = &s->session->addr,
2544                         .transport = mansession_get_transport(s),
2545                 },
2546                 .common.session_id = session_id,
2547
2548                 .challenge         = s->session->challenge,
2549                 .response          = response,
2550                 .expected_response = expected_response,
2551         };
2552
2553         snprintf(session_id, sizeof(session_id), "%p", s->session);
2554
2555         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
2556 }
2557
2558 static void report_session_limit(const struct mansession *s)
2559 {
2560         char session_id[32];
2561         struct ast_security_event_session_limit session_limit = {
2562                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
2563                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
2564                 .common.service    = "AMI",
2565                 .common.account_id = s->session->username,
2566                 .common.session_tv = &s->session->sessionstart_tv,
2567                 .common.local_addr = {
2568                         .addr      = &s->tcptls_session->parent->local_address,
2569                         .transport = mansession_get_transport(s),
2570                 },
2571                 .common.remote_addr = {
2572                         .addr      = &s->session->addr,
2573                         .transport = mansession_get_transport(s),
2574                 },
2575                 .common.session_id = session_id,
2576         };
2577
2578         snprintf(session_id, sizeof(session_id), "%p", s->session);
2579
2580         ast_security_event_report(AST_SEC_EVT(&session_limit));
2581 }
2582
2583 /*
2584  * Here we start with action_ handlers for AMI actions,
2585  * and the internal functions used by them.
2586  * Generally, the handlers are called action_foo()
2587  */
2588
2589 /* helper function for action_login() */
2590 static int authenticate(struct mansession *s, const struct message *m)
2591 {
2592         const char *username = astman_get_header(m, "Username");
2593         const char *password = astman_get_header(m, "Secret");
2594         int error = -1;
2595         struct ast_manager_user *user = NULL;
2596         regex_t *regex_filter;
2597         struct ao2_iterator filter_iter;
2598
2599         if (ast_strlen_zero(username)) {        /* missing username */
2600                 return -1;
2601         }
2602
2603         /* locate user in locked state */
2604         AST_RWLIST_WRLOCK(&users);
2605
2606         if (!(user = get_manager_by_name_locked(username))) {
2607                 report_invalid_user(s, username);
2608                 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2609         } else if (user->acl && (ast_apply_acl(user->acl, &s->session->addr, "Manager User ACL: ") == AST_SENSE_DENY)) {
2610                 report_failed_acl(s, username);
2611                 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2612         } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
2613                 const char *key = astman_get_header(m, "Key");
2614                 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
2615                         int x;
2616                         int len = 0;
2617                         char md5key[256] = "";
2618                         struct MD5Context md5;
2619                         unsigned char digest[16];
2620
2621                         MD5Init(&md5);
2622                         MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
2623                         MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
2624                         MD5Final(digest, &md5);
2625                         for (x = 0; x < 16; x++)
2626                                 len += sprintf(md5key + len, "%2.2x", digest[x]);
2627                         if (!strcmp(md5key, key)) {
2628                                 error = 0;
2629                         } else {
2630                                 report_failed_challenge_response(s, key, md5key);
2631                         }
2632                 } else {
2633                         ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
2634                                 S_OR(s->session->challenge, ""));
2635                 }
2636         } else if (user->secret) {
2637                 if (!strcmp(password, user->secret)) {
2638                         error = 0;
2639                 } else {
2640                         report_inval_password(s, username);
2641                 }
2642         }
2643
2644         if (error) {
2645                 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2646                 AST_RWLIST_UNLOCK(&users);
2647                 return -1;
2648         }
2649
2650         /* auth complete */
2651
2652         /* All of the user parameters are copied to the session so that in the event
2653         * of a reload and a configuration change, the session parameters are not
2654         * changed. */
2655         ast_copy_string(s->session->username, username, sizeof(s->session->username));
2656         s->session->readperm = user->readperm;
2657         s->session->writeperm = user->writeperm;
2658         s->session->writetimeout = user->writetimeout;
2659         if (user->chanvars) {
2660                 s->session->chanvars = ast_variables_dup(user->chanvars);
2661         }
2662
2663         filter_iter = ao2_iterator_init(user->whitefilters, 0);
2664         while ((regex_filter = ao2_iterator_next(&filter_iter))) {
2665                 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
2666                 ao2_t_ref(regex_filter, -1, "remove iterator ref");
2667         }
2668         ao2_iterator_destroy(&filter_iter);
2669
2670         filter_iter = ao2_iterator_init(user->blackfilters, 0);
2671         while ((regex_filter = ao2_iterator_next(&filter_iter))) {
2672                 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
2673                 ao2_t_ref(regex_filter, -1, "remove iterator ref");
2674         }
2675         ao2_iterator_destroy(&filter_iter);
2676
2677         s->session->sessionstart = time(NULL);
2678         s->session->sessionstart_tv = ast_tvnow();
2679         set_eventmask(s, astman_get_header(m, "Events"));
2680
2681         report_auth_success(s);
2682
2683         AST_RWLIST_UNLOCK(&users);
2684         return 0;
2685 }
2686
2687 static int action_ping(struct mansession *s, const struct message *m)
2688 {
2689         const char *actionid = astman_get_header(m, "ActionID");
2690         struct timeval now = ast_tvnow();
2691
2692         astman_append(s, "Response: Success\r\n");
2693         if (!ast_strlen_zero(actionid)){
2694                 astman_append(s, "ActionID: %s\r\n", actionid);
2695         }
2696         astman_append(
2697                 s,
2698                 "Ping: Pong\r\n"
2699                 "Timestamp: %ld.%06lu\r\n"
2700                 "\r\n",
2701                 (long) now.tv_sec, (unsigned long) now.tv_usec);
2702         return 0;
2703 }
2704
2705 static int action_getconfig(struct mansession *s, const struct message *m)
2706 {
2707         struct ast_config *cfg;
2708         const char *fn = astman_get_header(m, "Filename");
2709         const char *category = astman_get_header(m, "Category");
2710         int catcount = 0;
2711         int lineno = 0;
2712         char *cur_category = NULL;
2713         struct ast_variable *v;
2714         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2715
2716         if (ast_strlen_zero(fn)) {
2717                 astman_send_error(s, m, "Filename not specified");
2718                 return 0;
2719         }
2720         cfg = ast_config_load2(fn, "manager", config_flags);
2721         if (cfg == CONFIG_STATUS_FILEMISSING) {
2722                 astman_send_error(s, m, "Config file not found");
2723                 return 0;
2724         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2725                 astman_send_error(s, m, "Config file has invalid format");
2726                 return 0;
2727         }
2728
2729         astman_start_ack(s, m);
2730         while ((cur_category = ast_category_browse(cfg, cur_category))) {
2731                 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
2732                         lineno = 0;
2733                         astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
2734                         for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
2735                                 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
2736                         }
2737                         catcount++;
2738                 }
2739         }
2740         if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2741                 astman_append(s, "No categories found\r\n");
2742         }
2743         ast_config_destroy(cfg);
2744         astman_append(s, "\r\n");
2745
2746         return 0;
2747 }
2748
2749 static int action_listcategories(struct mansession *s, const struct message *m)
2750 {
2751         struct ast_config *cfg;
2752         const char *fn = astman_get_header(m, "Filename");
2753         char *category = NULL;
2754         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2755         int catcount = 0;
2756
2757         if (ast_strlen_zero(fn)) {
2758                 astman_send_error(s, m, "Filename not specified");
2759                 return 0;
2760         }
2761         if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2762                 astman_send_error(s, m, "Config file not found");
2763                 return 0;
2764         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2765                 astman_send_error(s, m, "Config file has invalid format");
2766                 return 0;
2767         }
2768         astman_start_ack(s, m);
2769         while ((category = ast_category_browse(cfg, category))) {
2770                 astman_append(s, "Category-%06d: %s\r\n", catcount, category);
2771                 catcount++;
2772         }
2773         if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2774                 astman_append(s, "Error: no categories found\r\n");
2775         }
2776         ast_config_destroy(cfg);
2777         astman_append(s, "\r\n");
2778
2779         return 0;
2780 }
2781
2782
2783
2784
2785 /*! The amount of space in out must be at least ( 2 * strlen(in) + 1 ) */
2786 static void json_escape(char *out, const char *in)
2787 {
2788         for (; *in; in++) {
2789                 if (*in == '\\' || *in == '\"') {
2790                         *out++ = '\\';
2791                 }
2792                 *out++ = *in;
2793         }
2794         *out = '\0';
2795 }
2796
2797 /*!
2798  * \internal
2799  * \brief Append a JSON escaped string to the manager stream.
2800  *
2801  * \param s AMI stream to append a string.
2802  * \param str String to append to the stream after JSON escaping it.
2803  *
2804  * \return Nothing
2805  */
2806 static void astman_append_json(struct mansession *s, const char *str)
2807 {
2808         char *buf;
2809
2810         buf = ast_alloca(2 * strlen(str) + 1);
2811         json_escape(buf, str);
2812         astman_append(s, "%s", buf);
2813 }
2814
2815 static int action_getconfigjson(struct mansession *s, const struct message *m)
2816 {
2817         struct ast_config *cfg;
2818         const char *fn = astman_get_header(m, "Filename");
2819         char *category = NULL;
2820         struct ast_variable *v;
2821         int comma1 = 0;
2822         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2823
2824         if (ast_strlen_zero(fn)) {
2825                 astman_send_error(s, m, "Filename not specified");
2826                 return 0;
2827         }
2828
2829         if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2830                 astman_send_error(s, m, "Config file not found");
2831                 return 0;
2832         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2833                 astman_send_error(s, m, "Config file has invalid format");
2834                 return 0;
2835         }
2836
2837         astman_start_ack(s, m);
2838         astman_append(s, "JSON: {");
2839         while ((category = ast_category_browse(cfg, category))) {
2840                 int comma2 = 0;
2841
2842                 astman_append(s, "%s\"", comma1 ? "," : "");
2843                 astman_append_json(s, category);
2844                 astman_append(s, "\":[");
2845                 comma1 = 1;
2846                 for (v = ast_variable_browse(cfg, category); v; v = v->next) {
2847                         astman_append(s, "%s\"", comma2 ? "," : "");
2848                         astman_append_json(s, v->name);
2849                         astman_append(s, "\":\"");
2850                         astman_append_json(s, v->value);
2851                         astman_append(s, "\"");
2852                         comma2 = 1;
2853                 }
2854                 astman_append(s, "]");
2855         }
2856         astman_append(s, "}\r\n\r\n");
2857
2858         ast_config_destroy(cfg);
2859
2860         return 0;
2861 }
2862
2863 /*! \brief helper function for action_updateconfig */
2864 static enum error_type handle_updates(struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
2865 {
2866         int x;
2867         char hdr[40];
2868         const char *action, *cat, *var, *value, *match, *line;
2869         struct ast_category *category;
2870         struct ast_variable *v;
2871         struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
2872         enum error_type result = 0;
2873
2874         for (x = 0; x < 100000; x++) {  /* 100000 = the max number of allowed updates + 1 */
2875                 unsigned int object = 0;
2876
2877                 snprintf(hdr, sizeof(hdr), "Action-%06d", x);
2878                 action = astman_get_header(m, hdr);
2879                 if (ast_strlen_zero(action))            /* breaks the for loop if no action header */
2880                         break;                          /* this could cause problems if actions come in misnumbered */
2881
2882                 snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
2883                 cat = astman_get_header(m, hdr);
2884                 if (ast_strlen_zero(cat)) {             /* every action needs a category */
2885                         result =  UNSPECIFIED_CATEGORY;
2886                         break;
2887                 }
2888
2889                 snprintf(hdr, sizeof(hdr), "Var-%06d", x);
2890                 var = astman_get_header(m, hdr);
2891
2892                 snprintf(hdr, sizeof(hdr), "Value-%06d", x);
2893                 value = astman_get_header(m, hdr);
2894
2895                 if (!ast_strlen_zero(value) && *value == '>') {
2896                         object = 1;
2897                         value++;
2898                 }
2899
2900                 snprintf(hdr, sizeof(hdr), "Match-%06d", x);
2901                 match = astman_get_header(m, hdr);
2902
2903                 snprintf(hdr, sizeof(hdr), "Line-%06d", x);
2904                 line = astman_get_header(m, hdr);
2905
2906                 if (!strcasecmp(action, "newcat")) {
2907                         if (ast_category_get(cfg,cat)) {        /* check to make sure the cat doesn't */
2908                                 result = FAILURE_NEWCAT;        /* already exist */
2909                                 break;
2910                         }
2911                         if (!(category = ast_category_new(cat, dfn, -1))) {
2912                                 result = FAILURE_ALLOCATION;
2913                                 break;
2914                         }
2915                         if (ast_strlen_zero(match)) {
2916                                 ast_category_append(cfg, category);
2917                         } else {
2918                                 ast_category_insert(cfg, category, match);
2919                         }
2920                 } else if (!strcasecmp(action, "renamecat")) {
2921                         if (ast_strlen_zero(value)) {
2922                                 result = UNSPECIFIED_ARGUMENT;
2923                                 break;
2924                         }
2925                         if (!(category = ast_category_get(cfg, cat))) {
2926                                 result = UNKNOWN_CATEGORY;
2927                                 break;
2928                         }
2929                         ast_category_rename(category, value);
2930                 } else if (!strcasecmp(action, "delcat")) {
2931                         if (ast_category_delete(cfg, cat)) {
2932                                 result = FAILURE_DELCAT;
2933                                 break;
2934                         }
2935                 } else if (!strcasecmp(action, "emptycat")) {
2936                         if (ast_category_empty(cfg, cat)) {
2937                                 result = FAILURE_EMPTYCAT;
2938                                 break;
2939                         }
2940                 } else if (!strcasecmp(action, "update")) {
2941                         if (ast_strlen_zero(var)) {
2942                                 result = UNSPECIFIED_ARGUMENT;
2943                                 break;
2944                         }
2945                         if (!(category = ast_category_get(cfg,cat))) {
2946                                 result = UNKNOWN_CATEGORY;
2947                                 break;
2948                         }
2949                         if (ast_variable_update(category, var, value, match, object)) {
2950                                 result = FAILURE_UPDATE;
2951                                 break;
2952                         }
2953                 } else if (!strcasecmp(action, "delete")) {
2954                         if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
2955                                 result = UNSPECIFIED_ARGUMENT;
2956                                 break;
2957                         }
2958                         if (!(category = ast_category_get(cfg, cat))) {
2959                                 result = UNKNOWN_CATEGORY;
2960                                 break;
2961                         }
2962                         if (ast_variable_delete(category, var, match, line)) {
2963                                 result = FAILURE_DELETE;
2964                                 break;
2965                         }
2966                 } else if (!strcasecmp(action, "append")) {
2967                         if (ast_strlen_zero(var)) {
2968                                 result = UNSPECIFIED_ARGUMENT;
2969                                 break;
2970                         }
2971                         if (!(category = ast_category_get(cfg, cat))) {
2972                                 result = UNKNOWN_CATEGORY;
2973                                 break;
2974                         }
2975                         if (!(v = ast_variable_new(var, value, dfn))) {
2976                                 result = FAILURE_ALLOCATION;
2977                                 break;
2978                         }
2979                         if (object || (match && !strcasecmp(match, "object"))) {
2980                                 v->object = 1;
2981                         }
2982                         ast_variable_append(category, v);
2983                 } else if (!strcasecmp(action, "insert")) {
2984                         if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
2985                                 result = UNSPECIFIED_ARGUMENT;
2986                                 break;
2987                         }
2988                         if (!(category = ast_category_get(cfg, cat))) {
2989                                 result = UNKNOWN_CATEGORY;
2990                                 break;
2991                         }
2992                         if (!(v = ast_variable_new(var, value, dfn))) {
2993                                 result = FAILURE_ALLOCATION;
2994                                 break;
2995                         }
2996                         ast_variable_insert(category, v, line);
2997                 }
2998                 else {
2999                         ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
3000                         result = UNKNOWN_ACTION;
3001                         break;
3002                 }
3003         }
3004         ast_free(str1);
3005         ast_free(str2);
3006         return result;
3007 }
3008
3009 static int action_updateconfig(struct mansession *s, const struct message *m)
3010 {
3011         struct ast_config *cfg;
3012         const char *sfn = astman_get_header(m, "SrcFilename");
3013         const char *dfn = astman_get_header(m, "DstFilename");
3014         int res;
3015         const char *rld = astman_get_header(m, "Reload");
3016         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
3017         enum error_type result;
3018
3019         if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
3020                 astman_send_error(s, m, "Filename not specified");
3021                 return 0;
3022         }
3023         if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
3024                 astman_send_error(s, m, "Config file not found");
3025                 return 0;
3026         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
3027                 astman_send_error(s, m, "Config file has invalid format");
3028                 return 0;
3029         }
3030         result = handle_updates(s, m, cfg, dfn);
3031         if (!result) {
3032                 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
3033                 res = ast_config_text_file_save(dfn, cfg, "Manager");
3034                 ast_config_destroy(cfg);
3035                 if (res) {
3036                         astman_send_error(s, m, "Save of config failed");
3037                         return 0;
3038                 }
3039                 astman_send_ack(s, m, NULL);
3040                 if (!ast_strlen_zero(rld)) {
3041                         if (ast_true(rld)) {
3042                                 rld = NULL;
3043                         }
3044                         ast_module_reload(rld);
3045                 }
3046         } else {
3047                 ast_config_destroy(cfg);
3048                 switch(result) {
3049                 case UNKNOWN_ACTION:
3050                         astman_send_error(s, m, "Unknown action command");
3051                         break;
3052                 case UNKNOWN_CATEGORY:
3053                         astman_send_error(s, m, "Given category does not exist");
3054                         break;
3055                 case UNSPECIFIED_CATEGORY:
3056                         astman_send_error(s, m, "Category not specified");
3057                         break;
3058                 case UNSPECIFIED_ARGUMENT:
3059                         astman_send_error(s, m, "Problem with category, value, or line (if required)");
3060                         break;
3061                 case FAILURE_ALLOCATION:
3062                         astman_send_error(s, m, "Memory allocation failure, this should not happen");
3063                         break;
3064                 case FAILURE_NEWCAT:
3065                         astman_send_error(s, m, "Create category did not complete successfully");
3066                         break;
3067                 case FAILURE_DELCAT:
3068                         astman_send_error(s, m, "Delete category did not complete successfully");
3069                         break;
3070                 case FAILURE_EMPTYCAT:
3071                         astman_send_error(s, m, "Empty category did not complete successfully");
3072                         break;
3073                 case FAILURE_UPDATE:
3074                         astman_send_error(s, m, "Update did not complete successfully");
3075                         break;
3076                 case FAILURE_DELETE:
3077                         astman_send_error(s, m, "Delete did not complete successfully");
3078                         break;
3079                 case FAILURE_APPEND:
3080                         astman_send_error(s, m, "Append did not complete successfully");
3081                         break;
3082                 }
3083         }
3084         return 0;
3085 }
3086
3087 static int action_createconfig(struct mansession *s, const struct message *m)
3088 {
3089         int fd;
3090         const char *fn = astman_get_header(m, "Filename");
3091         struct ast_str *filepath = ast_str_alloca(PATH_MAX);
3092         ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
3093         ast_str_append(&filepath, 0, "%s", fn);
3094
3095         if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
3096                 close(fd);
3097                 astman_send_ack(s, m, "New configuration file created successfully");
3098         } else {
3099                 astman_send_error(s, m, strerror(errno));
3100         }
3101
3102         return 0;
3103 }
3104
3105 static int action_waitevent(struct mansession *s, const struct message *m)
3106 {
3107         const char *timeouts = astman_get_header(m, "Timeout");
3108         int timeout = -1;
3109         int x;
3110         int needexit = 0;
3111         const char *id = astman_get_header(m, "ActionID");
3112         char idText[256];
3113
3114         if (!ast_strlen_zero(id)) {
3115                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3116         } else {
3117                 idText[0] = '\0';
3118         }
3119
3120         if (!ast_strlen_zero(timeouts)) {
3121                 sscanf(timeouts, "%30i", &timeout);
3122                 if (timeout < -1) {
3123                         timeout = -1;
3124                 }
3125                 /* XXX maybe put an upper bound, or prevent the use of 0 ? */
3126         }
3127
3128         ao2_lock(s->session);
3129         if (s->session->waiting_thread != AST_PTHREADT_NULL) {
3130                 pthread_kill(s->session->waiting_thread, SIGURG);
3131         }
3132
3133         if (s->session->managerid) { /* AMI-over-HTTP session */
3134                 /*
3135                  * Make sure the timeout is within the expire time of the session,
3136                  * as the client will likely abort the request if it does not see
3137                  * data coming after some amount of time.
3138                  */
3139                 time_t now = time(NULL);
3140                 int max = s->session->sessiontimeout - now - 10;
3141
3142                 if (max < 0) {  /* We are already late. Strange but possible. */
3143                         max = 0;
3144                 }
3145                 if (timeout < 0 || timeout > max) {
3146                         timeout = max;
3147                 }
3148                 if (!s->session->send_events) { /* make sure we record events */
3149                         s->session->send_events = -1;
3150                 }
3151         }
3152         ao2_unlock(s->session);
3153
3154         /* XXX should this go inside the lock ? */
3155         s->session->waiting_thread = pthread_self();    /* let new events wake up this thread */
3156         ast_debug(1, "Starting waiting for an event!\n");
3157
3158         for (x = 0; x < timeout || timeout < 0; x++) {
3159                 ao2_lock(s->session);
3160                 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
3161                         needexit = 1;
3162                 }
3163                 /* We can have multiple HTTP session point to the same mansession entry.
3164                  * The way we deal with it is not very nice: newcomers kick out the previous
3165                  * HTTP session. XXX this needs to be improved.
3166                  */
3167                 if (s->session->waiting_thread != pthread_self()) {
3168                         needexit = 1;
3169                 }
3170                 if (s->session->needdestroy) {
3171                         needexit = 1;
3172                 }
3173                 ao2_unlock(s->session);
3174                 if (needexit) {
3175                         break;
3176                 }
3177                 if (s->session->managerid == 0) {       /* AMI session */
3178                         if (ast_wait_for_input(s->session->fd, 1000)) {
3179                                 break;
3180                         }
3181                 } else {        /* HTTP session */
3182                         sleep(1);
3183                 }
3184         }
3185         ast_debug(1, "Finished waiting for an event!\n");
3186
3187         ao2_lock(s->session);
3188         if (s->session->waiting_thread == pthread_self()) {
3189                 struct eventqent *eqe = s->session->last_ev;
3190                 astman_send_response(s, m, "Success", "Waiting for Event completed.");
3191                 while ((eqe = advance_event(eqe))) {
3192                         if (((s->session->readperm & eqe->category) == eqe->category) &&
3193                             ((s->session->send_events & eqe->category) == eqe->category)) {
3194                                 astman_append(s, "%s", eqe->eventdata);
3195                         }
3196                         s->session->last_ev = eqe;
3197                 }
3198                 astman_append(s,
3199                         "Event: WaitEventComplete\r\n"
3200                         "%s"
3201                         "\r\n", idText);
3202                 s->session->waiting_thread = AST_PTHREADT_NULL;
3203         } else {
3204                 ast_debug(1, "Abandoning event request!\n");
3205         }
3206         ao2_unlock(s->session);
3207
3208         return 0;
3209 }
3210
3211 static int action_listcommands(struct mansession *s, const struct message *m)
3212 {
3213         struct manager_action *cur;
3214         struct ast_str *temp = ast_str_alloca(256);
3215
3216         astman_start_ack(s, m);
3217         AST_RWLIST_RDLOCK(&actions);
3218         AST_RWLIST_TRAVERSE(&actions, cur, list) {
3219                 if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
3220                         astman_append(s, "%s: %s (Priv: %s)\r\n",
3221                                 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
3222                 }
3223         }
3224         AST_RWLIST_UNLOCK(&actions);
3225         astman_append(s, "\r\n");
3226
3227         return 0;
3228 }
3229
3230 static int action_events(struct mansession *s, const struct message *m)
3231 {
3232         const char *mask = astman_get_header(m, "EventMask");
3233         int res, x;
3234         const char *id = astman_get_header(m, "ActionID");
3235         char id_text[256];
3236
3237         if (!ast_strlen_zero(id)) {
3238                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
3239         } else {
3240                 id_text[0] = '\0';
3241         }
3242
3243         res = set_eventmask(s, mask);
3244         if (broken_events_action) {
3245                 /* if this option is set we should not return a response on
3246                  * error, or when all events are set */
3247
3248                 if (res > 0) {
3249                         for (x = 0; x < ARRAY_LEN(perms); x++) {
3250                                 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
3251                                         return 0;
3252                                 }
3253                         }
3254                         astman_append(s, "Response: Success\r\n%s"
3255                                          "Events: On\r\n\r\n", id_text);
3256                 } else if (res == 0)
3257                         astman_append(s, "Response: Success\r\n%s"
3258                                          "Events: Off\r\n\r\n", id_text);
3259                 return 0;
3260         }
3261
3262         if (res > 0)
3263                 astman_append(s, "Response: Success\r\n%s"
3264                                  "Events: On\r\n\r\n", id_text);
3265         else if (res == 0)
3266                 astman_append(s, "Response: Success\r\n%s"
3267                                  "Events: Off\r\n\r\n", id_text);
3268         else
3269                 astman_send_error(s, m, "Invalid event mask");
3270
3271         return 0;
3272 }
3273
3274 static int action_logoff(struct mansession *s, const struct message *m)
3275 {
3276         astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
3277         return -1;
3278 }
3279
3280 static int action_login(struct mansession *s, const struct message *m)
3281 {
3282
3283         /* still authenticated - don't process again */
3284         if (s->session->authenticated) {
3285                 astman_send_ack(s, m, "Already authenticated");
3286                 return 0;
3287         }
3288
3289         if (authenticate(s, m)) {
3290                 sleep(1);
3291                 astman_send_error(s, m, "Authentication failed");
3292                 return -1;
3293         }
3294         s->session->authenticated = 1;
3295         ast_atomic_fetchadd_int(&unauth_sessions, -1);
3296         if (manager_displayconnects(s->session)) {
3297                 ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_sockaddr_stringify_addr(&s->session->addr));
3298         }
3299         astman_send_ack(s, m, "Authentication accepted");
3300         if ((s->session->send_events & EVENT_FLAG_SYSTEM)
3301                 && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
3302                 struct ast_str *auth = ast_str_alloca(80);
3303                 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
3304                 astman_append(s, "Event: FullyBooted\r\n"
3305                         "Privilege: %s\r\n"
3306                         "Status: Fully Booted\r\n\r\n", cat_str);
3307         }
3308         return 0;
3309 }
3310
3311 static int action_challenge(struct mansession *s, const struct message *m)
3312 {
3313         const char *authtype = astman_get_header(m, "AuthType");
3314
3315         if (!strcasecmp(authtype, "MD5")) {
3316                 if (ast_strlen_zero(s->session->challenge)) {
3317                         snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
3318                 }
3319                 mansession_lock(s);
3320                 astman_start_ack(s, m);
3321                 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
3322                 mansession_unlock(s);
3323         } else {
3324                 astman_send_error(s, m, "Must specify AuthType");
3325         }
3326         return 0;
3327 }
3328
3329 static int action_hangup(struct mansession *s, const struct message *m)
3330 {
3331         struct ast_channel *c = NULL;
3332         int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
3333         const char *id = astman_get_header(m, "ActionID");
3334         const char *name_or_regex = astman_get_header(m, "Channel");
3335         const char *cause = astman_get_header(m, "Cause");
3336         char idText[256];
3337         regex_t regexbuf;
3338         struct ast_channel_iterator *iter = NULL;
3339         struct ast_str *regex_string;
3340         int channels_matched = 0;
3341
3342         if (ast_strlen_zero(name_or_regex)) {
3343                 astman_send_error(s, m, "No channel specified");
3344                 return 0;
3345         }
3346
3347         if (!ast_strlen_zero(id)) {
3348                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3349         } else {
3350                 idText[0] = '\0';
3351         }
3352
3353         if (!ast_strlen_zero(cause)) {
3354                 char *endptr;
3355                 causecode = strtol(cause, &endptr, 10);
3356                 if (causecode < 0 || causecode > 127 || *endptr != '\0') {
3357                         ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
3358                         /* keep going, better to hangup without cause than to not hang up at all */
3359                         causecode = 0; /* do not set channel's hangupcause */
3360                 }
3361         }
3362
3363         /************************************************/
3364         /* Regular explicit match channel byname hangup */
3365
3366         if (name_or_regex[0] != '/') {
3367                 if (!(c = ast_channel_get_by_name(name_or_regex))) {
3368                         ast_log(LOG_NOTICE, "!!!!!!!!!! Can't find channel to hang up!\n");
3369                         astman_send_error(s, m, "No such channel");
3370                         return 0;
3371                 }
3372
3373                 ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
3374                         (s->session->managerid ? "HTTP " : ""),
3375                         s->session->username,
3376                         ast_sockaddr_stringify_addr(&s->session->addr),
3377                         ast_channel_name(c));
3378
3379                 ast_channel_softhangup_withcause_locked(c, causecode);
3380                 c = ast_channel_unref(c);
3381
3382                 astman_send_ack(s, m, "Channel Hungup");
3383
3384                 return 0;
3385         }
3386
3387         /***********************************************/
3388         /* find and hangup any channels matching regex */
3389
3390         regex_string = ast_str_create(strlen(name_or_regex));
3391         if (!regex_string) {
3392                 astman_send_error(s, m, "Memory Allocation Failure");
3393                 return 0;
3394         }
3395
3396         /* Make "/regex/" into "regex" */
3397         if (ast_regex_string_to_regex_pattern(name_or_regex, &regex_string) != 0) {
3398                 astman_send_error(s, m, "Regex format invalid, Channel param should be /regex/");
3399                 ast_free(regex_string);
3400                 return 0;
3401         }
3402
3403         /* if regex compilation fails, hangup fails */
3404         if (regcomp(&regexbuf, ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
3405                 astman_send_error_va(s, m, "Regex compile failed on: %s", name_or_regex);
3406                 ast_free(regex_string);
3407                 return 0;
3408         }
3409
3410         astman_send_listack(s, m, "Channels hung up will follow", "start");
3411
3412         iter = ast_channel_iterator_all_new();
3413         if (iter) {
3414                 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
3415                         if (regexec(&regexbuf, ast_channel_name(c), 0, NULL, 0)) {
3416                                 continue;
3417                         }
3418
3419                         ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
3420                                 (s->session->managerid ? "HTTP " : ""),
3421                                 s->session->username,
3422                                 ast_sockaddr_stringify_addr(&s->session->addr),
3423                                 ast_channel_name(c));
3424
3425                         ast_channel_softhangup_withcause_locked(c, causecode);
3426                         channels_matched++;
3427
3428                         astman_append(s,
3429                                 "Event: ChannelHungup\r\n"
3430                                 "Channel: %s\r\n"
3431                                 "%s"
3432                                 "\r\n", ast_channel_name(c), idText);
3433                 }
3434                 ast_channel_iterator_destroy(iter);
3435         }
3436
3437         regfree(&regexbuf);
3438         ast_free(regex_string);
3439
3440         astman_append(s,
3441                 "Event: ChannelsHungupListComplete\r\n"
3442                 "EventList: Complete\r\n"
3443                 "ListItems: %d\r\n"
3444                 "%s"
3445                 "\r\n", channels_matched, idText);
3446
3447         return 0;
3448 }
3449
3450 static int action_setvar(struct mansession *s, const struct message *m)
3451 {
3452         struct ast_channel *c = NULL;
3453         const char *name = astman_get_header(m, "Channel");
3454         const char *varname = astman_get_header(m, "Variable");
3455         const char *varval = astman_get_header(m, "Value");
3456         int res = 0;
3457
3458         if (ast_strlen_zero(varname)) {
3459                 astman_send_error(s, m, "No variable specified");
3460                 return 0;
3461         }
3462
3463         if (!ast_strlen_zero(name)) {
3464                 if (!(c = ast_channel_get_by_name(name))) {
3465                         astman_send_error(s, m, "No such channel");
3466                         return 0;
3467                 }
3468         }
3469
3470         res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
3471
3472         if (c) {
3473                 c = ast_channel_unref(c);
3474         }
3475         if (res == 0) {
3476                 astman_send_ack(s, m, "Variable Set");
3477         } else {
3478                 astman_send_error(s, m, "Variable not set");
3479         }
3480         return 0;
3481 }
3482
3483 static int action_getvar(struct mansession *s, const struct message *m)
3484 {
3485         struct ast_channel *c = NULL;
3486         const char *name = astman_get_header(m, "Channel");
3487         const char *varname = astman_get_header(m, "Variable");
3488         char *varval;