]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
manager.c: Add unit test for Originate app and appdata permissions
authorGeorge Joseph <gjoseph@sangoma.com>
Thu, 3 Oct 2024 15:10:36 +0000 (09:10 -0600)
committerGeorge Joseph <gjoseph@sangoma.com>
Tue, 8 Oct 2024 13:39:59 +0000 (13:39 +0000)
This unit test checks that dialplan apps and app data specified
as parameters for the Originate action are allowed with the
permissions the user has.

main/manager.c

index 69bfd8e5d3df8bd4ece6f1eecd92ff58a7fa6b99..e599da71a0544b7425a512b009d5af7f02401c4c 100644 (file)
@@ -6280,6 +6280,9 @@ static int app_match(const char *app, const char *data, const char *search)
  */
 static int appdata_match(const char *app, const char *data, const char *search)
 {
+       if (ast_strlen_zero(data)) {
+               return 0;
+       }
        return !!(strstr(data, search));
 }
 
@@ -6310,7 +6313,7 @@ static int queue_match(const char *app, const char *data, const char *search)
                AST_APP_ARG(position);
        );
 
-       if (!strcasestr(app, "queue")) {
+       if (!strcasestr(app, "queue") || ast_strlen_zero(data)) {
                return 0;
        }
 
@@ -6382,6 +6385,98 @@ static int is_originate_app_permitted(const char *app, const char *data,
        return 1;
 }
 
+#ifdef TEST_FRAMEWORK
+#define ALL_PERMISSIONS (INT_MAX)
+#define NO_PERMISSIONS (0)
+AST_TEST_DEFINE(originate_permissions_test)
+{
+       enum ast_test_result_state res = AST_TEST_PASS;
+
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = "originate_permissions_test";
+               info->category = "/main/manager/";
+               info->summary = "Test permissions for originate action";
+               info->description =
+                       "Make sure that dialplan apps/functions that need special "
+                       "permissions are prohibited if the user doesn't have the permission.";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
+       }
+
+       /*
+        * Check application matching. We don't need to check every one.
+        * The code is the same.
+        */
+
+       ast_test_validate(test, is_originate_app_permitted("exec",
+               NULL, EVENT_FLAG_SYSTEM), "exec permission check failed");
+       ast_test_validate(test, is_originate_app_permitted("exec",
+               NULL, EVENT_FLAG_SYSTEM | EVENT_FLAG_AGI), "exec check permission failed");
+       ast_test_validate(test, is_originate_app_permitted("exec",
+               NULL, ALL_PERMISSIONS), "exec check permission failed");
+       ast_test_validate(test, !is_originate_app_permitted("exec",
+               NULL, EVENT_FLAG_AGI), "exec permission check failed");
+       ast_test_validate(test, !is_originate_app_permitted("exec",
+               NULL, EVENT_FLAG_VERBOSE), "exec permission check failed");
+       ast_test_validate(test, !is_originate_app_permitted("exec",
+               NULL, NO_PERMISSIONS), "exec permission check failed");
+
+       /*
+        * If queue is used with the AGI parameter but without the SYSTEM or AGI
+        * permission, it should be denied. Queue param order:
+        * queuename,options,url,announceoverride,queuetimeoutstr,AGI,gosub,rule,position
+        * The values of the options aren't checked. They just have to be present.
+        */
+
+       /* AGI not specified should always be allowed */
+       ast_test_validate(test, is_originate_app_permitted("queue",
+               NULL, NO_PERMISSIONS), "Queue permission check failed");
+       ast_test_validate(test, is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,,gosub,rule,666",
+               EVENT_FLAG_ORIGINATE | EVENT_FLAG_HOOKRESPONSE ), "Queue permission check failed");
+
+       /* AGI specified with SYSTEM or AGI permission should be allowed */
+       ast_test_validate(test, is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,SomeAGIScript,gosub,rule,666",
+               EVENT_FLAG_SYSTEM | EVENT_FLAG_HOOKRESPONSE ), "Queue permission check failed");
+       ast_test_validate(test, is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,SomeAGIScript,gosub,rule,666",
+               EVENT_FLAG_AGI | EVENT_FLAG_HOOKRESPONSE ), "Queue permission check failed");
+       ast_test_validate(test, is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,SomeAGIScript,gosub,rule,666",
+               ALL_PERMISSIONS), "Queue permission check failed");
+
+       /* AGI specified without SYSTEM or AGI permission should be denied */
+       ast_test_validate(test, !is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,SomeAGIScript,gosub,rule,666",
+               NO_PERMISSIONS), "Queue permission check failed");
+       ast_test_validate(test, !is_originate_app_permitted("queue",
+               "somequeue,CcdHh,someURL,tt-monkeys,100,SomeAGIScript,gosub,rule,666",
+               EVENT_FLAG_ORIGINATE | EVENT_FLAG_HOOKRESPONSE ), "Queue permission check failed");
+
+       /*
+        * Check appdata.  The function name can appear anywhere in appdata.
+        */
+       ast_test_validate(test, is_originate_app_permitted("someapp",
+               "aaaDBbbb", EVENT_FLAG_SYSTEM), "exec permission check failed");
+       ast_test_validate(test, is_originate_app_permitted("someapp",
+               "aaa DB bbb", ALL_PERMISSIONS), "exec permission check failed");
+       ast_test_validate(test, !is_originate_app_permitted("someapp",
+               "aaaDBbbb", NO_PERMISSIONS), "exec permission check failed");
+       ast_test_validate(test, !is_originate_app_permitted("someapp",
+               "aaa DB bbb", NO_PERMISSIONS), "exec permission check failed");
+       /* The check is case-sensitive so although DB is a match, db isn't. */
+       ast_test_validate(test, is_originate_app_permitted("someapp",
+               "aaa db bbb", NO_PERMISSIONS), "exec permission check failed");
+
+       return res;
+}
+#undef ALL_PERMISSIONS
+#undef NO_PERMISSIONS
+#endif
+
 static int action_originate(struct mansession *s, const struct message *m)
 {
        const char *name = astman_get_header(m, "Channel");
@@ -9820,6 +9915,10 @@ static void manager_shutdown(void)
 {
        struct ast_manager_user *user;
 
+#ifdef TEST_FRAMEWORK
+       AST_TEST_UNREGISTER(originate_permissions_test);
+#endif
+
        /* This event is not actually transmitted, but causes all TCP sessions to be closed */
        manager_event(EVENT_FLAG_SHUTDOWN, "CloseSession", "CloseSession: true\r\n");
 
@@ -10521,9 +10620,14 @@ static int unload_module(void)
 
 static int load_module(void)
 {
+       int rc = 0;
        ast_register_cleanup(manager_shutdown);
 
-       return __init_manager(0, 0) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
+       rc = __init_manager(0, 0) ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SUCCESS;
+#ifdef TEST_FRAMEWORK
+       AST_TEST_REGISTER(originate_permissions_test);
+#endif
+       return rc;
 }
 
 static int reload_module(void)