CMakeLists.txt: bump minimum cmake version
[project/ubus.git] / ubusd_acl.c
index 992d0ea299366e25b7ee765207bcad208607c8e0..352c581c3d38b23c76ae520e66f1698e542b3e76 100644 (file)
@@ -26,6 +26,7 @@
 #include <libubox/vlist.h>
 #include <libubox/blobmsg_json.h>
 #include <libubox/avl-cmp.h>
+#include <libubox/ulog.h>
 
 #include "ubusd.h"
 
@@ -52,6 +53,7 @@ struct ubusd_acl_obj {
        bool subscribe;
        bool publish;
        bool listen;
+       bool send;
 };
 
 struct ubusd_acl_file {
@@ -115,7 +117,7 @@ ubusd_acl_check(struct ubus_client *cl, const char *obj,
                        if (!acl->partial)
                                continue;
 
-                       if (match_len != strlen(key))
+                       if (match_len != (int) strlen(key))
                                continue;
                }
 
@@ -138,15 +140,24 @@ ubusd_acl_check(struct ubus_client *cl, const char *obj,
                                return 0;
                        break;
 
+               case UBUS_ACL_SEND:
+                       if (acl->send)
+                               return 0;
+                       break;
+
                case UBUS_ACL_ACCESS:
                        if (acl->methods) {
                                struct blob_attr *cur;
-                               int rem;
+                               char *cur_method;
+                               size_t rem;
 
                                blobmsg_for_each_attr(cur, acl->methods, rem)
-                                       if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)
-                                               if (!strcmp(method, blobmsg_get_string(cur)))
+                                       if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING) {
+                                               cur_method = blobmsg_get_string(cur);
+
+                                               if (!strcmp(method, cur_method) || !strcmp("*", cur_method))
                                                        return 0;
+                                       }
                        }
                        break;
                }
@@ -165,19 +176,25 @@ ubusd_acl_init_client(struct ubus_client *cl, int fd)
 #ifdef SO_PEERCRED
        unsigned int len = sizeof(struct ucred);
 
-       if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
+       if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) {
+               ULOG_ERR("Failed getsockopt(): %m\n");
                return -1;
+       }
 #else
        memset(&cred, 0, sizeof(cred));
 #endif
 
        pwd = getpwuid(cred.uid);
-       if (!pwd)
+       if (!pwd) {
+               ULOG_ERR("Failed getpwuid(): %m\n");
                return -1;
+       }
 
        group = getgrgid(cred.gid);
-       if (!group)
+       if (!group) {
+               ULOG_ERR("Failed getgrgid(): %m\n");
                return -1;
+       }
 
        cl->uid = cred.uid;
        cl->gid = cred.gid;
@@ -292,6 +309,13 @@ static void ubusd_acl_add_listen(struct ubusd_acl_file *file, const char *obj)
        o->listen = true;
 }
 
+static void ubusd_acl_add_send(struct ubusd_acl_file *file, const char *obj)
+{
+       struct ubusd_acl_obj *o = ubusd_acl_alloc_obj(file, obj);
+
+       o->send = true;
+}
+
 enum {
        ACL_USER,
        ACL_GROUP,
@@ -300,6 +324,7 @@ enum {
        ACL_SUBSCRIBE,
        ACL_INHERIT,
        ACL_LISTEN,
+       ACL_SEND,
        __ACL_MAX
 };
 
@@ -311,13 +336,14 @@ static const struct blobmsg_policy acl_policy[__ACL_MAX] = {
        [ACL_SUBSCRIBE] = { .name = "subscribe", .type = BLOBMSG_TYPE_ARRAY },
        [ACL_INHERIT] = { .name = "inherit", .type = BLOBMSG_TYPE_ARRAY },
        [ACL_LISTEN] = { .name= "listen", .type = BLOBMSG_TYPE_ARRAY },
+       [ACL_SEND] = { .name= "send", .type = BLOBMSG_TYPE_ARRAY },
 };
 
 static void
 ubusd_acl_file_add(struct ubusd_acl_file *file)
 {
        struct blob_attr *tb[__ACL_MAX], *cur;
-       int rem;
+       size_t rem;
 
        blobmsg_parse(acl_policy, __ACL_MAX, tb, blob_data(file->blob),
                      blob_len(file->blob));
@@ -347,6 +373,11 @@ ubusd_acl_file_add(struct ubusd_acl_file *file)
                blobmsg_for_each_attr(cur, tb[ACL_LISTEN], rem)
                        if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)
                                ubusd_acl_add_listen(file, blobmsg_get_string(cur));
+
+       if (tb[ACL_SEND])
+               blobmsg_for_each_attr(cur, tb[ACL_SEND], rem)
+                       if (blobmsg_type(cur) == BLOBMSG_TYPE_STRING)
+                               ubusd_acl_add_send(file, blobmsg_get_string(cur));
 }
 
 static void
@@ -415,7 +446,7 @@ ubusd_acl_load(void)
 {
        struct stat st;
        glob_t gl;
-       int j;
+       size_t j;
        const char *suffix = "/*.json";
        char *path = alloca(strlen(ubusd_acl_dir) + strlen(suffix) + 1);
 
@@ -479,7 +510,7 @@ ubusd_reply_add(struct ubus_object *obj)
                        if (!acl->partial)
                                continue;
 
-                       if (match_len != strlen(key))
+                       if (match_len != (int) strlen(key))
                                continue;
                }
 
@@ -529,7 +560,7 @@ static int ubusd_reply_query(struct ubus_client *cl, struct ubus_msg_buf *ub, st
 static int ubusd_acl_recv(struct ubus_client *cl, struct ubus_msg_buf *ub, const char *method, struct blob_attr *msg)
 {
        if (!strcmp(method, "query"))
-               return ubusd_reply_query(cl, ub, ubus_parse_msg(ub->data), msg);
+               return ubusd_reply_query(cl, ub, ubus_parse_msg(ub->data, blob_raw_len(ub->data)), msg);
 
        return UBUS_STATUS_INVALID_COMMAND;
 }