Index: main/manager.c =================================================================== --- main/manager.c (revision 104172) +++ main/manager.c (working copy) @@ -158,6 +158,7 @@ time_t sessiontimeout; /*!< Session timeout if HTTP */ char username[80]; /*!< Logged in username */ char challenge[10]; /*!< Authentication challenge */ + char *contexts; /*!< Originate contexts */ int authenticated; /*!< Authentication status */ int readperm; /*!< Authorization for reading */ int writeperm; /*!< Authorization for writing */ @@ -183,11 +184,12 @@ struct ast_manager_user { char username[80]; char *secret; + char *contexts; /*!< Authorized contexts for Originate */ 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 readperm; /*!< Authorization for reading */ + int writeperm; /*!< Authorization for writing */ + int writetimeout; /*!< Per user Timeout for ast_carefulwrite() */ + int displayconnects; /*!< Whether to show on console when this user connects */ int keep; /*!< mark entries created on a reload */ AST_RWLIST_ENTRY(ast_manager_user) list; }; @@ -375,6 +377,49 @@ return 0; } +static void context_permit_item(char *specification, char **context, int *negate) +{ + *negate = 0; + *context = specification; + switch (specification[0]) { + case '-': + case '!': + *negate = 1; + /* Fall through */ + case '+': + *context = &specification[1]; + } +} + +static int context_permit(const char *specification, const char *context) +{ + char *spec, *found; + int i, negate, result = 0; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(arg)[100]; + ); + + spec = ast_strdupa(specification); + AST_STANDARD_APP_ARGS(args, spec); + + /* The two methods of specification are: + * 1) all,-context1,-context2 (all contexts except context1 and context2) + * 2) +context1,+context2 (only context1 and context2) + */ + for (i = 0; i < args.argc; i++) { + context_permit_item(args.arg[i], &found, &negate); + if (strcasecmp(found, "all") == 0 || strcmp(found, context) == 0) { + if (negate) { + result = 0; + } else { + result = 1; + } + } + } + + return result; +} + static int get_perm(const char *instr) { int x = 0, ret = 0; @@ -784,6 +829,9 @@ if (s->f != NULL) fclose(s->f); ast_mutex_destroy(&s->__lock); + if (s->contexts) { + ast_free(s->contexts); + } ast_free(s); unref_event(eqe); } @@ -1048,6 +1096,7 @@ s->writeperm = user->writeperm; s->writetimeout = user->writetimeout; s->sessionstart = time(NULL); + s->contexts = ast_strdup(user->contexts); set_eventmask(s, astman_get_header(m, "Events")); AST_RWLIST_UNLOCK(&users); @@ -2110,6 +2159,12 @@ astman_send_error(s, m, "Invalid timeout\n"); return 0; } + + if (!ast_strlen_zero(s->contexts) && !ast_strlen_zero(context) && !context_permit(s->contexts, context)) { + astman_send_error(s, m, "You are not permitted to originate calls in that context.\n"); + return 0; + } + ast_copy_string(tmp, name, sizeof(tmp)); tech = tmp; data = strchr(tmp, '/'); @@ -3778,6 +3833,7 @@ 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"); + const char *user_contexts = ast_variable_retrieve(ucfg, cat, "originatecontexts"); /* Look for an existing entry, * if none found - create one and add it to the list @@ -3808,6 +3864,8 @@ user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); if (!user_writetimeout) user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); + if (!user_contexts) + user_contexts = ast_variable_retrieve(ucfg, "general", "originatecontexts"); if (!ast_strlen_zero(user_secret)) { if (user->secret) @@ -3815,6 +3873,12 @@ user->secret = ast_strdup(user_secret); } + if (!ast_strlen_zero(user_contexts)) { + if (user->contexts) + ast_free(user->contexts); + user->contexts = ast_strdup(user_contexts); + } + if (user_read) user->readperm = get_perm(user_read); if (user_write) @@ -3886,6 +3950,8 @@ ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); else user->writetimeout = val; + } else if (!strcasecmp(var->name, "originatecontexts")) { + user->contexts = ast_strdup(val); } else ast_debug(1, "%s is an unknown option.\n", var->name); } @@ -3904,6 +3970,9 @@ /* Free their memory now */ if (user->secret) ast_free(user->secret); + if (user->contexts) { + ast_free(user->contexts); + } ast_free_ha(user->ha); ast_free(user); } Index: configs/manager.conf.sample =================================================================== --- configs/manager.conf.sample (revision 104172) +++ configs/manager.conf.sample (working copy) @@ -94,4 +94,7 @@ ; ;read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan ;write = system,call,agent,user,config,command,reporting +;originatecontexts = context1,context2 ; Allow originates from only context1 and context2 +;originatecontexts = all,-context1,-context2 ; Allow originates from all contexts except context1 and context2 +