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