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