session: support negative group expressions
[project/rpcd.git] / session.c
index 784d7b9870e54e2a31ce87bd34377e4427f70de3..3cac6d95da48802c3cd8243f6c7ef4809bb2056a 100644 (file)
--- a/session.c
+++ b/session.c
@@ -203,7 +203,7 @@ rpc_session_dump_acls(struct rpc_session *ses, struct blob_buf *b)
 }
 
 static void
-rpc_session_to_blob(struct rpc_session *ses)
+rpc_session_to_blob(struct rpc_session *ses, bool acls)
 {
        void *c;
 
@@ -213,6 +213,12 @@ rpc_session_to_blob(struct rpc_session *ses)
        blobmsg_add_u32(&buf, "timeout", ses->timeout);
        blobmsg_add_u32(&buf, "expires", uloop_timeout_remaining(&ses->t) / 1000);
 
+       if (acls) {
+               c = blobmsg_open_table(&buf, "acls");
+               rpc_session_dump_acls(ses, &buf);
+               blobmsg_close_table(&buf, c);
+       }
+
        c = blobmsg_open_table(&buf, "data");
        rpc_session_dump_data(ses, &buf);
        blobmsg_close_table(&buf, c);
@@ -222,7 +228,7 @@ static void
 rpc_session_dump(struct rpc_session *ses, struct ubus_context *ctx,
                  struct ubus_request_data *req)
 {
-       rpc_session_to_blob(ses);
+       rpc_session_to_blob(ses, true);
 
        ubus_send_reply(ctx, req, buf.head);
 }
@@ -621,7 +627,7 @@ rpc_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
                struct blob_attr *msg)
 {
        struct rpc_session *ses;
-       struct blob_attr *tb[__RPC_SA_MAX];
+       struct blob_attr *tb[__RPC_SS_MAX];
        struct blob_attr *attr;
        int rem;
 
@@ -651,7 +657,7 @@ rpc_handle_get(struct ubus_context *ctx, struct ubus_object *obj,
 {
        struct rpc_session *ses;
        struct rpc_session_data *data;
-       struct blob_attr *tb[__RPC_SA_MAX];
+       struct blob_attr *tb[__RPC_SG_MAX];
        struct blob_attr *attr;
        void *c;
        int rem;
@@ -857,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;
 
@@ -877,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 */
@@ -1296,7 +1324,7 @@ void rpc_session_freeze(void)
                        continue;
 
                snprintf(path, sizeof(path) - 1, RPC_SESSION_DIRECTORY "/%s", ses->id);
-               rpc_session_to_blob(ses);
+               rpc_session_to_blob(ses, false);
                rpc_blob_to_file(path, buf.head);
        }
 }