Commit the changes from issue #5240.
[asterisk/asterisk.git] / main / manager.c
index efa8640..5b220df 100644 (file)
@@ -177,6 +177,20 @@ struct mansession {
 
 static AST_LIST_HEAD_STATIC(sessions, mansession);
 
+struct ast_manager_user {
+       char username[80];
+       char *secret;
+       char *deny;
+       char *permit;
+       char *read;
+       char *write;
+       unsigned int displayconnects:1;
+       int keep;
+       AST_LIST_ENTRY(ast_manager_user) list;
+};
+
+static AST_LIST_HEAD_STATIC(users, ast_manager_user);
+
 static struct manager_action *first_action = NULL;
 AST_MUTEX_DEFINE_STATIC(actionlock);
 
@@ -380,6 +394,18 @@ static char *html_translate(char *in)
        return out;
 }
 
+
+
+static struct ast_manager_user *ast_get_manager_by_name_locked(const char *name)
+{
+       struct ast_manager_user *user = NULL;
+
+       AST_LIST_TRAVERSE(&users, user, list)
+               if (!strcasecmp(user->username, name))
+                       break;
+       return user;
+}
+
 void astman_append(struct mansession *s, const char *fmt, ...)
 {
        va_list ap;
@@ -424,6 +450,77 @@ static int handle_showmancmd(int fd, int argc, char *argv[])
        return RESULT_SUCCESS;
 }
 
+static int handle_showmanager(int fd, int argc, char *argv[])
+{
+       struct ast_manager_user *user = NULL;
+
+       if (argc != 4)
+               return RESULT_SHOWUSAGE;
+
+       AST_LIST_LOCK(&users);
+
+       if (!(user = ast_get_manager_by_name_locked(argv[3]))) {
+               ast_cli(fd, "There is no manager called %s\n", argv[3]);
+               AST_LIST_UNLOCK(&users);
+               return -1;
+       }
+
+       ast_cli(fd,"\n");
+       ast_cli(fd,
+               "       username: %s\n"
+               "         secret: %s\n"
+               "           deny: %s\n"
+               "         permit: %s\n"
+               "           read: %s\n"
+               "          write: %s\n"
+               "displayconnects: %s\n",
+               (user->username ? user->username : "(N/A)"),
+               (user->secret ? user->secret : "(N/A)"),
+               (user->deny ? user->deny : "(N/A)"),
+               (user->permit ? user->permit : "(N/A)"),
+               (user->read ? user->read : "(N/A)"),
+               (user->write ? user->write : "(N/A)"),
+               (user->displayconnects ? "yes" : "no"));
+
+       AST_LIST_UNLOCK(&users);
+
+       return RESULT_SUCCESS;
+}
+
+
+static int handle_showmanagers(int fd, int argc, char *argv[])
+{
+       struct ast_manager_user *user = NULL;
+       int count_amu = 0;
+
+       if (argc != 3)
+               return RESULT_SHOWUSAGE;
+
+       AST_LIST_LOCK(&users);
+
+       /* If there are no users, print out something along those lines */
+       if (AST_LIST_EMPTY(&users)) {
+               ast_cli(fd, "There are no manager users.\n");
+               AST_LIST_UNLOCK(&users);
+               return RESULT_SUCCESS;
+       }
+
+       ast_cli(fd, "\nusername\n--------\n");
+
+       AST_LIST_TRAVERSE(&users, user, list) {
+               ast_cli(fd, "%s\n", user->username);
+               count_amu++;
+       }
+
+       AST_LIST_UNLOCK(&users);
+
+       ast_cli(fd,"-------------------\n");
+       ast_cli(fd,"%d manager users configured.\n", count_amu);
+
+       return RESULT_SUCCESS;
+}
+
+
 /*! \brief  CLI command 
        Should change to "manager show commands" */
 static int handle_showmancmds(int fd, int argc, char *argv[])
@@ -478,38 +575,77 @@ static int handle_showmaneventq(int fd, int argc, char *argv[])
 }
 
 static char showmancmd_help[] = 
-"Usage: show manager command <actionname>\n"
+"Usage: manager show command <actionname>\n"
 "      Shows the detailed description for a specific Asterisk manager interface command.\n";
 
 static char showmancmds_help[] = 
-"Usage: show manager commands\n"
+"Usage: manager list commands\n"
 "      Prints a listing of all the available Asterisk manager interface commands.\n";
 
 static char showmanconn_help[] = 
-"Usage: show manager connected\n"
+"Usage: manager list connected\n"
 "      Prints a listing of the users that are currently connected to the\n"
 "Asterisk manager interface.\n";
 
 static char showmaneventq_help[] = 
-"Usage: show manager eventq\n"
+"Usage: manager list eventq\n"
 "      Prints a listing of all events pending in the Asterisk manger\n"
 "event queue.\n";
 
-static struct ast_cli_entry show_mancmd_cli =
-       { { "show", "manager", "command", NULL },
-       handle_showmancmd, "Show a manager interface command", showmancmd_help, complete_show_mancmd };
-
-static struct ast_cli_entry show_mancmds_cli =
-       { { "show", "manager", "commands", NULL },
-       handle_showmancmds, "List manager interface commands", showmancmds_help };
-
-static struct ast_cli_entry show_manconn_cli =
-       { { "show", "manager", "connected", NULL },
-       handle_showmanconn, "Show connected manager interface users", showmanconn_help };
-
-static struct ast_cli_entry show_maneventq_cli =
-       { { "show", "manager", "eventq", NULL },
-       handle_showmaneventq, "Show manager interface queued events", showmaneventq_help };
+static char showmanagers_help[] =
+"Usage: manager list users\n"
+"       Prints a listing of all managers that are currently configured on that\n"
+" system.\n";
+
+static char showmanager_help[] =
+" Usage: manager show user <user>\n"
+"        Display all information related to the manager user specified.\n";
+
+static struct ast_cli_entry cli_show_manager_command_deprecated = {
+       { "show", "manager", "command", NULL },
+       handle_showmancmd, NULL,
+       NULL, complete_show_mancmd };
+
+static struct ast_cli_entry cli_show_manager_commands_deprecated = {
+       { "show", "manager", "commands", NULL },
+       handle_showmancmds, NULL,
+       NULL };
+
+static struct ast_cli_entry cli_show_manager_connected_deprecated = {
+       { "show", "manager", "connected", NULL },
+       handle_showmanconn, NULL,
+       NULL };
+
+static struct ast_cli_entry cli_show_manager_eventq_deprecated = {
+       { "show", "manager", "eventq", NULL },
+       handle_showmaneventq, NULL,
+       NULL };
+
+static struct ast_cli_entry cli_manager[] = {
+       { { "manager", "show", "command", NULL },
+       handle_showmancmd, "Show a manager interface command",
+       showmancmd_help, complete_show_mancmd, &cli_show_manager_command_deprecated },
+
+       { { "manager", "list", "commands", NULL },
+       handle_showmancmds, "List manager interface commands",
+       showmancmds_help, NULL, &cli_show_manager_commands_deprecated },
+
+       { { "manager", "list", "connected", NULL },
+       handle_showmanconn, "List connected manager interface users",
+       showmanconn_help, NULL, &cli_show_manager_connected_deprecated },
+
+       { { "manager", "list", "eventq", NULL },
+       handle_showmaneventq, "List manager interface queued events",
+       showmaneventq_help, NULL, &cli_show_manager_eventq_deprecated },
+
+       { { "manager", "list", "users", NULL },
+       handle_showmanagers, "List configured manager users",
+       showmanagers_help, NULL, NULL },
+
+       { { "manager", "show", "user", NULL },
+       handle_showmanager, "Display information on a specific manager user",
+       showmanager_help, NULL, NULL },
+};
 
 static void unuse_eventqent(struct eventqent *e)
 {
@@ -947,6 +1083,7 @@ static char mandescr_updateconfig[] =
 "Variables (X's represent 6 digit number beginning with 000000):\n"
 "   SrcFilename:   Configuration filename to read(e.g. foo.conf)\n"
 "   DstFilename:   Configuration filename to write(e.g. foo.conf)\n"
+"   Reload:        Whether or not a reload should take place (or name of specific module)\n"
 "   Action-XXXXXX: Action to Take (NewCat,RenameCat,DelCat,Update,Delete,Append)\n"
 "   Cat-XXXXXX:    Category to operate on\n"
 "   Var-XXXXXX:    Variable to work on\n"
@@ -961,6 +1098,7 @@ static int action_updateconfig(struct mansession *s, struct message *m)
        int res;
        char idText[256] = "";
        char *id = astman_get_header(m, "ActionID");
+       char *rld = astman_get_header(m, "Reload");
 
        if (!ast_strlen_zero(id))
                snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
@@ -981,6 +1119,11 @@ static int action_updateconfig(struct mansession *s, struct message *m)
                return 0;
        }
        astman_append(s, "Response: Success\r\n%s\r\n", idText);
+       if (!ast_strlen_zero(rld)) {
+               if (ast_true(rld))
+                       rld = NULL;
+               ast_module_reload(rld); 
+       }
        return 0;
 }
 
@@ -2442,14 +2585,16 @@ static int webregged = 0;
 
 int init_manager(void)
 {
-       struct ast_config *cfg;
-       char *val;
+       struct ast_config *cfg = NULL;
+       char *val, *cat = NULL;
        int oldportno = portno;
        static struct sockaddr_in ba;
        int x = 1;
        int flags;
        int webenabled = 0;
        int newhttptimeout = 60;
+       struct ast_manager_user *user = NULL;
+
        if (!registered) {
                /* Register default actions */
                ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
@@ -2472,10 +2617,7 @@ int init_manager(void)
                ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
                ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
 
-               ast_cli_register(&show_mancmd_cli);
-               ast_cli_register(&show_mancmds_cli);
-               ast_cli_register(&show_manconn_cli);
-               ast_cli_register(&show_maneventq_cli);
+               ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
                ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
                registered = 1;
                /* Append placeholder event so master_eventq never runs dry */
@@ -2537,6 +2679,83 @@ int init_manager(void)
                ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
 #endif
        }
+
+       AST_LIST_LOCK(&users);
+
+       while ((cat = ast_category_browse(cfg, cat))) {
+               struct ast_variable *var = NULL;
+
+               if (!strcasecmp(cat, "general"))
+                       continue;
+
+               /* Look for an existing entry, if none found - create one and add it to the list */
+               if (!(user = ast_get_manager_by_name_locked(cat))) {
+                       if (!(user = ast_calloc(1, sizeof(*user))))
+                               break;
+                       /* Copy name over */
+                       ast_copy_string(user->username, cat, sizeof(user->username));
+                       /* Insert into list */
+                       AST_LIST_INSERT_TAIL(&users, user, list);
+               }
+
+               /* Make sure we keep this user and don't destroy it during cleanup */
+               user->keep = 1;
+
+               var = ast_variable_browse(cfg, cat);
+               while (var) {
+                       if (!strcasecmp(var->name, "secret")) {
+                               if (user->secret)
+                                       free(user->secret);
+                               user->secret = ast_strdup(var->value);
+                       } else if (!strcasecmp(var->name, "deny") ) {
+                               if (user->deny)
+                                       free(user->deny);
+                               user->deny = ast_strdup(var->value);
+                       } else if (!strcasecmp(var->name, "permit") ) {
+                               if (user->permit)
+                                       free(user->permit);
+                               user->permit = ast_strdup(var->value);
+                       }  else if (!strcasecmp(var->name, "read") ) {
+                               if (user->read)
+                                       free(user->read);
+                               user->read = ast_strdup(var->value);
+                       }  else if (!strcasecmp(var->name, "write") ) {
+                               if (user->write)
+                                       free(user->write);
+                               user->write = ast_strdup(var->value);
+                       }  else if (!strcasecmp(var->name, "displayconnects") )
+                               user->displayconnects = ast_true(var->value);
+                       else
+                               ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
+                       var = var->next;
+               }
+       }
+
+       /* Perform cleanup - essentially prune out old users that no longer exist */
+       AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
+               if (user->keep) {
+                       user->keep = 0;
+                       continue;
+               }
+               /* We do not need to keep this user so take them out of the list */
+               AST_LIST_REMOVE_CURRENT(&users, list);
+               /* Free their memory now */
+               if (user->secret)
+                       free(user->secret);
+               if (user->deny)
+                       free(user->deny);
+               if (user->permit)
+                       free(user->permit);
+               if (user->read)
+                       free(user->read);
+               if (user->write)
+                       free(user->write);
+               free(user);
+       }
+       AST_LIST_TRAVERSE_SAFE_END
+
+       AST_LIST_UNLOCK(&users);
+
        ast_config_destroy(cfg);
        
        if (webenabled && enabled) {