#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 |
| In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data. More... | |
| struct | mansession_session |
| struct | mansession_session::mansession_datastores |
| struct | permalias |
| struct | users |
| list of users found in the config file More... | |
| struct | variable_count |
Defines | |
| #define | ASTMAN_APPEND_BUF_INITSIZE 256 |
| initial allocated size for the astman_append_buf | |
| #define | DEFAULT_REALM "asterisk" |
| #define | FORMAT " %-25.25s %-15.15s\n" |
| #define | FORMAT2 " %-25.25s %-15d\n" |
| #define | GET_HEADER_FIRST_MATCH 0 |
| #define | GET_HEADER_LAST_MATCH 1 |
| #define | GET_HEADER_SKIP_EMPTY 2 |
| #define | HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" |
| #define | HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" |
| #define | HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" |
| #define | MANAGER_EVENT_BUF_INITSIZE 256 |
| #define | MAX_BLACKLIST_CMD_LEN 2 |
| Descriptor for a manager session, either on the AMI socket or over HTTP. | |
| #define | MSG_MOREDATA ((char *)astman_send_response) |
| #define | ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" |
| #define | TEST_STRING "<form action=\"manager\" method=\"post\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----></option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n" |
Enumerations | |
| enum | add_filter_result { FILTER_SUCCESS, FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL } |
| enum | error_type { UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT, FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT, FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND } |
| enum | output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML } |
Functions | |
| int | __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...) |
| static const char * | __astman_get_header (const struct message *m, char *var, int mode) |
| Return a matching header value. | |
| static void | __fini_actions (void) |
| static void | __fini_all_events (void) |
| static void | __fini_channelvars (void) |
| static void | __fini_manager_hooks (void) |
| static void | __fini_users (void) |
| static void | __init_actions (void) |
| static void | __init_all_events (void) |
| static void | __init_astman_append_buf (void) |
| thread local buffer for astman_append | |
| static void | __init_channelvars (void) |
| static int | __init_manager (int reload) |
| static void | __init_manager_event_buf (void) |
| static void | __init_manager_event_funcbuf (void) |
| static void | __init_manager_hooks (void) |
| static void | __init_userevent_buf (void) |
| static void | __init_users (void) |
| static int | action_aocmessage (struct mansession *s, const struct message *m) |
| static int | action_atxfer (struct mansession *s, const struct message *m) |
| static int | action_challenge (struct mansession *s, const struct message *m) |
| static int | action_command (struct mansession *s, const struct message *m) |
| Manager command "command" - execute CLI command. | |
| static int | action_coresettings (struct mansession *s, const struct message *m) |
| Show PBX core settings information. | |
| static int | action_coreshowchannels (struct mansession *s, const struct message *m) |
| Manager command "CoreShowChannels" - List currently defined channels and some information about them. | |
| static int | action_corestatus (struct mansession *s, const struct message *m) |
| Show PBX core status information. | |
| static int | action_createconfig (struct mansession *s, const struct message *m) |
| static void | action_destroy (void *obj) |
| static int | action_events (struct mansession *s, const struct message *m) |
| static int | action_extensionstate (struct mansession *s, const struct message *m) |
| static int | action_filter (struct mansession *s, const struct message *m) |
| static struct manager_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) |
| events are appended to a queue from where they can be dispatched to clients. | |
| int | ast_hook_send_action (struct manager_custom_hook *hook, const char *msg) |
| access for hooks to send action messages to ami | |
| static int | ast_instring (const char *bigstr, const char *smallstr, const char delim) |
| int | ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description) |
| register a new command with manager, including online help. This is the preferred way to register a manager command | |
| void | ast_manager_register_hook (struct manager_custom_hook *hook) |
| Add a custom hook to be called when an event is fired. | |
| static int | ast_manager_register_struct (struct manager_action *act) |
| int | ast_manager_unregister (char *action) |
| support functions to register/unregister AMI action handlers, | |
| void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
| Delete a custom hook to be called when an event is fired. | |
| void | astman_append (struct mansession *s, const char *fmt,...) |
| static void | astman_append_json (struct mansession *s, const char *str) |
| int | astman_datastore_add (struct mansession *s, struct ast_datastore *datastore) |
| Add a datastore to a session. | |
| struct ast_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) |
| send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
| static void | astman_start_ack (struct mansession *s, const struct message *m) |
| int | astman_verify_session_readpermissions (uint32_t ident, int perm) |
| Verify a session's read permissions against a permission mask. | |
| int | astman_verify_session_writepermissions (uint32_t ident, int perm) |
| Verify a session's write permissions against a permission mask. | |
| static int | auth_http_callback (struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, struct sockaddr_in *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | auth_manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | auth_mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | auth_rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | authenticate (struct mansession *s, const struct message *m) |
| static const char * | authority_to_str (int authority, struct ast_str **res) |
| Convert authority code to a list of options. | |
| static int | blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
| static struct mansession_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 | 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 char * | handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list commands. | |
| static char * | handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list connected. | |
| static char * | handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list eventq. | |
| static enum error_type | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn) |
| helper function for action_updateconfig | |
| int | init_manager (void) |
| Called by Asterisk initialization. | |
| static void | json_escape (char *out, const char *in) |
| static void | load_channelvars (struct ast_variable *var) |
| static struct ast_variable * | man_do_variable_value (struct ast_variable *head, const char *hdr_val) |
| static enum add_filter_result | manager_add_filter (const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters) |
| static int | manager_displayconnects (struct mansession_session *session) |
| Get displayconnects config option. | |
| static int | manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | manager_modulecheck (struct mansession *s, const struct message *m) |
| Manager function to check if module is loaded. | |
| static int | manager_moduleload (struct mansession *s, const struct message *m) |
| static int | manager_state_cb (const char *context, const char *exten, enum ast_extension_states state, void *data) |
| static int | mansession_cmp_fn (void *obj, void *arg, int flags) |
| static struct sockaddr_in * | mansession_encode_sin_local (const struct mansession *s, struct sockaddr_in *sin_local) |
| static enum ast_security_event_transport_type | mansession_get_transport (const struct mansession *s) |
| static void | mansession_lock (struct mansession *s) |
| Lock the 'mansession' structure. | |
| static void | mansession_unlock (struct mansession *s) |
| Unlock the 'mansession' structure. | |
| static int | match_filter (struct mansession *s, char *eventdata) |
| static int | mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| static int | process_events (struct mansession *s) |
| static int | process_message (struct mansession *s, const struct message *m) |
| Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed. | |
| static void | process_output (struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format) |
| static void | purge_events (void) |
| static void | purge_old_stuff (void *data) |
| cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most | |
| static void | purge_sessions (int n_max) |
| remove at most n_max stale session from the list. | |
| static int | rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers) |
| int | reload_manager (void) |
| Called by Asterisk module functions and the CLI command. | |
| static void | report_auth_success (const struct mansession *s) |
| static void | report_failed_acl (const struct mansession *s, const char *username) |
| static void | report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response) |
| static void | report_inval_password (const struct mansession *s, const char *username) |
| static void | report_invalid_user (const struct mansession *s, const char *username) |
| static void | report_req_bad_format (const struct mansession *s, const char *action) |
| static void | report_req_not_allowed (const struct mansession *s, const char *action) |
| static void | report_session_limit (const struct mansession *s) |
| static int | send_string (struct mansession *s, char *string) |
| static void | session_destroy (struct mansession_session *s) |
| static void | session_destructor (void *obj) |
| static void * | session_do (void *data) |
| The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ). | |
| static int | set_eventmask (struct mansession *s, const char *eventmask) |
| Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm. | |
| static int | strings_to_mask (const char *string) |
| static struct mansession_session * | unref_mansession (struct mansession_session *s) |
| Unreference manager session object. If no more references, then go ahead and delete it. | |
| static int | variable_count_cmp_fn (void *obj, void *vstr, int flags) |
| static int | variable_count_hash_fn (const void *vvc, const int flags) |
| static int | whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
| static void | xml_copy_escape (struct ast_str **out, const char *src, int mode) |
| static void | xml_translate (struct ast_str **out, char *in, struct ast_variable *get_vars, enum output_format format) |
| Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'. | |
Variables | |
| static int | allowmultiplelogin = 1 |
| static struct ast_http_uri | amanageruri |
| static struct ast_http_uri | amanagerxmluri |
| static struct ast_tcptls_session_args | ami_desc |
| static struct ast_tls_config | ami_tls_cfg |
| static struct ast_tcptls_session_args | amis_desc |
| static struct ast_http_uri | arawmanuri |
| static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
| static int | authlimit |
| static int | authtimeout |
| static int | block_sockets |
| static int | broken_events_action = 0 |
| static struct ast_cli_entry | cli_manager [] |
| struct { | |
| const char * words [AST_MAX_CMD_LEN] | |
| } | command_blacklist [] |
| static const char *const | contenttype [] |
| static int | displayconnects = 1 |
| static char | global_realm [MAXHOSTNAMELEN] |
| static int | httptimeout = 60 |
| static char * | manager_channelvars |
| static int | manager_debug = 0 |
| static int | manager_enabled = 0 |
| static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } |
| static struct ast_threadstorage | manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } |
| static struct ast_http_uri | manageruri |
| static struct ast_http_uri | managerxmluri |
| static struct permalias | perms [] |
| static struct ast_http_uri | rawmanuri |
| static int | registered = 0 |
| static struct ao2_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 |
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 5457 of file manager.c.
05457 { 05458 FORMAT_RAW, 05459 FORMAT_HTML, 05460 FORMAT_XML, 05461 };
| static int __init_manager | ( | int | reload | ) | [static] |
Definition at line 6635 of file manager.c.
References ast_manager_user::a1_hash, action_aocmessage(), action_atxfer(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ami_tls_cfg, ao2_container_alloc, ao2_t_callback, ao2_t_ref, append_event(), ARRAY_LEN, ast_append_ha(), ast_calloc, ast_category_browse(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_debug, ast_extension_state_add(), ast_free, ast_free_ha(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, ast_log(), ast_manager_register_xml, ast_md5_hash(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_sockaddr_setnull(), ast_sockaddr_to_sin, ast_ssl_setup(), ast_strdup, ast_strlen_zero(), ast_tcptls_server_start(), ast_tcptls_server_stop(), ast_tls_read_conf(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_manager_user::blackfilters, block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, DEFAULT_MANAGER_TLS_PORT, DEFAULT_REALM, ast_manager_user::displayconnects, ast_tls_config::enabled, EVENT_FLAG_AOC, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, free_channelvars(), get_manager_by_name_locked(), get_perm(), global_realm, ast_manager_user::ha, inet_aton(), ast_manager_user::keep, ast_variable::lineno, load_channelvars(), ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_add_filter(), manager_event, manager_modulecheck(), manager_moduleload(), manager_state_cb(), mansession_cmp_fn(), ast_variable::name, ast_variable::next, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_tls_config::pvtfile, ast_manager_user::readperm, S_OR, ast_manager_user::secret, ast_tcptls_session_args::tls_cfg, ast_manager_user::username, value, ast_variable::value, var, ast_manager_user::whitefilters, ast_manager_user::writeperm, and ast_manager_user::writetimeout.
Referenced by init_manager(), and reload_manager().
06636 { 06637 struct ast_config *ucfg = NULL, *cfg = NULL; 06638 const char *val; 06639 char *cat = NULL; 06640 int newhttptimeout = 60; 06641 struct ast_manager_user *user = NULL; 06642 struct ast_variable *var; 06643 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 06644 char a1[256]; 06645 char a1_hash[256]; 06646 struct sockaddr_in ami_desc_local_address_tmp = { 0, }; 06647 struct sockaddr_in amis_desc_local_address_tmp = { 0, }; 06648 int tls_was_enabled = 0; 06649 06650 manager_enabled = 0; 06651 06652 if (!registered) { 06653 /* Register default actions */ 06654 ast_manager_register_xml("Ping", 0, action_ping); 06655 ast_manager_register_xml("Events", 0, action_events); 06656 ast_manager_register_xml("Logoff", 0, action_logoff); 06657 ast_manager_register_xml("Login", 0, action_login); 06658 ast_manager_register_xml("Challenge", 0, action_challenge); 06659 ast_manager_register_xml("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup); 06660 ast_manager_register_xml("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status); 06661 ast_manager_register_xml("Setvar", EVENT_FLAG_CALL, action_setvar); 06662 ast_manager_register_xml("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar); 06663 ast_manager_register_xml("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig); 06664 ast_manager_register_xml("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson); 06665 ast_manager_register_xml("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig); 06666 ast_manager_register_xml("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig); 06667 ast_manager_register_xml("ListCategories", EVENT_FLAG_CONFIG, action_listcategories); 06668 ast_manager_register_xml("Redirect", EVENT_FLAG_CALL, action_redirect); 06669 ast_manager_register_xml("Atxfer", EVENT_FLAG_CALL, action_atxfer); 06670 ast_manager_register_xml("Originate", EVENT_FLAG_ORIGINATE, action_originate); 06671 ast_manager_register_xml("Command", EVENT_FLAG_COMMAND, action_command); 06672 ast_manager_register_xml("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate); 06673 ast_manager_register_xml("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout); 06674 ast_manager_register_xml("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus); 06675 ast_manager_register_xml("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount); 06676 ast_manager_register_xml("ListCommands", 0, action_listcommands); 06677 ast_manager_register_xml("SendText", EVENT_FLAG_CALL, action_sendtext); 06678 ast_manager_register_xml("UserEvent", EVENT_FLAG_USER, action_userevent); 06679 ast_manager_register_xml("WaitEvent", 0, action_waitevent); 06680 ast_manager_register_xml("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings); 06681 ast_manager_register_xml("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus); 06682 ast_manager_register_xml("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload); 06683 ast_manager_register_xml("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels); 06684 ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload); 06685 ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck); 06686 ast_manager_register_xml("AOCMessage", EVENT_FLAG_AOC, action_aocmessage); 06687 ast_manager_register_xml("Filter", EVENT_FLAG_SYSTEM, action_filter); 06688 06689 ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager)); 06690 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 06691 registered = 1; 06692 /* Append placeholder event so master_eventq never runs dry */ 06693 append_event("Event: Placeholder\r\n\r\n", 0); 06694 } 06695 if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) { 06696 return 0; 06697 } 06698 06699 displayconnects = 1; 06700 broken_events_action = 0; 06701 authtimeout = 30; 06702 authlimit = 50; 06703 manager_debug = 0; /* Debug disabled by default */ 06704 06705 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 06706 ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n"); 06707 return 0; 06708 } 06709 06710 /* default values */ 06711 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm)); 06712 ast_sockaddr_setnull(&ami_desc.local_address); 06713 ast_sockaddr_setnull(&amis_desc.local_address); 06714 06715 ami_desc_local_address_tmp.sin_family = AF_INET; 06716 amis_desc_local_address_tmp.sin_family = AF_INET; 06717 06718 ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT); 06719 06720 tls_was_enabled = (reload && ami_tls_cfg.enabled); 06721 06722 ami_tls_cfg.enabled = 0; 06723 if (ami_tls_cfg.certfile) { 06724 ast_free(ami_tls_cfg.certfile); 06725 } 06726 ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE); 06727 if (ami_tls_cfg.pvtfile) { 06728 ast_free(ami_tls_cfg.pvtfile); 06729 } 06730 ami_tls_cfg.pvtfile = ast_strdup(""); 06731 if (ami_tls_cfg.cipher) { 06732 ast_free(ami_tls_cfg.cipher); 06733 } 06734 ami_tls_cfg.cipher = ast_strdup(""); 06735 06736 free_channelvars(); 06737 06738 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 06739 val = var->value; 06740 06741 if (!ast_tls_read_conf(&ami_tls_cfg, &amis_desc, var->name, val)) { 06742 continue; 06743 } 06744 06745 if (!strcasecmp(var->name, "enabled")) { 06746 manager_enabled = ast_true(val); 06747 } else if (!strcasecmp(var->name, "block-sockets")) { 06748 block_sockets = ast_true(val); 06749 } else if (!strcasecmp(var->name, "webenabled")) { 06750 webmanager_enabled = ast_true(val); 06751 } else if (!strcasecmp(var->name, "port")) { 06752 ami_desc_local_address_tmp.sin_port = htons(atoi(val)); 06753 } else if (!strcasecmp(var->name, "bindaddr")) { 06754 if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) { 06755 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 06756 memset(&ami_desc_local_address_tmp.sin_addr, 0, 06757 sizeof(ami_desc_local_address_tmp.sin_addr)); 06758 } 06759 } else if (!strcasecmp(var->name, "brokeneventsaction")) { 06760 broken_events_action = ast_true(val); 06761 } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 06762 allowmultiplelogin = ast_true(val); 06763 } else if (!strcasecmp(var->name, "displayconnects")) { 06764 displayconnects = ast_true(val); 06765 } else if (!strcasecmp(var->name, "timestampevents")) { 06766 timestampevents = ast_true(val); 06767 } else if (!strcasecmp(var->name, "debug")) { 06768 manager_debug = ast_true(val); 06769 } else if (!strcasecmp(var->name, "httptimeout")) { 06770 newhttptimeout = atoi(val); 06771 } else if (!strcasecmp(var->name, "authtimeout")) { 06772 int timeout = atoi(var->value); 06773 06774 if (timeout < 1) { 06775 ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value); 06776 } else { 06777 authtimeout = timeout; 06778 } 06779 } else if (!strcasecmp(var->name, "authlimit")) { 06780 int limit = atoi(var->value); 06781 06782 if (limit < 1) { 06783 ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value); 06784 } else { 06785 authlimit = limit; 06786 } 06787 } else if (!strcasecmp(var->name, "channelvars")) { 06788 load_channelvars(var); 06789 } else { 06790 ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", 06791 var->name, val); 06792 } 06793 } 06794 06795 ast_sockaddr_to_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 06796 06797 /* if the amis address has not been set, default is the same as non secure ami */ 06798 if (!amis_desc_local_address_tmp.sin_addr.s_addr) { 06799 amis_desc_local_address_tmp.sin_addr = 06800 ami_desc_local_address_tmp.sin_addr; 06801 } 06802 06803 if (!amis_desc_local_address_tmp.sin_port) { 06804 amis_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_TLS_PORT); 06805 } 06806 06807 if (manager_enabled) { 06808 ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp); 06809 ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp); 06810 } 06811 06812 AST_RWLIST_WRLOCK(&users); 06813 06814 /* First, get users from users.conf */ 06815 ucfg = ast_config_load2("users.conf", "manager", config_flags); 06816 if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) { 06817 const char *hasmanager; 06818 int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager")); 06819 06820 while ((cat = ast_category_browse(ucfg, cat))) { 06821 if (!strcasecmp(cat, "general")) { 06822 continue; 06823 } 06824 06825 hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager"); 06826 if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) { 06827 const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret"); 06828 const char *user_read = ast_variable_retrieve(ucfg, cat, "read"); 06829 const char *user_write = ast_variable_retrieve(ucfg, cat, "write"); 06830 const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects"); 06831 const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout"); 06832 06833 /* Look for an existing entry, 06834 * if none found - create one and add it to the list 06835 */ 06836 if (!(user = get_manager_by_name_locked(cat))) { 06837 if (!(user = ast_calloc(1, sizeof(*user)))) { 06838 break; 06839 } 06840 06841 /* Copy name over */ 06842 ast_copy_string(user->username, cat, sizeof(user->username)); 06843 /* Insert into list */ 06844 AST_LIST_INSERT_TAIL(&users, user, list); 06845 user->ha = NULL; 06846 user->keep = 1; 06847 user->readperm = -1; 06848 user->writeperm = -1; 06849 /* Default displayconnect from [general] */ 06850 user->displayconnects = displayconnects; 06851 user->writetimeout = 100; 06852 } 06853 06854 if (!user_secret) { 06855 user_secret = ast_variable_retrieve(ucfg, "general", "secret"); 06856 } 06857 if (!user_read) { 06858 user_read = ast_variable_retrieve(ucfg, "general", "read"); 06859 } 06860 if (!user_write) { 06861 user_write = ast_variable_retrieve(ucfg, "general", "write"); 06862 } 06863 if (!user_displayconnects) { 06864 user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); 06865 } 06866 if (!user_writetimeout) { 06867 user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); 06868 } 06869 06870 if (!ast_strlen_zero(user_secret)) { 06871 if (user->secret) { 06872 ast_free(user->secret); 06873 } 06874 user->secret = ast_strdup(user_secret); 06875 } 06876 06877 if (user_read) { 06878 user->readperm = get_perm(user_read); 06879 } 06880 if (user_write) { 06881 user->writeperm = get_perm(user_write); 06882 } 06883 if (user_displayconnects) { 06884 user->displayconnects = ast_true(user_displayconnects); 06885 } 06886 if (user_writetimeout) { 06887 int value = atoi(user_writetimeout); 06888 if (value < 100) { 06889 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno); 06890 } else { 06891 user->writetimeout = value; 06892 } 06893 } 06894 } 06895 } 06896 ast_config_destroy(ucfg); 06897 } 06898 06899 /* cat is NULL here in any case */ 06900 06901 while ((cat = ast_category_browse(cfg, cat))) { 06902 struct ast_ha *oldha; 06903 06904 if (!strcasecmp(cat, "general")) { 06905 continue; 06906 } 06907 06908 /* Look for an existing entry, if none found - create one and add it to the list */ 06909 if (!(user = get_manager_by_name_locked(cat))) { 06910 if (!(user = ast_calloc(1, sizeof(*user)))) { 06911 break; 06912 } 06913 /* Copy name over */ 06914 ast_copy_string(user->username, cat, sizeof(user->username)); 06915 06916 user->ha = NULL; 06917 user->readperm = 0; 06918 user->writeperm = 0; 06919 /* Default displayconnect from [general] */ 06920 user->displayconnects = displayconnects; 06921 user->writetimeout = 100; 06922 user->whitefilters = ao2_container_alloc(1, NULL, NULL); 06923 user->blackfilters = ao2_container_alloc(1, NULL, NULL); 06924 06925 /* Insert into list */ 06926 AST_RWLIST_INSERT_TAIL(&users, user, list); 06927 } else { 06928 ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 06929 ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 06930 } 06931 06932 /* Make sure we keep this user and don't destroy it during cleanup */ 06933 user->keep = 1; 06934 oldha = user->ha; 06935 user->ha = NULL; 06936 06937 var = ast_variable_browse(cfg, cat); 06938 for (; var; var = var->next) { 06939 if (!strcasecmp(var->name, "secret")) { 06940 if (user->secret) { 06941 ast_free(user->secret); 06942 } 06943 user->secret = ast_strdup(var->value); 06944 } else if (!strcasecmp(var->name, "deny") || 06945 !strcasecmp(var->name, "permit")) { 06946 user->ha = ast_append_ha(var->name, var->value, user->ha, NULL); 06947 } else if (!strcasecmp(var->name, "read") ) { 06948 user->readperm = get_perm(var->value); 06949 } else if (!strcasecmp(var->name, "write") ) { 06950 user->writeperm = get_perm(var->value); 06951 } else if (!strcasecmp(var->name, "displayconnects") ) { 06952 user->displayconnects = ast_true(var->value); 06953 } else if (!strcasecmp(var->name, "writetimeout")) { 06954 int value = atoi(var->value); 06955 if (value < 100) { 06956 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); 06957 } else { 06958 user->writetimeout = value; 06959 } 06960 } else if (!strcasecmp(var->name, "eventfilter")) { 06961 const char *value = var->value; 06962 manager_add_filter(value, user->whitefilters, user->blackfilters); 06963 } else { 06964 ast_debug(1, "%s is an unknown option.\n", var->name); 06965 } 06966 } 06967 ast_free_ha(oldha); 06968 } 06969 ast_config_destroy(cfg); 06970 06971 /* Perform cleanup - essentially prune out old users that no longer exist */ 06972 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 06973 if (user->keep) { /* valid record. clear flag for the next round */ 06974 user->keep = 0; 06975 06976 /* Calculate A1 for Digest auth */ 06977 snprintf(a1, sizeof(a1), "%s:%s:%s", user->username, global_realm, user->secret); 06978 ast_md5_hash(a1_hash,a1); 06979 if (user->a1_hash) { 06980 ast_free(user->a1_hash); 06981 } 06982 user->a1_hash = ast_strdup(a1_hash); 06983 continue; 06984 } 06985 /* We do not need to keep this user so take them out of the list */ 06986 AST_RWLIST_REMOVE_CURRENT(list); 06987 ast_debug(4, "Pruning user '%s'\n", user->username); 06988 /* Free their memory now */ 06989 if (user->a1_hash) { 06990 ast_free(user->a1_hash); 06991 } 06992 if (user->secret) { 06993 ast_free(user->secret); 06994 } 06995 ao2_t_callback(user->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 06996 ao2_t_callback(user->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 06997 ao2_t_ref(user->whitefilters, -1, "decrement ref for white container, should be last one"); 06998 ao2_t_ref(user->blackfilters, -1, "decrement ref for black container, should be last one"); 06999 ast_free_ha(user->ha); 07000 ast_free(user); 07001 } 07002 AST_RWLIST_TRAVERSE_SAFE_END; 07003 07004 AST_RWLIST_UNLOCK(&users); 07005 07006 if (!reload) { 07007 /* If you have a NULL hash fn, you only need a single bucket */ 07008 sessions = ao2_container_alloc(1, NULL, mansession_cmp_fn); 07009 } 07010 07011 if (webmanager_enabled && manager_enabled) { 07012 if (!webregged) { 07013 07014 ast_http_uri_link(&rawmanuri); 07015 ast_http_uri_link(&manageruri); 07016 ast_http_uri_link(&managerxmluri); 07017 07018 ast_http_uri_link(&arawmanuri); 07019 ast_http_uri_link(&amanageruri); 07020 ast_http_uri_link(&amanagerxmluri); 07021 webregged = 1; 07022 } 07023 } else { 07024 if (webregged) { 07025 ast_http_uri_unlink(&rawmanuri); 07026 ast_http_uri_unlink(&manageruri); 07027 ast_http_uri_unlink(&managerxmluri); 07028 07029 ast_http_uri_unlink(&arawmanuri); 07030 ast_http_uri_unlink(&amanageruri); 07031 ast_http_uri_unlink(&amanagerxmluri); 07032 webregged = 0; 07033 } 07034 } 07035 07036 if (newhttptimeout > 0) { 07037 httptimeout = newhttptimeout; 07038 } 07039 07040 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled"); 07041 07042 ast_tcptls_server_start(&ami_desc); 07043 if (tls_was_enabled && !ami_tls_cfg.enabled) { 07044 ast_tcptls_server_stop(&amis_desc); 07045 } else if (ast_ssl_setup(amis_desc.tls_cfg)) { 07046 ast_tcptls_server_start(&amis_desc); 07047 } 07048 return 0; 07049 }
| int astman_datastore_add | ( | struct mansession * | s, | |
| struct ast_datastore * | datastore | |||
| ) |
Add a datastore to a session.
| 0 | success | |
| non-zero | failure |
Definition at line 7072 of file manager.c.
References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.
07073 { 07074 AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry); 07075 07076 return 0; 07077 }
| struct ast_datastore* astman_datastore_find | ( | struct mansession * | s, | |
| const struct ast_datastore_info * | info, | |||
| const char * | uid | |||
| ) | [read] |
Find a datastore on a session.
| pointer | to the datastore if found | |
| NULL | if not found |
Definition at line 7084 of file manager.c.
References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, mansession_session::datastores, ast_datastore::info, mansession::session, and ast_datastore::uid.
07085 { 07086 struct ast_datastore *datastore = NULL; 07087 07088 if (info == NULL) 07089 return NULL; 07090 07091 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) { 07092 if (datastore->info != info) { 07093 continue; 07094 } 07095 07096 if (uid == NULL) { 07097 /* matched by type only */ 07098 break; 07099 } 07100 07101 if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) { 07102 /* Matched by type AND uid */ 07103 break; 07104 } 07105 } 07106 AST_LIST_TRAVERSE_SAFE_END; 07107 07108 return datastore; 07109 }
| int astman_datastore_remove | ( | struct mansession * | s, | |
| struct ast_datastore * | datastore | |||
| ) |
Remove a datastore from a session.
| 0 | success | |
| non-zero | failure |
Definition at line 7079 of file manager.c.
References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.
07080 { 07081 return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1; 07082 }
| int astman_is_authed | ( | uint32_t | ident | ) |
Determinie if a manager session ident is authenticated.
Definition at line 5533 of file manager.c.
References ao2_unlock, mansession_session::authenticated, find_session(), and unref_mansession().
Referenced by http_post_callback(), and static_callback().
05534 { 05535 int authed; 05536 struct mansession_session *session; 05537 05538 if (!(session = find_session(ident, 0))) 05539 return 0; 05540 05541 authed = (session->authenticated != 0); 05542 05543 ao2_unlock(session); 05544 unref_mansession(session); 05545 05546 return authed; 05547 }
| int astman_verify_session_readpermissions | ( | uint32_t | ident, | |
| int | perm | |||
| ) |
Verify a session's read permissions against a permission mask.
| ident | session identity | |
| perm | permission mask to verify |
| 1 | if the session has the permission mask capabilities | |
| 0 | otherwise |
Definition at line 5549 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::readperm, and unref_mansession().
05550 { 05551 int result = 0; 05552 struct mansession_session *session; 05553 struct ao2_iterator i; 05554 05555 if (ident == 0) { 05556 return 0; 05557 } 05558 05559 i = ao2_iterator_init(sessions, 0); 05560 while ((session = ao2_iterator_next(&i))) { 05561 ao2_lock(session); 05562 if ((session->managerid == ident) && (session->readperm & perm)) { 05563 result = 1; 05564 ao2_unlock(session); 05565 unref_mansession(session); 05566 break; 05567 } 05568 ao2_unlock(session); 05569 unref_mansession(session); 05570 } 05571 ao2_iterator_destroy(&i); 05572 return result; 05573 }
| int astman_verify_session_writepermissions | ( | uint32_t | ident, | |
| int | perm | |||
| ) |
Verify a session's write permissions against a permission mask.
| ident | session identity | |
| perm | permission mask to verify |
| 1 | if the session has the permission mask capabilities, otherwise 0 | |
| 0 | otherwise |
Definition at line 5575 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, unref_mansession(), and mansession_session::writeperm.
Referenced by http_post_callback().
05576 { 05577 int result = 0; 05578 struct mansession_session *session; 05579 struct ao2_iterator i; 05580 05581 if (ident == 0) { 05582 return 0; 05583 } 05584 05585 i = ao2_iterator_init(sessions, 0); 05586 while ((session = ao2_iterator_next(&i))) { 05587 ao2_lock(session); 05588 if ((session->managerid == ident) && (session->writeperm & perm)) { 05589 result = 1; 05590 ao2_unlock(session); 05591 unref_mansession(session); 05592 break; 05593 } 05594 ao2_unlock(session); 05595 unref_mansession(session); 05596 } 05597 ao2_iterator_destroy(&i); 05598 return result; 05599 }
| static int auth_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| enum ast_http_method | method, | |||
| enum output_format | format, | |||
| struct sockaddr_in * | remote_address, | |||
| const char * | uri, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6079 of file manager.c.
References ast_manager_user::a1_hash, ao2_lock, ao2_unlock, ARRAY_LEN, ast_apply_ha(), ast_copy_string(), ast_debug, ast_free, ast_get_http_method(), ast_http_auth(), ast_http_error(), AST_HTTP_GET, ast_http_get_post_vars(), AST_HTTP_HEAD, AST_HTTP_POST, ast_http_send(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_malloc, ast_md5_hash(), ast_mutex_destroy, ast_mutex_init, ast_parse_digest(), ast_random(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_str_append(), ast_str_create(), ast_string_field_free_memory, ast_string_field_init, ast_strlen_zero(), ast_variables_destroy(), ast_verb, mansession_session::authenticated, build_mansession(), ast_http_digest::cnonce, mansession_session::datastores, ast_manager_user::displayconnects, errno, mansession_session::f, mansession::f, mansession_session::fd, mansession::fd, find_session_by_nonce(), FORMAT_HTML, FORMAT_XML, get_manager_by_name_locked(), global_realm, grab_last(), ast_manager_user::ha, message::hdrcount, message::headers, mansession_session::last_ev, mansession::lock, LOG_NOTICE, LOG_WARNING, mansession_session::managerid, ast_variable::name, mansession_session::nc, ast_http_digest::nc, mansession_session::needdestroy, ast_variable::next, ast_http_digest::nonce, mansession_session::noncetime, mansession_session::oldnonce, process_message(), process_output(), ast_http_digest::qop, mansession_session::readperm, ast_manager_user::readperm, ast_http_digest::response, mansession::session, session_destroy(), mansession_session::sessionstart, mansession_session::sessiontimeout, mansession_session::sin, ast_http_digest::uri, mansession_session::username, ast_manager_user::username, ast_http_digest::username, ast_variable::value, mansession_session::writeperm, ast_manager_user::writeperm, mansession_session::writetimeout, and ast_manager_user::writetimeout.
Referenced by auth_manager_http_callback(), auth_mxml_http_callback(), and auth_rawman_http_callback().
06085 { 06086 struct mansession_session *session = NULL; 06087 struct mansession s = { .session = NULL, .tcptls_session = ser }; 06088 struct ast_variable *v, *params = get_params; 06089 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 06090 struct ast_str *http_header = NULL, *out = NULL; 06091 size_t result_size = 512; 06092 struct message m = { 0 }; 06093 unsigned int idx; 06094 size_t hdrlen; 06095 06096 time_t time_now = time(NULL); 06097 unsigned long nonce = 0, nc; 06098 struct ast_http_digest d = { NULL, }; 06099 struct ast_manager_user *user = NULL; 06100 int stale = 0; 06101 char resp_hash[256]=""; 06102 /* Cache for user data */ 06103 char u_username[80]; 06104 int u_readperm; 06105 int u_writeperm; 06106 int u_writetimeout; 06107 int u_displayconnects; 06108 struct ast_sockaddr addr; 06109 06110 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 06111 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 06112 return -1; 06113 } 06114 06115 /* Find "Authorization: " header */ 06116 for (v = headers; v; v = v->next) { 06117 if (!strcasecmp(v->name, "Authorization")) { 06118 break; 06119 } 06120 } 06121 06122 if (!v || ast_strlen_zero(v->value)) { 06123 goto out_401; /* Authorization Header not present - send auth request */ 06124 } 06125 06126 /* Digest found - parse */ 06127 if (ast_string_field_init(&d, 128)) { 06128 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06129 return -1; 06130 } 06131 06132 if (ast_parse_digest(v->value, &d, 0, 1)) { 06133 /* Error in Digest - send new one */ 06134 nonce = 0; 06135 goto out_401; 06136 } 06137 if (sscanf(d.nonce, "%30lx", &nonce) != 1) { 06138 ast_log(LOG_WARNING, "Received incorrect nonce in Digest <%s>\n", d.nonce); 06139 nonce = 0; 06140 goto out_401; 06141 } 06142 06143 AST_RWLIST_WRLOCK(&users); 06144 user = get_manager_by_name_locked(d.username); 06145 if(!user) { 06146 AST_RWLIST_UNLOCK(&users); 06147 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06148 nonce = 0; 06149 goto out_401; 06150 } 06151 06152 ast_sockaddr_from_sin(&addr, remote_address); 06153 /* --- We have User for this auth, now check ACL */ 06154 if (user->ha && !ast_apply_ha(user->ha, &addr)) { 06155 AST_RWLIST_UNLOCK(&users); 06156 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username); 06157 ast_http_error(ser, 403, "Permission denied", "Permission denied\n"); 06158 return -1; 06159 } 06160 06161 /* --- We have auth, so check it */ 06162 06163 /* compute the expected response to compare with what we received */ 06164 { 06165 char a2[256]; 06166 char a2_hash[256]; 06167 char resp[256]; 06168 06169 /* XXX Now request method are hardcoded in A2 */ 06170 snprintf(a2, sizeof(a2), "%s:%s", ast_get_http_method(method), d.uri); 06171 ast_md5_hash(a2_hash, a2); 06172 06173 if (d.qop) { 06174 /* RFC 2617 */ 06175 snprintf(resp, sizeof(resp), "%s:%08lx:%s:%s:auth:%s", user->a1_hash, nonce, d.nc, d.cnonce, a2_hash); 06176 } else { 06177 /* RFC 2069 */ 06178 snprintf(resp, sizeof(resp), "%s:%08lx:%s", user->a1_hash, nonce, a2_hash); 06179 } 06180 ast_md5_hash(resp_hash, resp); 06181 } 06182 06183 if (!d.nonce || strncasecmp(d.response, resp_hash, strlen(resp_hash))) { 06184 /* Something was wrong, so give the client to try with a new challenge */ 06185 AST_RWLIST_UNLOCK(&users); 06186 nonce = 0; 06187 goto out_401; 06188 } 06189 06190 /* 06191 * User are pass Digest authentication. 06192 * Now, cache the user data and unlock user list. 06193 */ 06194 ast_copy_string(u_username, user->username, sizeof(u_username)); 06195 u_readperm = user->readperm; 06196 u_writeperm = user->writeperm; 06197 u_displayconnects = user->displayconnects; 06198 u_writetimeout = user->writetimeout; 06199 AST_RWLIST_UNLOCK(&users); 06200 06201 if (!(session = find_session_by_nonce(d.username, nonce, &stale))) { 06202 /* 06203 * Create new session. 06204 * While it is not in the list we don't need any locking 06205 */ 06206 if (!(session = build_mansession(*remote_address))) { 06207 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 06208 return -1; 06209 } 06210 ao2_lock(session); 06211 06212 ast_copy_string(session->username, u_username, sizeof(session->username)); 06213 session->managerid = nonce; 06214 session->last_ev = grab_last(); 06215 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 06216 06217 session->readperm = u_readperm; 06218 session->writeperm = u_writeperm; 06219 session->writetimeout = u_writetimeout; 06220 06221 if (u_displayconnects) { 06222 ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06223 } 06224 session->noncetime = session->sessionstart = time_now; 06225 session->authenticated = 1; 06226 } else if (stale) { 06227 /* 06228 * Session found, but nonce is stale. 06229 * 06230 * This could be because an old request (w/old nonce) arrived. 06231 * 06232 * This may be as the result of http proxy usage (separate delay or 06233 * multipath) or in a situation where a page was refreshed too quickly 06234 * (seen in Firefox). 06235 * 06236 * In this situation, we repeat the 401 auth with the current nonce 06237 * value. 06238 */ 06239 nonce = session->managerid; 06240 ao2_unlock(session); 06241 stale = 1; 06242 goto out_401; 06243 } else { 06244 sscanf(d.nc, "%30lx", &nc); 06245 if (session->nc >= nc || ((time_now - session->noncetime) > 62) ) { 06246 /* 06247 * Nonce time expired (> 2 minutes) or something wrong with nonce 06248 * counter. 06249 * 06250 * Create new nonce key and resend Digest auth request. Old nonce 06251 * is saved for stale checking... 06252 */ 06253 session->nc = 0; /* Reset nonce counter */ 06254 session->oldnonce = session->managerid; 06255 nonce = session->managerid = ast_random(); 06256 session->noncetime = time_now; 06257 ao2_unlock(session); 06258 stale = 1; 06259 goto out_401; 06260 } else { 06261 session->nc = nc; /* All OK, save nonce counter */ 06262 } 06263 } 06264 06265 06266 /* Reset session timeout. */ 06267 session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5); 06268 ao2_unlock(session); 06269 06270 ast_mutex_init(&s.lock); 06271 s.session = session; 06272 s.fd = mkstemp(template); /* create a temporary file for command output */ 06273 unlink(template); 06274 if (s.fd <= -1) { 06275 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 06276 goto auth_callback_out; 06277 } 06278 s.f = fdopen(s.fd, "w+"); 06279 if (!s.f) { 06280 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 06281 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 06282 close(s.fd); 06283 goto auth_callback_out; 06284 } 06285 06286 if (method == AST_HTTP_POST) { 06287 params = ast_http_get_post_vars(ser, headers); 06288 } 06289 06290 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 06291 hdrlen = strlen(v->name) + strlen(v->value) + 3; 06292 m.headers[m.hdrcount] = ast_malloc(hdrlen); 06293 if (!m.headers[m.hdrcount]) { 06294 /* Allocation failure */ 06295 continue; 06296 } 06297 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 06298 ast_verb(4, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 06299 ++m.hdrcount; 06300 } 06301 06302 if (process_message(&s, &m)) { 06303 if (u_displayconnects) { 06304 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 06305 } 06306 06307 session->needdestroy = 1; 06308 } 06309 06310 /* Free request headers. */ 06311 for (idx = 0; idx < m.hdrcount; ++idx) { 06312 ast_free((void *) m.headers[idx]); 06313 m.headers[idx] = NULL; 06314 } 06315 06316 if (s.f) { 06317 result_size = ftell(s.f); /* Calculate approx. size of result */ 06318 } 06319 06320 http_header = ast_str_create(80); 06321 out = ast_str_create(result_size * 2 + 512); 06322 06323 if (http_header == NULL || out == NULL) { 06324 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 06325 goto auth_callback_out; 06326 } 06327 06328 ast_str_append(&http_header, 0, "Content-type: text/%s\r\n", contenttype[format]); 06329 06330 if (format == FORMAT_XML) { 06331 ast_str_append(&out, 0, "<ajax-response>\n"); 06332 } else if (format == FORMAT_HTML) { 06333 ast_str_append(&out, 0, 06334 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 06335 "<html><head>\r\n" 06336 "<title>Asterisk™ Manager Interface</title>\r\n" 06337 "</head><body style=\"background-color: #ffffff;\">\r\n" 06338 "<form method=\"POST\">\r\n" 06339 "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n" 06340 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n" 06341 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>" 06342 "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n"); 06343 } 06344 06345 process_output(&s, &out, params, format); 06346 06347 if (format == FORMAT_XML) { 06348 ast_str_append(&out, 0, "</ajax-response>\n"); 06349 } else if (format == FORMAT_HTML) { 06350 ast_str_append(&out, 0, "</table></form></body></html>\r\n"); 06351 } 06352 06353 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06354 http_header = out = NULL; 06355 06356 auth_callback_out: 06357 ast_mutex_destroy(&s.lock); 06358 06359 /* Clear resources and unlock manager session */ 06360 if (method == AST_HTTP_POST && params) { 06361 ast_variables_destroy(params); 06362 } 06363 06364 ast_free(http_header); 06365 ast_free(out); 06366 06367 ao2_lock(session); 06368 if (session->f) { 06369 fclose(session->f); 06370 } 06371 session->f = NULL; 06372 session->fd = -1; 06373 ao2_unlock(session); 06374 06375 if (session->needdestroy) { 06376 ast_debug(1, "Need destroy, doing it now!\n"); 06377 session_destroy(session); 06378 } 06379 ast_string_field_free_memory(&d); 06380 return 0; 06381 06382 out_401: 06383 if (!nonce) { 06384 nonce = ast_random(); 06385 } 06386 06387 ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL); 06388 ast_string_field_free_memory(&d); 06389 return 0; 06390 }
| static int auth_manager_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6451 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_HTML, and ast_tcptls_session_instance::remote_address.
06452 { 06453 int retval; 06454 struct sockaddr_in ser_remote_address_tmp; 06455 06456 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06457 retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06458 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06459 return retval; 06460 }
| static int auth_mxml_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6462 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_XML, and ast_tcptls_session_instance::remote_address.
06463 { 06464 int retval; 06465 struct sockaddr_in ser_remote_address_tmp; 06466 06467 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06468 retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06469 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06470 return retval; 06471 }
| static int auth_rawman_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6473 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, auth_http_callback(), FORMAT_RAW, and ast_tcptls_session_instance::remote_address.
06474 { 06475 int retval; 06476 struct sockaddr_in ser_remote_address_tmp; 06477 06478 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06479 retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06480 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06481 return retval; 06482 }
| static struct mansession_session* find_session | ( | uint32_t | ident, | |
| int | incinuse | |||
| ) | [static, read] |
locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket).
Definition at line 5474 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_atomic_fetchadd_int(), mansession_session::inuse, mansession_session::managerid, mansession_session::needdestroy, and unref_mansession().
Referenced by astman_is_authed(), and generic_http_callback().
05475 { 05476 struct mansession_session *session; 05477 struct ao2_iterator i; 05478 05479 if (ident == 0) { 05480 return NULL; 05481 } 05482 05483 i = ao2_iterator_init(sessions, 0); 05484 while ((session = ao2_iterator_next(&i))) { 05485 ao2_lock(session); 05486 if (session->managerid == ident && !session->needdestroy) { 05487 ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0); 05488 break; 05489 } 05490 ao2_unlock(session); 05491 unref_mansession(session); 05492 } 05493 ao2_iterator_destroy(&i); 05494 05495 return session; 05496 }
| static struct mansession_session* find_session_by_nonce | ( | const char * | username, | |
| unsigned long | nonce, | |||
| int * | stale | |||
| ) | [static, read] |
locate an http session in the list. The search keys (nonce) and (username) is value from received "Authorization" http header. As well as in find_session() function, the value of the nonce can't be zero. (0 meansi, that the session used for AMI socket connection). Flag (stale) is set, if client used valid, but old, nonce value.
Definition at line 5507 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, mansession_session::managerid, mansession_session::oldnonce, unref_mansession(), and mansession_session::username.
Referenced by auth_http_callback().
05508 { 05509 struct mansession_session *session; 05510 struct ao2_iterator i; 05511 05512 if (nonce == 0 || username == NULL || stale == NULL) { 05513 return NULL; 05514 } 05515 05516 i = ao2_iterator_init(sessions, 0); 05517 while ((session = ao2_iterator_next(&i))) { 05518 ao2_lock(session); 05519 if (!strcasecmp(session->username, username) && session->managerid == nonce) { 05520 *stale = 0; 05521 break; 05522 } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) { 05523 *stale = 1; 05524 break; 05525 } 05526 ao2_unlock(session); 05527 unref_mansession(session); 05528 } 05529 ao2_iterator_destroy(&i); 05530 return session; 05531 }
| static int generic_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| enum ast_http_method | method, | |||
| enum output_format | format, | |||
| struct sockaddr_in * | remote_address, | |||
| const char * | uri, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 5864 of file manager.c.
References ao2_lock, ao2_unlock, ARRAY_LEN, ast_debug, ast_free, ast_http_error(), AST_HTTP_GET, ast_http_get_cookies(), ast_http_get_post_vars(), AST_HTTP_HEAD, AST_HTTP_POST, ast_http_send(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_malloc, ast_mutex_destroy, ast_mutex_init, AST_PTHREADT_NULL, ast_random(), ast_str_append(), ast_str_create(), ast_variables_destroy(), ast_verb, mansession_session::authenticated, build_mansession(), errno, mansession_session::f, mansession::f, mansession::fd, mansession_session::fd, find_session(), FORMAT_HTML, FORMAT_XML, grab_last(), message::hdrcount, message::headers, mansession_session::inuse, mansession::lock, LOG_WARNING, manager_displayconnects(), mansession_session::managerid, ast_variable::name, mansession_session::needdestroy, ast_variable::next, process_message(), process_output(), ROW_FMT, mansession_session::send_events, mansession::session, session_destroy(), mansession_session::sessiontimeout, mansession_session::sin, TEST_STRING, mansession_session::username, ast_variable::value, and mansession_session::waiting_thread.
Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().
05870 { 05871 struct mansession s = { .session = NULL, .tcptls_session = ser }; 05872 struct mansession_session *session = NULL; 05873 uint32_t ident = 0; 05874 int blastaway = 0; 05875 struct ast_variable *v, *cookies, *params = get_params; 05876 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 05877 struct ast_str *http_header = NULL, *out = NULL; 05878 struct message m = { 0 }; 05879 unsigned int idx; 05880 size_t hdrlen; 05881 05882 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) { 05883 ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method"); 05884 return -1; 05885 } 05886 05887 cookies = ast_http_get_cookies(headers); 05888 for (v = cookies; v; v = v->next) { 05889 if (!strcasecmp(v->name, "mansession_id")) { 05890 sscanf(v->value, "%30x", &ident); 05891 break; 05892 } 05893 } 05894 if (cookies) { 05895 ast_variables_destroy(cookies); 05896 } 05897 05898 if (!(session = find_session(ident, 1))) { 05899 05900 /**/ 05901 /* Create new session. 05902 * While it is not in the list we don't need any locking 05903 */ 05904 if (!(session = build_mansession(*remote_address))) { 05905 ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n"); 05906 return -1; 05907 } 05908 ao2_lock(session); 05909 session->sin = *remote_address; 05910 session->fd = -1; 05911 session->waiting_thread = AST_PTHREADT_NULL; 05912 session->send_events = 0; 05913 session->inuse = 1; 05914 /*!\note There is approximately a 1 in 1.8E19 chance that the following 05915 * calculation will produce 0, which is an invalid ID, but due to the 05916 * properties of the rand() function (and the constantcy of s), that 05917 * won't happen twice in a row. 05918 */ 05919 while ((session->managerid = ast_random() ^ (unsigned long) session) == 0); 05920 session->last_ev = grab_last(); 05921 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05922 } 05923 ao2_unlock(session); 05924 05925 http_header = ast_str_create(128); 05926 out = ast_str_create(2048); 05927 05928 ast_mutex_init(&s.lock); 05929 05930 if (http_header == NULL || out == NULL) { 05931 ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n"); 05932 goto generic_callback_out; 05933 } 05934 05935 s.session = session; 05936 s.fd = mkstemp(template); /* create a temporary file for command output */ 05937 unlink(template); 05938 if (s.fd <= -1) { 05939 ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)\n"); 05940 goto generic_callback_out; 05941 } 05942 s.f = fdopen(s.fd, "w+"); 05943 if (!s.f) { 05944 ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno)); 05945 ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)\n"); 05946 close(s.fd); 05947 goto generic_callback_out; 05948 } 05949 05950 if (method == AST_HTTP_POST) { 05951 params = ast_http_get_post_vars(ser, headers); 05952 } 05953 05954 for (v = params; v && m.hdrcount < ARRAY_LEN(m.headers); v = v->next) { 05955 hdrlen = strlen(v->name) + strlen(v->value) + 3; 05956 m.headers[m.hdrcount] = ast_malloc(hdrlen); 05957 if (!m.headers[m.hdrcount]) { 05958 /* Allocation failure */ 05959 continue; 05960 } 05961 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 05962 ast_debug(1, "HTTP Manager add header %s\n", m.headers[m.hdrcount]); 05963 ++m.hdrcount; 05964 } 05965 05966 if (process_message(&s, &m)) { 05967 if (session->authenticated) { 05968 if (manager_displayconnects(session)) { 05969 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 05970 } 05971 } else { 05972 if (displayconnects) { 05973 ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 05974 } 05975 } 05976 session->needdestroy = 1; 05977 } 05978 05979 /* Free request headers. */ 05980 for (idx = 0; idx < m.hdrcount; ++idx) { 05981 ast_free((void *) m.headers[idx]); 05982 m.headers[idx] = NULL; 05983 } 05984 05985 ast_str_append(&http_header, 0, 05986 "Content-type: text/%s\r\n" 05987 "Cache-Control: no-cache;\r\n" 05988 "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n" 05989 "Pragma: SuppressEvents\r\n", 05990 contenttype[format], 05991 session->managerid, httptimeout); 05992 05993 if (format == FORMAT_XML) { 05994 ast_str_append(&out, 0, "<ajax-response>\n"); 05995 } else if (format == FORMAT_HTML) { 05996 /* 05997 * When handling AMI-over-HTTP in HTML format, we provide a simple form for 05998 * debugging purposes. This HTML code should not be here, we 05999 * should read from some config file... 06000 */ 06001 06002 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" 06003 #define TEST_STRING \ 06004 "<form action=\"manager\" method=\"post\">\n\ 06005 Action: <select name=\"action\">\n\ 06006 <option value=\"\">-----></option>\n\ 06007 <option value=\"login\">login</option>\n\ 06008 <option value=\"command\">Command</option>\n\ 06009 <option value=\"waitevent\">waitevent</option>\n\ 06010 <option value=\"listcommands\">listcommands</option>\n\ 06011 </select>\n\ 06012 or <input name=\"action\"><br/>\n\ 06013 CLI Command <input name=\"command\"><br>\n\ 06014 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ 06015 <input type=\"submit\">\n</form>\n" 06016 06017 ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>"); 06018 ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 06019 ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>"); 06020 ast_str_append(&out, 0, ROW_FMT, TEST_STRING); 06021 } 06022 06023 process_output(&s, &out, params, format); 06024 06025 if (format == FORMAT_XML) { 06026 ast_str_append(&out, 0, "</ajax-response>\n"); 06027 } else if (format == FORMAT_HTML) { 06028 ast_str_append(&out, 0, "</table></body>\r\n"); 06029 } 06030 06031 ao2_lock(session); 06032 /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */ 06033 session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5); 06034 06035 if (session->needdestroy) { 06036 if (session->inuse == 1) { 06037 ast_debug(1, "Need destroy, doing it now!\n"); 06038 blastaway = 1; 06039 } else { 06040 ast_debug(1, "Need destroy, but can't do it yet!\n"); 06041 if (session->waiting_thread != AST_PTHREADT_NULL) { 06042 pthread_kill(session->waiting_thread, SIGURG); 06043 } 06044 session->inuse--; 06045 } 06046 } else { 06047 session->inuse--; 06048 } 06049 ao2_unlock(session); 06050 06051 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0); 06052 http_header = out = NULL; 06053 06054 generic_callback_out: 06055 ast_mutex_destroy(&s.lock); 06056 06057 /* Clear resource */ 06058 06059 if (method == AST_HTTP_POST && params) { 06060 ast_variables_destroy(params); 06061 } 06062 if (http_header) { 06063 ast_free(http_header); 06064 } 06065 if (out) { 06066 ast_free(out); 06067 } 06068 06069 if (session && blastaway) { 06070 session_destroy(session); 06071 } else if (session && session->f) { 06072 fclose(session->f); 06073 session->f = NULL; 06074 } 06075 06076 return 0; 06077 }
| static char* handle_manager_show_settings | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI command manager show settings.
Definition at line 6546 of file manager.c.
References ami_tls_cfg, ast_cli_args::argc, ast_cli(), AST_CLI_YESNO, ast_sockaddr_stringify(), block_sockets, ast_tls_config::certfile, ast_tls_config::cipher, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_tls_config::enabled, ast_cli_args::fd, FORMAT, FORMAT2, ast_tcptls_session_args::local_address, ast_tls_config::pvtfile, S_OR, and ast_cli_entry::usage.
06547 { 06548 switch (cmd) { 06549 case CLI_INIT: 06550 e->command = "manager show settings"; 06551 e->usage = 06552 "Usage: manager show settings\n" 06553 " Provides detailed list of the configuration of the Manager.\n"; 06554 return NULL; 06555 case CLI_GENERATE: 06556 return NULL; 06557 } 06558 #define FORMAT " %-25.25s %-15.15s\n" 06559 #define FORMAT2 " %-25.25s %-15d\n" 06560 if (a->argc != 3) { 06561 return CLI_SHOWUSAGE; 06562 } 06563 ast_cli(a->fd, "\nGlobal Settings:\n"); 06564 ast_cli(a->fd, "----------------\n"); 06565 ast_cli(a->fd, FORMAT, "Manager (AMI):", AST_CLI_YESNO(manager_enabled)); 06566 ast_cli(a->fd, FORMAT, "Web Manager (AMI/HTTP):", AST_CLI_YESNO(webmanager_enabled)); 06567 ast_cli(a->fd, FORMAT, "TCP Bindaddress:", manager_enabled != 0 ? ast_sockaddr_stringify(&ami_desc.local_address) : "Disabled"); 06568 ast_cli(a->fd, FORMAT2, "HTTP Timeout (minutes):", httptimeout); 06569 ast_cli(a->fd, FORMAT, "TLS Enable:", AST_CLI_YESNO(ami_tls_cfg.enabled)); 06570 ast_cli(a->fd, FORMAT, "TLS Bindaddress:", ami_tls_cfg.enabled != 0 ? ast_sockaddr_stringify(&amis_desc.local_address) : "Disabled"); 06571 ast_cli(a->fd, FORMAT, "TLS Certfile:", ami_tls_cfg.certfile); 06572 ast_cli(a->fd, FORMAT, "TLS Privatekey:", ami_tls_cfg.pvtfile); 06573 ast_cli(a->fd, FORMAT, "TLS Cipher:", ami_tls_cfg.cipher); 06574 ast_cli(a->fd, FORMAT, "Allow multiple login:", AST_CLI_YESNO(allowmultiplelogin)); 06575 ast_cli(a->fd, FORMAT, "Display connects:", AST_CLI_YESNO(displayconnects)); 06576 ast_cli(a->fd, FORMAT, "Timestamp events:", AST_CLI_YESNO(timestampevents)); 06577 ast_cli(a->fd, FORMAT, "Channel vars:", S_OR(manager_channelvars, "")); 06578 ast_cli(a->fd, FORMAT, "Debug:", AST_CLI_YESNO(manager_debug)); 06579 ast_cli(a->fd, FORMAT, "Block sockets:", AST_CLI_YESNO(block_sockets)); 06580 #undef FORMAT 06581 #undef FORMAT2 06582 06583 return CLI_SUCCESS; 06584 }
| int init_manager | ( | void | ) |
Called by Asterisk initialization.
Definition at line 7062 of file manager.c.
References __init_manager().
Referenced by main().
07063 { 07064 return __init_manager(0); 07065 }
| static void load_channelvars | ( | struct ast_variable * | var | ) | [static] |
Definition at line 6606 of file manager.c.
References ast_calloc, ast_free, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_strdupa, free_channelvars(), manager_channel_variable::isfunc, manager_channel_variable::name, eventqent::next, strsep(), and ast_variable::value.
Referenced by __init_manager().
06607 { 06608 struct manager_channel_variable *mcv; 06609 char *remaining = ast_strdupa(var->value); 06610 char *next; 06611 06612 ast_free(manager_channelvars); 06613 manager_channelvars = ast_strdup(var->value); 06614 06615 /* 06616 * XXX TODO: To allow dialplan functions to have more than one 06617 * parameter requires eliminating the '|' as a separator so we 06618 * could use AST_STANDARD_APP_ARGS() to separate items. 06619 */ 06620 free_channelvars(); 06621 AST_RWLIST_WRLOCK(&channelvars); 06622 while ((next = strsep(&remaining, ",|"))) { 06623 if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) { 06624 break; 06625 } 06626 strcpy(mcv->name, next); /* SAFE */ 06627 if (strchr(next, '(')) { 06628 mcv->isfunc = 1; 06629 } 06630 AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry); 06631 } 06632 AST_RWLIST_UNLOCK(&channelvars); 06633 }
| static int manager_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6392 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
06393 { 06394 int retval; 06395 struct sockaddr_in ser_remote_address_tmp; 06396 06397 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06398 retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers); 06399 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06400 return retval; 06401 }
| static int mxml_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6403 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
06404 { 06405 int retval; 06406 struct sockaddr_in ser_remote_address_tmp; 06407 06408 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06409 retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers); 06410 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06411 return retval; 06412 }
| static void process_output | ( | struct mansession * | s, | |
| struct ast_str ** | out, | |||
| struct ast_variable * | params, | |||
| enum output_format | format | |||
| ) | [static] |
Definition at line 5831 of file manager.c.
References ast_log(), ast_str_append(), mansession::f, mansession::fd, FORMAT_HTML, FORMAT_XML, LOG_WARNING, and xml_translate().
Referenced by auth_http_callback(), and generic_http_callback().
05832 { 05833 char *buf; 05834 size_t l; 05835 05836 if (!s->f) 05837 return; 05838 05839 /* Ensure buffer is NULL-terminated */ 05840 fprintf(s->f, "%c", 0); 05841 fflush(s->f); 05842 05843 if ((l = ftell(s->f))) { 05844 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s->fd, 0))) { 05845 ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n"); 05846 } else { 05847 if (format == FORMAT_XML || format == FORMAT_HTML) { 05848 xml_translate(out, buf, params, format); 05849 } else { 05850 ast_str_append(out, 0, "%s", buf); 05851 } 05852 munmap(buf, l); 05853 } 05854 } else if (format == FORMAT_XML || format == FORMAT_HTML) { 05855 xml_translate(out, "", params, format); 05856 } 05857 05858 fclose(s->f); 05859 s->f = NULL; 05860 close(s->fd); 05861 s->fd = -1; 05862 }
| static void purge_old_stuff | ( | void * | data | ) | [static] |
cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
Definition at line 6517 of file manager.c.
References purge_events(), and purge_sessions().
06518 { 06519 purge_sessions(1); 06520 purge_events(); 06521 }
| static int rawman_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
| const struct ast_http_uri * | urih, | |||
| const char * | uri, | |||
| enum ast_http_method | method, | |||
| struct ast_variable * | get_params, | |||
| struct ast_variable * | headers | |||
| ) | [static] |
Definition at line 6414 of file manager.c.
References ast_sockaddr_from_sin, ast_sockaddr_to_sin, FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
06415 { 06416 int retval; 06417 struct sockaddr_in ser_remote_address_tmp; 06418 06419 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 06420 retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers); 06421 ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp); 06422 return retval; 06423 }
| int reload_manager | ( | void | ) |
Called by Asterisk module functions and the CLI command.
Definition at line 7067 of file manager.c.
References __init_manager().
Referenced by handle_manager_reload().
07068 { 07069 return __init_manager(1); 07070 }
| static int variable_count_cmp_fn | ( | void * | obj, | |
| void * | vstr, | |||
| int | flags | |||
| ) | [static] |
Definition at line 5675 of file manager.c.
References CMP_MATCH, CMP_STOP, str, and variable_count::varname.
Referenced by xml_translate().
05676 { 05677 /* Due to the simplicity of struct variable_count, it makes no difference 05678 * if you pass in objects or strings, the same operation applies. This is 05679 * due to the fact that the hash occurs on the first element, which means 05680 * the address of both the struct and the string are exactly the same. */ 05681 struct variable_count *vc = obj; 05682 char *str = vstr; 05683 return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0; 05684 }
| static int variable_count_hash_fn | ( | const void * | vvc, | |
| const int | flags | |||
| ) | [static] |
Definition at line 5668 of file manager.c.
References ast_str_hash(), and variable_count::varname.
Referenced by xml_translate().
05669 { 05670 const struct variable_count *vc = vvc; 05671 05672 return ast_str_hash(vc->varname); 05673 }
| static void xml_copy_escape | ( | struct ast_str ** | out, | |
| const char * | src, | |||
| int | mode | |||
| ) | [static] |
Definition at line 5606 of file manager.c.
References ast_str_append().
Referenced by xml_translate().
05607 { 05608 /* store in a local buffer to avoid calling ast_str_append too often */ 05609 char buf[256]; 05610 char *dst = buf; 05611 int space = sizeof(buf); 05612 /* repeat until done and nothing to flush */ 05613 for ( ; *src || dst != buf ; src++) { 05614 if (*src == '\0' || space < 10) { /* flush */ 05615 *dst++ = '\0'; 05616 ast_str_append(out, 0, "%s", buf); 05617 dst = buf; 05618 space = sizeof(buf); 05619 if (*src == '\0') { 05620 break; 05621 } 05622 } 05623 05624 if ( (mode & 2) && !isalnum(*src)) { 05625 *dst++ = '_'; 05626 space--; 05627 continue; 05628 } 05629 switch (*src) { 05630 case '<': 05631 strcpy(dst, "<"); 05632 dst += 4; 05633 space -= 4; 05634 break; 05635 case '>': 05636 strcpy(dst, ">"); 05637 dst += 4; 05638 space -= 4; 05639 break; 05640 case '\"': 05641 strcpy(dst, """); 05642 dst += 6; 05643 space -= 6; 05644 break; 05645 case '\'': 05646 strcpy(dst, "'"); 05647 dst += 6; 05648 space -= 6; 05649 break; 05650 case '&': 05651 strcpy(dst, "&"); 05652 dst += 5; 05653 space -= 5; 05654 break; 05655 05656 default: 05657 *dst++ = mode ? tolower(*src) : *src; 05658 space--; 05659 } 05660 } 05661 }
| static void xml_translate | ( | struct ast_str ** | out, | |
| char * | in, | |||
| struct ast_variable * | get_vars, | |||
| enum output_format | format | |||
| ) | [static] |
Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.
At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications):
General: the unformatted text is used as a value of XML output: to be completed
* Each section is within <response type="object" id="xxx"> * where xxx is taken from ajaxdest variable or defaults to unknown * Each row is reported as an attribute Name="value" of an XML * entity named from the variable ajaxobjtype, default to "generic" *
HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a
Definition at line 5714 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_skip_blanks(), ast_str_append(), ast_strlen_zero(), ast_trim_blanks(), variable_count::count, FORMAT_XML, ast_variable::name, ast_variable::next, strsep(), ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().
Referenced by process_output().
05715 { 05716 struct ast_variable *v; 05717 const char *dest = NULL; 05718 char *var, *val; 05719 const char *objtype = NULL; 05720 int in_data = 0; /* parsing data */ 05721 int inobj = 0; 05722 int xml = (format == FORMAT_XML); 05723 struct variable_count *vc = NULL; 05724 struct ao2_container *vco = NULL; 05725 05726 if (xml) { 05727 /* dest and objtype need only for XML format */ 05728 for (v = get_vars; v; v = v->next) { 05729 if (!strcasecmp(v->name, "ajaxdest")) { 05730 dest = v->value; 05731 } else if (!strcasecmp(v->name, "ajaxobjtype")) { 05732 objtype = v->value; 05733 } 05734 } 05735 if (ast_strlen_zero(dest)) { 05736 dest = "unknown"; 05737 } 05738 if (ast_strlen_zero(objtype)) { 05739 objtype = "generic"; 05740 } 05741 } 05742 05743 /* we want to stop when we find an empty line */ 05744 while (in && *in) { 05745 val = strsep(&in, "\r\n"); /* mark start and end of line */ 05746 if (in && *in == '\n') { /* remove trailing \n if any */ 05747 in++; 05748 } 05749 ast_trim_blanks(val); 05750 ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val); 05751 if (ast_strlen_zero(val)) { 05752 /* empty line */ 05753 if (in_data) { 05754 /* close data in Opaque mode */ 05755 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05756 in_data = 0; 05757 } 05758 05759 if (inobj) { 05760 /* close block */ 05761 ast_str_append(out, 0, xml ? " /></response>\n" : 05762 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05763 inobj = 0; 05764 ao2_ref(vco, -1); 05765 vco = NULL; 05766 } 05767 continue; 05768 } 05769 05770 if (!inobj) { 05771 /* start new block */ 05772 if (xml) { 05773 ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype); 05774 } 05775 vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn); 05776 inobj = 1; 05777 } 05778 05779 if (in_data) { 05780 /* Process data field in Opaque mode. This is a 05781 * followup, so we re-add line feeds. */ 05782 ast_str_append(out, 0, xml ? "\n" : "<br>\n"); 05783 xml_copy_escape(out, val, 0); /* data field */ 05784 continue; 05785 } 05786 05787 /* We expect "Name: value" line here */ 05788 var = strsep(&val, ":"); 05789 if (val) { 05790 /* found the field name */ 05791 val = ast_skip_blanks(val); 05792 ast_trim_blanks(var); 05793 } else { 05794 /* field name not found, switch to opaque mode */ 05795 val = var; 05796 var = "Opaque-data"; 05797 in_data = 1; 05798 } 05799 05800 05801 ast_str_append(out, 0, xml ? " " : "<tr><td>"); 05802 if ((vc = ao2_find(vco, var, 0))) { 05803 vc->count++; 05804 } else { 05805 /* Create a new entry for this one */ 05806 vc = ao2_alloc(sizeof(*vc), NULL); 05807 vc->varname = var; 05808 vc->count = 1; 05809 ao2_link(vco, vc); 05810 } 05811 05812 xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */ 05813 if (vc->count > 1) { 05814 ast_str_append(out, 0, "-%d", vc->count); 05815 } 05816 ao2_ref(vc, -1); 05817 ast_str_append(out, 0, xml ? "='" : "</td><td>"); 05818 xml_copy_escape(out, val, 0); /* data field */ 05819 if (!in_data || !*in) { 05820 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 05821 } 05822 } 05823 05824 if (inobj) { 05825 ast_str_append(out, 0, xml ? " /></response>\n" : 05826 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 05827 ao2_ref(vco, -1); 05828 } 05829 }
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 6523 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().
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] |
Initial value:
{
[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] |
1.5.6