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"
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 |
struct | mansession_datastores |
struct | mansession_session |
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) |
send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
#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=\"\">-----></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 | 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 | mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG } |
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 | __init_astman_append_buf (void) |
thread local buffer for astman_append | |
static int | __init_manager (int reload) |
static void | __init_manager_event_buf (void) |
static void | __init_manager_event_funcbuf (void) |
static void | __init_userevent_buf (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 struct manager_action * | action_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 eventqent * | advance_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) |
int | ast_hook_send_action (struct manager_custom_hook *hook, const char *msg) |
Registered hooks can call this function to invoke actions and they will receive responses through registered callback. | |
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) |
Unregister a registered manager command. | |
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_datastore * | astman_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_variable * | astman_get_variables (const struct message *m) |
Get a linked list of the Variable: headers. | |
struct ast_variable * | astman_get_variables_order (const struct message *m, enum variable_orders order) |
Get a linked list of the Variable: headers with order specified. | |
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) |
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. Note that the EVENT_FLAG_ALL authority will always be returned. | |
static int | blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
static struct mansession_session * | build_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 | close_mansession_file (struct mansession *s) |
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_session * | find_session (uint32_t ident, int incinuse) |
static struct mansession_session * | find_session_by_nonce (const char *username, unsigned long nonce, int *stale) |
static void | free_channelvars (void) |
static int | function_capable_string_allowed_with_auths (const char *evaluating, int writepermlist) |
Checks to see if a string which can be used to evaluate functions should be rejected. | |
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_user * | get_manager_by_name_locked (const char *name) |
static int | get_perm (const char *instr) |
static struct eventqent * | grab_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 void | handle_parse_error (struct mansession *s, struct message *m, char *error) |
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) |
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_variable * | man_do_variable_value (struct ast_variable *head, const char *hdr_val) |
static int | manager_displayconnects (struct mansession_session *session) |
Get displayconnects config option. | |
static void | manager_free_user (struct ast_manager_user *user) |
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) |
static int | manager_moduleload (struct mansession *s, const struct message *m) |
static void | manager_set_defaults (void) |
static void | manager_shutdown (void) |
static int | manager_state_cb (char *context, char *exten, int 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) |
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_session * | unref_mansession (struct mansession_session *s) |
Unreference manager session object. If no more references, then go ahead and delete it. | |
static const char * | user_authority_to_str (int authority, struct ast_str **res) |
Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority. | |
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 | broken_events_action |
static struct ast_cli_entry | cli_manager [] |
struct { | |
const char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static const char *const | contenttype [] |
static const int | DEFAULT_AUTHLIMIT = 50 |
static const int | DEFAULT_AUTHTIMEOUT = 30 |
static const int | DEFAULT_BROKENEVENTSACTION = 0 |
static const int | DEFAULT_DISPLAYCONNECTS = 1 |
static const int | DEFAULT_ENABLED = 0 |
static const int | DEFAULT_HTTPTIMEOUT = 60 |
static const int | DEFAULT_MANAGERDEBUG = 0 |
static const int | DEFAULT_TIMESTAMPEVENTS = 0 |
static const int | DEFAULT_WEBENABLED = 0 |
static int | displayconnects |
static char | global_realm [MAXHOSTNAMELEN] |
static int | httptimeout |
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 struct ao2_container * | sessions = 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 |
The Asterisk Management Interface - AMI.
At the moment this file contains a number of functions, namely:
Definition in file manager.c.
#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=\"\">-----></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().
enum output_format |
END Doxygen group
Definition at line 5542 of file manager.c.
05542 { 05543 FORMAT_RAW, 05544 FORMAT_HTML, 05545 FORMAT_XML, 05546 };
static int __init_manager | ( | int | reload | ) | [static] |
Definition at line 6840 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_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_alloc, ao2_t_callback, ao2_t_link, ao2_t_ref, append_event(), ARRAY_LEN, ast_append_ha(), ast_calloc, ast_category_browse(), ast_cli_register_multiple(), 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_register_atexit(), 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_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, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, DEFAULT_MANAGER_TLS_PORT, ast_manager_user::displayconnects, ast_tls_config::enabled, event_filter_destructor(), EVENT_FLAG_AOC, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, get_manager_by_name_locked(), get_perm(), global_realm, ast_manager_user::ha, ast_manager_user::keep, ast_variable::lineno, load_channelvars(), ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_event, manager_free_user(), manager_modulecheck(), manager_moduleload(), manager_set_defaults(), manager_shutdown(), manager_state_cb(), mansession_cmp_fn(), ast_variable::name, ast_variable::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_manager_user::readperm, ast_manager_user::secret, sessions, 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().
06841 { 06842 struct ast_config *ucfg = NULL, *cfg = NULL; 06843 const char *val; 06844 char *cat = NULL; 06845 int newhttptimeout = DEFAULT_HTTPTIMEOUT; 06846 struct ast_manager_user *user = NULL; 06847 struct ast_variable *var; 06848 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 06849 char a1[256]; 06850 char a1_hash[256]; 06851 struct sockaddr_in ami_desc_local_address_tmp = { 0, }; 06852 struct sockaddr_in amis_desc_local_address_tmp = { 0, }; 06853 int tls_was_enabled = 0; 06854 06855 if (!reload) { 06856 ast_register_atexit(manager_shutdown); 06857 06858 /* Register default actions */ 06859 ast_manager_register_xml("Ping", 0, action_ping); 06860 ast_manager_register_xml("Events", 0, action_events); 06861 ast_manager_register_xml("Logoff", 0, action_logoff); 06862 ast_manager_register_xml("Login", 0, action_login); 06863 ast_manager_register_xml("Challenge", 0, action_challenge); 06864 ast_manager_register_xml("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup); 06865 ast_manager_register_xml("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status); 06866 ast_manager_register_xml("Setvar", EVENT_FLAG_CALL, action_setvar); 06867 ast_manager_register_xml("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar); 06868 ast_manager_register_xml("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig); 06869 ast_manager_register_xml("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson); 06870 ast_manager_register_xml("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig); 06871 ast_manager_register_xml("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig); 06872 ast_manager_register_xml("ListCategories", EVENT_FLAG_CONFIG, action_listcategories); 06873 ast_manager_register_xml("Redirect", EVENT_FLAG_CALL, action_redirect); 06874 ast_manager_register_xml("Atxfer", EVENT_FLAG_CALL, action_atxfer); 06875 ast_manager_register_xml("Originate", EVENT_FLAG_ORIGINATE, action_originate); 06876 ast_manager_register_xml("Command", EVENT_FLAG_COMMAND, action_command); 06877 ast_manager_register_xml("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate); 06878 ast_manager_register_xml("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout); 06879 ast_manager_register_xml("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus); 06880 ast_manager_register_xml("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount); 06881 ast_manager_register_xml("ListCommands", 0, action_listcommands); 06882 ast_manager_register_xml("SendText", EVENT_FLAG_CALL, action_sendtext); 06883 ast_manager_register_xml("UserEvent", EVENT_FLAG_USER, action_userevent); 06884 ast_manager_register_xml("WaitEvent", 0, action_waitevent); 06885 ast_manager_register_xml("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings); 06886 ast_manager_register_xml("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus); 06887 ast_manager_register_xml("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload); 06888 ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels); 06889 ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload); 06890 ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck); 06891 ast_manager_register_xml("AOCMessage", EVENT_FLAG_AOC, action_aocmessage); 06892 06893 ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager)); 06894 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 06895 06896 /* Append placeholder event so master_eventq never runs dry */ 06897 if (append_event("Event: Placeholder\r\n\r\n", 0)) { 06898 return -1; 06899 } 06900 06901 /* If you have a NULL hash fn, you only need a single bucket */ 06902 sessions = ao2_container_alloc(1, NULL, mansession_cmp_fn); 06903 if (!sessions) { 06904 return -1; 06905 } 06906 06907 /* Initialize all settings before first configuration load. */ 06908 manager_set_defaults(); 06909 } 06910 06911 cfg = ast_config_load2("manager.conf", "manager", config_flags); 06912 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 06913 return 0; 06914 } else if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 06915 ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid.\n"); 06916 return 0; 06917 } 06918 06919 if (reload) { 06920 /* Reset all settings before reloading configuration */ 06921 tls_was_enabled = ami_tls_cfg.enabled; 06922 manager_set_defaults(); 06923 } 06924 06925 ami_desc_local_address_tmp.sin_family = AF_INET; 06926 amis_desc_local_address_tmp.sin_family = AF_INET; 06927 06928 ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT); 06929 06930 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 06931 val = var->value; 06932 06933 /* read tls config options while preventing unsupported options from being set */ 06934 if (strcasecmp(var->name, "tlscafile") 06935 && strcasecmp(var->name, "tlscapath") 06936 && strcasecmp(var->name, "tlscadir") 06937 && strcasecmp(var->name, "tlsverifyclient") 06938 && strcasecmp(var->name, "tlsdontverifyserver") 06939 && strcasecmp(var->name, "tlsclientmethod") 06940 && strcasecmp(var->name, "sslclientmethod") 06941 && !ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) { 06942 continue; 06943 } 06944 06945 if (!strcasecmp(var->name, "enabled")) { 06946 manager_enabled = ast_true(val); 06947 } else if (!strcasecmp(var->name, "webenabled")) { 06948 webmanager_enabled = ast_true(val); 06949 } else if (!strcasecmp(var->name, "port")) { 06950 ami_desc_local_address_tmp.sin_port = htons(atoi(val)); 06951 } else if (!strcasecmp(var->name, "bindaddr")) { 06952 if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) { 06953 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 06954 memset(&ami_desc_local_address_tmp.sin_addr, 0, 06955 sizeof(ami_desc_local_address_tmp.sin_addr)); 06956 } 06957 } else if (!strcasecmp(var->name, "brokeneventsaction")) { 06958 broken_events_action = ast_true(val); 06959 } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 06960 allowmultiplelogin = ast_true(val); 06961 } else if (!strcasecmp(var->name, "displayconnects")) { 06962 displayconnects = ast_true(val); 06963 } else if (!strcasecmp(var->name, "timestampevents")) { 06964 timestampevents = ast_true(val); 06965 } else if (!strcasecmp(var->name, "debug")) { 06966 manager_debug = ast_true(val); 06967 } else if (!strcasecmp(var->name, "httptimeout")) { 06968 newhttptimeout = atoi(val); 06969 } else if (!strcasecmp(var->name, "authtimeout")) { 06970 int timeout = atoi(var->value); 06971 06972 if (timeout < 1) { 06973 ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value); 06974 } else { 06975 authtimeout = timeout; 06976 } 06977 } else if (!strcasecmp(var->name, "authlimit")) { 06978 int limit = atoi(var->value); 06979 06980 if (limit < 1) { 06981 ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value); 06982 } else { 06983 authlimit = limit; 06984 } 06985 } else if (!strcasecmp(var->name, "channelvars")) { 06986 load_channelvars(var); 06987 } else { 06988 ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", 06989 var->name, val); 06990 } 06991 } 06992 06993 ast_sockaddr_to_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 06994 06995 /* if the amis address has not been set, default is the same as non secure ami */ 06996 if (!amis_desc_local_address_tmp.sin_addr.s_addr) { 06997 amis_desc_local_address_tmp.sin_addr = 06998 ami_desc_local_address_tmp.sin_addr; 06999 } 07000 07001 if (!amis_desc_local_address_tmp.sin_port) { 07002 amis_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_TLS_PORT); 07003 } 07004 07005 if (manager_enabled) { 07006 ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp); 07007 ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 07008 } 07009 07010 AST_RWLIST_WRLOCK(&users); 07011 07012 /* First, get users from users.conf */ 07013 ucfg = ast_config_load2("users.conf", "manager", config_flags); 07014 if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) { 07015 const char *hasmanager; 07016 int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager")); 07017 07018 while ((cat = ast_category_browse(ucfg, cat))) { 07019 if (!strcasecmp(cat, "general")) { 07020 continue; 07021 } 07022 07023 hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager"); 07024 if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) { 07025 const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret"); 07026 const char *user_read = ast_variable_retrieve(ucfg, cat, "read"); 07027 const char *user_write = ast_variable_retrieve(ucfg, cat, "write"); 07028 const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects"); 07029 const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout"); 07030 07031 /* Look for an existing entry, 07032 * if none found - create one and add it to the list 07033 */ 07034 if (!(user = get_manager_by_name_locked(cat))) { 07035 if (!(user = ast_calloc(1, sizeof(*user)))) { 07036 break; 07037 } 07038 07039 /* Copy name over */ 07040 ast_copy_string(user->username, cat, sizeof(user->username)); 07041 /* Insert into list */ 07042 AST_LIST_INSERT_TAIL(&users, user, list); 07043 user->ha = NULL; 07044 user->keep = 1; 07045 user->readperm = -1; 07046 user->writeperm = -1; 07047 /* Default displayconnect from [general] */ 07048 user->displayconnects = displayconnects; 07049 user->writetimeout = 100; 07050 } 07051 07052 if (!user_secret) { 07053 user_secret = ast_variable_retrieve(ucfg, "general", "secret"); 07054 } 07055 if (!user_read) { 07056 user_read = ast_variable_retrieve(ucfg, "general", "read"); 07057 } 07058 if (!user_write) { 07059 user_write = ast_variable_retrieve(ucfg, "general", "write"); 07060 } 07061 if (!user_displayconnects) { 07062 user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); 07063 } 07064 if (!user_writetimeout) { 07065 user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); 07066 } 07067 07068 if (!ast_strlen_zero(user_secret)) { 07069 ast_free(user->secret); 07070 user->secret = ast_strdup(user_secret); 07071 } 07072 07073 if (user_read) { 07074 user->readperm = get_perm(user_read); 07075 } 07076 if (user_write) { 07077 user->writeperm = get_perm(user_write); 07078 } 07079 if (user_displayconnects) { 07080 user->displayconnects = ast_true(user_displayconnects); 07081 } 07082 if (user_writetimeout) { 07083 int value = atoi(user_writetimeout); 07084 if (value < 100) { 07085 ast_log(LOG_WARNING, "Invalid writetimeout value '%d' in users.conf\n", value); 07086 } else { 07087 user->writetimeout = value; 07088 } 07089 } 07090 } 07091 } 07092 ast_config_destroy(ucfg); 07093 } 07094 07095 /* cat is NULL here in any case */ 07096 07097 while ((cat = ast_category_browse(cfg, cat))) { 07098 struct ast_ha *oldha; 07099 07100 if (!strcasecmp(cat, "general")) { 07101 continue; 07102 } 07103 07104 /* Look for an existing entry, if none found - create one and add it to the list */ 07105 if (!(user = get_manager_by_name_locked(cat))) { 07106 if (!(user = ast_calloc(1, sizeof(*user)))) { 07107 break; 07108 } 07109 /* Copy name over */ 07110 ast_copy_string(user->username, cat, sizeof(user->username)); 07111 07112 user->ha = NULL; 07113 user->readperm = 0; 07114 user->writeperm = 0; 07115 /* Default displayconnect from [general] */ 07116 user->displayconnects = displayconnects; 07117 user->writetimeout = 100; 07118 user->whitefilters = ao2_container_alloc(1, NULL, NULL); 07119 user->blackfilters = ao2_container_alloc(1, NULL, NULL); 07120 if (!user->whitefilters || !user->blackfilters) { 07121 manager_free_user(user); 07122 break; 07123 } 07124 07125 /* Insert into list */ 07126 AST_RWLIST_INSERT_TAIL(&users, user, list); 07127 } else { 07128 ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 07129 ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 07130 } 07131 07132 /* Make sure we keep this user and don't destroy it during cleanup */ 07133 user->keep = 1; 07134 oldha = user->ha; 07135 user->ha = NULL; 07136 07137 var = ast_variable_browse(cfg, cat); 07138 for (; var; var = var->next) { 07139 if (!strcasecmp(var->name, "secret")) { 07140 ast_free(user->secret); 07141 user->secret = ast_strdup(var->value); 07142 } else if (!strcasecmp(var->name, "deny") || 07143 !strcasecmp(var->name, "permit")) { 07144 user->ha = ast_append_ha(var->name, var->value, user->ha, NULL); 07145 } else if (!strcasecmp(var->name, "read") ) { 07146 user->readperm = get_perm(var->value); 07147 } else if (!strcasecmp(var->name, "write") ) { 07148 user->writeperm = get_perm(var->value); 07149 } else if (!strcasecmp(var->name, "displayconnects") ) { 07150 user->displayconnects = ast_true(var->value); 07151 } else if (!strcasecmp(var->name, "writetimeout")) { 07152 int value = atoi(var->value); 07153 if (value < 100) { 07154 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); 07155 } else { 07156 user->writetimeout = value; 07157 } 07158 } else if (!strcasecmp(var->name, "eventfilter")) { 07159 const char *value = var->value; 07160 regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation"); 07161 if (new_filter) { 07162 int is_blackfilter; 07163 if (value[0] == '!') { 07164 is_blackfilter = 1; 07165 value++; 07166 } else { 07167 is_blackfilter = 0; 07168 } 07169 if (regcomp(new_filter, value, 0)) { /* XXX: the only place we use non-REG_EXTENDED */ 07170 ao2_t_ref(new_filter, -1, "failed to make regex"); 07171 } else { 07172 if (is_blackfilter) { 07173 ao2_t_link(user->blackfilters, new_filter, "link new filter into black user container"); 07174 } else { 07175 ao2_t_link(user->whitefilters, new_filter, "link new filter into white user container"); 07176 } 07177 } 07178 } 07179 } else { 07180 ast_debug(1, "%s is an unknown option.\n", var->name); 07181 } 07182 } 07183 ast_free_ha(oldha); 07184 } 07185 ast_config_destroy(cfg); 07186 07187 /* Perform cleanup - essentially prune out old users that no longer exist */ 07188 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 07189 if (user->keep) { /* valid record. clear flag for the next round */ 07190 user->keep = 0; 07191 07192 /* Calculate A1 for Digest auth */ 07193 snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret); 07194 ast_md5_hash(a1_hash,a1); 07195 ast_free(user->a1_hash); 07196 user->a1_hash = ast_strdup(a1_hash); 07197 continue; 07198 } 07199 /* We do not need to keep this user so take them out of the list */ 07200 AST_RWLIST_REMOVE_CURRENT(list); 07201 ast_debug(4, "Pruning user '%s'\n", user->username); 07202 manager_free_user(user); 07203 } 07204 AST_RWLIST_TRAVERSE_SAFE_END; 07205 07206 AST_RWLIST_UNLOCK(&users); 07207 07208 if (webmanager_enabled && manager_enabled) { 07209 if (!webregged) { 07210 ast_http_uri_link(&rawmanuri); 07211 ast_http_uri_link(&manageruri); 07212 ast_http_uri_link(&managerxmluri); 07213 07214 ast_http_uri_link(&arawmanuri); 07215 ast_http_uri_link(&amanageruri); 07216 ast_http_uri_link(&amanagerxmluri); 07217 webregged = 1; 07218 } 07219 } else { 07220 if (webregged) { 07221 ast_http_uri_unlink(&rawmanuri); 07222 ast_http_uri_unlink(&manageruri); 07223 ast_http_uri_unlink(&managerxmluri); 07224 07225 ast_http_uri_unlink(&arawmanuri); 07226 ast_http_uri_unlink(&amanageruri); 07227 ast_http_uri_unlink(&amanagerxmluri); 07228 webregged = 0; 07229 } 07230 } 07231 07232 if (newhttptimeout > 0) { 07233 httptimeout = newhttptimeout; 07234 } 07235 07236 manager_event(EVENT_FLAG_SYSTEM, "Reload", 07237 "Module: Manager\r\n" 07238 "Status: %s\r\n" 07239 "Message: Manager reload Requested\r\n", 07240 manager_enabled ? "Enabled" : "Disabled"); 07241 07242 ast_tcptls_server_start(&ami_desc); 07243 if (tls_was_enabled && !ami_tls_cfg.enabled) { 07244 ast_tcptls_server_stop(&amis_desc); 07245 } else if (ast_ssl_setup(amis_desc.tls_cfg)) { 07246 ast_tcptls_server_start(&amis_desc); 07247 } 07248 07249 return 0; 07250 }
int astman_datastore_add | ( | struct mansession * | s, | |
struct ast_datastore * | datastore | |||
) |
Add a datastore to a session.
0 | success | |
non-zero | failure |
Definition at line 7273 of file manager.c.
References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.
07274 { 07275 AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry); 07276 07277 return 0; 07278 }
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.
pointer | to the datastore if found | |
NULL | if not found |
Definition at line 7285 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.
07286 { 07287 struct ast_datastore *datastore = NULL; 07288 07289 if (info == NULL) 07290 return NULL; 07291 07292 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) { 07293 if (datastore->info != info) { 07294 continue; 07295 } 07296 07297 if (uid == NULL) { 07298 /* matched by type only */ 07299 break; 07300 } 07301 07302 if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { 07303 /* Matched by type AND uid */ 07304 break; 07305 } 07306 } 07307 AST_LIST_TRAVERSE_SAFE_END; 07308 07309 return datastore; 07310 }
int astman_datastore_remove | ( | struct mansession * | s, | |
struct ast_datastore * | datastore | |||
) |
Remove a datastore from a session.
0 | success | |
non-zero | failure |
Definition at line 7280 of file manager.c.
References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.
07281 { 07282 return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1; 07283 }
int astman_is_authed | ( | uint32_t | ident | ) |
Determinie if a manager session ident is authenticated.
Definition at line 5618 of file manager.c.
References ao2_unlock, mansession_session::authenticated, find_session(), and unref_mansession().
Referenced by http_post_callback(), and static_callback().
05619 { 05620 int authed; 05621 struct mansession_session *session; 05622 05623 if (!(session = find_session(ident, 0))) 05624 return 0; 05625 05626 authed = (session->authenticated != 0); 05627 05628 ao2_unlock(session); 05629 unref_mansession(session); 05630 05631 return authed; 05632 }
int astman_verify_session_readpermissions | ( | uint32_t | ident, | |
int | perm | |||
) |
Verify a session's read permissions against a permission mask.
ident | session identity | |
perm | permission mask to verify |
1 | if the session has the permission mask capabilities | |
0 | otherwise |
Definition at line 5634 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::readperm, sessions, and unref_mansession().
05635 { 05636 int result = 0; 05637 struct mansession_session *session; 05638 struct ao2_iterator i; 05639 05640 if (ident == 0) { 05641 return 0; 05642 } 05643 05644 i = ao2_iterator_init(sessions, 0); 05645 while ((session = ao2_iterator_next(&i))) { 05646 ao2_lock(session); 05647 if ((session->managerid == ident) && (session->readperm & perm)) { 05648 result = 1; 05649 ao2_unlock(session); 05650 unref_mansession(session); 05651 break; 05652 } 05653 ao2_unlock(session); 05654 unref_mansession(session); 05655 } 05656 ao2_iterator_destroy(&i); 05657 return result; 05658 }
int astman_verify_session_writepermissions | ( | uint32_t | ident, | |
int | perm | |||
) |
Verify a session's write permissions against a permission mask.
ident | session identity | |
perm | permission mask to verify |
1 | if the session has the permission mask capabilities, otherwise 0 | |
0 | otherwise |
Definition at line 5660 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, sessions, unref_mansession(), and mansession_session::writeperm.
Referenced by http_post_callback().
05661 { 05662 int result = 0; 05663 struct mansession_session *session; 05664 struct ao2_iterator i; 05665 05666 if (ident == 0) { 05667 return 0; 05668 } 05669 05670 i = ao2_iterator_init(sessions, 0); 05671 while ((session = ao2_iterator_next(&i))) { 05672 ao2_lock(session); 05673 if ((session->managerid == ident) && (session->writeperm & perm)) { 05674 result = 1; 05675 ao2_unlock(session); 05676 unref_mansession(session); 05677 break; 05678 } 05679 ao2_unlock(session); 05680 unref_mansession(session); 05681 } 05682 ao2_iterator_destroy(&i); 05683 return result; 05684 }
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 6181 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().
06187 { 06188 struct mansession_session *session = NULL; 06189 struct mansession s = { .session = NULL, .tcptls_session = ser }; 06190 struct ast_variable *v, *params = get_params; 06191 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 06192 struct ast_str *http_header = NULL, *out = NULL; 06193 size_t result_size = 512; 06194 struct message m = { 0 }; 06195 unsigned int idx; 06196 size_t hdrlen; 06197 06198 time_t time_now = time(NULL); 06199 unsigned long nonce = 0, nc; 06200 struct ast_http_digest d = { NULL, }; 06201 struct ast_manager_user *user = NULL; 06202 int stale = 0; 06203 char resp_hash[256]=""; 06204 /* Cache for user data */ 06205 char u_username[80]; 06206 int u_readperm; 06207 int u_writeperm; 06208 int u_writetimeout; 06209 int u_displayconnects; 06210 struct ast_sockaddr addr; 06211 06212 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 06213 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 06214 return -1; 06215 } 06216 06217 /* Find "Authorization: " header */ 06218 for (v = headers; v; v = v->next) { 06219 if (!strcasecmp(v->name, "Authorization")) { 06220 break; 06221 } 06222 } 06223 06224 if (!v || ast_strlen_zero(v->value)) { 06225 goto out_401; /* Authorization Header not present - send auth request */ 06226 } 06227 06228 /* Digest found - parse */ 06229 if (ast_string_field_init(&d, 128)) { 06230 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06231 return -1; 06232 } 06233 06234 if (ast_parse_digest(v->value, &d, 0, 1)) { 06235 /* Error in Digest - send new one */ 06236 nonce = 0; 06237 goto out_401; 06238 } 06239 if (sscanf(d.nonce, "%30lx", &nonce) != 1) { 06240 ast_log(LOG_WARNING, "Received incorrect nonce in Digest <%s>\n", d.nonce); 06241 nonce = 0; 06242 goto out_401; 06243 } 06244 06245 AST_RWLIST_WRLOCK(&users); 06246 user = get_manager_by_name_locked(d.username); 06247 if(!user) { 06248 AST_RWLIST_UNLOCK(&users); 06249 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06250 nonce = 0; 06251 goto out_401; 06252 } 06253 06254 ast_sockaddr_from_sin(&addr, remote_address); 06255 /* --- We have User for this auth, now check ACL */ 06256 if (user->ha && !ast_apply_ha(user->ha, &addr)) { 06257 AST_RWLIST_UNLOCK(&users); 06258 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06259 ast_http_error(ser, 403, "Permission denied", "Permission denied\n"); 06260 return -1; 06261 } 06262 06263 /* --- We have auth, so check it */ 06264 06265 /* compute the expected response to compare with what we received */ 06266 { 06267 char a2[256]; 06268 char a2_hash[256]; 06269 char resp[256]; 06270 06271 /* XXX Now request method are hardcoded in A2 */ 06272 snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri); 06273 ast_md5_hash(a2_hash, a2); 06274 06275 if (d.qop) { 06276 /* RFC 2617 */ 06277 snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash); 06278 } else { 06279 /* RFC 2069 */ 06280 snprintf(resp, sizeof(resp), "%s:%08lx:%s", user->a1_hash, nonce, a2_hash); 06281 } 06282 ast_md5_hash(resp_hash, resp); 06283 } 06284 06285 if (strncasecmp(d.response, resp_hash, strlen(resp_hash))) { 06286 /* Something was wrong, so give the client to try with a new challenge */ 06287 AST_RWLIST_UNLOCK(&users); 06288 nonce = 0; 06289 goto out_401; 06290 } 06291 06292 /* 06293 * User are pass Digest authentication. 06294 * Now, cache the user data and unlock user list. 06295 */ 06296 ast_copy_string(u_username, user->username, sizeof(u_username)); 06297 u_readperm = user->readperm; 06298 u_writeperm = user->writeperm; 06299 u_displayconnects = user->displayconnects; 06300 u_writetimeout = user->writetimeout; 06301 AST_RWLIST_UNLOCK(&users); 06302 06303 if (!(session = find_session_by_nonce(d.username, nonce, &stale))) { 06304 /* 06305 * Create new session. 06306 * While it is not in the list we don't need any locking 06307 */ 06308 if (!(session = build_mansession(*remote_address))) { 06309 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06310 return -1; 06311 } 06312 ao2_lock(session); 06313 06314 ast_copy_string(session->username, u_username, sizeof(session->username)); 06315 session->managerid = nonce; 06316 session->last_ev = grab_last(); 06317 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 06318 06319 session->readperm = u_readperm; 06320 session->writeperm = u_writeperm; 06321 session->writetimeout = u_writetimeout; 06322 06323 if (u_displayconnects) { 06324 ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06325 } 06326 session->noncetime = session->sessionstart = time_now; 06327 session->authenticated = 1; 06328 } else if (stale) { 06329 /* 06330 * Session found, but nonce is stale. 06331 * 06332 * This could be because an old request (w/old nonce) arrived. 06333 * 06334 * This may be as the result of http proxy usage (separate delay or 06335 * multipath) or in a situation where a page was refreshed too quickly 06336 * (seen in Firefox). 06337 * 06338 * In this situation, we repeat the 401 auth with the current nonce 06339 * value. 06340 */ 06341 nonce = session->managerid; 06342 ao2_unlock(session); 06343 stale = 1; 06344 goto out_401; 06345 } else { 06346 sscanf(d.nc, "%30lx", &nc); 06347 if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) { 06348 /* 06349 * Nonce time expired (> 2 minutes) or something wrong with nonce 06350 * counter. 06351 * 06352 * Create new nonce key and resend Digest auth request. Old nonce 06353 * is saved for stale checking... 06354 */ 06355 session->nc = 0; /* Reset nonce counter */ 06356 session->oldnonce = session->managerid; 06357 nonce = session->managerid = ast_random(); 06358 session->noncetime = time_now; 06359 ao2_unlock(session); 06360 stale = 1; 06361 goto out_401; 06362 } else { 06363 session->nc = nc; /* All OK, save nonce counter */ 06364 } 06365 } 06366 06367 06368 /* Reset session timeout. */ 06369 session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5); 06370 ao2_unlock(session); 06371 06372 ast_mutex_init(&s.lock); 06373 s.session = session; 06374 s.fd = mkstemp(template); /* create a temporary file for command output */ 06375 unlink(template); 06376 if (s.fd <= -1) { 06377 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 06378 goto auth_callback_out; 06379 } 06380 s.f = fdopen(s.fd, "w+"); 06381 if (!s.f) { 06382 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 06383 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 06384 close(s.fd); 06385 goto auth_callback_out; 06386 } 06387 06388 if (method == AST_HTTP_POST) { 06389 params = ast_http_get_post_vars(ser, headers); 06390 } 06391 06392 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 06393 hdrlen = strlen(v->name) + strlen(v->value) + 3; 06394 m.headers[m.hdrcount] = ast_malloc(hdrlen); 06395 if (!m.headers[m.hdrcount]) { 06396 /* Allocation failure */ 06397 continue; 06398 } 06399 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 06400 ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 06401 ++m.hdrcount; 06402 } 06403 06404 if (process_message(&s, &m)) { 06405 if (u_displayconnects) { 06406 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06407 } 06408 06409 session->needdestroy = 1; 06410 } 06411 06412 /* Free request headers. */ 06413 for (idx = 0; idx < m.hdrcount; ++idx) { 06414 ast_free((void *) m.headers[idx]); 06415 m.headers[idx] = NULL; 06416 } 06417 06418 if (s.f) { 06419 result_size = ftell(s.f); /* Calculate approx. size of result */ 06420 } 06421 06422 http_header = ast_str_create(80); 06423 out = ast_str_create(result_size * 2 + 512); 06424 06425 if (http_header == NULL || out == NULL) { 06426 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 06427 goto auth_callback_out; 06428 } 06429 06430 ast_str_append(&http_header, 0, "Content-type: text/%s\r\n", contenttype[format]); 06431 06432 if (format == FORMAT_XML) { 06433 ast_str_append(&out, 0, "<ajax-response>\n"); 06434 } else if (format == FORMAT_HTML) { 06435 ast_str_append(&out, 0, 06436 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 06437 "<html><head>\r\n" 06438 "<title>Asterisk™ Manager Interface</title>\r\n" 06439 "</head><body style=\"background-color: #ffffff;\">\r\n" 06440 "<form method=\"POST\">\r\n" 06441 "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n" 06442 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n" 06443 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>" 06444 "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n"); 06445 } 06446 06447 process_output(&s, &out, params, format); 06448 06449 if (format == FORMAT_XML) { 06450 ast_str_append(&out, 0, "</ajax-response>\n"); 06451 } else if (format == FORMAT_HTML) { 06452 ast_str_append(&out, 0, "</table></form></body></html>\r\n"); 06453 } 06454 06455 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06456 http_header = out = NULL; 06457 06458 auth_callback_out: 06459 ast_mutex_destroy(&s.lock); 06460 06461 /* Clear resources and unlock manager session */ 06462 if (method == AST_HTTP_POST && params) { 06463 ast_variables_destroy(params); 06464 } 06465 06466 ast_free(http_header); 06467 ast_free(out); 06468 06469 ao2_lock(session); 06470 if (session->f) { 06471 fclose(session->f); 06472 } 06473 session->f = NULL; 06474 session->fd = -1; 06475 ao2_unlock(session); 06476 06477 if (session->needdestroy) { 06478 ast_debug(1, "Need destroy, doing it now!\n"); 06479 session_destroy(session); 06480 } 06481 ast_string_field_free_memory(&d); 06482 return 0; 06483 06484 out_401: 06485 if (!nonce) { 06486 nonce = ast_random(); 06487 } 06488 06489 ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL); 06490 ast_string_field_free_memory(&d); 06491 return 0; 06492 }
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 6553 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.
06554 { 06555 int retval; 06556 struct sockaddr_in ser_remote_address_tmp; 06557 06558 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06559 retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06560 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06561 return retval; 06562 }
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 6564 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.
06565 { 06566 int retval; 06567 struct sockaddr_in ser_remote_address_tmp; 06568 06569 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06570 retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06571 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06572 return retval; 06573 }
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 6575 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.
06576 { 06577 int retval; 06578 struct sockaddr_in ser_remote_address_tmp; 06579 06580 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06581 retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06582 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06583 return retval; 06584 }
static void close_mansession_file | ( | struct mansession * | s | ) | [static] |
Definition at line 5916 of file manager.c.
References ast_log(), errno, mansession::f, mansession::fd, and LOG_ERROR.
Referenced by process_output().
05917 { 05918 if (s->f) { 05919 if (fclose(s->f)) { 05920 ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); 05921 } 05922 s->f = NULL; 05923 s->fd = -1; 05924 } else if (s->fd != -1) { 05925 /* 05926 * Issuing shutdown() is necessary here to avoid a race 05927 * condition where the last data written may not appear 05928 * in the TCP stream. See ASTERISK-23548 05929 */ 05930 shutdown(s->fd, SHUT_RDWR); 05931 if (close(s->fd)) { 05932 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 05933 } 05934 s->fd = -1; 05935 } else { 05936 ast_log(LOG_ERROR, "Attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n"); 05937 } 05938 }
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 5559 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, sessions, and unref_mansession().
Referenced by astman_is_authed(), and generic_http_callback().
05560 { 05561 struct mansession_session *session; 05562 struct ao2_iterator i; 05563 05564 if (ident == 0) { 05565 return NULL; 05566 } 05567 05568 i = ao2_iterator_init(sessions, 0); 05569 while ((session = ao2_iterator_next(&i))) { 05570 ao2_lock(session); 05571 if (session->managerid == ident && !session->needdestroy) { 05572 ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0); 05573 break; 05574 } 05575 ao2_unlock(session); 05576 unref_mansession(session); 05577 } 05578 ao2_iterator_destroy(&i); 05579 05580 return session; 05581 }
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 5592 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::oldnonce, sessions, unref_mansession(), and mansession_session::username.
Referenced by auth_http_callback().
05593 { 05594 struct mansession_session *session; 05595 struct ao2_iterator i; 05596 05597 if (nonce == 0 || username == NULL || stale == NULL) { 05598 return NULL; 05599 } 05600 05601 i = ao2_iterator_init(sessions, 0); 05602 while ((session = ao2_iterator_next(&i))) { 05603 ao2_lock(session); 05604 if (!strcasecmp(session->username, username) && session->managerid == nonce) { 05605 *stale = 0; 05606 break; 05607 } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) { 05608 *stale = 1; 05609 break; 05610 } 05611 ao2_unlock(session); 05612 unref_mansession(session); 05613 } 05614 ao2_iterator_destroy(&i); 05615 return session; 05616 }
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] |
Definition at line 5970 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().
05976 { 05977 struct mansession s = { .session = NULL, .tcptls_session = ser }; 05978 struct mansession_session *session = NULL; 05979 uint32_t ident = 0; 05980 int blastaway = 0; 05981 struct ast_variable *v, *cookies, *params = get_params; 05982 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 05983 struct ast_str *http_header = NULL, *out = NULL; 05984 struct message m = { 0 }; 05985 unsigned int idx; 05986 size_t hdrlen; 05987 05988 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 05989 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 05990 return -1; 05991 } 05992 05993 cookies = ast_http_get_cookies(headers); 05994 for (v = cookies; v; v = v->next) { 05995 if (!strcasecmp(v->name, "mansession_id")) { 05996 sscanf(v->value, "%30x", &ident); 05997 break; 05998 } 05999 } 06000 if (cookies) { 06001 ast_variables_destroy(cookies); 06002 } 06003 06004 if (!(session = find_session(ident, 1))) { 06005 06006 /**/ 06007 /* Create new session. 06008 * While it is not in the list we don't need any locking 06009 */ 06010 if (!(session = build_mansession(*remote_address))) { 06011 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06012 return -1; 06013 } 06014 ao2_lock(session); 06015 session->sin = *remote_address; 06016 session->fd = -1; 06017 session->waiting_thread = AST_PTHREADT_NULL; 06018 session->send_events = 0; 06019 session->inuse = 1; 06020 /*!\note There is approximately a 1 in 1.8E19 chance that the following 06021 * calculation will produce 0, which is an invalid ID, but due to the 06022 * properties of the rand() function (and the constantcy of s), that 06023 * won't happen twice in a row. 06024 */ 06025 while ((session->managerid = ast_random() ^ (unsigned long) session) == 0); 06026 session->last_ev = grab_last(); 06027 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 06028 } 06029 ao2_unlock(session); 06030 06031 http_header = ast_str_create(128); 06032 out = ast_str_create(2048); 06033 06034 ast_mutex_init(&s.lock); 06035 06036 if (http_header == NULL || out == NULL) { 06037 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 06038 goto generic_callback_out; 06039 } 06040 06041 s.session = session; 06042 s.fd = mkstemp(template); /* create a temporary file for command output */ 06043 unlink(template); 06044 if (s.fd <= -1) { 06045 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 06046 goto generic_callback_out; 06047 } 06048 s.f = fdopen(s.fd, "w+"); 06049 if (!s.f) { 06050 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 06051 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 06052 close(s.fd); 06053 goto generic_callback_out; 06054 } 06055 06056 if (method == AST_HTTP_POST) { 06057 params = ast_http_get_post_vars(ser, headers); 06058 } 06059 06060 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 06061 hdrlen = strlen(v->name) + strlen(v->value) + 3; 06062 m.headers[m.hdrcount] = ast_malloc(hdrlen); 06063 if (!m.headers[m.hdrcount]) { 06064 /* Allocation failure */ 06065 continue; 06066 } 06067 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 06068 ast_debug(1, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 06069 ++m.hdrcount; 06070 } 06071 06072 if (process_message(&s, &m)) { 06073 if (session->authenticated) { 06074 if (manager_displayconnects(session)) { 06075 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06076 } 06077 } else { 06078 if (displayconnects) { 06079 ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 06080 } 06081 } 06082 session->needdestroy = 1; 06083 } 06084 06085 /* Free request headers. */ 06086 for (idx = 0; idx < m.hdrcount; ++idx) { 06087 ast_free((void *) m.headers[idx]); 06088 m.headers[idx] = NULL; 06089 } 06090 06091 ast_str_append(&http_header, 0, 06092 "Content-type: text/%s\r\n" 06093 "Cache-Control: no-cache;\r\n" 06094 "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n" 06095 "Pragma: SuppressEvents\r\n", 06096 contenttype[format], 06097 session->managerid, httptimeout); 06098 06099 if (format == FORMAT_XML) { 06100 ast_str_append(&out, 0, "<ajax-response>\n"); 06101 } else if (format == FORMAT_HTML) { 06102 /* 06103 * When handling AMI-over-HTTP in HTML format, we provide a simple form for 06104 * debugging purposes. This HTML code should not be here, we 06105 * should read from some config file... 06106 */ 06107 06108 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" 06109 #define TEST_STRING \ 06110 "<form action=\"manager\" method=\"post\">\n\ 06111 Action: <select name=\"action\">\n\ 06112 <option value=\"\">-----></option>\n\ 06113 <option value=\"login\">login</option>\n\ 06114 <option value=\"command\">Command</option>\n\ 06115 <option value=\"waitevent\">waitevent</option>\n\ 06116 <option value=\"listcommands\">listcommands</option>\n\ 06117 </select>\n\ 06118 or <input name=\"action\"><br/>\n\ 06119 CLI Command <input name=\"command\"><br>\n\ 06120 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ 06121 <input type=\"submit\">\n</form>\n" 06122 06123 ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>"); 06124 ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 06125 ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>"); 06126 ast_str_append(&out, 0, ROW_FMT, TEST_STRING); 06127 } 06128 06129 process_output(&s, &out, params, format); 06130 06131 if (format == FORMAT_XML) { 06132 ast_str_append(&out, 0, "</ajax-response>\n"); 06133 } else if (format == FORMAT_HTML) { 06134 ast_str_append(&out, 0, "</table></body>\r\n"); 06135 } 06136 06137 ao2_lock(session); 06138 /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */ 06139 session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5); 06140 06141 if (session->needdestroy) { 06142 if (session->inuse == 1) { 06143 ast_debug(1, "Need destroy, doing it now!\n"); 06144 blastaway = 1; 06145 } else { 06146 ast_debug(1, "Need destroy, but can't do it yet!\n"); 06147 if (session->waiting_thread != AST_PTHREADT_NULL) { 06148 pthread_kill(session->waiting_thread, SIGURG); 06149 } 06150 session->inuse--; 06151 } 06152 } else { 06153 session->inuse--; 06154 } 06155 ao2_unlock(session); 06156 06157 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06158 http_header = out = NULL; 06159 06160 generic_callback_out: 06161 ast_mutex_destroy(&s.lock); 06162 06163 /* Clear resource */ 06164 06165 if (method == AST_HTTP_POST && params) { 06166 ast_variables_destroy(params); 06167 } 06168 ast_free(http_header); 06169 ast_free(out); 06170 06171 if (session && blastaway) { 06172 session_destroy(session); 06173 } else if (session && session->f) { 06174 fclose(session->f); 06175 session->f = NULL; 06176 } 06177 06178 return 0; 06179 }
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 6647 of file manager.c.
References ami_tls_cfg, ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, ast_sockaddr_stringify(), 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.
06648 { 06649 switch (cmd) { 06650 case CLI_INIT: 06651 e->command = "manager show settings"; 06652 e->usage = 06653 "Usage: manager show settings\n" 06654 " Provides detailed list of the configuration of the Manager.\n"; 06655 return NULL; 06656 case CLI_GENERATE: 06657 return NULL; 06658 } 06659 #define FORMAT " %-25.25s %-15.15s\n" 06660 #define FORMAT2 " %-25.25s %-15d\n" 06661 if (a->argc != 3) { 06662 return CLI_SHOWUSAGE; 06663 } 06664 ast_cli(a->fd, "\nGlobal Settings:\n"); 06665 ast_cli(a->fd, "----------------\n"); 06666 ast_cli(a->fd, FORMAT, "Manager (AMI):", AST_CLI_YESNO(manager_enabled)); 06667 ast_cli(a->fd, FORMAT, "Web Manager (AMI/HTTP):", AST_CLI_YESNO(webmanager_enabled)); 06668 ast_cli(a->fd, FORMAT, "TCP Bindaddress:", manager_enabled != 0 ? ast_sockaddr_stringify(&ami_desc.local_address) : "Disabled"); 06669 ast_cli(a->fd, FORMAT2, "HTTP Timeout (minutes):", httptimeout); 06670 ast_cli(a->fd, FORMAT, "TLS Enable:", AST_CLI_YESNO(ami_tls_cfg.enabled)); 06671 ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ami_tls_cfg.enabled != 0 ? ast_sockaddr_stringify(&amis_desc.local_address) : "Disabled"); 06672 ast_cli(a->fd, FORMAT, "TLS Certfile:", ami_tls_cfg.certfile); 06673 ast_cli(a->fd, FORMAT, "TLS Privatekey:", ami_tls_cfg.pvtfile); 06674 ast_cli(a->fd, FORMAT, "TLS Cipher:", ami_tls_cfg.cipher); 06675 ast_cli(a->fd, FORMAT, "Allow multiple login:", AST_CLI_YESNO(allowmultiplelogin)); 06676 ast_cli(a->fd, FORMAT, "Display connects:", AST_CLI_YESNO(displayconnects)); 06677 ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents)); 06678 ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, "")); 06679 ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug)); 06680 #undef FORMAT 06681 #undef FORMAT2 06682 06683 return CLI_SUCCESS; 06684 }
int init_manager | ( | void | ) |
Called by Asterisk initialization.
Definition at line 7263 of file manager.c.
References __init_manager().
Referenced by main().
07264 { 07265 return __init_manager(0); 07266 }
static void load_channelvars | ( | struct ast_variable * | var | ) | [static] |
Definition at line 6706 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, and ast_variable::value.
Referenced by __init_manager().
06707 { 06708 struct manager_channel_variable *mcv; 06709 char *remaining = ast_strdupa(var->value); 06710 char *next; 06711 06712 ast_free(manager_channelvars); 06713 manager_channelvars = ast_strdup(var->value); 06714 06715 /* 06716 * XXX TODO: To allow dialplan functions to have more than one 06717 * parameter requires eliminating the '|' as a separator so we 06718 * could use AST_STANDARD_APP_ARGS() to separate items. 06719 */ 06720 free_channelvars(); 06721 AST_RWLIST_WRLOCK(&channelvars); 06722 while ((next = strsep(&remaining, ",|"))) { 06723 if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) { 06724 break; 06725 } 06726 strcpy(mcv->name, next); /* SAFE */ 06727 if (strchr(next, '(')) { 06728 mcv->isfunc = 1; 06729 } 06730 AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry); 06731 } 06732 AST_RWLIST_UNLOCK(&channelvars); 06733 }
static void manager_free_user | ( | struct ast_manager_user * | user | ) | [static] |
Definition at line 6736 of file manager.c.
References ast_manager_user::a1_hash, ao2_t_ref, ast_free, ast_free_ha(), ast_manager_user::blackfilters, ast_manager_user::ha, ast_manager_user::secret, and ast_manager_user::whitefilters.
Referenced by __init_manager(), and manager_shutdown().
06737 { 06738 ast_free(user->a1_hash); 06739 ast_free(user->secret); 06740 if (user->whitefilters) { 06741 ao2_t_ref(user->whitefilters, -1, "decrement ref for white container, should be last one"); 06742 } 06743 if (user->blackfilters) { 06744 ao2_t_ref(user->blackfilters, -1, "decrement ref for black container, should be last one"); 06745 } 06746 ast_free_ha(user->ha); 06747 ast_free(user); 06748 }
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 6494 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.
06495 { 06496 int retval; 06497 struct sockaddr_in ser_remote_address_tmp; 06498 06499 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06500 retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06501 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06502 return retval; 06503 }
static void manager_set_defaults | ( | void | ) | [static] |
Definition at line 6811 of file manager.c.
References ami_tls_cfg, AST_CERTFILE, ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_free, ast_sockaddr_setnull(), ast_strdup, ast_tls_config::certfile, ast_tls_config::cipher, DEFAULT_REALM, ast_tls_config::enabled, free_channelvars(), global_realm, ast_tcptls_session_args::local_address, ast_tls_config::pvtfile, and S_OR.
Referenced by __init_manager().
06812 { 06813 manager_enabled = DEFAULT_ENABLED; 06814 webmanager_enabled = DEFAULT_WEBENABLED; 06815 manager_debug = DEFAULT_MANAGERDEBUG; 06816 displayconnects = DEFAULT_DISPLAYCONNECTS; 06817 broken_events_action = DEFAULT_BROKENEVENTSACTION; 06818 timestampevents = DEFAULT_TIMESTAMPEVENTS; 06819 httptimeout = DEFAULT_HTTPTIMEOUT; 06820 authtimeout = DEFAULT_AUTHTIMEOUT; 06821 authlimit = DEFAULT_AUTHLIMIT; 06822 06823 /* default values */ 06824 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), 06825 sizeof(global_realm)); 06826 ast_sockaddr_setnull(&ami_desc.local_address); 06827 ast_sockaddr_setnull(&amis_desc.local_address); 06828 06829 ami_tls_cfg.enabled = 0; 06830 ast_free(ami_tls_cfg.certfile); 06831 ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE); 06832 ast_free(ami_tls_cfg.pvtfile); 06833 ami_tls_cfg.pvtfile = ast_strdup(""); 06834 ast_free(ami_tls_cfg.cipher); 06835 ami_tls_cfg.cipher = ast_strdup(""); 06836 06837 free_channelvars(); 06838 }
static void manager_shutdown | ( | void | ) | [static] |
Definition at line 6751 of file manager.c.
References ami_tls_cfg, ARRAY_LEN, ast_cli_unregister_multiple(), ast_free, AST_LIST_REMOVE_HEAD, ast_manager_unregister(), ast_tcptls_server_stop(), ast_tls_config::certfile, ast_tls_config::cipher, ast_manager_user::list, manager_free_user(), and ast_tls_config::pvtfile.
Referenced by __init_manager().
06752 { 06753 struct ast_manager_user *user; 06754 06755 ast_manager_unregister("Ping"); 06756 ast_manager_unregister("Events"); 06757 ast_manager_unregister("Logoff"); 06758 ast_manager_unregister("Login"); 06759 ast_manager_unregister("Challenge"); 06760 ast_manager_unregister("Hangup"); 06761 ast_manager_unregister("Status"); 06762 ast_manager_unregister("Setvar"); 06763 ast_manager_unregister("Getvar"); 06764 ast_manager_unregister("GetConfig"); 06765 ast_manager_unregister("GetConfigJSON"); 06766 ast_manager_unregister("UpdateConfig"); 06767 ast_manager_unregister("CreateConfig"); 06768 ast_manager_unregister("ListCategories"); 06769 ast_manager_unregister("Redirect"); 06770 ast_manager_unregister("Atxfer"); 06771 ast_manager_unregister("Originate"); 06772 ast_manager_unregister("Command"); 06773 ast_manager_unregister("ExtensionState"); 06774 ast_manager_unregister("AbsoluteTimeout"); 06775 ast_manager_unregister("MailboxStatus"); 06776 ast_manager_unregister("MailboxCount"); 06777 ast_manager_unregister("ListCommands"); 06778 ast_manager_unregister("SendText"); 06779 ast_manager_unregister("UserEvent"); 06780 ast_manager_unregister("WaitEvent"); 06781 ast_manager_unregister("CoreSettings"); 06782 ast_manager_unregister("CoreStatus"); 06783 ast_manager_unregister("Reload"); 06784 ast_manager_unregister("CoreShowChannels"); 06785 ast_manager_unregister("ModuleLoad"); 06786 ast_manager_unregister("ModuleCheck"); 06787 ast_manager_unregister("AOCMessage"); 06788 ast_manager_unregister("Filter"); 06789 ast_cli_unregister_multiple(cli_manager, ARRAY_LEN(cli_manager)); 06790 06791 ast_tcptls_server_stop(&ami_desc); 06792 ast_tcptls_server_stop(&amis_desc); 06793 06794 ast_free(ami_tls_cfg.certfile); 06795 ami_tls_cfg.certfile = NULL; 06796 ast_free(ami_tls_cfg.pvtfile); 06797 ami_tls_cfg.pvtfile = NULL; 06798 ast_free(ami_tls_cfg.cipher); 06799 ami_tls_cfg.cipher = NULL; 06800 06801 /* 06802 * We cannot destroy the global sessions container. 06803 * References to it have no protection against shutdown. 06804 */ 06805 06806 while ((user = AST_LIST_REMOVE_HEAD(&users, list))) { 06807 manager_free_user(user); 06808 } 06809 }
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 6505 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.
06506 { 06507 int retval; 06508 struct sockaddr_in ser_remote_address_tmp; 06509 06510 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06511 retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06512 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06513 return retval; 06514 }
static void process_output | ( | struct mansession * | s, | |
struct ast_str ** | out, | |||
struct ast_variable * | params, | |||
enum output_format | format | |||
) | [static] |
Definition at line 5940 of file manager.c.
References ast_log(), ast_str_append(), close_mansession_file(), mansession::f, mansession::fd, FORMAT_HTML, FORMAT_XML, LOG_WARNING, and xml_translate().
Referenced by auth_http_callback(), and generic_http_callback().
05941 { 05942 char *buf; 05943 size_t l; 05944 05945 if (!s->f) 05946 return; 05947 05948 /* Ensure buffer is NULL-terminated */ 05949 fprintf(s->f, "%c", 0); 05950 fflush(s->f); 05951 05952 if ((l = ftell(s->f)) > 0) { 05953 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s->fd, 0))) { 05954 ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n"); 05955 } else { 05956 if (format == FORMAT_XML || format == FORMAT_HTML) { 05957 xml_translate(out, buf, params, format); 05958 } else { 05959 ast_str_append(out, 0, "%s", buf); 05960 } 05961 munmap(buf, l); 05962 } 05963 } else if (format == FORMAT_XML || format == FORMAT_HTML) { 05964 xml_translate(out, "", params, format); 05965 } 05966 05967 close_mansession_file(s); 05968 }
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 6618 of file manager.c.
References purge_events(), and purge_sessions().
06619 { 06620 purge_sessions(1); 06621 purge_events(); 06622 }
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 6516 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.
06517 { 06518 int retval; 06519 struct sockaddr_in ser_remote_address_tmp; 06520 06521 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06522 retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06523 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06524 return retval; 06525 }
int reload_manager | ( | void | ) |
Called by Asterisk module functions and the CLI command.
Definition at line 7268 of file manager.c.
References __init_manager().
Referenced by handle_manager_reload().
07269 { 07270 return __init_manager(1); 07271 }
static int variable_count_cmp_fn | ( | void * | obj, | |
void * | vstr, | |||
int | flags | |||
) | [static] |
Definition at line 5760 of file manager.c.
References CMP_MATCH, CMP_STOP, str, and variable_count::varname.
Referenced by xml_translate().
05761 { 05762 /* Due to the simplicity of struct variable_count, it makes no difference 05763 * if you pass in objects or strings, the same operation applies. This is 05764 * due to the fact that the hash occurs on the first element, which means 05765 * the address of both the struct and the string are exactly the same. */ 05766 struct variable_count *vc = obj; 05767 char *str = vstr; 05768 return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0; 05769 }
static int variable_count_hash_fn | ( | const void * | vvc, | |
const int | flags | |||
) | [static] |
Definition at line 5753 of file manager.c.
References ast_str_hash(), and variable_count::varname.
Referenced by xml_translate().
05754 { 05755 const struct variable_count *vc = vvc; 05756 05757 return ast_str_hash(vc->varname); 05758 }
static void xml_copy_escape | ( | struct ast_str ** | out, | |
const char * | src, | |||
int | mode | |||
) | [static] |
Definition at line 5691 of file manager.c.
References ast_str_append().
Referenced by xml_translate().
05692 { 05693 /* store in a local buffer to avoid calling ast_str_append too often */ 05694 char buf[256]; 05695 char *dst = buf; 05696 int space = sizeof(buf); 05697 /* repeat until done and nothing to flush */ 05698 for ( ; *src || dst != buf ; src++) { 05699 if (*src == '\0' || space < 10) { /* flush */ 05700 *dst++ = '\0'; 05701 ast_str_append(out, 0, "%s", buf); 05702 dst = buf; 05703 space = sizeof(buf); 05704 if (*src == '\0') { 05705 break; 05706 } 05707 } 05708 05709 if ( (mode & 2) && !isalnum(*src)) { 05710 *dst++ = '_'; 05711 space--; 05712 continue; 05713 } 05714 switch (*src) { 05715 case '<': 05716 strcpy(dst, "<"); 05717 dst += 4; 05718 space -= 4; 05719 break; 05720 case '>': 05721 strcpy(dst, ">"); 05722 dst += 4; 05723 space -= 4; 05724 break; 05725 case '\"': 05726 strcpy(dst, """); 05727 dst += 6; 05728 space -= 6; 05729 break; 05730 case '\'': 05731 strcpy(dst, "'"); 05732 dst += 6; 05733 space -= 6; 05734 break; 05735 case '&': 05736 strcpy(dst, "&"); 05737 dst += 5; 05738 space -= 5; 05739 break; 05740 05741 default: 05742 *dst++ = mode ? tolower(*src) : *src; 05743 space--; 05744 } 05745 } 05746 }
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 5799 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, ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().
Referenced by process_output().
05800 { 05801 struct ast_variable *v; 05802 const char *dest = NULL; 05803 char *var, *val; 05804 const char *objtype = NULL; 05805 int in_data = 0; /* parsing data */ 05806 int inobj = 0; 05807 int xml = (format == FORMAT_XML); 05808 struct variable_count *vc = NULL; 05809 struct ao2_container *vco = NULL; 05810 05811 if (xml) { 05812 /* dest and objtype need only for XML format */ 05813 for (v = get_vars; v; v = v->next) { 05814 if (!strcasecmp(v->name, "ajaxdest")) { 05815 dest = v->value; 05816 } else if (!strcasecmp(v->name, "ajaxobjtype")) { 05817 objtype = v->value; 05818 } 05819 } 05820 if (ast_strlen_zero(dest)) { 05821 dest = "unknown"; 05822 } 05823 if (ast_strlen_zero(objtype)) { 05824 objtype = "generic"; 05825 } 05826 } 05827 05828 /* we want to stop when we find an empty line */ 05829 while (in && *in) { 05830 val = strsep(&in, "\r\n"); /* mark start and end of line */ 05831 if (in && *in == '\n') { /* remove trailing \n if any */ 05832 in++; 05833 } 05834 ast_trim_blanks(val); 05835 ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val); 05836 if (ast_strlen_zero(val)) { 05837 /* empty line */ 05838 if (in_data) { 05839 /* close data in Opaque mode */ 05840 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05841 in_data = 0; 05842 } 05843 05844 if (inobj) { 05845 /* close block */ 05846 ast_str_append(out, 0, xml ? " /></response>\n" : 05847 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05848 inobj = 0; 05849 ao2_ref(vco, -1); 05850 vco = NULL; 05851 } 05852 continue; 05853 } 05854 05855 if (!inobj) { 05856 /* start new block */ 05857 if (xml) { 05858 ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype); 05859 } 05860 vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn); 05861 inobj = 1; 05862 } 05863 05864 if (in_data) { 05865 /* Process data field in Opaque mode. This is a 05866 * followup, so we re-add line feeds. */ 05867 ast_str_append(out, 0, xml ? "\n" : "<br>\n"); 05868 xml_copy_escape(out, val, 0); /* data field */ 05869 continue; 05870 } 05871 05872 /* We expect "Name: value" line here */ 05873 var = strsep(&val, ":"); 05874 if (val) { 05875 /* found the field name */ 05876 val = ast_skip_blanks(val); 05877 ast_trim_blanks(var); 05878 } else { 05879 /* field name not found, switch to opaque mode */ 05880 val = var; 05881 var = "Opaque-data"; 05882 in_data = 1; 05883 } 05884 05885 05886 ast_str_append(out, 0, xml ? " " : "<tr><td>"); 05887 if ((vc = ao2_find(vco, var, 0))) { 05888 vc->count++; 05889 } else { 05890 /* Create a new entry for this one */ 05891 vc = ao2_alloc(sizeof(*vc), NULL); 05892 vc->varname = var; 05893 vc->count = 1; 05894 ao2_link(vco, vc); 05895 } 05896 05897 xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */ 05898 if (vc->count > 1) { 05899 ast_str_append(out, 0, "-%d", vc->count); 05900 } 05901 ao2_ref(vc, -1); 05902 ast_str_append(out, 0, xml ? "='" : "</td><td>"); 05903 xml_copy_escape(out, val, 0); /* data field */ 05904 if (!in_data || !*in) { 05905 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05906 } 05907 } 05908 05909 if (inobj) { 05910 ast_str_append(out, 0, xml ? " /></response>\n" : 05911 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05912 ao2_ref(vco, -1); 05913 } 05914 }
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] |
Definition at line 6624 of file manager.c.
Referenced by __init_manager(), handle_manager_show_settings(), manager_set_defaults(), and manager_shutdown().
struct ast_tcptls_session_args amis_desc [static] |
struct ast_http_uri arawmanuri [static] |
struct ast_cli_entry cli_manager[] [static] |
const char* const contenttype[] [static] |
{ [FORMAT_RAW] = "plain", [FORMAT_HTML] = "html", [FORMAT_XML] = "xml", }
struct ast_http_uri manageruri [static] |
struct ast_http_uri managerxmluri [static] |
struct ast_http_uri rawmanuri [static] |
const char* words[AST_MAX_CMD_LEN] |
Definition at line 929 of file manager.c.
Referenced by check_blacklist().