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. | |
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 | 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_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 | block_sockets |
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_BLOCKSOCKETS = 0 |
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 int | registered = 0 |
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 5511 of file manager.c.
05511 { 05512 FORMAT_RAW, 05513 FORMAT_HTML, 05514 FORMAT_XML, 05515 };
static int __init_manager | ( | int | reload | ) | [static] |
Definition at line 6785 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_CERTFILE, ast_cli_register_multiple(), ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_debug, ast_extension_state_add(), ast_free, ast_free_ha(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, ast_log(), ast_manager_register_xml, ast_md5_hash(), ast_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_setnull(), ast_sockaddr_to_sin, ast_ssl_setup(), ast_strdup, ast_strlen_zero(), ast_tcptls_server_start(), ast_tcptls_server_stop(), ast_tls_read_conf(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_manager_user::blackfilters, block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, DEFAULT_MANAGER_TLS_PORT, DEFAULT_REALM, ast_manager_user::displayconnects, ast_tls_config::enabled, event_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, free_channelvars(), 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_shutdown(), manager_state_cb(), mansession_cmp_fn(), ast_variable::name, ast_variable::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_tls_config::pvtfile, ast_manager_user::readperm, S_OR, ast_manager_user::secret, 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().
06786 { 06787 struct ast_config *ucfg = NULL, *cfg = NULL; 06788 const char *val; 06789 char *cat = NULL; 06790 int newhttptimeout = DEFAULT_HTTPTIMEOUT; 06791 struct ast_manager_user *user = NULL; 06792 struct ast_variable *var; 06793 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 06794 char a1[256]; 06795 char a1_hash[256]; 06796 struct sockaddr_in ami_desc_local_address_tmp = { 0, }; 06797 struct sockaddr_in amis_desc_local_address_tmp = { 0, }; 06798 int tls_was_enabled = 0; 06799 06800 if (!registered) { 06801 /* Register default actions */ 06802 ast_manager_register_xml("Ping", 0, action_ping); 06803 ast_manager_register_xml("Events", 0, action_events); 06804 ast_manager_register_xml("Logoff", 0, action_logoff); 06805 ast_manager_register_xml("Login", 0, action_login); 06806 ast_manager_register_xml("Challenge", 0, action_challenge); 06807 ast_manager_register_xml("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup); 06808 ast_manager_register_xml("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status); 06809 ast_manager_register_xml("Setvar", EVENT_FLAG_CALL, action_setvar); 06810 ast_manager_register_xml("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar); 06811 ast_manager_register_xml("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig); 06812 ast_manager_register_xml("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson); 06813 ast_manager_register_xml("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig); 06814 ast_manager_register_xml("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig); 06815 ast_manager_register_xml("ListCategories", EVENT_FLAG_CONFIG, action_listcategories); 06816 ast_manager_register_xml("Redirect", EVENT_FLAG_CALL, action_redirect); 06817 ast_manager_register_xml("Atxfer", EVENT_FLAG_CALL, action_atxfer); 06818 ast_manager_register_xml("Originate", EVENT_FLAG_ORIGINATE, action_originate); 06819 ast_manager_register_xml("Command", EVENT_FLAG_COMMAND, action_command); 06820 ast_manager_register_xml("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate); 06821 ast_manager_register_xml("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout); 06822 ast_manager_register_xml("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus); 06823 ast_manager_register_xml("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount); 06824 ast_manager_register_xml("ListCommands", 0, action_listcommands); 06825 ast_manager_register_xml("SendText", EVENT_FLAG_CALL, action_sendtext); 06826 ast_manager_register_xml("UserEvent", EVENT_FLAG_USER, action_userevent); 06827 ast_manager_register_xml("WaitEvent", 0, action_waitevent); 06828 ast_manager_register_xml("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings); 06829 ast_manager_register_xml("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus); 06830 ast_manager_register_xml("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload); 06831 ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels); 06832 ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload); 06833 ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck); 06834 ast_manager_register_xml("AOCMessage", EVENT_FLAG_AOC, action_aocmessage); 06835 06836 ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager)); 06837 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 06838 registered = 1; 06839 /* Append placeholder event so master_eventq never runs dry */ 06840 append_event("Event: Placeholder\r\n\r\n", 0); 06841 } 06842 06843 ast_register_atexit(manager_shutdown); 06844 06845 if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 06846 return 0; 06847 } 06848 06849 manager_enabled = DEFAULT_ENABLED; 06850 webmanager_enabled = DEFAULT_WEBENABLED; 06851 manager_debug = DEFAULT_MANAGERDEBUG; 06852 displayconnects = DEFAULT_DISPLAYCONNECTS; 06853 broken_events_action = DEFAULT_BROKENEVENTSACTION; 06854 block_sockets = DEFAULT_BLOCKSOCKETS; 06855 timestampevents = DEFAULT_TIMESTAMPEVENTS; 06856 httptimeout = DEFAULT_HTTPTIMEOUT; 06857 authtimeout = DEFAULT_AUTHTIMEOUT; 06858 authlimit = DEFAULT_AUTHLIMIT; 06859 06860 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 06861 ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n"); 06862 return 0; 06863 } 06864 06865 /* default values */ 06866 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm)); 06867 ast_sockaddr_setnull(&ami_desc.local_address); 06868 ast_sockaddr_setnull(&amis_desc.local_address); 06869 06870 ami_desc_local_address_tmp.sin_family = AF_INET; 06871 amis_desc_local_address_tmp.sin_family = AF_INET; 06872 06873 ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT); 06874 06875 tls_was_enabled = (reload && ami_tls_cfg.enabled); 06876 06877 ami_tls_cfg.enabled = 0; 06878 if (ami_tls_cfg.certfile) { 06879 ast_free(ami_tls_cfg.certfile); 06880 } 06881 ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE); 06882 if (ami_tls_cfg.pvtfile) { 06883 ast_free(ami_tls_cfg.pvtfile); 06884 } 06885 ami_tls_cfg.pvtfile = ast_strdup(""); 06886 if (ami_tls_cfg.cipher) { 06887 ast_free(ami_tls_cfg.cipher); 06888 } 06889 ami_tls_cfg.cipher = ast_strdup(""); 06890 06891 free_channelvars(); 06892 06893 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 06894 val = var->value; 06895 06896 /* read tls config options while preventing unsupported options from being set */ 06897 if (strcasecmp(var->name, "tlscafile") 06898 && strcasecmp(var->name, "tlscapath") 06899 && strcasecmp(var->name, "tlscadir") 06900 && strcasecmp(var->name, "tlsverifyclient") 06901 && strcasecmp(var->name, "tlsdontverifyserver") 06902 && strcasecmp(var->name, "tlsclientmethod") 06903 && strcasecmp(var->name, "sslclientmethod") 06904 && !ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) { 06905 continue; 06906 } 06907 06908 if (!strcasecmp(var->name, "enabled")) { 06909 manager_enabled = ast_true(val); 06910 } else if (!strcasecmp(var->name, "block-sockets")) { 06911 block_sockets = ast_true(val); 06912 } else if (!strcasecmp(var->name, "webenabled")) { 06913 webmanager_enabled = ast_true(val); 06914 } else if (!strcasecmp(var->name, "port")) { 06915 ami_desc_local_address_tmp.sin_port = htons(atoi(val)); 06916 } else if (!strcasecmp(var->name, "bindaddr")) { 06917 if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) { 06918 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 06919 memset(&ami_desc_local_address_tmp.sin_addr, 0, 06920 sizeof(ami_desc_local_address_tmp.sin_addr)); 06921 } 06922 } else if (!strcasecmp(var->name, "brokeneventsaction")) { 06923 broken_events_action = ast_true(val); 06924 } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 06925 allowmultiplelogin = ast_true(val); 06926 } else if (!strcasecmp(var->name, "displayconnects")) { 06927 displayconnects = ast_true(val); 06928 } else if (!strcasecmp(var->name, "timestampevents")) { 06929 timestampevents = ast_true(val); 06930 } else if (!strcasecmp(var->name, "debug")) { 06931 manager_debug = ast_true(val); 06932 } else if (!strcasecmp(var->name, "httptimeout")) { 06933 newhttptimeout = atoi(val); 06934 } else if (!strcasecmp(var->name, "authtimeout")) { 06935 int timeout = atoi(var->value); 06936 06937 if (timeout < 1) { 06938 ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value); 06939 } else { 06940 authtimeout = timeout; 06941 } 06942 } else if (!strcasecmp(var->name, "authlimit")) { 06943 int limit = atoi(var->value); 06944 06945 if (limit < 1) { 06946 ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value); 06947 } else { 06948 authlimit = limit; 06949 } 06950 } else if (!strcasecmp(var->name, "channelvars")) { 06951 load_channelvars(var); 06952 } else { 06953 ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", 06954 var->name, val); 06955 } 06956 } 06957 06958 ast_sockaddr_to_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 06959 06960 /* if the amis address has not been set, default is the same as non secure ami */ 06961 if (!amis_desc_local_address_tmp.sin_addr.s_addr) { 06962 amis_desc_local_address_tmp.sin_addr = 06963 ami_desc_local_address_tmp.sin_addr; 06964 } 06965 06966 if (!amis_desc_local_address_tmp.sin_port) { 06967 amis_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_TLS_PORT); 06968 } 06969 06970 if (manager_enabled) { 06971 ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp); 06972 ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 06973 } 06974 06975 AST_RWLIST_WRLOCK(&users); 06976 06977 /* First, get users from users.conf */ 06978 ucfg = ast_config_load2("users.conf", "manager", config_flags); 06979 if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) { 06980 const char *hasmanager; 06981 int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager")); 06982 06983 while ((cat = ast_category_browse(ucfg, cat))) { 06984 if (!strcasecmp(cat, "general")) { 06985 continue; 06986 } 06987 06988 hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager"); 06989 if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) { 06990 const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret"); 06991 const char *user_read = ast_variable_retrieve(ucfg, cat, "read"); 06992 const char *user_write = ast_variable_retrieve(ucfg, cat, "write"); 06993 const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects"); 06994 const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout"); 06995 06996 /* Look for an existing entry, 06997 * if none found - create one and add it to the list 06998 */ 06999 if (!(user = get_manager_by_name_locked(cat))) { 07000 if (!(user = ast_calloc(1, sizeof(*user)))) { 07001 break; 07002 } 07003 07004 /* Copy name over */ 07005 ast_copy_string(user->username, cat, sizeof(user->username)); 07006 /* Insert into list */ 07007 AST_LIST_INSERT_TAIL(&users, user, list); 07008 user->ha = NULL; 07009 user->keep = 1; 07010 user->readperm = -1; 07011 user->writeperm = -1; 07012 /* Default displayconnect from [general] */ 07013 user->displayconnects = displayconnects; 07014 user->writetimeout = 100; 07015 } 07016 07017 if (!user_secret) { 07018 user_secret = ast_variable_retrieve(ucfg, "general", "secret"); 07019 } 07020 if (!user_read) { 07021 user_read = ast_variable_retrieve(ucfg, "general", "read"); 07022 } 07023 if (!user_write) { 07024 user_write = ast_variable_retrieve(ucfg, "general", "write"); 07025 } 07026 if (!user_displayconnects) { 07027 user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); 07028 } 07029 if (!user_writetimeout) { 07030 user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); 07031 } 07032 07033 if (!ast_strlen_zero(user_secret)) { 07034 if (user->secret) { 07035 ast_free(user->secret); 07036 } 07037 user->secret = ast_strdup(user_secret); 07038 } 07039 07040 if (user_read) { 07041 user->readperm = get_perm(user_read); 07042 } 07043 if (user_write) { 07044 user->writeperm = get_perm(user_write); 07045 } 07046 if (user_displayconnects) { 07047 user->displayconnects = ast_true(user_displayconnects); 07048 } 07049 if (user_writetimeout) { 07050 int value = atoi(user_writetimeout); 07051 if (value < 100) { 07052 ast_log(LOG_WARNING, "Invalid writetimeout value '%d' in users.conf\n", value); 07053 } else { 07054 user->writetimeout = value; 07055 } 07056 } 07057 } 07058 } 07059 ast_config_destroy(ucfg); 07060 } 07061 07062 /* cat is NULL here in any case */ 07063 07064 while ((cat = ast_category_browse(cfg, cat))) { 07065 struct ast_ha *oldha; 07066 07067 if (!strcasecmp(cat, "general")) { 07068 continue; 07069 } 07070 07071 /* Look for an existing entry, if none found - create one and add it to the list */ 07072 if (!(user = get_manager_by_name_locked(cat))) { 07073 if (!(user = ast_calloc(1, sizeof(*user)))) { 07074 break; 07075 } 07076 /* Copy name over */ 07077 ast_copy_string(user->username, cat, sizeof(user->username)); 07078 07079 user->ha = NULL; 07080 user->readperm = 0; 07081 user->writeperm = 0; 07082 /* Default displayconnect from [general] */ 07083 user->displayconnects = displayconnects; 07084 user->writetimeout = 100; 07085 user->whitefilters = ao2_container_alloc(1, NULL, NULL); 07086 user->blackfilters = ao2_container_alloc(1, NULL, NULL); 07087 07088 /* Insert into list */ 07089 AST_RWLIST_INSERT_TAIL(&users, user, list); 07090 } else { 07091 ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 07092 ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 07093 } 07094 07095 /* Make sure we keep this user and don't destroy it during cleanup */ 07096 user->keep = 1; 07097 oldha = user->ha; 07098 user->ha = NULL; 07099 07100 var = ast_variable_browse(cfg, cat); 07101 for (; var; var = var->next) { 07102 if (!strcasecmp(var->name, "secret")) { 07103 if (user->secret) { 07104 ast_free(user->secret); 07105 } 07106 user->secret = ast_strdup(var->value); 07107 } else if (!strcasecmp(var->name, "deny") || 07108 !strcasecmp(var->name, "permit")) { 07109 user->ha = ast_append_ha(var->name, var->value, user->ha, NULL); 07110 } else if (!strcasecmp(var->name, "read") ) { 07111 user->readperm = get_perm(var->value); 07112 } else if (!strcasecmp(var->name, "write") ) { 07113 user->writeperm = get_perm(var->value); 07114 } else if (!strcasecmp(var->name, "displayconnects") ) { 07115 user->displayconnects = ast_true(var->value); 07116 } else if (!strcasecmp(var->name, "writetimeout")) { 07117 int value = atoi(var->value); 07118 if (value < 100) { 07119 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); 07120 } else { 07121 user->writetimeout = value; 07122 } 07123 } else if (!strcasecmp(var->name, "eventfilter")) { 07124 const char *value = var->value; 07125 regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation"); 07126 if (new_filter) { 07127 int is_blackfilter; 07128 if (value[0] == '!') { 07129 is_blackfilter = 1; 07130 value++; 07131 } else { 07132 is_blackfilter = 0; 07133 } 07134 if (regcomp(new_filter, value, 0)) { 07135 ao2_t_ref(new_filter, -1, "failed to make regx"); 07136 } else { 07137 if (is_blackfilter) { 07138 ao2_t_link(user->blackfilters, new_filter, "link new filter into black user container"); 07139 } else { 07140 ao2_t_link(user->whitefilters, new_filter, "link new filter into white user container"); 07141 } 07142 } 07143 } 07144 } else { 07145 ast_debug(1, "%s is an unknown option.\n", var->name); 07146 } 07147 } 07148 ast_free_ha(oldha); 07149 } 07150 ast_config_destroy(cfg); 07151 07152 /* Perform cleanup - essentially prune out old users that no longer exist */ 07153 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 07154 if (user->keep) { /* valid record. clear flag for the next round */ 07155 user->keep = 0; 07156 07157 /* Calculate A1 for Digest auth */ 07158 snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret); 07159 ast_md5_hash(a1_hash,a1); 07160 if (user->a1_hash) { 07161 ast_free(user->a1_hash); 07162 } 07163 user->a1_hash = ast_strdup(a1_hash); 07164 continue; 07165 } 07166 /* We do not need to keep this user so take them out of the list */ 07167 AST_RWLIST_REMOVE_CURRENT(list); 07168 ast_debug(4, "Pruning user '%s'\n", user->username); 07169 manager_free_user(user); 07170 } 07171 AST_RWLIST_TRAVERSE_SAFE_END; 07172 07173 AST_RWLIST_UNLOCK(&users); 07174 07175 if (!reload) { 07176 /* If you have a NULL hash fn, you only need a single bucket */ 07177 sessions = ao2_container_alloc(1, NULL, mansession_cmp_fn); 07178 } 07179 07180 if (webmanager_enabled && manager_enabled) { 07181 if (!webregged) { 07182 07183 ast_http_uri_link(&rawmanuri); 07184 ast_http_uri_link(&manageruri); 07185 ast_http_uri_link(&managerxmluri); 07186 07187 ast_http_uri_link(&arawmanuri); 07188 ast_http_uri_link(&amanageruri); 07189 ast_http_uri_link(&amanagerxmluri); 07190 webregged = 1; 07191 } 07192 } else { 07193 if (webregged) { 07194 ast_http_uri_unlink(&rawmanuri); 07195 ast_http_uri_unlink(&manageruri); 07196 ast_http_uri_unlink(&managerxmluri); 07197 07198 ast_http_uri_unlink(&arawmanuri); 07199 ast_http_uri_unlink(&amanageruri); 07200 ast_http_uri_unlink(&amanagerxmluri); 07201 webregged = 0; 07202 } 07203 } 07204 07205 if (newhttptimeout > 0) { 07206 httptimeout = newhttptimeout; 07207 } 07208 07209 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled"); 07210 07211 ast_tcptls_server_start(&ami_desc); 07212 if (tls_was_enabled && !ami_tls_cfg.enabled) { 07213 ast_tcptls_server_stop(&amis_desc); 07214 } else if (ast_ssl_setup(amis_desc.tls_cfg)) { 07215 ast_tcptls_server_start(&amis_desc); 07216 } 07217 07218 return 0; 07219 }
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 7242 of file manager.c.
References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.
07243 { 07244 AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry); 07245 07246 return 0; 07247 }
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 7254 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.
07255 { 07256 struct ast_datastore *datastore = NULL; 07257 07258 if (info == NULL) 07259 return NULL; 07260 07261 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) { 07262 if (datastore->info != info) { 07263 continue; 07264 } 07265 07266 if (uid == NULL) { 07267 /* matched by type only */ 07268 break; 07269 } 07270 07271 if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { 07272 /* Matched by type AND uid */ 07273 break; 07274 } 07275 } 07276 AST_LIST_TRAVERSE_SAFE_END; 07277 07278 return datastore; 07279 }
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 7249 of file manager.c.
References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.
07250 { 07251 return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1; 07252 }
int astman_is_authed | ( | uint32_t | ident | ) |
Determinie if a manager session ident is authenticated.
Definition at line 5587 of file manager.c.
References ao2_unlock, mansession_session::authenticated, find_session(), and unref_mansession().
Referenced by http_post_callback(), and static_callback().
05588 { 05589 int authed; 05590 struct mansession_session *session; 05591 05592 if (!(session = find_session(ident, 0))) 05593 return 0; 05594 05595 authed = (session->authenticated != 0); 05596 05597 ao2_unlock(session); 05598 unref_mansession(session); 05599 05600 return authed; 05601 }
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 5603 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().
05604 { 05605 int result = 0; 05606 struct mansession_session *session; 05607 struct ao2_iterator i; 05608 05609 if (ident == 0) { 05610 return 0; 05611 } 05612 05613 i = ao2_iterator_init(sessions, 0); 05614 while ((session = ao2_iterator_next(&i))) { 05615 ao2_lock(session); 05616 if ((session->managerid == ident) && (session->readperm & perm)) { 05617 result = 1; 05618 ao2_unlock(session); 05619 unref_mansession(session); 05620 break; 05621 } 05622 ao2_unlock(session); 05623 unref_mansession(session); 05624 } 05625 ao2_iterator_destroy(&i); 05626 return result; 05627 }
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 5629 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().
05630 { 05631 int result = 0; 05632 struct mansession_session *session; 05633 struct ao2_iterator i; 05634 05635 if (ident == 0) { 05636 return 0; 05637 } 05638 05639 i = ao2_iterator_init(sessions, 0); 05640 while ((session = ao2_iterator_next(&i))) { 05641 ao2_lock(session); 05642 if ((session->managerid == ident) && (session->writeperm & perm)) { 05643 result = 1; 05644 ao2_unlock(session); 05645 unref_mansession(session); 05646 break; 05647 } 05648 ao2_unlock(session); 05649 unref_mansession(session); 05650 } 05651 ao2_iterator_destroy(&i); 05652 return result; 05653 }
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 6143 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().
06149 { 06150 struct mansession_session *session = NULL; 06151 struct mansession s = { .session = NULL, .tcptls_session = ser }; 06152 struct ast_variable *v, *params = get_params; 06153 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 06154 struct ast_str *http_header = NULL, *out = NULL; 06155 size_t result_size = 512; 06156 struct message m = { 0 }; 06157 unsigned int idx; 06158 size_t hdrlen; 06159 06160 time_t time_now = time(NULL); 06161 unsigned long nonce = 0, nc; 06162 struct ast_http_digest d = { NULL, }; 06163 struct ast_manager_user *user = NULL; 06164 int stale = 0; 06165 char resp_hash[256]=""; 06166 /* Cache for user data */ 06167 char u_username[80]; 06168 int u_readperm; 06169 int u_writeperm; 06170 int u_writetimeout; 06171 int u_displayconnects; 06172 struct ast_sockaddr addr; 06173 06174 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 06175 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 06176 return -1; 06177 } 06178 06179 /* Find "Authorization: " header */ 06180 for (v = headers; v; v = v->next) { 06181 if (!strcasecmp(v->name, "Authorization")) { 06182 break; 06183 } 06184 } 06185 06186 if (!v || ast_strlen_zero(v->value)) { 06187 goto out_401; /* Authorization Header not present - send auth request */ 06188 } 06189 06190 /* Digest found - parse */ 06191 if (ast_string_field_init(&d, 128)) { 06192 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06193 return -1; 06194 } 06195 06196 if (ast_parse_digest(v->value, &d, 0, 1)) { 06197 /* Error in Digest - send new one */ 06198 nonce = 0; 06199 goto out_401; 06200 } 06201 if (sscanf(d.nonce, "%30lx", &nonce) != 1) { 06202 ast_log(LOG_WARNING, "Received incorrect nonce in Digest <%s>\n", d.nonce); 06203 nonce = 0; 06204 goto out_401; 06205 } 06206 06207 AST_RWLIST_WRLOCK(&users); 06208 user = get_manager_by_name_locked(d.username); 06209 if(!user) { 06210 AST_RWLIST_UNLOCK(&users); 06211 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06212 nonce = 0; 06213 goto out_401; 06214 } 06215 06216 ast_sockaddr_from_sin(&addr, remote_address); 06217 /* --- We have User for this auth, now check ACL */ 06218 if (user->ha && !ast_apply_ha(user->ha, &addr)) { 06219 AST_RWLIST_UNLOCK(&users); 06220 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06221 ast_http_error(ser, 403, "Permission denied", "Permission denied\n"); 06222 return -1; 06223 } 06224 06225 /* --- We have auth, so check it */ 06226 06227 /* compute the expected response to compare with what we received */ 06228 { 06229 char a2[256]; 06230 char a2_hash[256]; 06231 char resp[256]; 06232 06233 /* XXX Now request method are hardcoded in A2 */ 06234 snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri); 06235 ast_md5_hash(a2_hash, a2); 06236 06237 if (d.qop) { 06238 /* RFC 2617 */ 06239 snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash); 06240 } else { 06241 /* RFC 2069 */ 06242 snprintf(resp, sizeof(resp), "%s:%08lx:%s", user->a1_hash, nonce, a2_hash); 06243 } 06244 ast_md5_hash(resp_hash, resp); 06245 } 06246 06247 if (strncasecmp(d.response, resp_hash, strlen(resp_hash))) { 06248 /* Something was wrong, so give the client to try with a new challenge */ 06249 AST_RWLIST_UNLOCK(&users); 06250 nonce = 0; 06251 goto out_401; 06252 } 06253 06254 /* 06255 * User are pass Digest authentication. 06256 * Now, cache the user data and unlock user list. 06257 */ 06258 ast_copy_string(u_username, user->username, sizeof(u_username)); 06259 u_readperm = user->readperm; 06260 u_writeperm = user->writeperm; 06261 u_displayconnects = user->displayconnects; 06262 u_writetimeout = user->writetimeout; 06263 AST_RWLIST_UNLOCK(&users); 06264 06265 if (!(session = find_session_by_nonce(d.username, nonce, &stale))) { 06266 /* 06267 * Create new session. 06268 * While it is not in the list we don't need any locking 06269 */ 06270 if (!(session = build_mansession(*remote_address))) { 06271 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06272 return -1; 06273 } 06274 ao2_lock(session); 06275 06276 ast_copy_string(session->username, u_username, sizeof(session->username)); 06277 session->managerid = nonce; 06278 session->last_ev = grab_last(); 06279 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 06280 06281 session->readperm = u_readperm; 06282 session->writeperm = u_writeperm; 06283 session->writetimeout = u_writetimeout; 06284 06285 if (u_displayconnects) { 06286 ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06287 } 06288 session->noncetime = session->sessionstart = time_now; 06289 session->authenticated = 1; 06290 } else if (stale) { 06291 /* 06292 * Session found, but nonce is stale. 06293 * 06294 * This could be because an old request (w/old nonce) arrived. 06295 * 06296 * This may be as the result of http proxy usage (separate delay or 06297 * multipath) or in a situation where a page was refreshed too quickly 06298 * (seen in Firefox). 06299 * 06300 * In this situation, we repeat the 401 auth with the current nonce 06301 * value. 06302 */ 06303 nonce = session->managerid; 06304 ao2_unlock(session); 06305 stale = 1; 06306 goto out_401; 06307 } else { 06308 sscanf(d.nc, "%30lx", &nc); 06309 if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) { 06310 /* 06311 * Nonce time expired (> 2 minutes) or something wrong with nonce 06312 * counter. 06313 * 06314 * Create new nonce key and resend Digest auth request. Old nonce 06315 * is saved for stale checking... 06316 */ 06317 session->nc = 0; /* Reset nonce counter */ 06318 session->oldnonce = session->managerid; 06319 nonce = session->managerid = ast_random(); 06320 session->noncetime = time_now; 06321 ao2_unlock(session); 06322 stale = 1; 06323 goto out_401; 06324 } else { 06325 session->nc = nc; /* All OK, save nonce counter */ 06326 } 06327 } 06328 06329 06330 /* Reset session timeout. */ 06331 session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5); 06332 ao2_unlock(session); 06333 06334 ast_mutex_init(&s.lock); 06335 s.session = session; 06336 s.fd = mkstemp(template); /* create a temporary file for command output */ 06337 unlink(template); 06338 if (s.fd <= -1) { 06339 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 06340 goto auth_callback_out; 06341 } 06342 s.f = fdopen(s.fd, "w+"); 06343 if (!s.f) { 06344 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 06345 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 06346 close(s.fd); 06347 goto auth_callback_out; 06348 } 06349 06350 if (method == AST_HTTP_POST) { 06351 params = ast_http_get_post_vars(ser, headers); 06352 } 06353 06354 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 06355 hdrlen = strlen(v->name) + strlen(v->value) + 3; 06356 m.headers[m.hdrcount] = ast_malloc(hdrlen); 06357 if (!m.headers[m.hdrcount]) { 06358 /* Allocation failure */ 06359 continue; 06360 } 06361 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 06362 ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 06363 ++m.hdrcount; 06364 } 06365 06366 if (process_message(&s, &m)) { 06367 if (u_displayconnects) { 06368 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06369 } 06370 06371 session->needdestroy = 1; 06372 } 06373 06374 /* Free request headers. */ 06375 for (idx = 0; idx < m.hdrcount; ++idx) { 06376 ast_free((void *) m.headers[idx]); 06377 m.headers[idx] = NULL; 06378 } 06379 06380 if (s.f) { 06381 result_size = ftell(s.f); /* Calculate approx. size of result */ 06382 } 06383 06384 http_header = ast_str_create(80); 06385 out = ast_str_create(result_size * 2 + 512); 06386 06387 if (http_header == NULL || out == NULL) { 06388 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 06389 goto auth_callback_out; 06390 } 06391 06392 ast_str_append(&http_header, 0, "Content-type: text/%s\r\n", contenttype[format]); 06393 06394 if (format == FORMAT_XML) { 06395 ast_str_append(&out, 0, "<ajax-response>\n"); 06396 } else if (format == FORMAT_HTML) { 06397 ast_str_append(&out, 0, 06398 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 06399 "<html><head>\r\n" 06400 "<title>Asterisk™ Manager Interface</title>\r\n" 06401 "</head><body style=\"background-color: #ffffff;\">\r\n" 06402 "<form method=\"POST\">\r\n" 06403 "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n" 06404 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n" 06405 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>" 06406 "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n"); 06407 } 06408 06409 process_output(&s, &out, params, format); 06410 06411 if (format == FORMAT_XML) { 06412 ast_str_append(&out, 0, "</ajax-response>\n"); 06413 } else if (format == FORMAT_HTML) { 06414 ast_str_append(&out, 0, "</table></form></body></html>\r\n"); 06415 } 06416 06417 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06418 http_header = out = NULL; 06419 06420 auth_callback_out: 06421 ast_mutex_destroy(&s.lock); 06422 06423 /* Clear resources and unlock manager session */ 06424 if (method == AST_HTTP_POST && params) { 06425 ast_variables_destroy(params); 06426 } 06427 06428 ast_free(http_header); 06429 ast_free(out); 06430 06431 ao2_lock(session); 06432 if (session->f) { 06433 fclose(session->f); 06434 } 06435 session->f = NULL; 06436 session->fd = -1; 06437 ao2_unlock(session); 06438 06439 if (session->needdestroy) { 06440 ast_debug(1, "Need destroy, doing it now!\n"); 06441 session_destroy(session); 06442 } 06443 ast_string_field_free_memory(&d); 06444 return 0; 06445 06446 out_401: 06447 if (!nonce) { 06448 nonce = ast_random(); 06449 } 06450 06451 ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL); 06452 ast_string_field_free_memory(&d); 06453 return 0; 06454 }
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 6515 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.
06516 { 06517 int retval; 06518 struct sockaddr_in ser_remote_address_tmp; 06519 06520 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06521 retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06522 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06523 return retval; 06524 }
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 6526 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.
06527 { 06528 int retval; 06529 struct sockaddr_in ser_remote_address_tmp; 06530 06531 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06532 retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06533 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06534 return retval; 06535 }
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 6537 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.
06538 { 06539 int retval; 06540 struct sockaddr_in ser_remote_address_tmp; 06541 06542 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06543 retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06544 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06545 return retval; 06546 }
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 5528 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().
05529 { 05530 struct mansession_session *session; 05531 struct ao2_iterator i; 05532 05533 if (ident == 0) { 05534 return NULL; 05535 } 05536 05537 i = ao2_iterator_init(sessions, 0); 05538 while ((session = ao2_iterator_next(&i))) { 05539 ao2_lock(session); 05540 if (session->managerid == ident && !session->needdestroy) { 05541 ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0); 05542 break; 05543 } 05544 ao2_unlock(session); 05545 unref_mansession(session); 05546 } 05547 ao2_iterator_destroy(&i); 05548 05549 return session; 05550 }
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 5561 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().
05562 { 05563 struct mansession_session *session; 05564 struct ao2_iterator i; 05565 05566 if (nonce == 0 || username == NULL || stale == NULL) { 05567 return NULL; 05568 } 05569 05570 i = ao2_iterator_init(sessions, 0); 05571 while ((session = ao2_iterator_next(&i))) { 05572 ao2_lock(session); 05573 if (!strcasecmp(session->username, username) && session->managerid == nonce) { 05574 *stale = 0; 05575 break; 05576 } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) { 05577 *stale = 1; 05578 break; 05579 } 05580 ao2_unlock(session); 05581 unref_mansession(session); 05582 } 05583 ao2_iterator_destroy(&i); 05584 return session; 05585 }
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 5928 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().
05934 { 05935 struct mansession s = { .session = NULL, .tcptls_session = ser }; 05936 struct mansession_session *session = NULL; 05937 uint32_t ident = 0; 05938 int blastaway = 0; 05939 struct ast_variable *v, *cookies, *params = get_params; 05940 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 05941 struct ast_str *http_header = NULL, *out = NULL; 05942 struct message m = { 0 }; 05943 unsigned int idx; 05944 size_t hdrlen; 05945 05946 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 05947 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 05948 return -1; 05949 } 05950 05951 cookies = ast_http_get_cookies(headers); 05952 for (v = cookies; v; v = v->next) { 05953 if (!strcasecmp(v->name, "mansession_id")) { 05954 sscanf(v->value, "%30x", &ident); 05955 break; 05956 } 05957 } 05958 if (cookies) { 05959 ast_variables_destroy(cookies); 05960 } 05961 05962 if (!(session = find_session(ident, 1))) { 05963 05964 /**/ 05965 /* Create new session. 05966 * While it is not in the list we don't need any locking 05967 */ 05968 if (!(session = build_mansession(*remote_address))) { 05969 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 05970 return -1; 05971 } 05972 ao2_lock(session); 05973 session->sin = *remote_address; 05974 session->fd = -1; 05975 session->waiting_thread = AST_PTHREADT_NULL; 05976 session->send_events = 0; 05977 session->inuse = 1; 05978 /*!\note There is approximately a 1 in 1.8E19 chance that the following 05979 * calculation will produce 0, which is an invalid ID, but due to the 05980 * properties of the rand() function (and the constantcy of s), that 05981 * won't happen twice in a row. 05982 */ 05983 while ((session->managerid = ast_random() ^ (unsigned long) session) == 0); 05984 session->last_ev = grab_last(); 05985 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05986 } 05987 ao2_unlock(session); 05988 05989 http_header = ast_str_create(128); 05990 out = ast_str_create(2048); 05991 05992 ast_mutex_init(&s.lock); 05993 05994 if (http_header == NULL || out == NULL) { 05995 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 05996 goto generic_callback_out; 05997 } 05998 05999 s.session = session; 06000 s.fd = mkstemp(template); /* create a temporary file for command output */ 06001 unlink(template); 06002 if (s.fd <= -1) { 06003 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 06004 goto generic_callback_out; 06005 } 06006 s.f = fdopen(s.fd, "w+"); 06007 if (!s.f) { 06008 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 06009 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 06010 close(s.fd); 06011 goto generic_callback_out; 06012 } 06013 06014 if (method == AST_HTTP_POST) { 06015 params = ast_http_get_post_vars(ser, headers); 06016 } 06017 06018 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 06019 hdrlen = strlen(v->name) + strlen(v->value) + 3; 06020 m.headers[m.hdrcount] = ast_malloc(hdrlen); 06021 if (!m.headers[m.hdrcount]) { 06022 /* Allocation failure */ 06023 continue; 06024 } 06025 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 06026 ast_debug(1, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 06027 ++m.hdrcount; 06028 } 06029 06030 if (process_message(&s, &m)) { 06031 if (session->authenticated) { 06032 if (manager_displayconnects(session)) { 06033 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06034 } 06035 } else { 06036 if (displayconnects) { 06037 ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 06038 } 06039 } 06040 session->needdestroy = 1; 06041 } 06042 06043 /* Free request headers. */ 06044 for (idx = 0; idx < m.hdrcount; ++idx) { 06045 ast_free((void *) m.headers[idx]); 06046 m.headers[idx] = NULL; 06047 } 06048 06049 ast_str_append(&http_header, 0, 06050 "Content-type: text/%s\r\n" 06051 "Cache-Control: no-cache;\r\n" 06052 "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n" 06053 "Pragma: SuppressEvents\r\n", 06054 contenttype[format], 06055 session->managerid, httptimeout); 06056 06057 if (format == FORMAT_XML) { 06058 ast_str_append(&out, 0, "<ajax-response>\n"); 06059 } else if (format == FORMAT_HTML) { 06060 /* 06061 * When handling AMI-over-HTTP in HTML format, we provide a simple form for 06062 * debugging purposes. This HTML code should not be here, we 06063 * should read from some config file... 06064 */ 06065 06066 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" 06067 #define TEST_STRING \ 06068 "<form action=\"manager\" method=\"post\">\n\ 06069 Action: <select name=\"action\">\n\ 06070 <option value=\"\">-----></option>\n\ 06071 <option value=\"login\">login</option>\n\ 06072 <option value=\"command\">Command</option>\n\ 06073 <option value=\"waitevent\">waitevent</option>\n\ 06074 <option value=\"listcommands\">listcommands</option>\n\ 06075 </select>\n\ 06076 or <input name=\"action\"><br/>\n\ 06077 CLI Command <input name=\"command\"><br>\n\ 06078 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ 06079 <input type=\"submit\">\n</form>\n" 06080 06081 ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>"); 06082 ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 06083 ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>"); 06084 ast_str_append(&out, 0, ROW_FMT, TEST_STRING); 06085 } 06086 06087 process_output(&s, &out, params, format); 06088 06089 if (format == FORMAT_XML) { 06090 ast_str_append(&out, 0, "</ajax-response>\n"); 06091 } else if (format == FORMAT_HTML) { 06092 ast_str_append(&out, 0, "</table></body>\r\n"); 06093 } 06094 06095 ao2_lock(session); 06096 /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */ 06097 session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5); 06098 06099 if (session->needdestroy) { 06100 if (session->inuse == 1) { 06101 ast_debug(1, "Need destroy, doing it now!\n"); 06102 blastaway = 1; 06103 } else { 06104 ast_debug(1, "Need destroy, but can't do it yet!\n"); 06105 if (session->waiting_thread != AST_PTHREADT_NULL) { 06106 pthread_kill(session->waiting_thread, SIGURG); 06107 } 06108 session->inuse--; 06109 } 06110 } else { 06111 session->inuse--; 06112 } 06113 ao2_unlock(session); 06114 06115 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06116 http_header = out = NULL; 06117 06118 generic_callback_out: 06119 ast_mutex_destroy(&s.lock); 06120 06121 /* Clear resource */ 06122 06123 if (method == AST_HTTP_POST && params) { 06124 ast_variables_destroy(params); 06125 } 06126 if (http_header) { 06127 ast_free(http_header); 06128 } 06129 if (out) { 06130 ast_free(out); 06131 } 06132 06133 if (session && blastaway) { 06134 session_destroy(session); 06135 } else if (session && session->f) { 06136 fclose(session->f); 06137 session->f = NULL; 06138 } 06139 06140 return 0; 06141 }
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 6610 of file manager.c.
References ami_tls_cfg, ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, ast_sockaddr_stringify(), block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_tls_config::enabled, ast_cli_args::fd, FORMAT, FORMAT2, ast_tcptls_session_args::local_address, ast_tls_config::pvtfile, S_OR, and ast_cli_entry::usage.
06611 { 06612 switch (cmd) { 06613 case CLI_INIT: 06614 e->command = "manager show settings"; 06615 e->usage = 06616 "Usage: manager show settings\n" 06617 " Provides detailed list of the configuration of the Manager.\n"; 06618 return NULL; 06619 case CLI_GENERATE: 06620 return NULL; 06621 } 06622 #define FORMAT " %-25.25s %-15.15s\n" 06623 #define FORMAT2 " %-25.25s %-15d\n" 06624 if (a->argc != 3) { 06625 return CLI_SHOWUSAGE; 06626 } 06627 ast_cli(a->fd, "\nGlobal Settings:\n"); 06628 ast_cli(a->fd, "----------------\n"); 06629 ast_cli(a->fd, FORMAT, "Manager (AMI):", AST_CLI_YESNO(manager_enabled)); 06630 ast_cli(a->fd, FORMAT, "Web Manager (AMI/HTTP):", AST_CLI_YESNO(webmanager_enabled)); 06631 ast_cli(a->fd, FORMAT, "TCP Bindaddress:", manager_enabled != 0 ? ast_sockaddr_stringify(&ami_desc.local_address) : "Disabled"); 06632 ast_cli(a->fd, FORMAT2, "HTTP Timeout (minutes):", httptimeout); 06633 ast_cli(a->fd, FORMAT, "TLS Enable:", AST_CLI_YESNO(ami_tls_cfg.enabled)); 06634 ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ami_tls_cfg.enabled != 0 ? ast_sockaddr_stringify(&amis_desc.local_address) : "Disabled"); 06635 ast_cli(a->fd, FORMAT, "TLS Certfile:", ami_tls_cfg.certfile); 06636 ast_cli(a->fd, FORMAT, "TLS Privatekey:", ami_tls_cfg.pvtfile); 06637 ast_cli(a->fd, FORMAT, "TLS Cipher:", ami_tls_cfg.cipher); 06638 ast_cli(a->fd, FORMAT, "Allow multiple login:", AST_CLI_YESNO(allowmultiplelogin)); 06639 ast_cli(a->fd, FORMAT, "Display connects:", AST_CLI_YESNO(displayconnects)); 06640 ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents)); 06641 ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, "")); 06642 ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug)); 06643 ast_cli(a->fd, FORMAT, "Block sockets:", AST_CLI_YESNO(block_sockets)); 06644 #undef FORMAT 06645 #undef FORMAT2 06646 06647 return CLI_SUCCESS; 06648 }
int init_manager | ( | void | ) |
Called by Asterisk initialization.
Definition at line 7232 of file manager.c.
References __init_manager().
Referenced by main().
07233 { 07234 return __init_manager(0); 07235 }
static void load_channelvars | ( | struct ast_variable * | var | ) | [static] |
Definition at line 6670 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().
06671 { 06672 struct manager_channel_variable *mcv; 06673 char *remaining = ast_strdupa(var->value); 06674 char *next; 06675 06676 ast_free(manager_channelvars); 06677 manager_channelvars = ast_strdup(var->value); 06678 06679 /* 06680 * XXX TODO: To allow dialplan functions to have more than one 06681 * parameter requires eliminating the '|' as a separator so we 06682 * could use AST_STANDARD_APP_ARGS() to separate items. 06683 */ 06684 free_channelvars(); 06685 AST_RWLIST_WRLOCK(&channelvars); 06686 while ((next = strsep(&remaining, ",|"))) { 06687 if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) { 06688 break; 06689 } 06690 strcpy(mcv->name, next); /* SAFE */ 06691 if (strchr(next, '(')) { 06692 mcv->isfunc = 1; 06693 } 06694 AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry); 06695 } 06696 AST_RWLIST_UNLOCK(&channelvars); 06697 }
static void manager_free_user | ( | struct ast_manager_user * | user | ) | [static] |
Definition at line 6700 of file manager.c.
References ast_manager_user::a1_hash, ao2_t_callback, ao2_t_ref, ast_free, ast_free_ha(), ast_manager_user::blackfilters, ast_manager_user::ha, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_manager_user::secret, and ast_manager_user::whitefilters.
Referenced by __init_manager(), and manager_shutdown().
06701 { 06702 if (user->a1_hash) { 06703 ast_free(user->a1_hash); 06704 } 06705 if (user->secret) { 06706 ast_free(user->secret); 06707 } 06708 ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 06709 ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 06710 ao2_t_ref(user->whitefilters, -1, "decrement ref for white container, should be last one"); 06711 ao2_t_ref(user->blackfilters, -1, "decrement ref for black container, should be last one"); 06712 ast_free_ha(user->ha); 06713 ast_free(user); 06714 }
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 6456 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.
06457 { 06458 int retval; 06459 struct sockaddr_in ser_remote_address_tmp; 06460 06461 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06462 retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06463 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06464 return retval; 06465 }
static void manager_shutdown | ( | void | ) | [static] |
Definition at line 6717 of file manager.c.
References ami_tls_cfg, ao2_ref, 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(), ast_tls_config::pvtfile, and sessions.
Referenced by __init_manager().
06718 { 06719 struct ast_manager_user *user; 06720 06721 if (registered) { 06722 ast_manager_unregister("Ping"); 06723 ast_manager_unregister("Events"); 06724 ast_manager_unregister("Logoff"); 06725 ast_manager_unregister("Login"); 06726 ast_manager_unregister("Challenge"); 06727 ast_manager_unregister("Hangup"); 06728 ast_manager_unregister("Status"); 06729 ast_manager_unregister("Setvar"); 06730 ast_manager_unregister("Getvar"); 06731 ast_manager_unregister("GetConfig"); 06732 ast_manager_unregister("GetConfigJSON"); 06733 ast_manager_unregister("UpdateConfig"); 06734 ast_manager_unregister("CreateConfig"); 06735 ast_manager_unregister("ListCategories"); 06736 ast_manager_unregister("Redirect"); 06737 ast_manager_unregister("Atxfer"); 06738 ast_manager_unregister("Originate"); 06739 ast_manager_unregister("Command"); 06740 ast_manager_unregister("ExtensionState"); 06741 ast_manager_unregister("AbsoluteTimeout"); 06742 ast_manager_unregister("MailboxStatus"); 06743 ast_manager_unregister("MailboxCount"); 06744 ast_manager_unregister("ListCommands"); 06745 ast_manager_unregister("SendText"); 06746 ast_manager_unregister("UserEvent"); 06747 ast_manager_unregister("WaitEvent"); 06748 ast_manager_unregister("CoreSettings"); 06749 ast_manager_unregister("CoreStatus"); 06750 ast_manager_unregister("Reload"); 06751 ast_manager_unregister("CoreShowChannels"); 06752 ast_manager_unregister("ModuleLoad"); 06753 ast_manager_unregister("ModuleCheck"); 06754 ast_manager_unregister("AOCMessage"); 06755 ast_manager_unregister("Filter"); 06756 ast_cli_unregister_multiple(cli_manager, ARRAY_LEN(cli_manager)); 06757 } 06758 06759 ast_tcptls_server_stop(&ami_desc); 06760 ast_tcptls_server_stop(&amis_desc); 06761 06762 if (ami_tls_cfg.certfile) { 06763 ast_free(ami_tls_cfg.certfile); 06764 ami_tls_cfg.certfile = NULL; 06765 } 06766 if (ami_tls_cfg.pvtfile) { 06767 ast_free(ami_tls_cfg.pvtfile); 06768 ami_tls_cfg.pvtfile = NULL; 06769 } 06770 if (ami_tls_cfg.cipher) { 06771 ast_free(ami_tls_cfg.cipher); 06772 ami_tls_cfg.cipher = NULL; 06773 } 06774 06775 if (sessions) { 06776 ao2_ref(sessions, -1); 06777 sessions = NULL; 06778 } 06779 06780 while ((user = AST_LIST_REMOVE_HEAD(&users, list))) { 06781 manager_free_user(user); 06782 } 06783 }
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 6467 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.
06468 { 06469 int retval; 06470 struct sockaddr_in ser_remote_address_tmp; 06471 06472 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06473 retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06474 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06475 return retval; 06476 }
static void process_output | ( | struct mansession * | s, | |
struct ast_str ** | out, | |||
struct ast_variable * | params, | |||
enum output_format | format | |||
) | [static] |
Definition at line 5885 of file manager.c.
References ast_log(), ast_str_append(), errno, mansession::f, mansession::fd, FORMAT_HTML, FORMAT_XML, LOG_ERROR, LOG_WARNING, and xml_translate().
Referenced by auth_http_callback(), and generic_http_callback().
05886 { 05887 char *buf; 05888 size_t l; 05889 05890 if (!s->f) 05891 return; 05892 05893 /* Ensure buffer is NULL-terminated */ 05894 fprintf(s->f, "%c", 0); 05895 fflush(s->f); 05896 05897 if ((l = ftell(s->f)) > 0) { 05898 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s->fd, 0))) { 05899 ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n"); 05900 } else { 05901 if (format == FORMAT_XML || format == FORMAT_HTML) { 05902 xml_translate(out, buf, params, format); 05903 } else { 05904 ast_str_append(out, 0, "%s", buf); 05905 } 05906 munmap(buf, l); 05907 } 05908 } else if (format == FORMAT_XML || format == FORMAT_HTML) { 05909 xml_translate(out, "", params, format); 05910 } 05911 05912 if (s->f) { 05913 if (fclose(s->f)) { 05914 ast_log(LOG_ERROR, "fclose() failed: %s\n", strerror(errno)); 05915 } 05916 s->f = NULL; 05917 s->fd = -1; 05918 } else if (s->fd != -1) { 05919 if (close(s->fd)) { 05920 ast_log(LOG_ERROR, "close() failed: %s\n", strerror(errno)); 05921 } 05922 s->fd = -1; 05923 } else { 05924 ast_log(LOG_ERROR, "process output attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n"); 05925 } 05926 }
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 6581 of file manager.c.
References purge_events(), and purge_sessions().
06582 { 06583 purge_sessions(1); 06584 purge_events(); 06585 }
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 6478 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.
06479 { 06480 int retval; 06481 struct sockaddr_in ser_remote_address_tmp; 06482 06483 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06484 retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06485 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06486 return retval; 06487 }
int reload_manager | ( | void | ) |
Called by Asterisk module functions and the CLI command.
Definition at line 7237 of file manager.c.
References __init_manager().
Referenced by handle_manager_reload().
07238 { 07239 return __init_manager(1); 07240 }
static int variable_count_cmp_fn | ( | void * | obj, | |
void * | vstr, | |||
int | flags | |||
) | [static] |
Definition at line 5729 of file manager.c.
References CMP_MATCH, CMP_STOP, str, and variable_count::varname.
Referenced by xml_translate().
05730 { 05731 /* Due to the simplicity of struct variable_count, it makes no difference 05732 * if you pass in objects or strings, the same operation applies. This is 05733 * due to the fact that the hash occurs on the first element, which means 05734 * the address of both the struct and the string are exactly the same. */ 05735 struct variable_count *vc = obj; 05736 char *str = vstr; 05737 return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0; 05738 }
static int variable_count_hash_fn | ( | const void * | vvc, | |
const int | flags | |||
) | [static] |
Definition at line 5722 of file manager.c.
References ast_str_hash(), and variable_count::varname.
Referenced by xml_translate().
05723 { 05724 const struct variable_count *vc = vvc; 05725 05726 return ast_str_hash(vc->varname); 05727 }
static void xml_copy_escape | ( | struct ast_str ** | out, | |
const char * | src, | |||
int | mode | |||
) | [static] |
Definition at line 5660 of file manager.c.
References ast_str_append().
Referenced by xml_translate().
05661 { 05662 /* store in a local buffer to avoid calling ast_str_append too often */ 05663 char buf[256]; 05664 char *dst = buf; 05665 int space = sizeof(buf); 05666 /* repeat until done and nothing to flush */ 05667 for ( ; *src || dst != buf ; src++) { 05668 if (*src == '\0' || space < 10) { /* flush */ 05669 *dst++ = '\0'; 05670 ast_str_append(out, 0, "%s", buf); 05671 dst = buf; 05672 space = sizeof(buf); 05673 if (*src == '\0') { 05674 break; 05675 } 05676 } 05677 05678 if ( (mode & 2) && !isalnum(*src)) { 05679 *dst++ = '_'; 05680 space--; 05681 continue; 05682 } 05683 switch (*src) { 05684 case '<': 05685 strcpy(dst, "<"); 05686 dst += 4; 05687 space -= 4; 05688 break; 05689 case '>': 05690 strcpy(dst, ">"); 05691 dst += 4; 05692 space -= 4; 05693 break; 05694 case '\"': 05695 strcpy(dst, """); 05696 dst += 6; 05697 space -= 6; 05698 break; 05699 case '\'': 05700 strcpy(dst, "'"); 05701 dst += 6; 05702 space -= 6; 05703 break; 05704 case '&': 05705 strcpy(dst, "&"); 05706 dst += 5; 05707 space -= 5; 05708 break; 05709 05710 default: 05711 *dst++ = mode ? tolower(*src) : *src; 05712 space--; 05713 } 05714 } 05715 }
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 5768 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().
05769 { 05770 struct ast_variable *v; 05771 const char *dest = NULL; 05772 char *var, *val; 05773 const char *objtype = NULL; 05774 int in_data = 0; /* parsing data */ 05775 int inobj = 0; 05776 int xml = (format == FORMAT_XML); 05777 struct variable_count *vc = NULL; 05778 struct ao2_container *vco = NULL; 05779 05780 if (xml) { 05781 /* dest and objtype need only for XML format */ 05782 for (v = get_vars; v; v = v->next) { 05783 if (!strcasecmp(v->name, "ajaxdest")) { 05784 dest = v->value; 05785 } else if (!strcasecmp(v->name, "ajaxobjtype")) { 05786 objtype = v->value; 05787 } 05788 } 05789 if (ast_strlen_zero(dest)) { 05790 dest = "unknown"; 05791 } 05792 if (ast_strlen_zero(objtype)) { 05793 objtype = "generic"; 05794 } 05795 } 05796 05797 /* we want to stop when we find an empty line */ 05798 while (in && *in) { 05799 val = strsep(&in, "\r\n"); /* mark start and end of line */ 05800 if (in && *in == '\n') { /* remove trailing \n if any */ 05801 in++; 05802 } 05803 ast_trim_blanks(val); 05804 ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val); 05805 if (ast_strlen_zero(val)) { 05806 /* empty line */ 05807 if (in_data) { 05808 /* close data in Opaque mode */ 05809 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05810 in_data = 0; 05811 } 05812 05813 if (inobj) { 05814 /* close block */ 05815 ast_str_append(out, 0, xml ? " /></response>\n" : 05816 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05817 inobj = 0; 05818 ao2_ref(vco, -1); 05819 vco = NULL; 05820 } 05821 continue; 05822 } 05823 05824 if (!inobj) { 05825 /* start new block */ 05826 if (xml) { 05827 ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype); 05828 } 05829 vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn); 05830 inobj = 1; 05831 } 05832 05833 if (in_data) { 05834 /* Process data field in Opaque mode. This is a 05835 * followup, so we re-add line feeds. */ 05836 ast_str_append(out, 0, xml ? "\n" : "<br>\n"); 05837 xml_copy_escape(out, val, 0); /* data field */ 05838 continue; 05839 } 05840 05841 /* We expect "Name: value" line here */ 05842 var = strsep(&val, ":"); 05843 if (val) { 05844 /* found the field name */ 05845 val = ast_skip_blanks(val); 05846 ast_trim_blanks(var); 05847 } else { 05848 /* field name not found, switch to opaque mode */ 05849 val = var; 05850 var = "Opaque-data"; 05851 in_data = 1; 05852 } 05853 05854 05855 ast_str_append(out, 0, xml ? " " : "<tr><td>"); 05856 if ((vc = ao2_find(vco, var, 0))) { 05857 vc->count++; 05858 } else { 05859 /* Create a new entry for this one */ 05860 vc = ao2_alloc(sizeof(*vc), NULL); 05861 vc->varname = var; 05862 vc->count = 1; 05863 ao2_link(vco, vc); 05864 } 05865 05866 xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */ 05867 if (vc->count > 1) { 05868 ast_str_append(out, 0, "-%d", vc->count); 05869 } 05870 ao2_ref(vc, -1); 05871 ast_str_append(out, 0, xml ? "='" : "</td><td>"); 05872 xml_copy_escape(out, val, 0); /* data field */ 05873 if (!in_data || !*in) { 05874 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05875 } 05876 } 05877 05878 if (inobj) { 05879 ast_str_append(out, 0, xml ? " /></response>\n" : 05880 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05881 ao2_ref(vco, -1); 05882 } 05883 }
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 6587 of file manager.c.
Referenced by __init_manager(), handle_manager_show_settings(), 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] |
int registered = 0 [static] |
const char* words[AST_MAX_CMD_LEN] |
Definition at line 929 of file manager.c.
Referenced by check_blacklist().