diff options
author | Olle Johansson <oej@edvina.net> | 2007-12-16 13:32:48 +0000 |
---|---|---|
committer | Olle Johansson <oej@edvina.net> | 2007-12-16 13:32:48 +0000 |
commit | 130fe4000a9ce1fd28dd2362db1e0ee23b05ef68 (patch) | |
tree | 58e0ee6c8be17a7a17c08aad101e1c03da93a8c6 | |
parent | df17bc73f01b18d85c2c322bb546323c2c57f5d2 (diff) |
Change manager so that registered accounts are stored in memory. This opens for a
manager realtime implementation.
If you change accounts in manager.conf, you now need to reload to activate the
changes (deletions, additions). This was not the case with 1.4.
Reported by: ys
Patches:
trunk93163_manager_reload.c.diff uploaded by ys (license 281)
(closes issue #11414)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@93165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | CHANGES | 13 | ||||
-rw-r--r-- | main/manager.c | 305 |
2 files changed, 152 insertions, 166 deletions
@@ -11,7 +11,7 @@ AMI - The manager (TCP/TLS/HTTP) * Added the URI redirect option for the built-in HTTP server * The output of CallerID in Manager events is now more consistent. CallerIDNum is used for number and CallerIDName for name. - * enable https support for builtin web server. + * Enable https support for builtin web server. See configs/http.conf.sample for details. * Added a new action, GetConfigJSON, which can return the contents of an Asterisk configuration file in JSON format. This is intended to help @@ -27,6 +27,10 @@ AMI - The manager (TCP/TLS/HTTP) * Added 'DBDel' and 'DBDelTree' manager commands. * cdr_manager now reports events via the "cdr" level, separating it from the very verbose "call" level. + * Manager users are now stored in memory. If you change the manager account + list (delete or add accounts) you need to reload manager. + * Added Masquerade manager event for when a masquerade happens between + two channels. Dialplan functions ------------------ @@ -112,6 +116,10 @@ IAX2 changes * Added support for OSP. The token is set and retrieved through the CHANNEL() dialplan function. +XMPP Google Talk/Jingle changes +------------------------------- + * Added the bindaddr option to gtalk.conf. + Skinny changes ------------- * Added skinny show device, skinny show line, and skinny show settings CLI commands. @@ -337,7 +345,6 @@ AGI Changes Miscellaneous ------------- - * Added the bindaddr option to gtalk.conf. * Ability to use libcap to set high ToS bits when non-root on Linux. If configure is unable to find libcap then you can use --with-cap to specify the path. @@ -349,8 +356,6 @@ Miscellaneous command to be run after rotation. This is primarily useful with rotatestrategry=rotate, to allow a limit on the number of logfiles kept and to ensure that the oldest log file gets deleted. - * Added Masquerade manager event for when a masquerade happens between - two channels. * Added maxfiles option to options section of asterisk.conf which allows you to specify what Asterisk should set as the maximum number of open files when it loads. * Added the jittertargetextra configuration option. diff --git a/main/manager.c b/main/manager.c index 4a7c59474..d46ae3760 100644 --- a/main/manager.c +++ b/main/manager.c @@ -167,10 +167,10 @@ static AST_LIST_HEAD_STATIC(sessions, mansession); struct ast_manager_user { char username[80]; char *secret; - char *deny; - char *permit; - char *read; - char *write; + struct ast_ha *ha; /*!< ACL setting */ + int readperm; /*! Authorization for reading */ + int writeperm; /*! Authorization for writing */ + int writetimeout; /*! Per user Timeout for ast_carefulwrite() */ int displayconnects; /*!< XXX unused */ int keep; /*!< mark entries created on a reload */ AST_RWLIST_ENTRY(ast_manager_user) list; @@ -519,6 +519,9 @@ static char *handle_showmanager(struct ast_cli_entry *e, int cmd, struct ast_cli struct ast_manager_user *user = NULL; int l, which; char *ret = NULL; + struct ast_str *rauthority = ast_str_alloca(80); + struct ast_str *wauthority = ast_str_alloca(80); + switch (cmd) { case CLI_INIT: e->command = "manager show user"; @@ -557,17 +560,15 @@ static char *handle_showmanager(struct ast_cli_entry *e, int cmd, struct ast_cli ast_cli(a->fd, " username: %s\n" " secret: %s\n" - " deny: %s\n" - " permit: %s\n" - " read: %s\n" - " write: %s\n" + " acl: %s\n" + " read perm: %s\n" + " write perm: %s\n" "displayconnects: %s\n", (user->username ? user->username : "(N/A)"), (user->secret ? "<Set>" : "(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->ha ? "yes" : "no"), + authority_to_str(user->readperm, &rauthority), + authority_to_str(user->writeperm, &wauthority), (user->displayconnects ? "yes" : "no")); AST_RWLIST_UNLOCK(&users); @@ -956,118 +957,22 @@ static int set_eventmask(struct mansession *s, const char *eventmask) /* helper function for action_login() */ static int authenticate(struct mansession *s, const struct message *m) { - const char *user = astman_get_header(m, "Username"); + const char *username = astman_get_header(m, "Username"); + const char *password = astman_get_header(m, "Secret"); int error = -1; - struct ast_ha *ha = NULL; - char *password = NULL; - int readperm = 0, writeperm = 0; - struct ast_flags config_flags = { 0 }; - - if (ast_strlen_zero(user)) /* missing username */ - return -1; - - { - /* - * XXX there should be no need to scan the config file again here, - * suffices to call get_manager_by_name_locked() to fetch - * the user's entry. - */ - struct ast_config *cfg = ast_config_load("manager.conf", config_flags); - char *cat = NULL; - struct ast_variable *v; + struct ast_manager_user *user = NULL; - if (!cfg) + if (ast_strlen_zero(username)) /* missing username */ return -1; - while ( (cat = ast_category_browse(cfg, cat)) ) { - /* "general" is not a valid user */ - if (strcasecmp(cat, user) || !strcasecmp(cat, "general")) - continue; - /* collect parameters for the user's entry */ - for (v = ast_variable_browse(cfg, cat); v; v = v->next) { - if (!strcasecmp(v->name, "secret")) - password = ast_strdupa(v->value); - else if (!strcasecmp(v->name, "read")) - readperm = get_perm(v->value); - else if (!strcasecmp(v->name, "write")) - writeperm = get_perm(v->value); - else if (!strcasecmp(v->name, "permit") || - !strcasecmp(v->name, "deny")) { - ha = ast_append_ha(v->name, v->value, ha, NULL); - } else if (!strcasecmp(v->name, "writetimeout")) { - int val = atoi(v->value); - - if (val < 100) - ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", v->value, v->lineno); - else - s->writetimeout = val; - } - } - break; - } - ast_config_destroy(cfg); - if (!cat) { - /* Didn't find the user in manager.conf, check users.conf */ - int hasmanager = 0; - cfg = ast_config_load("users.conf", config_flags); - if (!cfg) - return -1; - while ( (cat = ast_category_browse(cfg, cat)) ) { - if (!strcasecmp(cat, user) && strcasecmp(cat, "general")) - break; - } - if (!cat) { - ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user); - ast_config_destroy(cfg); - return -1; - } - /* collect parameters for the user's entry from users.conf */ - for (v = ast_variable_browse(cfg, cat); v; v = v->next) { - if (!strcasecmp(v->name, "secret")) - password = ast_strdupa(v->value); - else if (!strcasecmp(v->name, "read")) - readperm = get_perm(v->value); - else if (!strcasecmp(v->name, "write")) - writeperm = get_perm(v->value); - else if (!strcasecmp(v->name, "permit") || - !strcasecmp(v->name, "deny")) { - ha = ast_append_ha(v->name, v->value, ha, NULL); - } else if (!strcasecmp(v->name, "writetimeout")) { - int val = atoi(v->value); - - if (val < 100) - ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", v->value, v->lineno); - else - s->writetimeout = val; - } else if (!strcasecmp(v->name, "hasmanager")) - hasmanager = ast_true(v->value); - else if (!strcasecmp(v->name, "managerread")) - readperm = get_perm(v->value); - else if (!strcasecmp(v->name, "managerwrite")) - writeperm = get_perm(v->value); - } - ast_config_destroy(cfg); - if (!hasmanager) { - ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user); - return -1; - } - if (!readperm) - readperm = -1; - if (!writeperm) - writeperm = -1; - } - - } + /* locate user in locked state */ + AST_RWLIST_WRLOCK(&users); - if (ha) { - int good = ast_apply_ha(ha, &(s->sin)); - ast_free_ha(ha); - if (!good) { - ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user); - return -1; - } - } - if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { + if (!(user = get_manager_by_name_locked(username))) { + ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username); + } else if (user->ha && !ast_apply_ha(user->ha, &(s->sin))) { + ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username); + } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { const char *key = astman_get_header(m, "Key"); if (!ast_strlen_zero(key) && !ast_strlen_zero(s->challenge) && !ast_strlen_zero(password)) { @@ -1088,22 +993,26 @@ static int authenticate(struct mansession *s, const struct message *m) } else { ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", S_OR(s->challenge, "")); - return -1; } - } else if (password) { - const char *pass = astman_get_header(m, "Secret"); - if (!strcmp(password, pass)) - error = 0; - } + } else if (password && user->secret && !strcmp(password, user->secret)) + error = 0; + if (error) { - ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), user); + ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->sin.sin_addr), username); + AST_RWLIST_UNLOCK(&users); return -1; } - ast_copy_string(s->username, user, sizeof(s->username)); - s->readperm = readperm; - s->writeperm = writeperm; + + /* auth complete */ + + ast_copy_string(s->username, username, sizeof(s->username)); + s->readperm = user->readperm; + s->writeperm = user->writeperm; + s->writetimeout = user->writetimeout; s->sessionstart = time(NULL); set_eventmask(s, astman_get_header(m, "Events")); + + AST_RWLIST_UNLOCK(&users); return 0; } @@ -3409,7 +3318,7 @@ static struct server_args amis_desc = { static int __init_manager(int reload) { - struct ast_config *cfg = NULL; + struct ast_config *ucfg = NULL, *cfg = NULL; const char *val; char *cat = NULL; int newhttptimeout = 60; @@ -3461,7 +3370,7 @@ static int __init_manager(int reload) displayconnects = 1; if (!cfg) { - ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); + ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf. Asterisk management interface (AMI) disabled.\n"); return 0; } @@ -3537,7 +3446,83 @@ static int __init_manager(int reload) AST_RWLIST_WRLOCK(&users); + /* First, get users from users.conf */ + ucfg = ast_config_load("users.conf", config_flags); + if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED)) { + const char *hasmanager; + int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager")); + + while ((cat = ast_category_browse(ucfg, cat))) { + if (!strcasecmp(cat, "general")) + continue; + + hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager"); + if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) { + const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret"); + const char *user_read = ast_variable_retrieve(ucfg, cat, "read"); + const char *user_write = ast_variable_retrieve(ucfg, cat, "write"); + const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects"); + const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout"); + + /* Look for an existing entry, + * if none found - create one and add it to the list + */ + if (!(user = 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); + user->ha = NULL; + user->readperm = -1; + user->writeperm = -1; + /* Default displayconnect from [general] */ + user->displayconnects = displayconnects; + user->writetimeout = 100; + } + + if (!user_secret) + user_secret = ast_variable_retrieve(ucfg, "general", "secret"); + if (!user_read) + user_read = ast_variable_retrieve(ucfg, "general", "read"); + if (!user_write) + user_write = ast_variable_retrieve(ucfg, "general", "write"); + if (!user_displayconnects) + user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); + if (!user_writetimeout) + user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); + + if (!ast_strlen_zero(user_secret)) { + if (user->secret) + ast_free(user->secret); + user->secret = ast_strdup(user_secret); + } + + if (user_read) + user->readperm = get_perm(user_read); + if (user_write) + user->writeperm = get_perm(user_write); + if (user_displayconnects) + user->displayconnects = ast_true(user_displayconnects); + + if (user_writetimeout) { + int val = atoi(user_writetimeout); + if (val < 100) + ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno); + else + user->writetimeout = val; + } + } + } + ast_config_destroy(ucfg); + } + + /* cat is NULL here in any case */ + while ((cat = ast_category_browse(cfg, cat))) { + struct ast_ha *oldha; if (!strcasecmp(cat, "general")) continue; @@ -3548,45 +3533,50 @@ static int __init_manager(int reload) break; /* Copy name over */ ast_copy_string(user->username, cat, sizeof(user->username)); + + user->ha = NULL; + user->readperm = 0; + user->writeperm = 0; + /* Default displayconnect from [general] */ + user->displayconnects = displayconnects; + user->writetimeout = 100; + /* Insert into list */ AST_RWLIST_INSERT_TAIL(&users, user, list); } /* Make sure we keep this user and don't destroy it during cleanup */ user->keep = 1; - /* Default displayconnect to [general] */ - user->displayconnects = displayconnects; + oldha = user->ha; + user->ha = NULL; var = ast_variable_browse(cfg, cat); - while (var) { + for (; var; var = var->next) { if (!strcasecmp(var->name, "secret")) { if (user->secret) ast_free(user->secret); user->secret = ast_strdup(var->value); - } else if (!strcasecmp(var->name, "deny") ) { - if (user->deny) - ast_free(user->deny); - user->deny = ast_strdup(var->value); - } else if (!strcasecmp(var->name, "permit") ) { - if (user->permit) - ast_free(user->permit); - user->permit = ast_strdup(var->value); + } else if (!strcasecmp(var->name, "deny") || + !strcasecmp(var->name, "permit")) { + user->ha = ast_append_ha(var->name, var->value, user->ha, NULL); } else if (!strcasecmp(var->name, "read") ) { - if (user->read) - ast_free(user->read); - user->read = ast_strdup(var->value); + user->readperm = get_perm(var->value); } else if (!strcasecmp(var->name, "write") ) { - if (user->write) - ast_free(user->write); - user->write = ast_strdup(var->value); - } else if (!strcasecmp(var->name, "displayconnects") ) + user->writeperm = get_perm(var->value); + } else if (!strcasecmp(var->name, "displayconnects") ) { user->displayconnects = ast_true(var->value); - else { + } else if (!strcasecmp(var->name, "writetimeout")) { + int val = atoi(var->value); + if (val < 100) + ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); + else + user->writetimeout = val; + } else ast_debug(1, "%s is an unknown option.\n", var->name); - } - var = var->next; } + ast_free_ha(oldha); } + ast_config_destroy(cfg); /* Perform cleanup - essentially prune out old users that no longer exist */ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { @@ -3599,22 +3589,13 @@ static int __init_manager(int reload) /* Free their memory now */ if (user->secret) ast_free(user->secret); - if (user->deny) - ast_free(user->deny); - if (user->permit) - ast_free(user->permit); - if (user->read) - ast_free(user->read); - if (user->write) - ast_free(user->write); + ast_free_ha(user->ha); ast_free(user); } AST_RWLIST_TRAVERSE_SAFE_END; AST_RWLIST_UNLOCK(&users); - ast_config_destroy(cfg); - if (webmanager_enabled && manager_enabled) { if (!webregged) { ast_http_uri_link(&rawmanuri); |