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