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