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