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