Event well was going dry.
[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                 /* Never release the last event */
1068                 if (!AST_RWLIST_NEXT(ev, eq_next)) {
1069                         break;
1070                 }
1071
1072                 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
1073                 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
1074                         AST_RWLIST_REMOVE_CURRENT(eq_next);
1075                         ast_free(ev);
1076                 }
1077         }
1078         AST_RWLIST_TRAVERSE_SAFE_END;
1079         AST_RWLIST_UNLOCK(&all_events);
1080 }
1081
1082 /*!
1083  * helper functions to convert back and forth between
1084  * string and numeric representation of set of flags
1085  */
1086 static const struct permalias {
1087         int num;
1088         const char *label;
1089 } perms[] = {
1090         { EVENT_FLAG_SYSTEM, "system" },
1091         { EVENT_FLAG_CALL, "call" },
1092         { EVENT_FLAG_LOG, "log" },
1093         { EVENT_FLAG_VERBOSE, "verbose" },
1094         { EVENT_FLAG_COMMAND, "command" },
1095         { EVENT_FLAG_AGENT, "agent" },
1096         { EVENT_FLAG_USER, "user" },
1097         { EVENT_FLAG_CONFIG, "config" },
1098         { EVENT_FLAG_DTMF, "dtmf" },
1099         { EVENT_FLAG_REPORTING, "reporting" },
1100         { EVENT_FLAG_CDR, "cdr" },
1101         { EVENT_FLAG_DIALPLAN, "dialplan" },
1102         { EVENT_FLAG_ORIGINATE, "originate" },
1103         { EVENT_FLAG_AGI, "agi" },
1104         { EVENT_FLAG_CC, "cc" },
1105         { EVENT_FLAG_AOC, "aoc" },
1106         { INT_MAX, "all" },
1107         { 0, "none" },
1108 };
1109
1110 /*! \brief Convert authority code to a list of options */
1111 static const char *authority_to_str(int authority, struct ast_str **res)
1112 {
1113         int i;
1114         char *sep = "";
1115
1116         ast_str_reset(*res);
1117         for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
1118                 if (authority & perms[i].num) {
1119                         ast_str_append(res, 0, "%s%s", sep, perms[i].label);
1120                         sep = ",";
1121                 }
1122         }
1123
1124         if (ast_str_strlen(*res) == 0)  /* replace empty string with something sensible */
1125                 ast_str_append(res, 0, "<none>");
1126
1127         return ast_str_buffer(*res);
1128 }
1129
1130 /*! Tells you if smallstr exists inside bigstr
1131    which is delim by delim and uses no buf or stringsep
1132    ast_instring("this|that|more","this",'|') == 1;
1133
1134    feel free to move this to app.c -anthm */
1135 static int ast_instring(const char *bigstr, const char *smallstr, const char delim)
1136 {
1137         const char *val = bigstr, *next;
1138
1139         do {
1140                 if ((next = strchr(val, delim))) {
1141                         if (!strncmp(val, smallstr, (next - val))) {
1142                                 return 1;
1143                         } else {
1144                                 continue;
1145                         }
1146                 } else {
1147                         return !strcmp(smallstr, val);
1148                 }
1149         } while (*(val = (next + 1)));
1150
1151         return 0;
1152 }
1153
1154 static int get_perm(const char *instr)
1155 {
1156         int x = 0, ret = 0;
1157
1158         if (!instr) {
1159                 return 0;
1160         }
1161
1162         for (x = 0; x < ARRAY_LEN(perms); x++) {
1163                 if (ast_instring(instr, perms[x].label, ',')) {
1164                         ret |= perms[x].num;
1165                 }
1166         }
1167
1168         return ret;
1169 }
1170
1171 /*!
1172  * A number returns itself, false returns 0, true returns all flags,
1173  * other strings return the flags that are set.
1174  */
1175 static int strings_to_mask(const char *string)
1176 {
1177         const char *p;
1178
1179         if (ast_strlen_zero(string)) {
1180                 return -1;
1181         }
1182
1183         for (p = string; *p; p++) {
1184                 if (*p < '0' || *p > '9') {
1185                         break;
1186                 }
1187         }
1188         if (!*p) { /* all digits */
1189                 return atoi(string);
1190         }
1191         if (ast_false(string)) {
1192                 return 0;
1193         }
1194         if (ast_true(string)) { /* all permissions */
1195                 int x, ret = 0;
1196                 for (x = 0; x < ARRAY_LEN(perms); x++) {
1197                         ret |= perms[x].num;
1198                 }
1199                 return ret;
1200         }
1201         return get_perm(string);
1202 }
1203
1204 /*! \brief Unreference manager session object.
1205      If no more references, then go ahead and delete it */
1206 static struct mansession_session *unref_mansession(struct mansession_session *s)
1207 {
1208         int refcount = ao2_ref(s, -1);
1209         if (manager_debug) {
1210                 ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
1211         }
1212         return s;
1213 }
1214
1215 static void session_destructor(void *obj)
1216 {
1217         struct mansession_session *session = obj;
1218         struct eventqent *eqe = session->last_ev;
1219         struct ast_datastore *datastore;
1220
1221         /* Get rid of each of the data stores on the session */
1222         while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
1223                 /* Free the data store */
1224                 ast_datastore_free(datastore);
1225         }
1226
1227         if (session->f != NULL) {
1228                 fclose(session->f);
1229         }
1230         if (eqe) {
1231                 ast_atomic_fetchadd_int(&eqe->usecount, -1);
1232         }
1233 }
1234
1235 /*! \brief Allocate manager session structure and add it to the list of sessions */
1236 static struct mansession_session *build_mansession(struct sockaddr_in sin)
1237 {
1238         struct mansession_session *newsession;
1239
1240         if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
1241                 return NULL;
1242         }
1243         newsession->fd = -1;
1244         newsession->waiting_thread = AST_PTHREADT_NULL;
1245         newsession->writetimeout = 100;
1246         newsession->send_events = -1;
1247         newsession->sin = sin;
1248
1249         ao2_link(sessions, newsession);
1250
1251         return newsession;
1252 }
1253
1254 static int mansession_cmp_fn(void *obj, void *arg, int flags)
1255 {
1256         struct mansession_session *s = obj;
1257         char *str = arg;
1258         return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
1259 }
1260
1261 static void session_destroy(struct mansession_session *s)
1262 {
1263         unref_mansession(s);
1264         ao2_unlink(sessions, s);
1265 }
1266
1267
1268 static int check_manager_session_inuse(const char *name)
1269 {
1270         struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
1271         int inuse = 0;
1272
1273         if (session) {
1274                 inuse = 1;
1275                 unref_mansession(session);
1276         }
1277         return inuse;
1278 }
1279
1280
1281 /*!
1282  * lookup an entry in the list of registered users.
1283  * must be called with the list lock held.
1284  */
1285 static struct ast_manager_user *get_manager_by_name_locked(const char *name)
1286 {
1287         struct ast_manager_user *user = NULL;
1288
1289         AST_RWLIST_TRAVERSE(&users, user, list) {
1290                 if (!strcasecmp(user->username, name)) {
1291                         break;
1292                 }
1293         }
1294
1295         return user;
1296 }
1297
1298 /*! \brief Get displayconnects config option.
1299  *  \param session manager session to get parameter from.
1300  *  \return displayconnects config option value.
1301  */
1302 static int manager_displayconnects (struct mansession_session *session)
1303 {
1304         struct ast_manager_user *user = NULL;
1305         int ret = 0;
1306
1307         AST_RWLIST_RDLOCK(&users);
1308         if ((user = get_manager_by_name_locked (session->username))) {
1309                 ret = user->displayconnects;
1310         }
1311         AST_RWLIST_UNLOCK(&users);
1312
1313         return ret;
1314 }
1315
1316 static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1317 {
1318         struct manager_action *cur;
1319         struct ast_str *authority;
1320         int num, l, which;
1321         char *ret = NULL;
1322 #ifdef AST_XML_DOCS
1323         char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
1324 #endif
1325
1326         switch (cmd) {
1327         case CLI_INIT:
1328                 e->command = "manager show command";
1329                 e->usage =
1330                         "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
1331                         "       Shows the detailed description for a specific Asterisk manager interface command.\n";
1332                 return NULL;
1333         case CLI_GENERATE:
1334                 l = strlen(a->word);
1335                 which = 0;
1336                 AST_RWLIST_RDLOCK(&actions);
1337                 AST_RWLIST_TRAVERSE(&actions, cur, list) {
1338                         if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
1339                                 ret = ast_strdup(cur->action);
1340                                 break;  /* make sure we exit even if ast_strdup() returns NULL */
1341                         }
1342                 }
1343                 AST_RWLIST_UNLOCK(&actions);
1344                 return ret;
1345         }
1346         authority = ast_str_alloca(80);
1347         if (a->argc < 4) {
1348                 return CLI_SHOWUSAGE;
1349         }
1350
1351 #ifdef AST_XML_DOCS
1352         /* setup the titles */
1353         term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
1354         term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
1355         term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
1356         term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
1357         term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
1358 #endif
1359
1360         AST_RWLIST_RDLOCK(&actions);
1361         AST_RWLIST_TRAVERSE(&actions, cur, list) {
1362                 for (num = 3; num < a->argc; num++) {
1363                         if (!strcasecmp(cur->action, a->argv[num])) {
1364 #ifdef AST_XML_DOCS
1365                                 if (cur->docsrc == AST_XML_DOC) {
1366                                         ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
1367                                                 syntax_title,
1368                                                 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
1369                                                 synopsis_title,
1370                                                 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
1371                                                 description_title,
1372                                                 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
1373                                                 arguments_title,
1374                                                 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
1375                                                 seealso_title,
1376                                                 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
1377                                 } else {
1378 #endif
1379                                         ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
1380                                                         cur->action, cur->synopsis,
1381                                                         authority_to_str(cur->authority, &authority),
1382                                                         S_OR(cur->description, ""));
1383 #ifdef AST_XML_DOCS
1384                                 }
1385 #endif
1386                         }
1387                 }
1388         }
1389         AST_RWLIST_UNLOCK(&actions);
1390
1391         return CLI_SUCCESS;
1392 }
1393
1394 static char *handle_mandebug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1395 {
1396         switch (cmd) {
1397         case CLI_INIT:
1398                 e->command = "manager set debug [on|off]";
1399                 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
1400                 return NULL;
1401         case CLI_GENERATE:
1402                 return NULL;
1403         }
1404
1405         if (a->argc == 3) {
1406                 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
1407         } else if (a->argc == 4) {
1408                 if (!strcasecmp(a->argv[3], "on")) {
1409                         manager_debug = 1;
1410                 } else if (!strcasecmp(a->argv[3], "off")) {
1411                         manager_debug = 0;
1412                 } else {
1413                         return CLI_SHOWUSAGE;
1414                 }
1415         }
1416         return CLI_SUCCESS;
1417 }
1418
1419 static char *handle_showmanager(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1420 {
1421         struct ast_manager_user *user = NULL;
1422         int l, which;
1423         char *ret = NULL;
1424         struct ast_str *rauthority = ast_str_alloca(128);
1425         struct ast_str *wauthority = ast_str_alloca(128);
1426
1427         switch (cmd) {
1428         case CLI_INIT:
1429                 e->command = "manager show user";
1430                 e->usage =
1431                         " Usage: manager show user <user>\n"
1432                         "        Display all information related to the manager user specified.\n";
1433                 return NULL;
1434         case CLI_GENERATE:
1435                 l = strlen(a->word);
1436                 which = 0;
1437                 if (a->pos != 3) {
1438                         return NULL;
1439                 }
1440                 AST_RWLIST_RDLOCK(&users);
1441                 AST_RWLIST_TRAVERSE(&users, user, list) {
1442                         if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
1443                                 ret = ast_strdup(user->username);
1444                                 break;
1445                         }
1446                 }
1447                 AST_RWLIST_UNLOCK(&users);
1448                 return ret;
1449         }
1450
1451         if (a->argc != 4) {
1452                 return CLI_SHOWUSAGE;
1453         }
1454
1455         AST_RWLIST_RDLOCK(&users);
1456
1457         if (!(user = get_manager_by_name_locked(a->argv[3]))) {
1458                 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
1459                 AST_RWLIST_UNLOCK(&users);
1460                 return CLI_SUCCESS;
1461         }
1462
1463         ast_cli(a->fd, "\n");
1464         ast_cli(a->fd,
1465                 "       username: %s\n"
1466                 "         secret: %s\n"
1467                 "            acl: %s\n"
1468                 "      read perm: %s\n"
1469                 "     write perm: %s\n"
1470                 "displayconnects: %s\n",
1471                 (user->username ? user->username : "(N/A)"),
1472                 (user->secret ? "<Set>" : "(N/A)"),
1473                 (user->ha ? "yes" : "no"),
1474                 authority_to_str(user->readperm, &rauthority),
1475                 authority_to_str(user->writeperm, &wauthority),
1476                 (user->displayconnects ? "yes" : "no"));
1477
1478         AST_RWLIST_UNLOCK(&users);
1479
1480         return CLI_SUCCESS;
1481 }
1482
1483 static char *handle_showmanagers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1484 {
1485         struct ast_manager_user *user = NULL;
1486         int count_amu = 0;
1487         switch (cmd) {
1488         case CLI_INIT:
1489                 e->command = "manager show users";
1490                 e->usage =
1491                         "Usage: manager show users\n"
1492                         "       Prints a listing of all managers that are currently configured on that\n"
1493                         " system.\n";
1494                 return NULL;
1495         case CLI_GENERATE:
1496                 return NULL;
1497         }
1498         if (a->argc != 3) {
1499                 return CLI_SHOWUSAGE;
1500         }
1501
1502         AST_RWLIST_RDLOCK(&users);
1503
1504         /* If there are no users, print out something along those lines */
1505         if (AST_RWLIST_EMPTY(&users)) {
1506                 ast_cli(a->fd, "There are no manager users.\n");
1507                 AST_RWLIST_UNLOCK(&users);
1508                 return CLI_SUCCESS;
1509         }
1510
1511         ast_cli(a->fd, "\nusername\n--------\n");
1512
1513         AST_RWLIST_TRAVERSE(&users, user, list) {
1514                 ast_cli(a->fd, "%s\n", user->username);
1515                 count_amu++;
1516         }
1517
1518         AST_RWLIST_UNLOCK(&users);
1519
1520         ast_cli(a->fd,"-------------------\n"
1521                       "%d manager users configured.\n", count_amu);
1522         return CLI_SUCCESS;
1523 }
1524
1525 /*! \brief  CLI command  manager list commands */
1526 static char *handle_showmancmds(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1527 {
1528         struct manager_action *cur;
1529         struct ast_str *authority;
1530 #define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
1531         switch (cmd) {
1532         case CLI_INIT:
1533                 e->command = "manager show commands";
1534                 e->usage =
1535                         "Usage: manager show commands\n"
1536                         "       Prints a listing of all the available Asterisk manager interface commands.\n";
1537                 return NULL;
1538         case CLI_GENERATE:
1539                 return NULL;
1540         }
1541         authority = ast_str_alloca(80);
1542         ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
1543         ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
1544
1545         AST_RWLIST_RDLOCK(&actions);
1546         AST_RWLIST_TRAVERSE(&actions, cur, list)
1547                 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
1548         AST_RWLIST_UNLOCK(&actions);
1549
1550         return CLI_SUCCESS;
1551 }
1552
1553 /*! \brief CLI command manager list connected */
1554 static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1555 {
1556         struct mansession_session *session;
1557         time_t now = time(NULL);
1558 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
1559 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
1560         int count = 0;
1561         struct ao2_iterator i;
1562
1563         switch (cmd) {
1564         case CLI_INIT:
1565                 e->command = "manager show connected";
1566                 e->usage =
1567                         "Usage: manager show connected\n"
1568                         "       Prints a listing of the users that are currently connected to the\n"
1569                         "Asterisk manager interface.\n";
1570                 return NULL;
1571         case CLI_GENERATE:
1572                 return NULL;
1573         }
1574
1575         ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
1576
1577         i = ao2_iterator_init(sessions, 0);
1578         while ((session = ao2_iterator_next(&i))) {
1579                 ao2_lock(session);
1580                 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);
1581                 count++;
1582                 ao2_unlock(session);
1583                 unref_mansession(session);
1584         }
1585         ao2_iterator_destroy(&i);
1586         ast_cli(a->fd, "%d users connected.\n", count);
1587
1588         return CLI_SUCCESS;
1589 }
1590
1591 /*! \brief CLI command manager list eventq */
1592 /* Should change to "manager show connected" */
1593 static char *handle_showmaneventq(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1594 {
1595         struct eventqent *s;
1596         switch (cmd) {
1597         case CLI_INIT:
1598                 e->command = "manager show eventq";
1599                 e->usage =
1600                         "Usage: manager show eventq\n"
1601                         "       Prints a listing of all events pending in the Asterisk manger\n"
1602                         "event queue.\n";
1603                 return NULL;
1604         case CLI_GENERATE:
1605                 return NULL;
1606         }
1607         AST_RWLIST_RDLOCK(&all_events);
1608         AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
1609                 ast_cli(a->fd, "Usecount: %d\n", s->usecount);
1610                 ast_cli(a->fd, "Category: %d\n", s->category);
1611                 ast_cli(a->fd, "Event:\n%s", s->eventdata);
1612         }
1613         AST_RWLIST_UNLOCK(&all_events);
1614
1615         return CLI_SUCCESS;
1616 }
1617
1618 /*! \brief CLI command manager reload */
1619 static char *handle_manager_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1620 {
1621         switch (cmd) {
1622         case CLI_INIT:
1623                 e->command = "manager reload";
1624                 e->usage =
1625                         "Usage: manager reload\n"
1626                         "       Reloads the manager configuration.\n";
1627                 return NULL;
1628         case CLI_GENERATE:
1629                 return NULL;
1630         }
1631         if (a->argc > 2) {
1632                 return CLI_SHOWUSAGE;
1633         }
1634         reload_manager();
1635         return CLI_SUCCESS;
1636 }
1637
1638 static struct eventqent *advance_event(struct eventqent *e)
1639 {
1640         struct eventqent *next;
1641
1642         AST_RWLIST_RDLOCK(&all_events);
1643         if ((next = AST_RWLIST_NEXT(e, eq_next))) {
1644                 ast_atomic_fetchadd_int(&next->usecount, 1);
1645                 ast_atomic_fetchadd_int(&e->usecount, -1);
1646         }
1647         AST_RWLIST_UNLOCK(&all_events);
1648         return next;
1649 }
1650
1651 /*
1652  * Generic function to return either the first or the last matching header
1653  * from a list of variables, possibly skipping empty strings.
1654  * At the moment there is only one use of this function in this file,
1655  * so we make it static.
1656  */
1657 #define GET_HEADER_FIRST_MATCH  0
1658 #define GET_HEADER_LAST_MATCH   1
1659 #define GET_HEADER_SKIP_EMPTY   2
1660 static const char *__astman_get_header(const struct message *m, char *var, int mode)
1661 {
1662         int x, l = strlen(var);
1663         const char *result = "";
1664
1665         for (x = 0; x < m->hdrcount; x++) {
1666                 const char *h = m->headers[x];
1667                 if (!strncasecmp(var, h, l) && h[l] == ':' && h[l+1] == ' ') {
1668                         const char *value = h + l + 2;
1669                         /* found a potential candidate */
1670                         if (mode & GET_HEADER_SKIP_EMPTY && ast_strlen_zero(value))
1671                                 continue;       /* not interesting */
1672                         if (mode & GET_HEADER_LAST_MATCH)
1673                                 result = value; /* record the last match so far */
1674                         else
1675                                 return value;
1676                 }
1677         }
1678
1679         return "";
1680 }
1681
1682 /*
1683  * Return the first matching variable from an array.
1684  * This is the legacy function and is implemented in therms of
1685  * __astman_get_header().
1686  */
1687 const char *astman_get_header(const struct message *m, char *var)
1688 {
1689         return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
1690 }
1691
1692
1693 struct ast_variable *astman_get_variables(const struct message *m)
1694 {
1695         int varlen, x, y;
1696         struct ast_variable *head = NULL, *cur;
1697
1698         AST_DECLARE_APP_ARGS(args,
1699                 AST_APP_ARG(vars)[32];
1700         );
1701
1702         varlen = strlen("Variable: ");
1703
1704         for (x = 0; x < m->hdrcount; x++) {
1705                 char *parse, *var, *val;
1706
1707                 if (strncasecmp("Variable: ", m->headers[x], varlen)) {
1708                         continue;
1709                 }
1710                 parse = ast_strdupa(m->headers[x] + varlen);
1711
1712                 AST_STANDARD_APP_ARGS(args, parse);
1713                 if (!args.argc) {
1714                         continue;
1715                 }
1716                 for (y = 0; y < args.argc; y++) {
1717                         if (!args.vars[y]) {
1718                                 continue;
1719                         }
1720                         var = val = ast_strdupa(args.vars[y]);
1721                         strsep(&val, "=");
1722                         if (!val || ast_strlen_zero(var)) {
1723                                 continue;
1724                         }
1725                         cur = ast_variable_new(var, val, "");
1726                         cur->next = head;
1727                         head = cur;
1728                 }
1729         }
1730
1731         return head;
1732 }
1733
1734 /* access for hooks to send action messages to ami */
1735
1736 int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
1737 {
1738         const char *action;
1739         int ret = 0;
1740         struct manager_action *tmp;
1741         struct mansession s = {.session = NULL, };
1742         struct message m = { 0 };
1743         char header_buf[1025] = { '\0' };
1744         const char *src = msg;
1745         int x = 0;
1746         int curlen;
1747
1748         if (hook == NULL) {
1749                 return -1;
1750         }
1751
1752         /* convert msg string to message struct */
1753         curlen = strlen(msg);
1754         for (x = 0; x < curlen; x++) {
1755                 int cr; /* set if we have \r */
1756                 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
1757                         cr = 2; /* Found. Update length to include \r\n */
1758                 else if (src[x] == '\n')
1759                         cr = 1; /* also accept \n only */
1760                 else
1761                         continue;
1762                 /* don't copy empty lines */
1763                 if (x) {
1764                         memmove(header_buf, src, x);    /*... but trim \r\n */
1765                         header_buf[x] = '\0';           /* terminate the string */
1766                         m.headers[m.hdrcount++] = ast_strdupa(header_buf);
1767                 }
1768                 x += cr;
1769                 curlen -= x;            /* remaining size */
1770                 src += x;               /* update pointer */
1771                 x = -1;                 /* reset loop */
1772         }
1773
1774         action = astman_get_header(&m,"Action");
1775         if (action && strcasecmp(action,"login")) {
1776
1777                 AST_RWLIST_RDLOCK(&actions);
1778                 AST_RWLIST_TRAVERSE(&actions, tmp, list) {
1779                         if (strcasecmp(action, tmp->action))
1780                                 continue;
1781                         /*
1782                         * we have to simulate a session for this action request
1783                         * to be able to pass it down for processing
1784                         * This is necessary to meet the previous design of manager.c
1785                         */
1786                         s.hook = hook;
1787                         s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
1788                         ret = tmp->func(&s, &m);
1789                         break;
1790                 }
1791                 AST_RWLIST_UNLOCK(&actions);
1792         }
1793         return ret;
1794 }
1795
1796
1797 /*!
1798  * helper function to send a string to the socket.
1799  * Return -1 on error (e.g. buffer full).
1800  */
1801 static int send_string(struct mansession *s, char *string)
1802 {
1803         /* It's a result from one of the hook's action invocation */
1804         if (s->hook) {
1805                 /*
1806                  * to send responses, we're using the same function
1807                  * as for receiving events. We call the event "HookResponse"
1808                  */
1809                 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
1810                 return 0;
1811         } else if (s->f) {
1812                 return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout);
1813         } else {
1814                 return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout);
1815         }
1816 }
1817
1818 /*!
1819  * \brief thread local buffer for astman_append
1820  *
1821  * \note This can not be defined within the astman_append() function
1822  *       because it declares a couple of functions that get used to
1823  *       initialize the thread local storage key.
1824  */
1825 AST_THREADSTORAGE(astman_append_buf);
1826 AST_THREADSTORAGE(userevent_buf);
1827
1828 /*! \brief initial allocated size for the astman_append_buf */
1829 #define ASTMAN_APPEND_BUF_INITSIZE   256
1830
1831 /*!
1832  * utility functions for creating AMI replies
1833  */
1834 void astman_append(struct mansession *s, const char *fmt, ...)
1835 {
1836         va_list ap;
1837         struct ast_str *buf;
1838
1839         if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
1840                 return;
1841         }
1842
1843         va_start(ap, fmt);
1844         ast_str_set_va(&buf, 0, fmt, ap);
1845         va_end(ap);
1846
1847         if (s->f != NULL || s->session->f != NULL) {
1848                 send_string(s, ast_str_buffer(buf));
1849         } else {
1850                 ast_verbose("fd == -1 in astman_append, should not happen\n");
1851         }
1852 }
1853
1854 /*! \note NOTE: XXX this comment is unclear and possibly wrong.
1855    Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER
1856    hold the session lock _or_ be running in an action callback (in which case s->session->busy will
1857    be non-zero). In either of these cases, there is no need to lock-protect the session's
1858    fd, since no other output will be sent (events will be queued), and no input will
1859    be read until either the current action finishes or get_input() obtains the session
1860    lock.
1861  */
1862
1863 /*! \brief send a response with an optional message,
1864  * and terminate it with an empty line.
1865  * m is used only to grab the 'ActionID' field.
1866  *
1867  * Use the explicit constant MSG_MOREDATA to remove the empty line.
1868  * XXX MSG_MOREDATA should go to a header file.
1869  */
1870 #define MSG_MOREDATA    ((char *)astman_send_response)
1871 static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
1872 {
1873         const char *id = astman_get_header(m, "ActionID");
1874
1875         astman_append(s, "Response: %s\r\n", resp);
1876         if (!ast_strlen_zero(id)) {
1877                 astman_append(s, "ActionID: %s\r\n", id);
1878         }
1879         if (listflag) {
1880                 astman_append(s, "Eventlist: %s\r\n", listflag);        /* Start, complete, cancelled */
1881         }
1882         if (msg == MSG_MOREDATA) {
1883                 return;
1884         } else if (msg) {
1885                 astman_append(s, "Message: %s\r\n\r\n", msg);
1886         } else {
1887                 astman_append(s, "\r\n");
1888         }
1889 }
1890
1891 void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
1892 {
1893         astman_send_response_full(s, m, resp, msg, NULL);
1894 }
1895
1896 void astman_send_error(struct mansession *s, const struct message *m, char *error)
1897 {
1898         astman_send_response_full(s, m, "Error", error, NULL);
1899 }
1900
1901 void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
1902 {
1903         astman_send_response_full(s, m, "Success", msg, NULL);
1904 }
1905
1906 static void astman_start_ack(struct mansession *s, const struct message *m)
1907 {
1908         astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
1909 }
1910
1911 void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
1912 {
1913         astman_send_response_full(s, m, "Success", msg, listflag);
1914 }
1915
1916 /*! \brief Lock the 'mansession' structure. */
1917 static void mansession_lock(struct mansession *s)
1918 {
1919         ast_mutex_lock(&s->lock);
1920 }
1921
1922 /*! \brief Unlock the 'mansession' structure. */
1923 static void mansession_unlock(struct mansession *s)
1924 {
1925         ast_mutex_unlock(&s->lock);
1926 }
1927
1928 /*! \brief
1929    Rather than braindead on,off this now can also accept a specific int mask value
1930    or a ',' delim list of mask strings (the same as manager.conf) -anthm
1931 */
1932 static int set_eventmask(struct mansession *s, const char *eventmask)
1933 {
1934         int maskint = strings_to_mask(eventmask);
1935
1936         mansession_lock(s);
1937         if (maskint >= 0) {
1938                 s->session->send_events = maskint;
1939         }
1940         mansession_unlock(s);
1941
1942         return maskint;
1943 }
1944
1945 static enum ast_security_event_transport_type mansession_get_transport(const struct mansession *s)
1946 {
1947         return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS :
1948                         AST_SECURITY_EVENT_TRANSPORT_TCP;
1949 }
1950
1951 static struct sockaddr_in *mansession_encode_sin_local(const struct mansession *s,
1952                 struct sockaddr_in *sin_local)
1953 {
1954         *sin_local = s->tcptls_session->parent->local_address;
1955
1956         return sin_local;
1957 }
1958
1959 static void report_invalid_user(const struct mansession *s, const char *username)
1960 {
1961         struct sockaddr_in sin_local;
1962         char session_id[32];
1963         struct ast_security_event_inval_acct_id inval_acct_id = {
1964                 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
1965                 .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
1966                 .common.service    = "AMI",
1967                 .common.account_id = username,
1968                 .common.session_tv = &s->session->sessionstart_tv,
1969                 .common.local_addr = {
1970                         .sin       = mansession_encode_sin_local(s, &sin_local),
1971                         .transport = mansession_get_transport(s),
1972                 },
1973                 .common.remote_addr = {
1974                         .sin       = &s->session->sin,
1975                         .transport = mansession_get_transport(s),
1976                 },
1977                 .common.session_id = session_id,
1978         };
1979
1980         snprintf(session_id, sizeof(session_id), "%p", s);
1981
1982         ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
1983 }
1984
1985 static void report_failed_acl(const struct mansession *s, const char *username)
1986 {
1987         struct sockaddr_in sin_local;
1988         char session_id[32];
1989         struct ast_security_event_failed_acl failed_acl_event = {
1990                 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
1991                 .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
1992                 .common.service    = "AMI",
1993                 .common.account_id = username,
1994                 .common.session_tv = &s->session->sessionstart_tv,
1995                 .common.local_addr = {
1996                         .sin       = mansession_encode_sin_local(s, &sin_local),
1997                         .transport = mansession_get_transport(s),
1998                 },
1999                 .common.remote_addr = {
2000                         .sin       = &s->session->sin,
2001                         .transport = mansession_get_transport(s),
2002                 },
2003                 .common.session_id = session_id,
2004         };
2005
2006         snprintf(session_id, sizeof(session_id), "%p", s->session);
2007
2008         ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
2009 }
2010
2011 static void report_inval_password(const struct mansession *s, const char *username)
2012 {
2013         struct sockaddr_in sin_local;
2014         char session_id[32];
2015         struct ast_security_event_inval_password inval_password = {
2016                 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
2017                 .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
2018                 .common.service    = "AMI",
2019                 .common.account_id = username,
2020                 .common.session_tv = &s->session->sessionstart_tv,
2021                 .common.local_addr = {
2022                         .sin       = mansession_encode_sin_local(s, &sin_local),
2023                         .transport = mansession_get_transport(s),
2024                 },
2025                 .common.remote_addr = {
2026                         .sin       = &s->session->sin,
2027                         .transport = mansession_get_transport(s),
2028                 },
2029                 .common.session_id = session_id,
2030         };
2031
2032         snprintf(session_id, sizeof(session_id), "%p", s->session);
2033
2034         ast_security_event_report(AST_SEC_EVT(&inval_password));
2035 }
2036
2037 static void report_auth_success(const struct mansession *s)
2038 {
2039         struct sockaddr_in sin_local;
2040         char session_id[32];
2041         struct ast_security_event_successful_auth successful_auth = {
2042                 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
2043                 .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
2044                 .common.service    = "AMI",
2045                 .common.account_id = s->session->username,
2046                 .common.session_tv = &s->session->sessionstart_tv,
2047                 .common.local_addr = {
2048                         .sin       = mansession_encode_sin_local(s, &sin_local),
2049                         .transport = mansession_get_transport(s),
2050                 },
2051                 .common.remote_addr = {
2052                         .sin       = &s->session->sin,
2053                         .transport = mansession_get_transport(s),
2054                 },
2055                 .common.session_id = session_id,
2056         };
2057
2058         snprintf(session_id, sizeof(session_id), "%p", s->session);
2059
2060         ast_security_event_report(AST_SEC_EVT(&successful_auth));
2061 }
2062
2063 static void report_req_not_allowed(const struct mansession *s, const char *action)
2064 {
2065         struct sockaddr_in sin_local;
2066         char session_id[32];
2067         char request_type[64];
2068         struct ast_security_event_req_not_allowed req_not_allowed = {
2069                 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
2070                 .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
2071                 .common.service    = "AMI",
2072                 .common.account_id = s->session->username,
2073                 .common.session_tv = &s->session->sessionstart_tv,
2074                 .common.local_addr = {
2075                         .sin       = mansession_encode_sin_local(s, &sin_local),
2076                         .transport = mansession_get_transport(s),
2077                 },
2078                 .common.remote_addr = {
2079                         .sin       = &s->session->sin,
2080                         .transport = mansession_get_transport(s),
2081                 },
2082                 .common.session_id = session_id,
2083
2084                 .request_type      = request_type,
2085         };
2086
2087         snprintf(session_id, sizeof(session_id), "%p", s->session);
2088         snprintf(request_type, sizeof(request_type), "Action: %s", action);
2089
2090         ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
2091 }
2092
2093 static void report_req_bad_format(const struct mansession *s, const char *action)
2094 {
2095         struct sockaddr_in sin_local;
2096         char session_id[32];
2097         char request_type[64];
2098         struct ast_security_event_req_bad_format req_bad_format = {
2099                 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
2100                 .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
2101                 .common.service    = "AMI",
2102                 .common.account_id = s->session->username,
2103                 .common.session_tv = &s->session->sessionstart_tv,
2104                 .common.local_addr = {
2105                         .sin       = mansession_encode_sin_local(s, &sin_local),
2106                         .transport = mansession_get_transport(s),
2107                 },
2108                 .common.remote_addr = {
2109                         .sin       = &s->session->sin,
2110                         .transport = mansession_get_transport(s),
2111                 },
2112                 .common.session_id = session_id,
2113
2114                 .request_type      = request_type,
2115         };
2116
2117         snprintf(session_id, sizeof(session_id), "%p", s->session);
2118         snprintf(request_type, sizeof(request_type), "Action: %s", action);
2119
2120         ast_security_event_report(AST_SEC_EVT(&req_bad_format));
2121 }
2122
2123 static void report_failed_challenge_response(const struct mansession *s,
2124                 const char *response, const char *expected_response)
2125 {
2126         struct sockaddr_in sin_local;
2127         char session_id[32];
2128         struct ast_security_event_chal_resp_failed chal_resp_failed = {
2129                 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
2130                 .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
2131                 .common.service    = "AMI",
2132                 .common.account_id = s->session->username,
2133                 .common.session_tv = &s->session->sessionstart_tv,
2134                 .common.local_addr = {
2135                         .sin       = mansession_encode_sin_local(s, &sin_local),
2136                         .transport = mansession_get_transport(s),
2137                 },
2138                 .common.remote_addr = {
2139                         .sin       = &s->session->sin,
2140                         .transport = mansession_get_transport(s),
2141                 },
2142                 .common.session_id = session_id,
2143
2144                 .challenge         = s->session->challenge,
2145                 .response          = response,
2146                 .expected_response = expected_response,
2147         };
2148
2149         snprintf(session_id, sizeof(session_id), "%p", s->session);
2150
2151         ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
2152 }
2153
2154 static void report_session_limit(const struct mansession *s)
2155 {
2156         struct sockaddr_in sin_local;
2157         char session_id[32];
2158         struct ast_security_event_session_limit session_limit = {
2159                 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
2160                 .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
2161                 .common.service    = "AMI",
2162                 .common.account_id = s->session->username,
2163                 .common.session_tv = &s->session->sessionstart_tv,
2164                 .common.local_addr = {
2165                         .sin       = mansession_encode_sin_local(s, &sin_local),
2166                         .transport = mansession_get_transport(s),
2167                 },
2168                 .common.remote_addr = {
2169                         .sin       = &s->session->sin,
2170                         .transport = mansession_get_transport(s),
2171                 },
2172                 .common.session_id = session_id,
2173         };
2174
2175         snprintf(session_id, sizeof(session_id), "%p", s->session);
2176
2177         ast_security_event_report(AST_SEC_EVT(&session_limit));
2178 }
2179
2180 /*
2181  * Here we start with action_ handlers for AMI actions,
2182  * and the internal functions used by them.
2183  * Generally, the handlers are called action_foo()
2184  */
2185
2186 /* helper function for action_login() */
2187 static int authenticate(struct mansession *s, const struct message *m)
2188 {
2189         const char *username = astman_get_header(m, "Username");
2190         const char *password = astman_get_header(m, "Secret");
2191         int error = -1;
2192         struct ast_manager_user *user = NULL;
2193
2194         if (ast_strlen_zero(username)) {        /* missing username */
2195                 return -1;
2196         }
2197
2198         /* locate user in locked state */
2199         AST_RWLIST_WRLOCK(&users);
2200
2201         if (!(user = get_manager_by_name_locked(username))) {
2202                 report_invalid_user(s, username);
2203                 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
2204         } else if (user->ha && !ast_apply_ha(user->ha, &(s->session->sin))) {
2205                 report_failed_acl(s, username);
2206                 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
2207         } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
2208                 const char *key = astman_get_header(m, "Key");
2209                 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
2210                         int x;
2211                         int len = 0;
2212                         char md5key[256] = "";
2213                         struct MD5Context md5;
2214                         unsigned char digest[16];
2215
2216                         MD5Init(&md5);
2217                         MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
2218                         MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
2219                         MD5Final(digest, &md5);
2220                         for (x = 0; x < 16; x++)
2221                                 len += sprintf(md5key + len, "%2.2x", digest[x]);
2222                         if (!strcmp(md5key, key)) {
2223                                 error = 0;
2224                         } else {
2225                                 report_failed_challenge_response(s, key, md5key);
2226                         }
2227                 } else {
2228                         ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
2229                                 S_OR(s->session->challenge, ""));
2230                 }
2231         } else if (user->secret) {
2232                 if (!strcmp(password, user->secret)) {
2233                         error = 0;
2234                 } else {
2235                         report_inval_password(s, username);
2236                 }
2237         }
2238
2239         if (error) {
2240                 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
2241                 AST_RWLIST_UNLOCK(&users);
2242                 return -1;
2243         }
2244
2245         /* auth complete */
2246
2247         ast_copy_string(s->session->username, username, sizeof(s->session->username));
2248         s->session->readperm = user->readperm;
2249         s->session->writeperm = user->writeperm;
2250         s->session->writetimeout = user->writetimeout;
2251         s->session->sessionstart = time(NULL);
2252         s->session->sessionstart_tv = ast_tvnow();
2253         set_eventmask(s, astman_get_header(m, "Events"));
2254
2255         report_auth_success(s);
2256
2257         AST_RWLIST_UNLOCK(&users);
2258         return 0;
2259 }
2260
2261 static int action_ping(struct mansession *s, const struct message *m)
2262 {
2263         const char *actionid = astman_get_header(m, "ActionID");
2264         struct timeval now = ast_tvnow();
2265
2266         astman_append(s, "Response: Success\r\n");
2267         if (!ast_strlen_zero(actionid)){
2268                 astman_append(s, "ActionID: %s\r\n", actionid);
2269         }
2270         astman_append(
2271                 s,
2272                 "Ping: Pong\r\n"
2273                 "Timestamp: %ld.%06lu\r\n"
2274                 "\r\n",
2275                 (long) now.tv_sec, (unsigned long) now.tv_usec);
2276         return 0;
2277 }
2278
2279 static int action_getconfig(struct mansession *s, const struct message *m)
2280 {
2281         struct ast_config *cfg;
2282         const char *fn = astman_get_header(m, "Filename");
2283         const char *category = astman_get_header(m, "Category");
2284         int catcount = 0;
2285         int lineno = 0;
2286         char *cur_category = NULL;
2287         struct ast_variable *v;
2288         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2289
2290         if (ast_strlen_zero(fn)) {
2291                 astman_send_error(s, m, "Filename not specified");
2292                 return 0;
2293         }
2294         cfg = ast_config_load2(fn, "manager", config_flags);
2295         if (cfg == CONFIG_STATUS_FILEMISSING) {
2296                 astman_send_error(s, m, "Config file not found");
2297                 return 0;
2298         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2299                 astman_send_error(s, m, "Config file has invalid format");
2300                 return 0;
2301         }
2302
2303         astman_start_ack(s, m);
2304         while ((cur_category = ast_category_browse(cfg, cur_category))) {
2305                 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
2306                         lineno = 0;
2307                         astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
2308                         for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
2309                                 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
2310                         }
2311                         catcount++;
2312                 }
2313         }
2314         if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2315                 astman_append(s, "No categories found\r\n");
2316         }
2317         ast_config_destroy(cfg);
2318         astman_append(s, "\r\n");
2319
2320         return 0;
2321 }
2322
2323 static int action_listcategories(struct mansession *s, const struct message *m)
2324 {
2325         struct ast_config *cfg;
2326         const char *fn = astman_get_header(m, "Filename");
2327         char *category = NULL;
2328         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2329         int catcount = 0;
2330
2331         if (ast_strlen_zero(fn)) {
2332                 astman_send_error(s, m, "Filename not specified");
2333                 return 0;
2334         }
2335         if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2336                 astman_send_error(s, m, "Config file not found");
2337                 return 0;
2338         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2339                 astman_send_error(s, m, "Config file has invalid format");
2340                 return 0;
2341         }
2342         astman_start_ack(s, m);
2343         while ((category = ast_category_browse(cfg, category))) {
2344                 astman_append(s, "Category-%06d: %s\r\n", catcount, category);
2345                 catcount++;
2346         }
2347         if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2348                 astman_append(s, "Error: no categories found\r\n");
2349         }
2350         ast_config_destroy(cfg);
2351         astman_append(s, "\r\n");
2352
2353         return 0;
2354 }
2355
2356
2357
2358
2359 /*! The amount of space in out must be at least ( 2 * strlen(in) + 1 ) */
2360 static void json_escape(char *out, const char *in)
2361 {
2362         for (; *in; in++) {
2363                 if (*in == '\\' || *in == '\"') {
2364                         *out++ = '\\';
2365                 }
2366                 *out++ = *in;
2367         }
2368         *out = '\0';
2369 }
2370
2371 static int action_getconfigjson(struct mansession *s, const struct message *m)
2372 {
2373         struct ast_config *cfg;
2374         const char *fn = astman_get_header(m, "Filename");
2375         char *category = NULL;
2376         struct ast_variable *v;
2377         int comma1 = 0;
2378         char *buf = NULL;
2379         unsigned int buf_len = 0;
2380         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2381
2382         if (ast_strlen_zero(fn)) {
2383                 astman_send_error(s, m, "Filename not specified");
2384                 return 0;
2385         }
2386
2387         if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2388                 astman_send_error(s, m, "Config file not found");
2389                 return 0;
2390         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2391                 astman_send_error(s, m, "Config file has invalid format");
2392                 return 0;
2393         }
2394
2395         buf_len = 512;
2396         buf = alloca(buf_len);
2397
2398         astman_start_ack(s, m);
2399         astman_append(s, "JSON: {");
2400         while ((category = ast_category_browse(cfg, category))) {
2401                 int comma2 = 0;
2402                 if (buf_len < 2 * strlen(category) + 1) {
2403                         buf_len *= 2;
2404                         buf = alloca(buf_len);
2405                 }
2406                 json_escape(buf, category);
2407                 astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf);
2408                 if (!comma1) {
2409                         comma1 = 1;
2410                 }
2411                 for (v = ast_variable_browse(cfg, category); v; v = v->next) {
2412                         if (comma2) {
2413                                 astman_append(s, ",");
2414                         }
2415                         if (buf_len < 2 * strlen(v->name) + 1) {
2416                                 buf_len *= 2;
2417                                 buf = alloca(buf_len);
2418                         }
2419                         json_escape(buf, v->name);
2420                         astman_append(s, "\"%s", buf);
2421                         if (buf_len < 2 * strlen(v->value) + 1) {
2422                                 buf_len *= 2;
2423                                 buf = alloca(buf_len);
2424                         }
2425                         json_escape(buf, v->value);
2426                         astman_append(s, "%s\"", buf);
2427                         if (!comma2) {
2428                                 comma2 = 1;
2429                         }
2430                 }
2431                 astman_append(s, "]");
2432         }
2433         astman_append(s, "}\r\n\r\n");
2434
2435         ast_config_destroy(cfg);
2436
2437         return 0;
2438 }
2439
2440 /* helper function for action_updateconfig */
2441 static enum error_type handle_updates(struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
2442 {
2443         int x;
2444         char hdr[40];
2445         const char *action, *cat, *var, *value, *match, *line;
2446         struct ast_category *category;
2447         struct ast_variable *v;
2448         struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
2449         enum error_type result = 0;
2450
2451         for (x = 0; x < 100000; x++) {  /* 100000 = the max number of allowed updates + 1 */
2452                 unsigned int object = 0;
2453
2454                 snprintf(hdr, sizeof(hdr), "Action-%06d", x);
2455                 action = astman_get_header(m, hdr);
2456                 if (ast_strlen_zero(action))            /* breaks the for loop if no action header */
2457                         break;                          /* this could cause problems if actions come in misnumbered */
2458
2459                 snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
2460                 cat = astman_get_header(m, hdr);
2461                 if (ast_strlen_zero(cat)) {             /* every action needs a category */
2462                         result =  UNSPECIFIED_CATEGORY;
2463                         break;
2464                 }
2465
2466                 snprintf(hdr, sizeof(hdr), "Var-%06d", x);
2467                 var = astman_get_header(m, hdr);
2468
2469                 snprintf(hdr, sizeof(hdr), "Value-%06d", x);
2470                 value = astman_get_header(m, hdr);
2471
2472                 if (!ast_strlen_zero(value) && *value == '>') {
2473                         object = 1;
2474                         value++;
2475                 }
2476
2477                 snprintf(hdr, sizeof(hdr), "Match-%06d", x);
2478                 match = astman_get_header(m, hdr);
2479
2480                 snprintf(hdr, sizeof(hdr), "Line-%06d", x);
2481                 line = astman_get_header(m, hdr);
2482
2483                 if (!strcasecmp(action, "newcat")) {
2484                         if (ast_category_get(cfg,cat)) {        /* check to make sure the cat doesn't */
2485                                 result = FAILURE_NEWCAT;        /* already exist */
2486                                 break;
2487                         }
2488                         if (!(category = ast_category_new(cat, dfn, -1))) {
2489                                 result = FAILURE_ALLOCATION;
2490                                 break;
2491                         }
2492                         if (ast_strlen_zero(match)) {
2493                                 ast_category_append(cfg, category);
2494                         } else {
2495                                 ast_category_insert(cfg, category, match);
2496                         }
2497                 } else if (!strcasecmp(action, "renamecat")) {
2498                         if (ast_strlen_zero(value)) {
2499                                 result = UNSPECIFIED_ARGUMENT;
2500                                 break;
2501                         }
2502                         if (!(category = ast_category_get(cfg, cat))) {
2503                                 result = UNKNOWN_CATEGORY;
2504                                 break;
2505                         }
2506                         ast_category_rename(category, value);
2507                 } else if (!strcasecmp(action, "delcat")) {
2508                         if (ast_category_delete(cfg, cat)) {
2509                                 result = FAILURE_DELCAT;
2510                                 break;
2511                         }
2512                 } else if (!strcasecmp(action, "emptycat")) {
2513                         if (ast_category_empty(cfg, cat)) {
2514                                 result = FAILURE_EMPTYCAT;
2515                                 break;
2516                         }
2517                 } else if (!strcasecmp(action, "update")) {
2518                         if (ast_strlen_zero(var)) {
2519                                 result = UNSPECIFIED_ARGUMENT;
2520                                 break;
2521                         }
2522                         if (!(category = ast_category_get(cfg,cat))) {
2523                                 result = UNKNOWN_CATEGORY;
2524                                 break;
2525                         }
2526                         if (ast_variable_update(category, var, value, match, object)) {
2527                                 result = FAILURE_UPDATE;
2528                                 break;
2529                         }
2530                 } else if (!strcasecmp(action, "delete")) {
2531                         if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
2532                                 result = UNSPECIFIED_ARGUMENT;
2533                                 break;
2534                         }
2535                         if (!(category = ast_category_get(cfg, cat))) {
2536                                 result = UNKNOWN_CATEGORY;
2537                                 break;
2538                         }
2539                         if (ast_variable_delete(category, var, match, line)) {
2540                                 result = FAILURE_DELETE;
2541                                 break;
2542                         }
2543                 } else if (!strcasecmp(action, "append")) {
2544                         if (ast_strlen_zero(var)) {
2545                                 result = UNSPECIFIED_ARGUMENT;
2546                                 break;
2547                         }
2548                         if (!(category = ast_category_get(cfg, cat))) {
2549                                 result = UNKNOWN_CATEGORY;
2550                                 break;
2551                         }
2552                         if (!(v = ast_variable_new(var, value, dfn))) {
2553                                 result = FAILURE_ALLOCATION;
2554                                 break;
2555                         }
2556                         if (object || (match && !strcasecmp(match, "object"))) {
2557                                 v->object = 1;
2558                         }
2559                         ast_variable_append(category, v);
2560                 } else if (!strcasecmp(action, "insert")) {
2561                         if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
2562                                 result = UNSPECIFIED_ARGUMENT;
2563                                 break;
2564                         }
2565                         if (!(category = ast_category_get(cfg, cat))) {
2566                                 result = UNKNOWN_CATEGORY;
2567                                 break;
2568                         }
2569                         if (!(v = ast_variable_new(var, value, dfn))) {
2570                                 result = FAILURE_ALLOCATION;
2571                                 break;
2572                         }
2573                         ast_variable_insert(category, v, line);
2574                 }
2575                 else {
2576                         ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
2577                         result = UNKNOWN_ACTION;
2578                         break;
2579                 }
2580         }
2581         ast_free(str1);
2582         ast_free(str2);
2583         return result;
2584 }
2585
2586 static int action_updateconfig(struct mansession *s, const struct message *m)
2587 {
2588         struct ast_config *cfg;
2589         const char *sfn = astman_get_header(m, "SrcFilename");
2590         const char *dfn = astman_get_header(m, "DstFilename");
2591         int res;
2592         const char *rld = astman_get_header(m, "Reload");
2593         struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2594         enum error_type result;
2595
2596         if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
2597                 astman_send_error(s, m, "Filename not specified");
2598                 return 0;
2599         }
2600         if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
2601                 astman_send_error(s, m, "Config file not found");
2602                 return 0;
2603         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2604                 astman_send_error(s, m, "Config file has invalid format");
2605                 return 0;
2606         }
2607         result = handle_updates(s, m, cfg, dfn);
2608         if (!result) {
2609                 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
2610                 res = ast_config_text_file_save(dfn, cfg, "Manager");
2611                 ast_config_destroy(cfg);
2612                 if (res) {
2613                         astman_send_error(s, m, "Save of config failed");
2614                         return 0;
2615                 }
2616                 astman_send_ack(s, m, NULL);
2617                 if (!ast_strlen_zero(rld)) {
2618                         if (ast_true(rld)) {
2619                                 rld = NULL;
2620                         }
2621                         ast_module_reload(rld);
2622                 }
2623         } else {
2624                 ast_config_destroy(cfg);
2625                 switch(result) {
2626                 case UNKNOWN_ACTION:
2627                         astman_send_error(s, m, "Unknown action command");
2628                         break;
2629                 case UNKNOWN_CATEGORY:
2630                         astman_send_error(s, m, "Given category does not exist");
2631                         break;
2632                 case UNSPECIFIED_CATEGORY:
2633                         astman_send_error(s, m, "Category not specified");
2634                         break;
2635                 case UNSPECIFIED_ARGUMENT:
2636                         astman_send_error(s, m, "Problem with category, value, or line (if required)");
2637                         break;
2638                 case FAILURE_ALLOCATION:
2639                         astman_send_error(s, m, "Memory allocation failure, this should not happen");
2640                         break;
2641                 case FAILURE_NEWCAT:
2642                         astman_send_error(s, m, "Create category did not complete successfully");
2643                         break;
2644                 case FAILURE_DELCAT:
2645                         astman_send_error(s, m, "Delete category did not complete successfully");
2646                         break;
2647                 case FAILURE_EMPTYCAT:
2648                         astman_send_error(s, m, "Empty category did not complete successfully");
2649                         break;
2650                 case FAILURE_UPDATE:
2651                         astman_send_error(s, m, "Update did not complete successfully");
2652                         break;
2653                 case FAILURE_DELETE:
2654                         astman_send_error(s, m, "Delete did not complete successfully");
2655                         break;
2656                 case FAILURE_APPEND:
2657                         astman_send_error(s, m, "Append did not complete successfully");
2658                         break;
2659                 }
2660         }
2661         return 0;
2662 }
2663
2664 static int action_createconfig(struct mansession *s, const struct message *m)
2665 {
2666         int fd;
2667         const char *fn = astman_get_header(m, "Filename");
2668         struct ast_str *filepath = ast_str_alloca(PATH_MAX);
2669         ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
2670         ast_str_append(&filepath, 0, "%s", fn);
2671
2672         if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
2673                 close(fd);
2674                 astman_send_ack(s, m, "New configuration file created successfully");
2675         } else {
2676                 astman_send_error(s, m, strerror(errno));
2677         }
2678
2679         return 0;
2680 }
2681
2682 static int action_waitevent(struct mansession *s, const struct message *m)
2683 {
2684         const char *timeouts = astman_get_header(m, "Timeout");
2685         int timeout = -1;
2686         int x;
2687         int needexit = 0;
2688         const char *id = astman_get_header(m, "ActionID");
2689         char idText[256];
2690
2691         if (!ast_strlen_zero(id)) {
2692                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
2693         } else {
2694                 idText[0] = '\0';
2695         }
2696
2697         if (!ast_strlen_zero(timeouts)) {
2698                 sscanf(timeouts, "%30i", &timeout);
2699                 if (timeout < -1) {
2700                         timeout = -1;
2701                 }
2702                 /* XXX maybe put an upper bound, or prevent the use of 0 ? */
2703         }
2704
2705         mansession_lock(s);
2706         if (s->session->waiting_thread != AST_PTHREADT_NULL) {
2707                 pthread_kill(s->session->waiting_thread, SIGURG);
2708         }
2709
2710         if (s->session->managerid) { /* AMI-over-HTTP session */
2711                 /*
2712                  * Make sure the timeout is within the expire time of the session,
2713                  * as the client will likely abort the request if it does not see
2714                  * data coming after some amount of time.
2715                  */
2716                 time_t now = time(NULL);
2717                 int max = s->session->sessiontimeout - now - 10;
2718
2719                 if (max < 0) {  /* We are already late. Strange but possible. */
2720                         max = 0;
2721                 }
2722                 if (timeout < 0 || timeout > max) {
2723                         timeout = max;
2724                 }
2725                 if (!s->session->send_events) { /* make sure we record events */
2726                         s->session->send_events = -1;
2727                 }
2728         }
2729         mansession_unlock(s);
2730
2731         /* XXX should this go inside the lock ? */
2732         s->session->waiting_thread = pthread_self();    /* let new events wake up this thread */
2733         ast_debug(1, "Starting waiting for an event!\n");
2734
2735         for (x = 0; x < timeout || timeout < 0; x++) {
2736                 mansession_lock(s);
2737                 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
2738                         needexit = 1;
2739                 }
2740                 /* We can have multiple HTTP session point to the same mansession entry.
2741                  * The way we deal with it is not very nice: newcomers kick out the previous
2742                  * HTTP session. XXX this needs to be improved.
2743                  */
2744                 if (s->session->waiting_thread != pthread_self()) {
2745                         needexit = 1;
2746                 }
2747                 if (s->session->needdestroy) {
2748                         needexit = 1;
2749                 }
2750                 mansession_unlock(s);
2751                 if (needexit) {
2752                         break;
2753                 }
2754                 if (s->session->managerid == 0) {       /* AMI session */
2755                         if (ast_wait_for_input(s->session->fd, 1000)) {
2756                                 break;
2757                         }
2758                 } else {        /* HTTP session */
2759                         sleep(1);
2760                 }
2761         }
2762         ast_debug(1, "Finished waiting for an event!\n");
2763
2764         mansession_lock(s);
2765         if (s->session->waiting_thread == pthread_self()) {
2766                 struct eventqent *eqe = s->session->last_ev;
2767                 astman_send_response(s, m, "Success", "Waiting for Event completed.");
2768                 AST_RWLIST_RDLOCK(&all_events);
2769                 while ((eqe = advance_event(eqe))) {
2770                         if (((s->session->readperm & eqe->category) == eqe->category) &&
2771                             ((s->session->send_events & eqe->category) == eqe->category)) {
2772                                 astman_append(s, "%s", eqe->eventdata);
2773                         }
2774                         s->session->last_ev = eqe;
2775                 }
2776                 AST_RWLIST_UNLOCK(&all_events);
2777                 astman_append(s,
2778                         "Event: WaitEventComplete\r\n"
2779                         "%s"
2780                         "\r\n", idText);
2781                 s->session->waiting_thread = AST_PTHREADT_NULL;
2782         } else {
2783                 ast_debug(1, "Abandoning event request!\n");
2784         }
2785         mansession_unlock(s);
2786         return 0;
2787 }
2788
2789 /*! \note The actionlock is read-locked by the caller of this function */
2790 static int action_listcommands(struct mansession *s, const struct message *m)
2791 {
2792         struct manager_action *cur;
2793         struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */
2794
2795         astman_start_ack(s, m);
2796         AST_RWLIST_TRAVERSE(&actions, cur, list) {
2797                 if (s->session->writeperm & cur->authority || cur->authority == 0) {
2798                         astman_append(s, "%s: %s (Priv: %s)\r\n",
2799                                 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
2800                 }
2801         }
2802         astman_append(s, "\r\n");
2803
2804         return 0;
2805 }
2806
2807 static int action_events(struct mansession *s, const struct message *m)
2808 {
2809         const char *mask = astman_get_header(m, "EventMask");
2810         int res, x;
2811
2812         res = set_eventmask(s, mask);
2813         if (broken_events_action) {
2814                 /* if this option is set we should not return a response on
2815                  * error, or when all events are set */
2816
2817                 if (res > 0) {
2818                         for (x = 0; x < ARRAY_LEN(perms); x++) {
2819                                 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
2820                                         return 0;
2821                                 }
2822                         }
2823                         astman_append(s, "Response: Success\r\n"
2824                                          "Events: On\r\n\r\n");
2825                 } else if (res == 0)
2826                         astman_append(s, "Response: Success\r\n"
2827                                          "Events: Off\r\n\r\n");
2828                 return 0;
2829         }
2830
2831         if (res > 0)
2832                 astman_append(s, "Response: Success\r\n"
2833                                  "Events: On\r\n\r\n");
2834         else if (res == 0)
2835                 astman_append(s, "Response: Success\r\n"
2836                                  "Events: Off\r\n\r\n");
2837         else
2838                 astman_send_error(s, m, "Invalid event mask");
2839
2840         return 0;
2841 }
2842
2843 static int action_logoff(struct mansession *s, const struct message *m)
2844 {
2845         astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
2846         return -1;
2847 }
2848
2849 static int action_login(struct mansession *s, const struct message *m)
2850 {
2851
2852         /* still authenticated - don't process again */
2853         if (s->session->authenticated) {
2854                 astman_send_ack(s, m, "Already authenticated");
2855                 return 0;
2856         }
2857
2858         if (authenticate(s, m)) {
2859                 sleep(1);
2860                 astman_send_error(s, m, "Authentication failed");
2861                 return -1;
2862         }
2863         s->session->authenticated = 1;
2864         if (manager_displayconnects(s->session)) {
2865                 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));
2866         }
2867         astman_send_ack(s, m, "Authentication accepted");
2868         if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
2869                 manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
2870         }
2871         return 0;
2872 }
2873
2874 static int action_challenge(struct mansession *s, const struct message *m)
2875 {
2876         const char *authtype = astman_get_header(m, "AuthType");
2877
2878         if (!strcasecmp(authtype, "MD5")) {
2879                 if (ast_strlen_zero(s->session->challenge)) {
2880                         snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
2881                 }
2882                 mansession_lock(s);
2883                 astman_start_ack(s, m);
2884                 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
2885                 mansession_unlock(s);
2886         } else {
2887                 astman_send_error(s, m, "Must specify AuthType");
2888         }
2889         return 0;
2890 }
2891
2892 static int action_hangup(struct mansession *s, const struct message *m)
2893 {
2894         struct ast_channel *c = NULL;
2895         int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
2896         const char *name = astman_get_header(m, "Channel");
2897         const char *cause = astman_get_header(m, "Cause");
2898
2899         if (ast_strlen_zero(name)) {
2900                 astman_send_error(s, m, "No channel specified");
2901                 return 0;
2902         }
2903
2904         if (!ast_strlen_zero(cause)) {
2905                 char *endptr;
2906                 causecode = strtol(cause, &endptr, 10);
2907                 if (causecode < 0 || causecode > 127 || *endptr != '\0') {
2908                         ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
2909                         /* keep going, better to hangup without cause than to not hang up at all */
2910                         causecode = 0; /* do not set channel's hangupcause */
2911                 }
2912         }
2913
2914         if (!(c = ast_channel_get_by_name(name))) {
2915                 astman_send_error(s, m, "No such channel");
2916                 return 0;
2917         }
2918
2919         ast_channel_lock(c);
2920         if (causecode > 0) {
2921                 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
2922                                 c->name, causecode, c->hangupcause);
2923                 c->hangupcause = causecode;
2924         }
2925         ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
2926         ast_channel_unlock(c);
2927
2928         c = ast_channel_unref(c);
2929
2930         astman_send_ack(s, m, "Channel Hungup");
2931
2932         return 0;
2933 }
2934
2935 static int action_setvar(struct mansession *s, const struct message *m)
2936 {
2937         struct ast_channel *c = NULL;
2938         const char *name = astman_get_header(m, "Channel");
2939         const char *varname = astman_get_header(m, "Variable");
2940         const char *varval = astman_get_header(m, "Value");
2941         int res = 0;
2942         
2943         if (ast_strlen_zero(varname)) {
2944                 astman_send_error(s, m, "No variable specified");
2945                 return 0;
2946         }
2947
2948         if (!ast_strlen_zero(name)) {
2949                 if (!(c = ast_channel_get_by_name(name))) {
2950                         astman_send_error(s, m, "No such channel");
2951                         return 0;
2952                 }
2953         }
2954
2955         res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
2956
2957         if (c) {
2958                 c = ast_channel_unref(c);
2959         }
2960         if (res == 0) {
2961                 astman_send_ack(s, m, "Variable Set");  
2962         } else {
2963                 astman_send_error(s, m, "Variable not set");
2964         }
2965         return 0;
2966 }
2967
2968 static int action_getvar(struct mansession *s, const struct message *m)
2969 {
2970         struct ast_channel *c = NULL;
2971         const char *name = astman_get_header(m, "Channel");
2972         const char *varname = astman_get_header(m, "Variable");
2973         char *varval;
2974         char workspace[1024] = "";
2975
2976         if (ast_strlen_zero(varname)) {
2977                 astman_send_error(s, m, "No variable specified");
2978                 return 0;
2979         }
2980
2981         if (!ast_strlen_zero(name)) {
2982                 if (!(c = ast_channel_get_by_name(name))) {
2983                         astman_send_error(s, m, "No such channel");
2984                         return 0;
2985                 }
2986         }
2987
2988         if (varname[strlen(varname) - 1] == ')') {
2989                 if (!c) {
2990                         c = ast_dummy_channel_alloc();
2991                         if (c) {
2992                                 ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
2993                                 c = ast_channel_release(c);
2994                         } else
2995                                 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
2996                 } else {
2997                         ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
2998                 }
2999                 varval = workspace;
3000         } else {
3001                 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
3002         }
3003
3004         if (c) {
3005                 c = ast_channel_unref(c);
3006         }
3007
3008         astman_start_ack(s, m);
3009         astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, varval);
3010
3011         return 0;
3012 }
3013
3014 /*! \brief Manager "status" command to show channels */
3015 /* Needs documentation... */
3016 static int action_status(struct mansession *s, const struct message *m)
3017 {
3018         const char *name = astman_get_header(m, "Channel");
3019         const char *cvariables = astman_get_header(m, "Variables");
3020         char *variables = ast_strdupa(S_OR(cvariables, ""));
3021         struct ast_channel *c;
3022         char bridge[256];
3023         struct timeval now = ast_tvnow();
3024         long elapsed_seconds = 0;
3025         int channels = 0;
3026         int all = ast_strlen_zero(name); /* set if we want all channels */
3027         const char *id = astman_get_header(m, "ActionID");
3028         char idText[256];
3029         AST_DECLARE_APP_ARGS(vars,
3030                 AST_APP_ARG(name)[100];
3031         );
3032         struct ast_str *str = ast_str_create(1000);
3033         struct ast_channel_iterator *iter = NULL;
3034
3035         if (!ast_strlen_zero(id)) {
3036                 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3037         } else {
3038                 idText[0] = '\0';
3039         }
3040
3041         if (all) {
3042                 if (!(iter = ast_channel_iterator_all_new())) {
3043                         ast_free(str);
3044                         astman_send_error(s, m, "Memory Allocation Failure");