Fri Feb 10 06:36:47 2012

Asterisk developer's documentation


manager.c File Reference

The Asterisk Management Interface - AMI. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <regex.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/ast_version.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"
#include "asterisk/features.h"
#include "asterisk/security_events.h"
#include "asterisk/aoc.h"
#include "asterisk/stringfields.h"

Include dependency graph for manager.c:

Go to the source code of this file.

Data Structures

struct  actions
 list of actions registered More...
struct  all_events
struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  channelvars
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  manager_channel_variable
struct  manager_hooks
 list of hooks registered More...
struct  mansession
 In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data. More...
struct  mansession_session
struct  mansession_session::mansession_datastores
struct  permalias
struct  users
 list of users found in the config file More...
struct  variable_count

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define DEFAULT_REALM   "asterisk"
#define FORMAT   " %-25.25s %-15.15s\n"
#define FORMAT2   " %-25.25s %-15d\n"
#define GET_HEADER_FIRST_MATCH   0
#define GET_HEADER_LAST_MATCH   1
#define GET_HEADER_SKIP_EMPTY   2
#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"
#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MSG_MOREDATA   ((char *)astman_send_response)
#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
#define TEST_STRING   "<form action=\"manager\" method=\"post\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----&gt;</option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n"

Enumerations

enum  add_filter_result { FILTER_SUCCESS, FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL }
enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}
enum  output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }

Functions

int __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
static const char * __astman_get_header (const struct message *m, char *var, int mode)
 Return a matching header value.
static void __fini_actions (void)
static void __fini_all_events (void)
static void __fini_channelvars (void)
static void __fini_manager_hooks (void)
static void __fini_users (void)
static void __init_actions (void)
static void __init_all_events (void)
static void __init_astman_append_buf (void)
 thread local buffer for astman_append
static void __init_channelvars (void)
static int __init_manager (int reload)
static void __init_manager_event_buf (void)
static void __init_manager_event_funcbuf (void)
static void __init_manager_hooks (void)
static void __init_userevent_buf (void)
static void __init_users (void)
static int action_aocmessage (struct mansession *s, const struct message *m)
static int action_atxfer (struct mansession *s, const struct message *m)
static int action_challenge (struct mansession *s, const struct message *m)
static int action_command (struct mansession *s, const struct message *m)
 Manager command "command" - execute CLI command.
static int action_coresettings (struct mansession *s, const struct message *m)
 Show PBX core settings information.
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
static int action_createconfig (struct mansession *s, const struct message *m)
static void action_destroy (void *obj)
static int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
static int action_filter (struct mansession *s, const struct message *m)
static struct manager_actionaction_find (const char *name)
static int action_getconfig (struct mansession *s, const struct message *m)
static int action_getconfigjson (struct mansession *s, const struct message *m)
static int action_getvar (struct mansession *s, const struct message *m)
static int action_hangup (struct mansession *s, const struct message *m)
static int action_listcategories (struct mansession *s, const struct message *m)
static int action_listcommands (struct mansession *s, const struct message *m)
static int action_login (struct mansession *s, const struct message *m)
static int action_logoff (struct mansession *s, const struct message *m)
static int action_mailboxcount (struct mansession *s, const struct message *m)
static int action_mailboxstatus (struct mansession *s, const struct message *m)
static int action_originate (struct mansession *s, const struct message *m)
static int action_ping (struct mansession *s, const struct message *m)
static int action_redirect (struct mansession *s, const struct message *m)
 action_redirect: The redirect manager command
static int action_reload (struct mansession *s, const struct message *m)
 Send a reload event.
static int action_sendtext (struct mansession *s, const struct message *m)
static int action_setvar (struct mansession *s, const struct message *m)
static int action_status (struct mansession *s, const struct message *m)
 Manager "status" command to show channels.
static int action_timeout (struct mansession *s, const struct message *m)
static int action_updateconfig (struct mansession *s, const struct message *m)
static int action_userevent (struct mansession *s, const struct message *m)
static int action_waitevent (struct mansession *s, const struct message *m)
static struct eventqentadvance_event (struct eventqent *e)
static int aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
static void append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan)
static int append_event (const char *str, int category)
 events are appended to a queue from where they can be dispatched to clients.
int ast_hook_send_action (struct manager_custom_hook *hook, const char *msg)
 access for hooks to send action messages to ami
static int ast_instring (const char *bigstr, const char *smallstr, const char delim)
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
 register a new command with manager, including online help. This is the preferred way to register a manager command
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired.
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 support functions to register/unregister AMI action handlers,
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
void astman_append (struct mansession *s, const char *fmt,...)
static void astman_append_json (struct mansession *s, const char *str)
int astman_datastore_add (struct mansession *s, struct ast_datastore *datastore)
 Add a datastore to a session.
struct ast_datastoreastman_datastore_find (struct mansession *s, const struct ast_datastore_info *info, const char *uid)
 Find a datastore on a session.
int astman_datastore_remove (struct mansession *s, struct ast_datastore *datastore)
 Remove a datastore from a session.
const char * astman_get_header (const struct message *m, char *var)
 Return the first matching variable from an array.
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
int astman_is_authed (uint32_t ident)
 Determinie if a manager session ident is authenticated.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
static void astman_start_ack (struct mansession *s, const struct message *m)
int astman_verify_session_readpermissions (uint32_t ident, int perm)
 Verify a session's read permissions against a permission mask.
int astman_verify_session_writepermissions (uint32_t ident, int perm)
 Verify a session's write permissions against a permission mask.
static int auth_http_callback (struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, struct sockaddr_in *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers)
static int auth_manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static int auth_mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static int auth_rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static int authenticate (struct mansession *s, const struct message *m)
static const char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static int blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags)
static struct mansession_sessionbuild_mansession (struct sockaddr_in sin)
 Allocate manager session structure and add it to the list of sessions.
static int check_blacklist (const char *cmd)
int check_manager_enabled (void)
 Check if AMI is enabled.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled (void)
 Check if AMI/HTTP is enabled.
static void destroy_fast_originate_helper (struct fast_originate_helper *doomed)
static int do_message (struct mansession *s)
static void event_filter_destructor (void *obj)
static void * fast_originate (void *data)
static struct mansession_sessionfind_session (uint32_t ident, int incinuse)
static struct mansession_sessionfind_session_by_nonce (const char *username, unsigned long nonce, int *stale)
static void free_channelvars (void)
static int generic_http_callback (struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, struct sockaddr_in *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers)
static int get_input (struct mansession *s, char *output)
static struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_manager_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager show settings.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
 helper function for action_updateconfig
int init_manager (void)
 Called by Asterisk initialization.
static void json_escape (char *out, const char *in)
static void load_channelvars (struct ast_variable *var)
static struct ast_variableman_do_variable_value (struct ast_variable *head, const char *hdr_val)
static enum add_filter_result manager_add_filter (const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static int manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static int manager_modulecheck (struct mansession *s, const struct message *m)
 Manager function to check if module is loaded.
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (const char *context, const char *exten, enum ast_extension_states state, void *data)
static int mansession_cmp_fn (void *obj, void *arg, int flags)
static struct sockaddr_in * mansession_encode_sin_local (const struct mansession *s, struct sockaddr_in *sin_local)
static enum
ast_security_event_transport_type 
mansession_get_transport (const struct mansession *s)
static void mansession_lock (struct mansession *s)
 Lock the 'mansession' structure.
static void mansession_unlock (struct mansession *s)
 Unlock the 'mansession' structure.
static int match_filter (struct mansession *s, char *eventdata)
static int mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
 Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.
static void process_output (struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format)
static void purge_events (void)
static void purge_old_stuff (void *data)
 cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static int rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
int reload_manager (void)
 Called by Asterisk module functions and the CLI command.
static void report_auth_success (const struct mansession *s)
static void report_failed_acl (const struct mansession *s, const char *username)
static void report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response)
static void report_inval_password (const struct mansession *s, const char *username)
static void report_invalid_user (const struct mansession *s, const char *username)
static void report_req_bad_format (const struct mansession *s, const char *action)
static void report_req_not_allowed (const struct mansession *s, const char *action)
static void report_session_limit (const struct mansession *s)
static int send_string (struct mansession *s, char *string)
static void session_destroy (struct mansession_session *s)
static void session_destructor (void *obj)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static struct mansession_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
static int variable_count_cmp_fn (void *obj, void *vstr, int flags)
static int variable_count_hash_fn (const void *vvc, const int flags)
static int whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags)
static void xml_copy_escape (struct ast_str **out, const char *src, int mode)
static void xml_translate (struct ast_str **out, char *in, struct ast_variable *get_vars, enum output_format format)
 Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

Variables

static int allowmultiplelogin = 1
static struct ast_http_uri amanageruri
static struct ast_http_uri amanagerxmluri
static struct
ast_tcptls_session_args 
ami_desc
static struct ast_tls_config ami_tls_cfg
static struct
ast_tcptls_session_args 
amis_desc
static struct ast_http_uri arawmanuri
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
static int authlimit
static int authtimeout
static int block_sockets
static int broken_events_action = 0
static struct ast_cli_entry cli_manager []
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static const char *const contenttype []
static int displayconnects = 1
static char global_realm [MAXHOSTNAMELEN]
static int httptimeout = 60
static char * manager_channelvars
static int manager_debug = 0
static int manager_enabled = 0
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
static struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , }
static struct ast_http_uri manageruri
static struct ast_http_uri managerxmluri
static struct permalias perms []
static struct ast_http_uri rawmanuri
static int registered = 0
static struct ao2_containersessions = NULL
static int timestampevents
static int unauth_sessions = 0
static struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
static int webmanager_enabled = 0
static int webregged = 0


Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
OpenSSL http://www.openssl.org - for AMI/SSL
At the moment this file contains a number of functions, namely:

manager.conf

Definition in file manager.c.


Define Documentation

#define FORMAT   " %-25.25s %-15.15s\n"

#define FORMAT2   " %-25.25s %-15d\n"

#define HSMC_FORMAT   " %-15.15s %-15.15s %-55.55s\n"

Referenced by handle_showmancmds().

#define HSMCONN_FORMAT1   " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"

Referenced by handle_showmanconn().

#define HSMCONN_FORMAT2   " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"

Referenced by handle_showmanconn().

#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"

Referenced by generic_http_callback().

#define TEST_STRING   "<form action=\"manager\" method=\"post\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----&gt;</option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n"

Referenced by generic_http_callback().


Enumeration Type Documentation

END Doxygen group

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 5457 of file manager.c.

05457                    {
05458    FORMAT_RAW,
05459    FORMAT_HTML,
05460    FORMAT_XML,
05461 };


Function Documentation

static int __init_manager ( int  reload  )  [static]

Definition at line 6635 of file manager.c.

References ast_manager_user::a1_hash, action_aocmessage(), action_atxfer(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ami_tls_cfg, ao2_container_alloc, ao2_t_callback, ao2_t_ref, append_event(), ARRAY_LEN, ast_append_ha(), ast_calloc, ast_category_browse(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_debug, ast_extension_state_add(), ast_free, ast_free_ha(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, ast_log(), ast_manager_register_xml, ast_md5_hash(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_sockaddr_setnull(), ast_sockaddr_to_sin, ast_ssl_setup(), ast_strdup, ast_strlen_zero(), ast_tcptls_server_start(), ast_tcptls_server_stop(), ast_tls_read_conf(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_manager_user::blackfilters, block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, DEFAULT_MANAGER_TLS_PORT, DEFAULT_REALM, ast_manager_user::displayconnects, ast_tls_config::enabled, EVENT_FLAG_AOC, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, free_channelvars(), get_manager_by_name_locked(), get_perm(), global_realm, ast_manager_user::ha, inet_aton(), ast_manager_user::keep, ast_variable::lineno, load_channelvars(), ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_add_filter(), manager_event, manager_modulecheck(), manager_moduleload(), manager_state_cb(), mansession_cmp_fn(), ast_variable::name, ast_variable::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_tls_config::pvtfile, ast_manager_user::readperm, S_OR, ast_manager_user::secret, ast_tcptls_session_args::tls_cfg, ast_manager_user::username, value, ast_variable::value, var, ast_manager_user::whitefilters, ast_manager_user::writeperm, and ast_manager_user::writetimeout.

Referenced by init_manager(), and reload_manager().

06636 {
06637    struct ast_config *ucfg = NULL, *cfg = NULL;
06638    const char *val;
06639    char *cat = NULL;
06640    int newhttptimeout = 60;
06641    struct ast_manager_user *user = NULL;
06642    struct ast_variable *var;
06643    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
06644    char a1[256];
06645    char a1_hash[256];
06646    struct sockaddr_in ami_desc_local_address_tmp = { 0, };
06647    struct sockaddr_in amis_desc_local_address_tmp = { 0, };
06648    int tls_was_enabled = 0;
06649 
06650    manager_enabled = 0;
06651 
06652    if (!registered) {
06653       /* Register default actions */
06654       ast_manager_register_xml("Ping", 0, action_ping);
06655       ast_manager_register_xml("Events", 0, action_events);
06656       ast_manager_register_xml("Logoff", 0, action_logoff);
06657       ast_manager_register_xml("Login", 0, action_login);
06658       ast_manager_register_xml("Challenge", 0, action_challenge);
06659       ast_manager_register_xml("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup);
06660       ast_manager_register_xml("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status);
06661       ast_manager_register_xml("Setvar", EVENT_FLAG_CALL, action_setvar);
06662       ast_manager_register_xml("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar);
06663       ast_manager_register_xml("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig);
06664       ast_manager_register_xml("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson);
06665       ast_manager_register_xml("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig);
06666       ast_manager_register_xml("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig);
06667       ast_manager_register_xml("ListCategories", EVENT_FLAG_CONFIG, action_listcategories);
06668       ast_manager_register_xml("Redirect", EVENT_FLAG_CALL, action_redirect);
06669       ast_manager_register_xml("Atxfer", EVENT_FLAG_CALL, action_atxfer);
06670       ast_manager_register_xml("Originate", EVENT_FLAG_ORIGINATE, action_originate);
06671       ast_manager_register_xml("Command", EVENT_FLAG_COMMAND, action_command);
06672       ast_manager_register_xml("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate);
06673       ast_manager_register_xml("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout);
06674       ast_manager_register_xml("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus);
06675       ast_manager_register_xml("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount);
06676       ast_manager_register_xml("ListCommands", 0, action_listcommands);
06677       ast_manager_register_xml("SendText", EVENT_FLAG_CALL, action_sendtext);
06678       ast_manager_register_xml("UserEvent", EVENT_FLAG_USER, action_userevent);
06679       ast_manager_register_xml("WaitEvent", 0, action_waitevent);
06680       ast_manager_register_xml("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings);
06681       ast_manager_register_xml("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus);
06682       ast_manager_register_xml("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload);
06683       ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels);
06684       ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload);
06685       ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck);
06686       ast_manager_register_xml("AOCMessage", EVENT_FLAG_AOC, action_aocmessage);
06687       ast_manager_register_xml("Filter", EVENT_FLAG_SYSTEM, action_filter);
06688 
06689       ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
06690       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
06691       registered = 1;
06692       /* Append placeholder event so master_eventq never runs dry */
06693       append_event("Event: Placeholder\r\n\r\n", 0);
06694    }
06695    if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
06696       return 0;
06697    }
06698 
06699    displayconnects = 1;
06700    broken_events_action = 0;
06701    authtimeout = 30;
06702    authlimit = 50;
06703    manager_debug = 0;      /* Debug disabled by default */
06704 
06705    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
06706       ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n");
06707       return 0;
06708    }
06709 
06710    /* default values */
06711    ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm));
06712    ast_sockaddr_setnull(&ami_desc.local_address);
06713    ast_sockaddr_setnull(&amis_desc.local_address);
06714 
06715    ami_desc_local_address_tmp.sin_family = AF_INET;
06716    amis_desc_local_address_tmp.sin_family = AF_INET;
06717 
06718    ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT);
06719 
06720    tls_was_enabled = (reload && ami_tls_cfg.enabled);
06721 
06722    ami_tls_cfg.enabled = 0;
06723    if (ami_tls_cfg.certfile) {
06724       ast_free(ami_tls_cfg.certfile);
06725    }
06726    ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
06727    if (ami_tls_cfg.pvtfile) {
06728       ast_free(ami_tls_cfg.pvtfile);
06729    }
06730    ami_tls_cfg.pvtfile = ast_strdup("");
06731    if (ami_tls_cfg.cipher) {
06732       ast_free(ami_tls_cfg.cipher);
06733    }
06734    ami_tls_cfg.cipher = ast_strdup("");
06735 
06736    free_channelvars();
06737 
06738    for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
06739       val = var->value;
06740 
06741       if (!ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) {
06742          continue;
06743       }
06744 
06745       if (!strcasecmp(var->name, "enabled")) {
06746          manager_enabled = ast_true(val);
06747       } else if (!strcasecmp(var->name, "block-sockets")) {
06748          block_sockets = ast_true(val);
06749       } else if (!strcasecmp(var->name, "webenabled")) {
06750          webmanager_enabled = ast_true(val);
06751       } else if (!strcasecmp(var->name, "port")) {
06752          ami_desc_local_address_tmp.sin_port = htons(atoi(val));
06753       } else if (!strcasecmp(var->name, "bindaddr")) {
06754          if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) {
06755             ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
06756             memset(&ami_desc_local_address_tmp.sin_addr, 0,
06757                    sizeof(ami_desc_local_address_tmp.sin_addr));
06758          }
06759       } else if (!strcasecmp(var->name, "brokeneventsaction")) {
06760          broken_events_action = ast_true(val);
06761       } else if (!strcasecmp(var->name, "allowmultiplelogin")) {
06762          allowmultiplelogin = ast_true(val);
06763       } else if (!strcasecmp(var->name, "displayconnects")) {
06764          displayconnects = ast_true(val);
06765       } else if (!strcasecmp(var->name, "timestampevents")) {
06766          timestampevents = ast_true(val);
06767       } else if (!strcasecmp(var->name, "debug")) {
06768          manager_debug = ast_true(val);
06769       } else if (!strcasecmp(var->name, "httptimeout")) {
06770          newhttptimeout = atoi(val);
06771       } else if (!strcasecmp(var->name, "authtimeout")) {
06772          int timeout = atoi(var->value);
06773 
06774          if (timeout < 1) {
06775             ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value);
06776          } else {
06777             authtimeout = timeout;
06778          }
06779       } else if (!strcasecmp(var->name, "authlimit")) {
06780          int limit = atoi(var->value);
06781 
06782          if (limit < 1) {
06783             ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value);
06784          } else {
06785             authlimit = limit;
06786          }
06787       } else if (!strcasecmp(var->name, "channelvars")) {
06788          load_channelvars(var);
06789       } else {
06790          ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
06791             var->name, val);
06792       }
06793    }
06794 
06795    ast_sockaddr_to_sin(&amis_desc.local_address, &amis_desc_local_address_tmp);
06796 
06797    /* if the amis address has not been set, default is the same as non secure ami */
06798    if (!amis_desc_local_address_tmp.sin_addr.s_addr) {
06799       amis_desc_local_address_tmp.sin_addr =
06800           ami_desc_local_address_tmp.sin_addr;
06801    }
06802 
06803    if (!amis_desc_local_address_tmp.sin_port) {
06804       amis_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_TLS_PORT);
06805    }
06806 
06807    if (manager_enabled) {
06808       ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp);
06809       ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp);
06810    }
06811 
06812    AST_RWLIST_WRLOCK(&users);
06813 
06814    /* First, get users from users.conf */
06815    ucfg = ast_config_load2("users.conf", "manager", config_flags);
06816    if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) {
06817       const char *hasmanager;
06818       int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
06819 
06820       while ((cat = ast_category_browse(ucfg, cat))) {
06821          if (!strcasecmp(cat, "general")) {
06822             continue;
06823          }
06824 
06825          hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
06826          if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
06827             const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
06828             const char *user_read = ast_variable_retrieve(ucfg, cat, "read");
06829             const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
06830             const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
06831             const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
06832 
06833             /* Look for an existing entry,
06834              * if none found - create one and add it to the list
06835              */
06836             if (!(user = get_manager_by_name_locked(cat))) {
06837                if (!(user = ast_calloc(1, sizeof(*user)))) {
06838                   break;
06839                }
06840 
06841                /* Copy name over */
06842                ast_copy_string(user->username, cat, sizeof(user->username));
06843                /* Insert into list */
06844                AST_LIST_INSERT_TAIL(&users, user, list);
06845                user->ha = NULL;
06846                user->keep = 1;
06847                user->readperm = -1;
06848                user->writeperm = -1;
06849                /* Default displayconnect from [general] */
06850                user->displayconnects = displayconnects;
06851                user->writetimeout = 100;
06852             }
06853 
06854             if (!user_secret) {
06855                user_secret = ast_variable_retrieve(ucfg, "general", "secret");
06856             }
06857             if (!user_read) {
06858                user_read = ast_variable_retrieve(ucfg, "general", "read");
06859             }
06860             if (!user_write) {
06861                user_write = ast_variable_retrieve(ucfg, "general", "write");
06862             }
06863             if (!user_displayconnects) {
06864                user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
06865             }
06866             if (!user_writetimeout) {
06867                user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
06868             }
06869 
06870             if (!ast_strlen_zero(user_secret)) {
06871                if (user->secret) {
06872                   ast_free(user->secret);
06873                }
06874                user->secret = ast_strdup(user_secret);
06875             }
06876 
06877             if (user_read) {
06878                user->readperm = get_perm(user_read);
06879             }
06880             if (user_write) {
06881                user->writeperm = get_perm(user_write);
06882             }
06883             if (user_displayconnects) {
06884                user->displayconnects = ast_true(user_displayconnects);
06885             }
06886             if (user_writetimeout) {
06887                int value = atoi(user_writetimeout);
06888                if (value < 100) {
06889                   ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
06890                } else {
06891                   user->writetimeout = value;
06892                }
06893             }
06894          }
06895       }
06896       ast_config_destroy(ucfg);
06897    }
06898 
06899    /* cat is NULL here in any case */
06900 
06901    while ((cat = ast_category_browse(cfg, cat))) {
06902       struct ast_ha *oldha;
06903 
06904       if (!strcasecmp(cat, "general")) {
06905          continue;
06906       }
06907 
06908       /* Look for an existing entry, if none found - create one and add it to the list */
06909       if (!(user = get_manager_by_name_locked(cat))) {
06910          if (!(user = ast_calloc(1, sizeof(*user)))) {
06911             break;
06912          }
06913          /* Copy name over */
06914          ast_copy_string(user->username, cat, sizeof(user->username));
06915 
06916          user->ha = NULL;
06917          user->readperm = 0;
06918          user->writeperm = 0;
06919          /* Default displayconnect from [general] */
06920          user->displayconnects = displayconnects;
06921          user->writetimeout = 100;
06922          user->whitefilters = ao2_container_alloc(1, NULL, NULL);
06923          user->blackfilters = ao2_container_alloc(1, NULL, NULL);
06924 
06925          /* Insert into list */
06926          AST_RWLIST_INSERT_TAIL(&users, user, list);
06927       } else {
06928          ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
06929          ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
06930       }
06931 
06932       /* Make sure we keep this user and don't destroy it during cleanup */
06933       user->keep = 1;
06934       oldha = user->ha;
06935       user->ha = NULL;
06936 
06937       var = ast_variable_browse(cfg, cat);
06938       for (; var; var = var->next) {
06939          if (!strcasecmp(var->name, "secret")) {
06940             if (user->secret) {
06941                ast_free(user->secret);
06942             }
06943             user->secret = ast_strdup(var->value);
06944          } else if (!strcasecmp(var->name, "deny") ||
06945                    !strcasecmp(var->name, "permit")) {
06946             user->ha = ast_append_ha(var->name, var->value, user->ha, NULL);
06947          }  else if (!strcasecmp(var->name, "read") ) {
06948             user->readperm = get_perm(var->value);
06949          }  else if (!strcasecmp(var->name, "write") ) {
06950             user->writeperm = get_perm(var->value);
06951          }  else if (!strcasecmp(var->name, "displayconnects") ) {
06952             user->displayconnects = ast_true(var->value);
06953          } else if (!strcasecmp(var->name, "writetimeout")) {
06954             int value = atoi(var->value);
06955             if (value < 100) {
06956                ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
06957             } else {
06958                user->writetimeout = value;
06959             }
06960          } else if (!strcasecmp(var->name, "eventfilter")) {
06961             const char *value = var->value;
06962                                 manager_add_filter(value, user->whitefilters, user->blackfilters);
06963          } else {
06964             ast_debug(1, "%s is an unknown option.\n", var->name);
06965          }
06966       }
06967       ast_free_ha(oldha);
06968    }
06969    ast_config_destroy(cfg);
06970 
06971    /* Perform cleanup - essentially prune out old users that no longer exist */
06972    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
06973       if (user->keep) { /* valid record. clear flag for the next round */
06974          user->keep = 0;
06975 
06976          /* Calculate A1 for Digest auth */
06977          snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret);
06978          ast_md5_hash(a1_hash,a1);
06979          if (user->a1_hash) {
06980             ast_free(user->a1_hash);
06981          }
06982          user->a1_hash = ast_strdup(a1_hash);
06983          continue;
06984       }
06985       /* We do not need to keep this user so take them out of the list */
06986       AST_RWLIST_REMOVE_CURRENT(list);
06987       ast_debug(4, "Pruning user '%s'\n", user->username);
06988       /* Free their memory now */
06989       if (user->a1_hash) {
06990          ast_free(user->a1_hash);
06991       }
06992       if (user->secret) {
06993          ast_free(user->secret);
06994       }
06995       ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
06996       ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
06997       ao2_t_ref(user->whitefilters, -1, "decrement ref for white container, should be last one");
06998       ao2_t_ref(user->blackfilters, -1, "decrement ref for black container, should be last one");
06999       ast_free_ha(user->ha);
07000       ast_free(user);
07001    }
07002    AST_RWLIST_TRAVERSE_SAFE_END;
07003 
07004    AST_RWLIST_UNLOCK(&users);
07005 
07006    if (!reload) {
07007       /* If you have a NULL hash fn, you only need a single bucket */
07008       sessions = ao2_container_alloc(1, NULL, mansession_cmp_fn);
07009    }
07010 
07011    if (webmanager_enabled && manager_enabled) {
07012       if (!webregged) {
07013 
07014          ast_http_uri_link(&rawmanuri);
07015          ast_http_uri_link(&manageruri);
07016          ast_http_uri_link(&managerxmluri);
07017 
07018          ast_http_uri_link(&arawmanuri);
07019          ast_http_uri_link(&amanageruri);
07020          ast_http_uri_link(&amanagerxmluri);
07021          webregged = 1;
07022       }
07023    } else {
07024       if (webregged) {
07025          ast_http_uri_unlink(&rawmanuri);
07026          ast_http_uri_unlink(&manageruri);
07027          ast_http_uri_unlink(&managerxmluri);
07028 
07029          ast_http_uri_unlink(&arawmanuri);
07030          ast_http_uri_unlink(&amanageruri);
07031          ast_http_uri_unlink(&amanagerxmluri);
07032          webregged = 0;
07033       }
07034    }
07035 
07036    if (newhttptimeout > 0) {
07037       httptimeout = newhttptimeout;
07038    }
07039 
07040    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
07041 
07042    ast_tcptls_server_start(&ami_desc);
07043    if (tls_was_enabled && !ami_tls_cfg.enabled) {
07044       ast_tcptls_server_stop(&amis_desc);
07045    } else if (ast_ssl_setup(amis_desc.tls_cfg)) {
07046       ast_tcptls_server_start(&amis_desc);
07047    }
07048    return 0;
07049 }

int astman_datastore_add ( struct mansession s,
struct ast_datastore datastore 
)

Add a datastore to a session.

Return values:
0 success
non-zero failure
Since:
1.6.1

Definition at line 7072 of file manager.c.

References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.

07073 {
07074    AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
07075 
07076    return 0;
07077 }

struct ast_datastore* astman_datastore_find ( struct mansession s,
const struct ast_datastore_info info,
const char *  uid 
) [read]

Find a datastore on a session.

Return values:
pointer to the datastore if found
NULL if not found
Since:
1.6.1

Definition at line 7084 of file manager.c.

References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, mansession_session::datastores, ast_datastore::info, mansession::session, and ast_datastore::uid.

07085 {
07086    struct ast_datastore *datastore = NULL;
07087 
07088    if (info == NULL)
07089       return NULL;
07090 
07091    AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
07092       if (datastore->info != info) {
07093          continue;
07094       }
07095 
07096       if (uid == NULL) {
07097          /* matched by type only */
07098          break;
07099       }
07100 
07101       if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
07102          /* Matched by type AND uid */
07103          break;
07104       }
07105    }
07106    AST_LIST_TRAVERSE_SAFE_END;
07107 
07108    return datastore;
07109 }

int astman_datastore_remove ( struct mansession s,
struct ast_datastore datastore 
)

Remove a datastore from a session.

Return values:
0 success
non-zero failure
Since:
1.6.1

Definition at line 7079 of file manager.c.

References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.

07080 {
07081    return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
07082 }

int astman_is_authed ( uint32_t  ident  ) 

Determinie if a manager session ident is authenticated.

Definition at line 5533 of file manager.c.

References ao2_unlock, mansession_session::authenticated, find_session(), and unref_mansession().

Referenced by http_post_callback(), and static_callback().

05534 {
05535    int authed;
05536    struct mansession_session *session;
05537 
05538    if (!(session = find_session(ident, 0)))
05539       return 0;
05540 
05541    authed = (session->authenticated != 0);
05542 
05543    ao2_unlock(session);
05544    unref_mansession(session);
05545 
05546    return authed;
05547 }

int astman_verify_session_readpermissions ( uint32_t  ident,
int  perm 
)

Verify a session's read permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Return values:
1 if the session has the permission mask capabilities
0 otherwise

Definition at line 5549 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::readperm, and unref_mansession().

05550 {
05551    int result = 0;
05552    struct mansession_session *session;
05553    struct ao2_iterator i;
05554 
05555    if (ident == 0) {
05556       return 0;
05557    }
05558 
05559    i = ao2_iterator_init(sessions, 0);
05560    while ((session = ao2_iterator_next(&i))) {
05561       ao2_lock(session);
05562       if ((session->managerid == ident) && (session->readperm & perm)) {
05563          result = 1;
05564          ao2_unlock(session);
05565          unref_mansession(session);
05566          break;
05567       }
05568       ao2_unlock(session);
05569       unref_mansession(session);
05570    }
05571    ao2_iterator_destroy(&i);
05572    return result;
05573 }

int astman_verify_session_writepermissions ( uint32_t  ident,
int  perm 
)

Verify a session's write permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Return values:
1 if the session has the permission mask capabilities, otherwise 0
0 otherwise

Definition at line 5575 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, unref_mansession(), and mansession_session::writeperm.

Referenced by http_post_callback().

05576 {
05577    int result = 0;
05578    struct mansession_session *session;
05579    struct ao2_iterator i;
05580 
05581    if (ident == 0) {
05582       return 0;
05583    }
05584 
05585    i = ao2_iterator_init(sessions, 0);
05586    while ((session = ao2_iterator_next(&i))) {
05587       ao2_lock(session);
05588       if ((session->managerid == ident) && (session->writeperm & perm)) {
05589          result = 1;
05590          ao2_unlock(session);
05591          unref_mansession(session);
05592          break;
05593       }
05594       ao2_unlock(session);
05595       unref_mansession(session);
05596    }
05597    ao2_iterator_destroy(&i);
05598    return result;
05599 }

static int auth_http_callback ( struct ast_tcptls_session_instance ser,
enum ast_http_method  method,
enum output_format  format,
struct sockaddr_in *  remote_address,
const char *  uri,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6079 of file manager.c.

References ast_manager_user::a1_hash, ao2_lock, ao2_unlock, ARRAY_LEN, ast_apply_ha(), ast_copy_string(), ast_debug, ast_free, ast_get_http_method(), ast_http_auth(), ast_http_error(), AST_HTTP_GET, ast_http_get_post_vars(), AST_HTTP_HEAD, AST_HTTP_POST, ast_http_send(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_malloc, ast_md5_hash(), ast_mutex_destroy, ast_mutex_init, ast_parse_digest(), ast_random(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_str_append(), ast_str_create(), ast_string_field_free_memory, ast_string_field_init, ast_strlen_zero(), ast_variables_destroy(), ast_verb, mansession_session::authenticated, build_mansession(), ast_http_digest::cnonce, mansession_session::datastores, ast_manager_user::displayconnects, errno, mansession_session::f, mansession::f, mansession_session::fd, mansession::fd, find_session_by_nonce(), FORMAT_HTML, FORMAT_XML, get_manager_by_name_locked(), global_realm, grab_last(), ast_manager_user::ha, message::hdrcount, message::headers, mansession_session::last_ev, mansession::lock, LOG_NOTICE, LOG_WARNING, mansession_session::managerid, ast_variable::name, mansession_session::nc, ast_http_digest::nc, mansession_session::needdestroy, ast_variable::next, ast_http_digest::nonce, mansession_session::noncetime, mansession_session::oldnonce, process_message(), process_output(), ast_http_digest::qop, mansession_session::readperm, ast_manager_user::readperm, ast_http_digest::response, mansession::session, session_destroy(), mansession_session::sessionstart, mansession_session::sessiontimeout, mansession_session::sin, ast_http_digest::uri, mansession_session::username, ast_manager_user::username, ast_http_digest::username, ast_variable::value, mansession_session::writeperm, ast_manager_user::writeperm, mansession_session::writetimeout, and ast_manager_user::writetimeout.

Referenced by auth_manager_http_callback(), auth_mxml_http_callback(), and auth_rawman_http_callback().

06085 {
06086    struct mansession_session *session = NULL;
06087    struct mansession s = { .session = NULL, .tcptls_session = ser };
06088    struct ast_variable *v, *params = get_params;
06089    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
06090    struct ast_str *http_header = NULL, *out = NULL;
06091    size_t result_size = 512;
06092    struct message m = { 0 };
06093    unsigned int idx;
06094    size_t hdrlen;
06095 
06096    time_t time_now = time(NULL);
06097    unsigned long nonce = 0, nc;
06098    struct ast_http_digest d = { NULL, };
06099    struct ast_manager_user *user = NULL;
06100    int stale = 0;
06101    char resp_hash[256]="";
06102    /* Cache for user data */
06103    char u_username[80];
06104    int u_readperm;
06105    int u_writeperm;
06106    int u_writetimeout;
06107    int u_displayconnects;
06108    struct ast_sockaddr addr;
06109 
06110    if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
06111       ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
06112       return -1;
06113    }
06114 
06115    /* Find "Authorization: " header */
06116    for (v = headers; v; v = v->next) {
06117       if (!strcasecmp(v->name, "Authorization")) {
06118          break;
06119       }
06120    }
06121 
06122    if (!v || ast_strlen_zero(v->value)) {
06123       goto out_401; /* Authorization Header not present - send auth request */
06124    }
06125 
06126    /* Digest found - parse */
06127    if (ast_string_field_init(&d, 128)) {
06128       ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
06129       return -1;
06130    }
06131 
06132    if (ast_parse_digest(v->value, &d, 0, 1)) {
06133       /* Error in Digest - send new one */
06134       nonce = 0;
06135       goto out_401;
06136    }
06137    if (sscanf(d.nonce, "%30lx", &nonce) != 1) {
06138       ast_log(LOG_WARNING, "Received incorrect nonce in Digest <%s>\n", d.nonce);
06139       nonce = 0;
06140       goto out_401;
06141    }
06142 
06143    AST_RWLIST_WRLOCK(&users);
06144    user = get_manager_by_name_locked(d.username);
06145    if(!user) {
06146       AST_RWLIST_UNLOCK(&users);
06147       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
06148       nonce = 0;
06149       goto out_401;
06150    }
06151 
06152    ast_sockaddr_from_sin(&addr, remote_address);
06153    /* --- We have User for this auth, now check ACL */
06154    if (user->ha && !ast_apply_ha(user->ha, &addr)) {
06155       AST_RWLIST_UNLOCK(&users);
06156       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
06157       ast_http_error(ser, 403, "Permission denied", "Permission denied\n");
06158       return -1;
06159    }
06160 
06161    /* --- We have auth, so check it */
06162 
06163    /* compute the expected response to compare with what we received */
06164    {
06165       char a2[256];
06166       char a2_hash[256];
06167       char resp[256];
06168 
06169       /* XXX Now request method are hardcoded in A2 */
06170       snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri);
06171       ast_md5_hash(a2_hash, a2);
06172 
06173       if (d.qop) {
06174          /* RFC 2617 */
06175          snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash);
06176       }  else {
06177          /* RFC 2069 */
06178          snprintf(resp, sizeof(resp), "%s:%08lx:%s", user->a1_hash, nonce, a2_hash);
06179       }
06180       ast_md5_hash(resp_hash, resp);
06181    }
06182 
06183    if (!d.nonce  || strncasecmp(d.response, resp_hash, strlen(resp_hash))) {
06184       /* Something was wrong, so give the client to try with a new challenge */
06185       AST_RWLIST_UNLOCK(&users);
06186       nonce = 0;
06187       goto out_401;
06188    }
06189 
06190    /*
06191     * User are pass Digest authentication.
06192     * Now, cache the user data and unlock user list.
06193     */
06194    ast_copy_string(u_username, user->username, sizeof(u_username));
06195    u_readperm = user->readperm;
06196    u_writeperm = user->writeperm;
06197    u_displayconnects = user->displayconnects;
06198    u_writetimeout = user->writetimeout;
06199    AST_RWLIST_UNLOCK(&users);
06200 
06201    if (!(session = find_session_by_nonce(d.username, nonce, &stale))) {
06202       /*
06203        * Create new session.
06204        * While it is not in the list we don't need any locking
06205        */
06206       if (!(session = build_mansession(*remote_address))) {
06207          ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
06208          return -1;
06209       }
06210       ao2_lock(session);
06211 
06212       ast_copy_string(session->username, u_username, sizeof(session->username));
06213       session->managerid = nonce;
06214       session->last_ev = grab_last();
06215       AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
06216 
06217       session->readperm = u_readperm;
06218       session->writeperm = u_writeperm;
06219       session->writetimeout = u_writetimeout;
06220 
06221       if (u_displayconnects) {
06222          ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
06223       }
06224       session->noncetime = session->sessionstart = time_now;
06225       session->authenticated = 1;
06226    } else if (stale) {
06227       /*
06228        * Session found, but nonce is stale.
06229        *
06230        * This could be because an old request (w/old nonce) arrived.
06231        *
06232        * This may be as the result of http proxy usage (separate delay or
06233        * multipath) or in a situation where a page was refreshed too quickly
06234        * (seen in Firefox).
06235        *
06236        * In this situation, we repeat the 401 auth with the current nonce
06237        * value.
06238        */
06239       nonce = session->managerid;
06240       ao2_unlock(session);
06241       stale = 1;
06242       goto out_401;
06243    } else {
06244       sscanf(d.nc, "%30lx", &nc);
06245       if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) {
06246          /*
06247           * Nonce time expired (> 2 minutes) or something wrong with nonce
06248           * counter.
06249           *
06250           * Create new nonce key and resend Digest auth request. Old nonce
06251           * is saved for stale checking...
06252           */
06253          session->nc = 0; /* Reset nonce counter */
06254          session->oldnonce = session->managerid;
06255          nonce = session->managerid = ast_random();
06256          session->noncetime = time_now;
06257          ao2_unlock(session);
06258          stale = 1;
06259          goto out_401;
06260       } else {
06261          session->nc = nc; /* All OK, save nonce counter */
06262       }
06263    }
06264 
06265 
06266    /* Reset session timeout. */
06267    session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5);
06268    ao2_unlock(session);
06269 
06270    ast_mutex_init(&s.lock);
06271    s.session = session;
06272    s.fd = mkstemp(template);  /* create a temporary file for command output */
06273    unlink(template);
06274    if (s.fd <= -1) {
06275       ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n");
06276       goto auth_callback_out;
06277    }
06278    s.f = fdopen(s.fd, "w+");
06279    if (!s.f) {
06280       ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno));
06281       ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n");
06282       close(s.fd);
06283       goto auth_callback_out;
06284    }
06285 
06286    if (method == AST_HTTP_POST) {
06287       params = ast_http_get_post_vars(ser, headers);
06288    }
06289 
06290    for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) {
06291       hdrlen = strlen(v->name) + strlen(v->value) + 3;
06292       m.headers[m.hdrcount] = ast_malloc(hdrlen);
06293       if (!m.headers[m.hdrcount]) {
06294          /* Allocation failure */
06295          continue;
06296       }
06297       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
06298       ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]);
06299       ++m.hdrcount;
06300    }
06301 
06302    if (process_message(&s, &m)) {
06303       if (u_displayconnects) {
06304          ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
06305       }
06306 
06307       session->needdestroy = 1;
06308    }
06309 
06310    /* Free request headers. */
06311    for (idx = 0; idx < m.hdrcount; ++idx) {
06312       ast_free((void *) m.headers[idx]);
06313       m.headers[idx] = NULL;
06314    }
06315 
06316    if (s.f) {
06317       result_size = ftell(s.f); /* Calculate approx. size of result */
06318    }
06319 
06320    http_header = ast_str_create(80);
06321    out = ast_str_create(result_size * 2 + 512);
06322 
06323    if (http_header == NULL || out == NULL) {
06324       ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
06325       goto auth_callback_out;
06326    }
06327 
06328    ast_str_append(&http_header, 0, "Content-type: text/%s\r\n", contenttype[format]);
06329 
06330    if (format == FORMAT_XML) {
06331       ast_str_append(&out, 0, "<ajax-response>\n");
06332    } else if (format == FORMAT_HTML) {
06333       ast_str_append(&out, 0,
06334       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
06335       "<html><head>\r\n"
06336       "<title>Asterisk&trade; Manager Interface</title>\r\n"
06337       "</head><body style=\"background-color: #ffffff;\">\r\n"
06338       "<form method=\"POST\">\r\n"
06339       "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n"
06340       "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n"
06341       "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>"
06342       "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n");
06343    }
06344 
06345    process_output(&s, &out, params, format);
06346 
06347    if (format == FORMAT_XML) {
06348       ast_str_append(&out, 0, "</ajax-response>\n");
06349    } else if (format == FORMAT_HTML) {
06350       ast_str_append(&out, 0, "</table></form></body></html>\r\n");
06351    }
06352 
06353    ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
06354    http_header = out = NULL;
06355 
06356 auth_callback_out:
06357    ast_mutex_destroy(&s.lock);
06358 
06359    /* Clear resources and unlock manager session */
06360    if (method == AST_HTTP_POST && params) {
06361       ast_variables_destroy(params);
06362    }
06363 
06364    ast_free(http_header);
06365    ast_free(out);
06366 
06367    ao2_lock(session);
06368    if (session->f) {
06369       fclose(session->f);
06370    }
06371    session->f = NULL;
06372    session->fd = -1;
06373    ao2_unlock(session);
06374 
06375    if (session->needdestroy) {
06376       ast_debug(1, "Need destroy, doing it now!\n");
06377       session_destroy(session);
06378    }
06379    ast_string_field_free_memory(&d);
06380    return 0;
06381 
06382 out_401:
06383    if (!nonce) {
06384       nonce = ast_random();
06385    }
06386 
06387    ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL);
06388    ast_string_field_free_memory(&d);
06389    return 0;
06390 }

static int auth_manager_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6451 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_HTML, and ast_tcptls_session_instance::remote_address.

06452 {
06453    int retval;
06454    struct sockaddr_in ser_remote_address_tmp;
06455 
06456    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06457    retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
06458    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06459    return retval;
06460 }

static int auth_mxml_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6462 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_XML, and ast_tcptls_session_instance::remote_address.

06463 {
06464    int retval;
06465    struct sockaddr_in ser_remote_address_tmp;
06466 
06467    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06468    retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
06469    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06470    return retval;
06471 }

static int auth_rawman_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6473 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_RAW, and ast_tcptls_session_instance::remote_address.

06474 {
06475    int retval;
06476    struct sockaddr_in ser_remote_address_tmp;
06477 
06478    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06479    retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
06480    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06481    return retval;
06482 }

static struct mansession_session* find_session ( uint32_t  ident,
int  incinuse 
) [static, read]

locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket).

Definition at line 5474 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_atomic_fetchadd_int(), mansession_session::inuse, mansession_session::managerid, mansession_session::needdestroy, and unref_mansession().

Referenced by astman_is_authed(), and generic_http_callback().

05475 {
05476    struct mansession_session *session;
05477    struct ao2_iterator i;
05478 
05479    if (ident == 0) {
05480       return NULL;
05481    }
05482 
05483    i = ao2_iterator_init(sessions, 0);
05484    while ((session = ao2_iterator_next(&i))) {
05485       ao2_lock(session);
05486       if (session->managerid == ident && !session->needdestroy) {
05487          ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
05488          break;
05489       }
05490       ao2_unlock(session);
05491       unref_mansession(session);
05492    }
05493    ao2_iterator_destroy(&i);
05494 
05495    return session;
05496 }

static struct mansession_session* find_session_by_nonce ( const char *  username,
unsigned long  nonce,
int *  stale 
) [static, read]

locate an http session in the list. The search keys (nonce) and (username) is value from received "Authorization" http header. As well as in find_session() function, the value of the nonce can't be zero. (0 meansi, that the session used for AMI socket connection). Flag (stale) is set, if client used valid, but old, nonce value.

Definition at line 5507 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::oldnonce, unref_mansession(), and mansession_session::username.

Referenced by auth_http_callback().

05508 {
05509    struct mansession_session *session;
05510    struct ao2_iterator i;
05511 
05512    if (nonce == 0 || username == NULL || stale == NULL) {
05513       return NULL;
05514    }
05515 
05516    i = ao2_iterator_init(sessions, 0);
05517    while ((session = ao2_iterator_next(&i))) {
05518       ao2_lock(session);
05519       if (!strcasecmp(session->username, username) && session->managerid == nonce) {
05520          *stale = 0;
05521          break;
05522       } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) {
05523          *stale = 1;
05524          break;
05525       }
05526       ao2_unlock(session);
05527       unref_mansession(session);
05528    }
05529    ao2_iterator_destroy(&i);
05530    return session;
05531 }

static int generic_http_callback ( struct ast_tcptls_session_instance ser,
enum ast_http_method  method,
enum output_format  format,
struct sockaddr_in *  remote_address,
const char *  uri,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Note:
There is approximately a 1 in 1.8E19 chance that the following calculation will produce 0, which is an invalid ID, but due to the properties of the rand() function (and the constantcy of s), that won't happen twice in a row.

Definition at line 5864 of file manager.c.

References ao2_lock, ao2_unlock, ARRAY_LEN, ast_debug, ast_free, ast_http_error(), AST_HTTP_GET, ast_http_get_cookies(), ast_http_get_post_vars(), AST_HTTP_HEAD, AST_HTTP_POST, ast_http_send(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_malloc, ast_mutex_destroy, ast_mutex_init, AST_PTHREADT_NULL, ast_random(), ast_str_append(), ast_str_create(), ast_variables_destroy(), ast_verb, mansession_session::authenticated, build_mansession(), errno, mansession_session::f, mansession::f, mansession::fd, mansession_session::fd, find_session(), FORMAT_HTML, FORMAT_XML, grab_last(), message::hdrcount, message::headers, mansession_session::inuse, mansession::lock, LOG_WARNING, manager_displayconnects(), mansession_session::managerid, ast_variable::name, mansession_session::needdestroy, ast_variable::next, process_message(), process_output(), ROW_FMT, mansession_session::send_events, mansession::session, session_destroy(), mansession_session::sessiontimeout, mansession_session::sin, TEST_STRING, mansession_session::username, ast_variable::value, and mansession_session::waiting_thread.

Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().

05870 {
05871    struct mansession s = { .session = NULL, .tcptls_session = ser };
05872    struct mansession_session *session = NULL;
05873    uint32_t ident = 0;
05874    int blastaway = 0;
05875    struct ast_variable *v, *cookies, *params = get_params;
05876    char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
05877    struct ast_str *http_header = NULL, *out = NULL;
05878    struct message m = { 0 };
05879    unsigned int idx;
05880    size_t hdrlen;
05881 
05882    if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
05883       ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
05884       return -1;
05885    }
05886 
05887    cookies = ast_http_get_cookies(headers);
05888    for (v = cookies; v; v = v->next) {
05889       if (!strcasecmp(v->name, "mansession_id")) {
05890          sscanf(v->value, "%30x", &ident);
05891          break;
05892       }
05893    }
05894    if (cookies) {
05895       ast_variables_destroy(cookies);
05896    }
05897 
05898    if (!(session = find_session(ident, 1))) {
05899 
05900       /**/
05901       /* Create new session.
05902        * While it is not in the list we don't need any locking
05903        */
05904       if (!(session = build_mansession(*remote_address))) {
05905          ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
05906          return -1;
05907       }
05908       ao2_lock(session);
05909       session->sin = *remote_address;
05910       session->fd = -1;
05911       session->waiting_thread = AST_PTHREADT_NULL;
05912       session->send_events = 0;
05913       session->inuse = 1;
05914       /*!\note There is approximately a 1 in 1.8E19 chance that the following
05915        * calculation will produce 0, which is an invalid ID, but due to the
05916        * properties of the rand() function (and the constantcy of s), that
05917        * won't happen twice in a row.
05918        */
05919       while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
05920       session->last_ev = grab_last();
05921       AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
05922    }
05923    ao2_unlock(session);
05924 
05925    http_header = ast_str_create(128);
05926    out = ast_str_create(2048);
05927 
05928    ast_mutex_init(&s.lock);
05929 
05930    if (http_header == NULL || out == NULL) {
05931       ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
05932       goto generic_callback_out;
05933    }
05934 
05935    s.session = session;
05936    s.fd = mkstemp(template);  /* create a temporary file for command output */
05937    unlink(template);
05938    if (s.fd <= -1) {
05939       ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n");
05940       goto generic_callback_out;
05941    }
05942    s.f = fdopen(s.fd, "w+");
05943    if (!s.f) {
05944       ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno));
05945       ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n");
05946       close(s.fd);
05947       goto generic_callback_out;
05948    }
05949 
05950    if (method == AST_HTTP_POST) {
05951       params = ast_http_get_post_vars(ser, headers);
05952    }
05953 
05954    for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) {
05955       hdrlen = strlen(v->name) + strlen(v->value) + 3;
05956       m.headers[m.hdrcount] = ast_malloc(hdrlen);
05957       if (!m.headers[m.hdrcount]) {
05958          /* Allocation failure */
05959          continue;
05960       }
05961       snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
05962       ast_debug(1, "HTTP Manager add header %s\n", m.headers[m.hdrcount]);
05963       ++m.hdrcount;
05964    }
05965 
05966    if (process_message(&s, &m)) {
05967       if (session->authenticated) {
05968          if (manager_displayconnects(session)) {
05969             ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
05970          }
05971       } else {
05972          if (displayconnects) {
05973             ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
05974          }
05975       }
05976       session->needdestroy = 1;
05977    }
05978 
05979    /* Free request headers. */
05980    for (idx = 0; idx < m.hdrcount; ++idx) {
05981       ast_free((void *) m.headers[idx]);
05982       m.headers[idx] = NULL;
05983    }
05984 
05985    ast_str_append(&http_header, 0,
05986       "Content-type: text/%s\r\n"
05987       "Cache-Control: no-cache;\r\n"
05988       "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n"
05989       "Pragma: SuppressEvents\r\n",
05990       contenttype[format],
05991       session->managerid, httptimeout);
05992 
05993    if (format == FORMAT_XML) {
05994       ast_str_append(&out, 0, "<ajax-response>\n");
05995    } else if (format == FORMAT_HTML) {
05996       /*
05997        * When handling AMI-over-HTTP in HTML format, we provide a simple form for
05998        * debugging purposes. This HTML code should not be here, we
05999        * should read from some config file...
06000        */
06001 
06002 #define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
06003 #define TEST_STRING \
06004    "<form action=\"manager\" method=\"post\">\n\
06005    Action: <select name=\"action\">\n\
06006       <option value=\"\">-----&gt;</option>\n\
06007       <option value=\"login\">login</option>\n\
06008       <option value=\"command\">Command</option>\n\
06009       <option value=\"waitevent\">waitevent</option>\n\
06010       <option value=\"listcommands\">listcommands</option>\n\
06011    </select>\n\
06012    or <input name=\"action\"><br/>\n\
06013    CLI Command <input name=\"command\"><br>\n\
06014    user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\
06015    <input type=\"submit\">\n</form>\n"
06016 
06017       ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
06018       ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
06019       ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
06020       ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
06021    }
06022 
06023    process_output(&s, &out, params, format);
06024 
06025    if (format == FORMAT_XML) {
06026       ast_str_append(&out, 0, "</ajax-response>\n");
06027    } else if (format == FORMAT_HTML) {
06028       ast_str_append(&out, 0, "</table></body>\r\n");
06029    }
06030 
06031    ao2_lock(session);
06032    /* Reset HTTP timeout.  If we're not authenticated, keep it extremely short */
06033    session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
06034 
06035    if (session->needdestroy) {
06036       if (session->inuse == 1) {
06037          ast_debug(1, "Need destroy, doing it now!\n");
06038          blastaway = 1;
06039       } else {
06040          ast_debug(1, "Need destroy, but can't do it yet!\n");
06041          if (session->waiting_thread != AST_PTHREADT_NULL) {
06042             pthread_kill(session->waiting_thread, SIGURG);
06043          }
06044          session->inuse--;
06045       }
06046    } else {
06047       session->inuse--;
06048    }
06049    ao2_unlock(session);
06050 
06051    ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
06052    http_header = out = NULL;
06053 
06054 generic_callback_out:
06055    ast_mutex_destroy(&s.lock);
06056 
06057    /* Clear resource */
06058 
06059    if (method == AST_HTTP_POST && params) {
06060       ast_variables_destroy(params);
06061    }
06062    if (http_header) {
06063       ast_free(http_header);
06064    }
06065    if (out) {
06066       ast_free(out);
06067    }
06068 
06069    if (session && blastaway) {
06070       session_destroy(session);
06071    } else if (session && session->f) {
06072       fclose(session->f);
06073       session->f = NULL;
06074    }
06075 
06076    return 0;
06077 }

static char* handle_manager_show_settings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

CLI command manager show settings.

Definition at line 6546 of file manager.c.

References ami_tls_cfg, ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, ast_sockaddr_stringify(), block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_tls_config::enabled, ast_cli_args::fd, FORMAT, FORMAT2, ast_tcptls_session_args::local_address, ast_tls_config::pvtfile, S_OR, and ast_cli_entry::usage.

06547 {
06548    switch (cmd) {
06549    case CLI_INIT:
06550       e->command = "manager show settings";
06551       e->usage =
06552          "Usage: manager show settings\n"
06553          "       Provides detailed list of the configuration of the Manager.\n";
06554       return NULL;
06555    case CLI_GENERATE:
06556       return NULL;
06557    }
06558 #define FORMAT "  %-25.25s  %-15.15s\n"
06559 #define FORMAT2 "  %-25.25s  %-15d\n"
06560    if (a->argc != 3) {
06561       return CLI_SHOWUSAGE;
06562    }
06563    ast_cli(a->fd, "\nGlobal Settings:\n");
06564    ast_cli(a->fd, "----------------\n");
06565    ast_cli(a->fd, FORMAT, "Manager (AMI):", AST_CLI_YESNO(manager_enabled));
06566    ast_cli(a->fd, FORMAT, "Web Manager (AMI/HTTP):", AST_CLI_YESNO(webmanager_enabled));
06567    ast_cli(a->fd, FORMAT, "TCP Bindaddress:", manager_enabled != 0 ? ast_sockaddr_stringify(&ami_desc.local_address) : "Disabled");
06568    ast_cli(a->fd, FORMAT2, "HTTP Timeout (minutes):", httptimeout);
06569    ast_cli(a->fd, FORMAT, "TLS Enable:", AST_CLI_YESNO(ami_tls_cfg.enabled));
06570    ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ami_tls_cfg.enabled != 0 ? ast_sockaddr_stringify(&amis_desc.local_address) : "Disabled");
06571    ast_cli(a->fd, FORMAT, "TLS Certfile:", ami_tls_cfg.certfile);
06572    ast_cli(a->fd, FORMAT, "TLS Privatekey:", ami_tls_cfg.pvtfile);
06573    ast_cli(a->fd, FORMAT, "TLS Cipher:", ami_tls_cfg.cipher);
06574    ast_cli(a->fd, FORMAT, "Allow multiple login:", AST_CLI_YESNO(allowmultiplelogin));
06575    ast_cli(a->fd, FORMAT, "Display connects:", AST_CLI_YESNO(displayconnects));
06576    ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents));
06577    ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, ""));
06578    ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug));
06579    ast_cli(a->fd, FORMAT, "Block sockets:", AST_CLI_YESNO(block_sockets));
06580 #undef FORMAT
06581 #undef FORMAT2
06582 
06583    return CLI_SUCCESS;
06584 }

int init_manager ( void   ) 

Called by Asterisk initialization.

Definition at line 7062 of file manager.c.

References __init_manager().

Referenced by main().

07063 {
07064    return __init_manager(0);
07065 }

static void load_channelvars ( struct ast_variable var  )  [static]

Definition at line 6606 of file manager.c.

References ast_calloc, ast_free, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_strdupa, free_channelvars(), manager_channel_variable::isfunc, manager_channel_variable::name, eventqent::next, strsep(), and ast_variable::value.

Referenced by __init_manager().

06607 {
06608    struct manager_channel_variable *mcv;
06609    char *remaining = ast_strdupa(var->value);
06610    char *next;
06611 
06612    ast_free(manager_channelvars);
06613    manager_channelvars = ast_strdup(var->value);
06614 
06615    /*
06616     * XXX TODO: To allow dialplan functions to have more than one
06617     * parameter requires eliminating the '|' as a separator so we
06618     * could use AST_STANDARD_APP_ARGS() to separate items.
06619     */
06620    free_channelvars();
06621    AST_RWLIST_WRLOCK(&channelvars);
06622    while ((next = strsep(&remaining, ",|"))) {
06623       if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) {
06624          break;
06625       }
06626       strcpy(mcv->name, next); /* SAFE */
06627       if (strchr(next, '(')) {
06628          mcv->isfunc = 1;
06629       }
06630       AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry);
06631    }
06632    AST_RWLIST_UNLOCK(&channelvars);
06633 }

static int manager_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6392 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

06393 {
06394    int retval;
06395    struct sockaddr_in ser_remote_address_tmp;
06396 
06397    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06398    retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
06399    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06400    return retval;
06401 }

static int mxml_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6403 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

06404 {
06405    int retval;
06406    struct sockaddr_in ser_remote_address_tmp;
06407 
06408    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06409    retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
06410    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06411    return retval;
06412 }

static void process_output ( struct mansession s,
struct ast_str **  out,
struct ast_variable params,
enum output_format  format 
) [static]

Definition at line 5831 of file manager.c.

References ast_log(), ast_str_append(), mansession::f, mansession::fd, FORMAT_HTML, FORMAT_XML, LOG_WARNING, and xml_translate().

Referenced by auth_http_callback(), and generic_http_callback().

05832 {
05833    char *buf;
05834    size_t l;
05835 
05836    if (!s->f)
05837       return;
05838 
05839    /* Ensure buffer is NULL-terminated */
05840    fprintf(s->f, "%c", 0);
05841    fflush(s->f);
05842 
05843    if ((l = ftell(s->f))) {
05844       if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s->fd, 0))) {
05845          ast_log(LOG_WARNING, "mmap failed.  Manager output was not processed\n");
05846       } else {
05847          if (format == FORMAT_XML || format == FORMAT_HTML) {
05848             xml_translate(out, buf, params, format);
05849          } else {
05850             ast_str_append(out, 0, "%s", buf);
05851          }
05852          munmap(buf, l);
05853       }
05854    } else if (format == FORMAT_XML || format == FORMAT_HTML) {
05855       xml_translate(out, "", params, format);
05856    }
05857 
05858    fclose(s->f);
05859    s->f = NULL;
05860    close(s->fd);
05861    s->fd = -1;
05862 }

static void purge_old_stuff ( void *  data  )  [static]

cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most

Definition at line 6517 of file manager.c.

References purge_events(), and purge_sessions().

06518 {
06519    purge_sessions(1);
06520    purge_events();
06521 }

static int rawman_http_callback ( struct ast_tcptls_session_instance ser,
const struct ast_http_uri urih,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
) [static]

Definition at line 6414 of file manager.c.

References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::remote_address.

06415 {
06416    int retval;
06417    struct sockaddr_in ser_remote_address_tmp;
06418 
06419    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
06420    retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
06421    ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
06422    return retval;
06423 }

int reload_manager ( void   ) 

Called by Asterisk module functions and the CLI command.

Definition at line 7067 of file manager.c.

References __init_manager().

Referenced by handle_manager_reload().

07068 {
07069    return __init_manager(1);
07070 }

static int variable_count_cmp_fn ( void *  obj,
void *  vstr,
int  flags 
) [static]

Definition at line 5675 of file manager.c.

References CMP_MATCH, CMP_STOP, str, and variable_count::varname.

Referenced by xml_translate().

05676 {
05677    /* Due to the simplicity of struct variable_count, it makes no difference
05678     * if you pass in objects or strings, the same operation applies. This is
05679     * due to the fact that the hash occurs on the first element, which means
05680     * the address of both the struct and the string are exactly the same. */
05681    struct variable_count *vc = obj;
05682    char *str = vstr;
05683    return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
05684 }

static int variable_count_hash_fn ( const void *  vvc,
const int  flags 
) [static]

Definition at line 5668 of file manager.c.

References ast_str_hash(), and variable_count::varname.

Referenced by xml_translate().

05669 {
05670    const struct variable_count *vc = vvc;
05671 
05672    return ast_str_hash(vc->varname);
05673 }

static void xml_copy_escape ( struct ast_str **  out,
const char *  src,
int  mode 
) [static]

Definition at line 5606 of file manager.c.

References ast_str_append().

Referenced by xml_translate().

05607 {
05608    /* store in a local buffer to avoid calling ast_str_append too often */
05609    char buf[256];
05610    char *dst = buf;
05611    int space = sizeof(buf);
05612    /* repeat until done and nothing to flush */
05613    for ( ; *src || dst != buf ; src++) {
05614       if (*src == '\0' || space < 10) {   /* flush */
05615          *dst++ = '\0';
05616          ast_str_append(out, 0, "%s", buf);
05617          dst = buf;
05618          space = sizeof(buf);
05619          if (*src == '\0') {
05620             break;
05621          }
05622       }
05623 
05624       if ( (mode & 2) && !isalnum(*src)) {
05625          *dst++ = '_';
05626          space--;
05627          continue;
05628       }
05629       switch (*src) {
05630       case '<':
05631          strcpy(dst, "&lt;");
05632          dst += 4;
05633          space -= 4;
05634          break;
05635       case '>':
05636          strcpy(dst, "&gt;");
05637          dst += 4;
05638          space -= 4;
05639          break;
05640       case '\"':
05641          strcpy(dst, "&quot;");
05642          dst += 6;
05643          space -= 6;
05644          break;
05645       case '\'':
05646          strcpy(dst, "&apos;");
05647          dst += 6;
05648          space -= 6;
05649          break;
05650       case '&':
05651          strcpy(dst, "&amp;");
05652          dst += 5;
05653          space -= 5;
05654          break;
05655 
05656       default:
05657          *dst++ = mode ? tolower(*src) : *src;
05658          space--;
05659       }
05660    }
05661 }

static void xml_translate ( struct ast_str **  out,
char *  in,
struct ast_variable get_vars,
enum output_format  format 
) [static]

Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications):

General: the unformatted text is used as a value of XML output: to be completed

 *   Each section is within <response type="object" id="xxx">
 *   where xxx is taken from ajaxdest variable or defaults to unknown
 *   Each row is reported as an attribute Name="value" of an XML
 *   entity named from the variable ajaxobjtype, default to "generic"
 * 

HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a


Definition at line 5714 of file manager.c.

References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_skip_blanks(), ast_str_append(), ast_strlen_zero(), ast_trim_blanks(), variable_count::count, FORMAT_XML, ast_variable::name, ast_variable::next, strsep(), ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().

Referenced by process_output().

05715 {
05716    struct ast_variable *v;
05717    const char *dest = NULL;
05718    char *var, *val;
05719    const char *objtype = NULL;
05720    int in_data = 0;  /* parsing data */
05721    int inobj = 0;
05722    int xml = (format == FORMAT_XML);
05723    struct variable_count *vc = NULL;
05724    struct ao2_container *vco = NULL;
05725 
05726    if (xml) {
05727       /* dest and objtype need only for XML format */
05728       for (v = get_vars; v; v = v->next) {
05729          if (!strcasecmp(v->name, "ajaxdest")) {
05730             dest = v->value;
05731          } else if (!strcasecmp(v->name, "ajaxobjtype")) {
05732             objtype = v->value;
05733          }
05734       }
05735       if (ast_strlen_zero(dest)) {
05736          dest = "unknown";
05737       }
05738       if (ast_strlen_zero(objtype)) {
05739          objtype = "generic";
05740       }
05741    }
05742 
05743    /* we want to stop when we find an empty line */
05744    while (in && *in) {
05745       val = strsep(&in, "\r\n"); /* mark start and end of line */
05746       if (in && *in == '\n') {   /* remove trailing \n if any */
05747          in++;
05748       }
05749       ast_trim_blanks(val);
05750       ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
05751       if (ast_strlen_zero(val)) {
05752          /* empty line */
05753          if (in_data) {
05754             /* close data in Opaque mode */
05755             ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
05756             in_data = 0;
05757          }
05758 
05759          if (inobj) {
05760             /* close block */
05761             ast_str_append(out, 0, xml ? " /></response>\n" :
05762                "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
05763             inobj = 0;
05764             ao2_ref(vco, -1);
05765             vco = NULL;
05766          }
05767          continue;
05768       }
05769 
05770       if (!inobj) {
05771          /* start new block */
05772          if (xml) {
05773             ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
05774          }
05775          vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
05776          inobj = 1;
05777       }
05778 
05779       if (in_data) {
05780          /* Process data field in Opaque mode. This is a
05781           * followup, so we re-add line feeds. */
05782          ast_str_append(out, 0, xml ? "\n" : "<br>\n");
05783          xml_copy_escape(out, val, 0);   /* data field */
05784          continue;
05785       }
05786 
05787       /* We expect "Name: value" line here */
05788       var = strsep(&val, ":");
05789       if (val) {
05790          /* found the field name */
05791          val = ast_skip_blanks(val);
05792          ast_trim_blanks(var);
05793       } else {
05794          /* field name not found, switch to opaque mode */
05795          val = var;
05796          var = "Opaque-data";
05797          in_data = 1;
05798       }
05799 
05800 
05801       ast_str_append(out, 0, xml ? " " : "<tr><td>");
05802       if ((vc = ao2_find(vco, var, 0))) {
05803          vc->count++;
05804       } else {
05805          /* Create a new entry for this one */
05806          vc = ao2_alloc(sizeof(*vc), NULL);
05807          vc->varname = var;
05808          vc->count = 1;
05809          ao2_link(vco, vc);
05810       }
05811 
05812       xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */
05813       if (vc->count > 1) {
05814          ast_str_append(out, 0, "-%d", vc->count);
05815       }
05816       ao2_ref(vc, -1);
05817       ast_str_append(out, 0, xml ? "='" : "</td><td>");
05818       xml_copy_escape(out, val, 0); /* data field */
05819       if (!in_data || !*in) {
05820          ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
05821       }
05822    }
05823 
05824    if (inobj) {
05825       ast_str_append(out, 0, xml ? " /></response>\n" :
05826          "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
05827       ao2_ref(vco, -1);
05828    }
05829 }


Variable Documentation

struct ast_http_uri amanageruri [static]

Definition at line 6493 of file manager.c.

struct ast_http_uri amanagerxmluri [static]

Definition at line 6502 of file manager.c.

Definition at line 6524 of file manager.c.

struct ast_tls_config ami_tls_cfg [static]

Definition at line 6523 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

Definition at line 6535 of file manager.c.

struct ast_http_uri arawmanuri [static]

Definition at line 6484 of file manager.c.

struct ast_cli_entry cli_manager[] [static]

Definition at line 6586 of file manager.c.

const char* const contenttype[] [static]

Initial value:

 {
   [FORMAT_RAW] = "plain",
   [FORMAT_HTML] = "html",
   [FORMAT_XML] =  "xml",
}

Definition at line 5463 of file manager.c.

struct ast_http_uri manageruri [static]

Definition at line 6433 of file manager.c.

struct ast_http_uri managerxmluri [static]

Definition at line 6441 of file manager.c.

struct ast_http_uri rawmanuri [static]

Definition at line 6425 of file manager.c.

int registered = 0 [static]

Definition at line 6511 of file manager.c.

int webregged = 0 [static]

Definition at line 6512 of file manager.c.

const char* words[AST_MAX_CMD_LEN]

Definition at line 961 of file manager.c.

Referenced by check_blacklist().


Generated on Fri Feb 10 06:36:47 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6