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