62 #include <sys/types.h> 1483 #define DEFAULT_REALM "asterisk" 1501 #ifdef TEST_FRAMEWORK 1506 #define MGR_SHOW_TERMINAL_WIDTH 80 1508 #define MAX_VARS 128 1511 #define EVENT_FLAG_SHUTDOWN -1 1523 #define MAX_BLACKLIST_CMD_LEN 2 1524 static const struct {
1527 {{
"module",
"load",
NULL }},
1528 {{
"module",
"unload",
NULL }},
1529 {{
"restart",
"gracefully",
NULL }},
1536 if (!acl_change_sub) {
1590 struct timeval sessionstart_tv;
1710 if (!strcasecmp(name, act->
action)) {
1711 ao2_t_ref(act, +1,
"found action object");
1756 size_t index,
struct ast_str **res,
1766 const char *parent_key,
struct ast_str **res,
1771 ast_str_set(&key_str, 0,
"%s/%s", parent_key, key);
1794 if (exclusion_cb && key && exclusion_cb(key)) {
1808 key, j, res, exclusion_cb);
1817 key, res, exclusion_cb);
1832 #define manager_event_sessions(sessions, category, event, contents , ...) \ 1833 __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__) 1835 #define any_manager_listeners(sessions) \ 1836 ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks)) 1892 if (!event_buffer) {
1916 "class_type", class_type,
2043 #define MAX_AUTH_PERM_STRING 150 2050 strstr(evaluating,
"SHELL") ||
2051 strstr(evaluating,
"EVAL")
2092 if (authority &
perms[i].num) {
2112 static int ast_instring(
const char *bigstr,
const char *smallstr,
const char delim)
2114 const char *
val = bigstr, *next;
2117 if ((next = strchr(val, delim))) {
2118 if (!strncmp(val, smallstr, (next - val))) {
2124 return !strcmp(smallstr, val);
2126 }
while (*(val = (next + 1)));
2160 for (p =
string; *p; p++) {
2161 if (*p < '0' || *p >
'9') {
2166 return atoi(
string);
2185 int refcount =
ao2_ref(s, -1);
2187 ast_debug(1,
"Mansession: %p refcount now %d\n", s, refcount - 1);
2194 regex_t *regex_filter = obj;
2195 regfree(regex_filter);
2290 session =
ao2_find(sessions, (
char *) name, 0);
2310 if (!strcasecmp(user->
username, name)) {
2346 const char *auth_str;
2348 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
2349 char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
2354 e->
command =
"manager show command";
2356 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 2357 " Shows the detailed description for a specific Asterisk manager interface command.\n";
2360 l = strlen(a->
word);
2392 for (num = 3; num < a->
argc; num++) {
2393 if (!strcasecmp(cur->
action, a->
argv[num])) {
2406 if (!syntax || !synopsis || !description || !arguments
2407 || !seealso || !privilege || !responses) {
2415 ast_cli(a->
fd,
"Allocation failure.\n");
2421 ast_cli(a->
fd,
"%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s",
2422 syntax_title, syntax,
2423 synopsis_title, synopsis,
2424 description_title, description,
2425 arguments_title, arguments,
2426 seealso_title, seealso,
2427 privilege_title, privilege,
2428 list_responses_title);
2440 ast_cli(a->
fd,
"%s", final_response_title);
2459 ast_cli(a->
fd,
"Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
2476 e->
command =
"manager set debug [on|off]";
2477 e->
usage =
"Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
2485 }
else if (a->
argc == 4) {
2486 if (!strcasecmp(a->
argv[3],
"on")) {
2488 }
else if (!strcasecmp(a->
argv[3],
"off")) {
2507 e->
command =
"manager show user";
2509 " Usage: manager show user <user>\n" 2510 " Display all information related to the manager user specified.\n";
2513 l = strlen(a->
word);
2536 ast_cli(a->
fd,
"There is no manager called %s\n", a->
argv[3]);
2548 " displayconnects: %s\n" 2549 "allowmultiplelogin: %s\n",
2551 (user->
secret ?
"<Set>" :
"(N/A)"),
2576 e->
command =
"manager show users";
2578 "Usage: manager show users\n" 2579 " Prints a listing of all managers that are currently configured on that\n" 2593 ast_cli(a->
fd,
"There are no manager users.\n");
2598 ast_cli(a->
fd,
"\nusername\n--------\n");
2608 "%d manager users configured.\n", count_amu);
2617 int space_remaining;
2618 #define HSMC_FORMAT " %-*.*s %-.*s\n" 2621 e->
command =
"manager show commands";
2623 "Usage: manager show commands\n" 2624 " Prints a listing of all the available Asterisk manager interface commands.\n";
2632 int incoming_len = strlen(cur->
action);
2633 if (incoming_len > name_len) {
2634 name_len = incoming_len;
2639 if (space_remaining < 0) {
2640 space_remaining = 0;
2659 time_t now = time(
NULL);
2660 #define HSMCONN_FORMAT1 " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 2661 #define HSMCONN_FORMAT2 " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 2667 e->
command =
"manager show connected";
2669 "Usage: manager show connected\n" 2670 " Prints a listing of the users that are currently connected to the\n" 2671 "Asterisk manager interface.\n";
2677 ast_cli(a->
fd,
HSMCONN_FORMAT1,
"Username",
"IP Address",
"Start",
"Elapsed",
"FileDes",
"HttpCnt",
"Read",
"Write");
2699 ast_cli(a->
fd,
"%d users connected.\n", count);
2711 e->
command =
"manager show eventq";
2713 "Usage: manager show eventq\n" 2714 " Prints a listing of all events pending in the Asterisk manger\n" 2724 ast_cli(a->
fd,
"Event:\n%s", s->eventdata);
2738 e->
command =
"manager reload";
2740 "Usage: manager reload\n" 2741 " Reloads the manager configuration.\n";
2766 #define GET_HEADER_FIRST_MATCH 0 2767 #define GET_HEADER_LAST_MATCH 1 2768 #define GET_HEADER_SKIP_EMPTY 2 2785 int x, l = strlen(var);
2792 for (x = 0; x < m->
hdrcount; x++) {
2793 const char *h = m->
headers[x];
2794 if (!strncasecmp(var, h, l) && h[l] ==
':') {
2795 const char *
value = h + l + 1;
2878 for (y = 0; y <
args.argc; y++) {
2883 if (!
args.vars[y]) {
2886 var = val =
args.vars[y];
2918 static const char var_hdr[] =
"Variable:";
2921 varlen = strlen(var_hdr);
2922 for (x = 0; x < m->
hdrcount; x++) {
2923 if (strncasecmp(var_hdr, m->
headers[x], varlen)) {
2943 struct message m = { 0 };
2960 curlen = strlen(src);
2961 for (x = 0; x < curlen; x++) {
2963 if (src[x] ==
'\r' && x+1 < curlen && src[x+1] ==
'\n')
2965 else if (src[x] ==
'\n')
2984 if (!strcasecmp(action,
"login")) {
3007 if (!act_found->
module || mod_ref) {
3008 ret = act_found->
func(&s, &m);
3014 ao2_t_ref(act_found, -1,
"done with found action object");
3042 len = strlen(
string);
3066 #define ASTMAN_APPEND_BUF_INITSIZE 256 3073 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3100 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3114 #define MSG_MOREDATA ((char *)astman_send_response) 3216 ast_str_set(&buf, 0,
"Event: %s\r\n", event_name);
3221 "EventList: Complete\r\n" 3222 "ListItems: %d\r\n",
3287 char session_id[32];
3291 .common.service =
"AMI",
3292 .common.account_id = username,
3294 .common.local_addr = {
3298 .common.remote_addr = {
3302 .common.session_id = session_id,
3305 snprintf(session_id,
sizeof(session_id),
"%p", s);
3312 char session_id[32];
3316 .common.service =
"AMI",
3317 .common.account_id = username,
3319 .common.local_addr = {
3323 .common.remote_addr = {
3327 .common.session_id = session_id,
3330 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3337 char session_id[32];
3341 .common.service =
"AMI",
3342 .common.account_id = username,
3344 .common.local_addr = {
3348 .common.remote_addr = {
3352 .common.session_id = session_id,
3355 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3362 char session_id[32];
3366 .common.service =
"AMI",
3369 .common.local_addr = {
3373 .common.remote_addr = {
3377 .common.session_id = session_id,
3380 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3387 char session_id[32];
3388 char request_type[64];
3392 .common.service =
"AMI",
3395 .common.local_addr = {
3399 .common.remote_addr = {
3403 .common.session_id = session_id,
3408 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3409 snprintf(request_type,
sizeof(request_type),
"Action: %s", action);
3416 char session_id[32];
3421 .common.service =
"AMI",
3424 .common.local_addr = {
3428 .common.remote_addr = {
3432 .common.session_id = session_id,
3437 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3438 snprintf(request_type,
sizeof(request_type),
"Action: %s", action);
3444 const char *response,
const char *expected_response)
3446 char session_id[32];
3450 .common.service =
"AMI",
3453 .common.local_addr = {
3457 .common.remote_addr = {
3461 .common.session_id = session_id,
3468 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3475 char session_id[32];
3479 .common.service =
"AMI",
3482 .common.local_addr = {
3486 .common.remote_addr = {
3490 .common.session_id = session_id,
3493 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3511 regex_t *regex_filter;
3532 char md5key[256] =
"";
3534 unsigned char digest[16];
3540 for (x = 0; x < 16; x++)
3541 len += sprintf(md5key + len,
"%02hhx", digest[x]);
3542 if (!strcmp(md5key, key)) {
3548 ast_debug(1,
"MD5 authentication is not possible. challenge: '%s'\n",
3551 }
else if (user->
secret) {
3552 if (!strcmp(password, user->
secret)) {
3581 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3588 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3614 "Timestamp: %ld.%06lu\r\n" 3616 (
long) now.tv_sec, (
unsigned long) now.tv_usec);
3626 const char *category_name;
3653 astman_append(s,
"Category-%06d: %s\r\n", catcount, category_name);
3710 if (catcount == 0) {
3724 if (*in ==
'\\' || *in ==
'\"') {
3757 const char *category_name;
3828 for (x = 0; x < 100000; x++) {
3829 unsigned int object = 0;
3833 int ignoreerror = 0;
3841 snprintf(hdr,
sizeof(hdr),
"Action-%06d", x);
3846 snprintf(hdr,
sizeof(hdr),
"Cat-%06d", x);
3853 snprintf(hdr,
sizeof(hdr),
"Var-%06d", x);
3856 snprintf(hdr,
sizeof(hdr),
"Value-%06d", x);
3864 snprintf(hdr,
sizeof(hdr),
"Match-%06d", x);
3867 snprintf(hdr,
sizeof(hdr),
"Line-%06d", x);
3870 snprintf(hdr,
sizeof(hdr),
"Options-%06d", x);
3873 char copy[strlen(options) + 1];
3874 strcpy(copy, options);
3877 if (!strcasecmp(
"allowdups", token)) {
3881 if (!strcasecmp(
"template", token)) {
3885 if (!strcasecmp(
"ignoreerror", token)) {
3908 if (!strcasecmp(action,
"newcat")) {
3910 char *tmpl_name =
NULL;
3950 if (category !=
NULL) {
3961 }
else if (!strcasecmp(action,
"renamecat")) {
3977 }
else if (!strcasecmp(action,
"delcat")) {
3984 if (!foundcat && !ignoreerror) {
3988 }
else if (!strcasecmp(action,
"emptycat")) {
3999 }
else if (!strcasecmp(action,
"update")) {
4023 }
else if (!strcasecmp(action,
"delete")) {
4043 if (!foundvar && !ignoreerror) {
4047 }
else if (!strcasecmp(action,
"append")) {
4059 if (
object || (match && !strcasecmp(match,
"object"))) {
4070 }
else if (!strcasecmp(action,
"insert")) {
4110 const char *preserve_effective_context_string =
astman_get_header(m,
"PreserveEffectiveContext");
4216 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4222 sscanf(timeouts,
"%30i", &timeout);
4243 time_t now = time(
NULL);
4249 if (timeout < 0 || timeout > max) {
4261 ast_debug(1,
"Starting waiting for an event!\n");
4263 for (x = 0; x < timeout || timeout < 0; x++) {
4292 ast_debug(1,
"Finished waiting for an event!\n");
4312 "Event: WaitEventComplete\r\n" 4318 ast_debug(1,
"Abandoning event request!\n");
4351 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
4363 if (!strcasecmp(
perms[x].label,
"all") && res ==
perms[x].
num) {
4368 "Events: On\r\n\r\n", id_text);
4369 }
else if (res == 0)
4371 "Events: Off\r\n\r\n", id_text);
4377 "Events: On\r\n\r\n", id_text);
4380 "Events: Off\r\n\r\n", id_text);
4419 long lastreloaded = 0;
4425 uptime = tmp.tv_sec;
4430 lastreloaded = tmp.tv_sec;
4436 "LastReload: %ld\r\n" 4437 "Status: Fully Booted\r\n\r\n", cat_str, uptime, lastreloaded);
4446 if (!strcasecmp(authtype,
"MD5")) {
4471 int channels_matched = 0;
4479 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4486 causecode = strtol(cause, &endptr, 10);
4487 if (causecode < 0 || causecode > 127 || *endptr !=
'\0') {
4497 if (name_or_regex[0] !=
'/') {
4505 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4523 if (!regex_string) {
4530 astman_send_error(s, m,
"Regex format invalid, Channel param should be /regex/");
4536 if (regcomp(®exbuf,
ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
4551 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4561 "Event: ChannelHungup\r\n" 4616 char workspace[1024];
4636 workspace[0] =
'\0';
4637 if (varname[strlen(varname) - 1] ==
')') {
4641 ast_func_read(c, (
char *) varname, workspace,
sizeof(workspace));
4643 ast_log(
LOG_ERROR,
"Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
4645 ast_func_read(c, (
char *) varname, workspace,
sizeof(workspace));
4657 astman_append(s,
"Variable: %s\r\nValue: %s\r\n\r\n", varname,
S_OR(varval,
""));
4665 long elapsed_seconds;
4683 if (!snapshot_str) {
4687 if (all_variables) {
4692 if (!variable_str) {
4701 for (i = 0; i < varc; i++) {
4702 char valbuf[512], *ret =
NULL;
4704 if (vars[i][strlen(vars[i]) - 1] ==
')') {
4705 if (
ast_func_read(chan, vars[i], valbuf,
sizeof(valbuf)) < 0) {
4713 ast_str_append(&variable_str, 0,
"Variable: %s=%s\r\n", vars[i], ret);
4717 if (all_variables) {
4731 "Privilege: Call\r\n" 4735 "EffectiveConnectedLineNum: %s\r\n" 4736 "EffectiveConnectedLineName: %s\r\n" 4737 "TimeToHangup: %ld\r\n" 4739 "Application: %s\r\n" 4741 "Nativeformats: %s\r\n" 4742 "Readformat: %s\r\n" 4744 "Writeformat: %s\r\n" 4745 "Writetrans: %s\r\n" 4746 "Callgroup: %llu\r\n" 4747 "Pickupgroup: %llu\r\n" 4768 (
long)elapsed_seconds,
4782 int all_variables = 0;
4795 all_variables =
ast_true(all_chan_variables);
4820 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
4833 generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
4871 obj_size = payload_size +
sizeof(*obj);
4878 obj->action = action;
4879 obj->payload_size = payload_size;
4880 memcpy(obj->payload, payload, payload_size);
4912 const char *content_type)
5009 if (sscanf(priority,
"%30d", &pi) != 1) {
5027 if (sscanf(priority2,
"%30d", &pi2) != 1) {
5038 snprintf(buf,
sizeof(buf),
"Channel does not exist: %s", name);
5062 snprintf(buf,
sizeof(buf),
"ExtraChannel does not exist: %s", name2);
5201 for (digit = feature_code; *
digit; ++
digit) {
5239 if (!feature_code) {
5245 for (digit = feature_code; *
digit; ++
digit) {
5261 char *cmd_copy, *cur_cmd;
5273 cmd_words[i] = cur_cmd;
5298 char *
buf =
NULL, *final_buf =
NULL, *delim, *output;
5299 char template[] =
"/tmp/ast-ami-XXXXXX";
5313 if ((fd = mkstemp(
template)) < 0) {
5322 if ((len = lseek(fd, 0, SEEK_END)) < 0) {
5323 astman_append(s,
"Message: Failed to determine number of characters: %s\r\n", strerror(
errno));
5324 goto action_command_cleanup;
5331 if (!buf || !final_buf) {
5333 goto action_command_cleanup;
5336 if (lseek(fd, 0, SEEK_SET) < 0) {
5337 astman_append(s,
"Message: Failed to set position on temporary file: %s\r\n", strerror(
errno));
5338 goto action_command_cleanup;
5341 if (read(fd, buf, len) < 0) {
5342 astman_append(s,
"Message: Failed to read from temporary file: %s\r\n", strerror(
errno));
5343 goto action_command_cleanup;
5348 final_buf[
len] =
'\0';
5351 if (len && final_buf[len - 1] ==
'\n') {
5352 final_buf[len - 1] =
'\0';
5358 while ((output =
strsep(&delim,
"\n"))) {
5362 action_command_cleanup:
5451 "Application: %s\r\n" 5455 "CallerIDNum: %s\r\n" 5456 "CallerIDName: %s\r\n",