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