session: support negative group expressions
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 12 Sep 2013 11:10:30 +0000 (13:10 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 12 Sep 2013 11:10:30 +0000 (13:10 +0200)
This change allows excluding specific groups after a wildcard expression.
The following example would grant read access to any acl group except the
group named "example".

  list read '*'
  list read '!example'

session.c

index dad7bf1ccede4be3fc4f692175f4e964c49f4a04..3cac6d95da48802c3cd8243f6c7ef4809bb2056a 100644 (file)
--- a/session.c
+++ b/session.c
@@ -863,6 +863,7 @@ static bool
 rpc_login_test_permission(struct uci_section *s,
                           const char *perm, const char *group)
 {
+       const char *p;
        struct uci_option *o;
        struct uci_element *e, *l;
 
@@ -883,9 +884,30 @@ rpc_login_test_permission(struct uci_section *s,
                if (strcmp(o->e.name, perm))
                        continue;
 
-               uci_foreach_element(&o->v.list, l)
-                       if (l->name && !fnmatch(l->name, group, 0))
+               /* Match negative expressions first. If a negative expression matches
+                * the current group name then deny access. */
+               uci_foreach_element(&o->v.list, l) {
+                       p = l->name;
+
+                       if (!p || *p != '!')
+                               continue;
+
+                       while (isspace(*++p));
+
+                       if (!*p)
+                               continue;
+
+                       if (!fnmatch(p, group, 0))
+                               return false;
+               }
+
+               uci_foreach_element(&o->v.list, l) {
+                       if (!l->name || !*l->name || *l->name == '!')
+                               continue;
+
+                       if (!fnmatch(l->name, group, 0))
                                return true;
+               }
        }
 
        /* make sure that write permission implies read permission */