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