*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
-static const struct blobmsg_policy new_policy = {
- .name = "timeout", .type = BLOBMSG_TYPE_INT32
+enum {
+ RPC_SN_TIMEOUT,
+ __RPC_SN_MAX,
+};
+static const struct blobmsg_policy new_policy[__RPC_SN_MAX] = {
+ [RPC_SN_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
-static const struct blobmsg_policy sid_policy = {
- .name = "sid", .type = BLOBMSG_TYPE_STRING
+enum {
+ RPC_SI_SID,
+ __RPC_SI_MAX,
+};
+static const struct blobmsg_policy sid_policy[__RPC_SI_MAX] = {
+ [RPC_SI_SID] = { .name = "ubus_rpc_session", .type = BLOBMSG_TYPE_STRING },
[RPC_SA_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING },
[RPC_SA_OBJECTS] = { .name = "objects", .type = BLOBMSG_TYPE_ARRAY },
};
[RPC_SA_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING },
[RPC_SA_OBJECTS] = { .name = "objects", .type = BLOBMSG_TYPE_ARRAY },
};
[RPC_SP_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING },
[RPC_SP_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_STRING },
[RPC_SP_FUNCTION] = { .name = "function", .type = BLOBMSG_TYPE_STRING },
[RPC_SP_SCOPE] = { .name = "scope", .type = BLOBMSG_TYPE_STRING },
[RPC_SP_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_STRING },
[RPC_SP_FUNCTION] = { .name = "function", .type = BLOBMSG_TYPE_STRING },
[RPC_DUMP_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
[RPC_DUMP_EXPIRES] = { .name = "expires", .type = BLOBMSG_TYPE_INT32 },
[RPC_DUMP_TIMEOUT] = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
[RPC_DUMP_EXPIRES] = { .name = "expires", .type = BLOBMSG_TYPE_INT32 },
!fnmatch((_acl)->object, (_obj), FNM_NOESCAPE) && \
!fnmatch((_acl)->function, (_func), FNM_NOESCAPE))
!fnmatch((_acl)->object, (_obj), FNM_NOESCAPE) && \
!fnmatch((_acl)->function, (_func), FNM_NOESCAPE))
- fread(buf, 1, sizeof(buf), f);
+ ret = fread(buf, 1, sizeof(buf), f);
for (i = 0; i < sizeof(buf); i++)
sprintf(dest + (i<<1), "%02x", buf[i]);
for (i = 0; i < sizeof(buf); i++)
sprintf(dest + (i<<1), "%02x", buf[i]);
blobmsg_add_u32(&buf, "timeout", ses->timeout);
blobmsg_add_u32(&buf, "expires", uloop_timeout_remaining(&ses->t) / 1000);
blobmsg_add_u32(&buf, "timeout", ses->timeout);
blobmsg_add_u32(&buf, "expires", uloop_timeout_remaining(&ses->t) / 1000);
- c = blobmsg_open_table(&buf, "acls");
- rpc_session_dump_acls(ses, &buf);
- blobmsg_close_table(&buf, c);
+ 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);
c = blobmsg_open_table(&buf, "data");
rpc_session_dump_data(ses, &buf);
rpc_session_dump(struct rpc_session *ses, struct ubus_context *ctx,
struct ubus_request_data *req)
{
rpc_session_dump(struct rpc_session *ses, struct ubus_context *ctx,
struct ubus_request_data *req)
{
- blobmsg_parse(&new_policy, 1, &tb, blob_data(msg), blob_len(msg));
+ blobmsg_parse(new_policy, __RPC_SN_MAX, &tb, blob_data(msg), blob_len(msg));
- blobmsg_parse(&sid_policy, 1, &tb, blob_data(msg), blob_len(msg));
+ blobmsg_parse(sid_policy, __RPC_SI_MAX, &tb, blob_data(msg), blob_len(msg));
const char *scope, const char *object, const char *function)
{
struct rpc_session_acl *acl;
const char *scope, const char *object, const char *function)
{
struct rpc_session_acl *acl;
const char *scope, const char *object, const char *function)
{
struct rpc_session_acl *acl, *next;
const char *scope, const char *object, const char *function)
{
struct rpc_session_acl *acl, *next;
- int (*cb)(struct rpc_session *ses, struct ubus_context *ctx,
- const char *scope, const char *object, const char *function);
+ int (*cb)(struct rpc_session *ses,
+ const char *scope, const char *object, const char *function);
blobmsg_parse(acl_policy, __RPC_SA_MAX, tb, blob_data(msg), blob_len(msg));
blobmsg_parse(acl_policy, __RPC_SA_MAX, tb, blob_data(msg), blob_len(msg));
- return cb(ses, ctx, scope, NULL, NULL);
+ return cb(ses, scope, NULL, NULL);
- cb(ses, ctx, scope, object, function);
+ cb(ses, scope, object, function);
blobmsg_parse(perm_policy, __RPC_SP_MAX, tb, blob_data(msg), blob_len(msg));
blobmsg_parse(perm_policy, __RPC_SP_MAX, tb, blob_data(msg), blob_len(msg));
return UBUS_STATUS_INVALID_ARGUMENT;
ses = rpc_session_get(blobmsg_data(tb[RPC_SP_SID]));
if (!ses)
return UBUS_STATUS_NOT_FOUND;
return UBUS_STATUS_INVALID_ARGUMENT;
ses = rpc_session_get(blobmsg_data(tb[RPC_SP_SID]));
if (!ses)
return UBUS_STATUS_NOT_FOUND;
- if (tb[RPC_SP_SCOPE])
- scope = blobmsg_data(tb[RPC_SP_SCOPE]);
+ blob_buf_init(&buf, 0);
+
+ if (tb[RPC_SP_OBJECT] && tb[RPC_SP_FUNCTION])
+ {
+ if (tb[RPC_SP_SCOPE])
+ scope = blobmsg_data(tb[RPC_SP_SCOPE]);
- allow = rpc_session_acl_allowed(ses, scope,
- blobmsg_data(tb[RPC_SP_OBJECT]),
- blobmsg_data(tb[RPC_SP_FUNCTION]));
+ allow = rpc_session_acl_allowed(ses, scope,
+ blobmsg_data(tb[RPC_SP_OBJECT]),
+ blobmsg_data(tb[RPC_SP_FUNCTION]));
+
+ blobmsg_add_u8(&buf, "access", allow);
+ }
+ else
+ {
+ rpc_session_dump_acls(ses, &buf);
+ }
continue;
data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
continue;
data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
continue;
data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
continue;
data = avl_find_element(&ses->data, blobmsg_data(attr), data, avl);
- blobmsg_parse(&sid_policy, 1, &tb, blob_data(msg), blob_len(msg));
+ blobmsg_parse(sid_policy, __RPC_SI_MAX, &tb, blob_data(msg), blob_len(msg));
rpc_login_test_permission(struct uci_section *s,
const char *perm, const char *group)
{
rpc_login_test_permission(struct uci_section *s,
const char *perm, const char *group)
{
- 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))
- rpc_session_grant(ses, NULL, blobmsg_name(acl_scope),
- blobmsg_name(acl_obj),
- blobmsg_data(acl_func));
+ rpc_session_grant(ses, blobmsg_name(acl_scope),
+ blobmsg_name(acl_obj),
+ blobmsg_data(acl_func));
- rpc_session_grant(ses, NULL, blobmsg_name(acl_scope),
- blobmsg_data(acl_obj),
- blobmsg_name(acl_perm));
+ rpc_session_grant(ses, blobmsg_name(acl_scope),
+ blobmsg_data(acl_obj),
+ blobmsg_name(acl_perm));
blob_for_each_attr(acl_group, acl.head, rem) {
/* Iterate permission objects in each access group object */
blobmsg_for_each_attr(acl_perm, acl_group, rem2) {
blob_for_each_attr(acl_group, acl.head, rem) {
/* Iterate permission objects in each access group object */
blobmsg_for_each_attr(acl_perm, acl_group, rem2) {
* access groups without having to test access of each single
* <scope>/<object>/<function> tuple defined in a group.
*/
* access groups without having to test access of each single
* <scope>/<object>/<function> tuple defined in a group.
*/
- rpc_session_grant(ses, NULL, "access-group",
- blobmsg_name(acl_group),
- blobmsg_name(acl_perm));
+ rpc_session_grant(ses, "access-group",
+ blobmsg_name(acl_group),
+ blobmsg_name(acl_perm));
- struct blob_attr *tb[__RPC_DUMP_MAX], *scope, *object, *function;
+ struct uci_section *login;
+ struct blob_attr *tb[__RPC_DUMP_MAX], *data;
blobmsg_parse(dump_policy, __RPC_DUMP_MAX, tb,
blob_data(attr), blob_len(attr));
blobmsg_parse(dump_policy, __RPC_DUMP_MAX, tb,
blob_data(attr), blob_len(attr));
- blobmsg_for_each_attr(scope, tb[RPC_DUMP_ACLS], rem) {
- blobmsg_for_each_attr(object, scope, rem2) {
- blobmsg_for_each_attr(function, object, rem3) {
- rpc_session_grant(ses, NULL, blobmsg_name(scope),
- blobmsg_name(object),
- blobmsg_data(function));
- }
- }
+ blobmsg_for_each_attr(data, tb[RPC_DUMP_DATA], rem) {
+ rpc_session_set(ses, blobmsg_name(data), data);
+
+ if (!strcmp(blobmsg_name(data), "username"))
+ user = blobmsg_get_string(data);
- blobmsg_for_each_attr(object, tb[RPC_DUMP_DATA], rem) {
- rpc_session_set(ses, blobmsg_name(object), object);
+ if (uci && user) {
+ login = rpc_login_test_login(uci, user, NULL);
+ if (login)
+ rpc_login_setup_acls(ses, login);
- UBUS_METHOD("create", rpc_handle_create, &new_policy),
- UBUS_METHOD("list", rpc_handle_list, &sid_policy),
+ UBUS_METHOD("create", rpc_handle_create, new_policy),
+ UBUS_METHOD("list", rpc_handle_list, sid_policy),
UBUS_METHOD("grant", rpc_handle_acl, acl_policy),
UBUS_METHOD("revoke", rpc_handle_acl, acl_policy),
UBUS_METHOD("access", rpc_handle_access, perm_policy),
UBUS_METHOD("set", rpc_handle_set, set_policy),
UBUS_METHOD("get", rpc_handle_get, get_policy),
UBUS_METHOD("unset", rpc_handle_unset, get_policy),
UBUS_METHOD("grant", rpc_handle_acl, acl_policy),
UBUS_METHOD("revoke", rpc_handle_acl, acl_policy),
UBUS_METHOD("access", rpc_handle_access, perm_policy),
UBUS_METHOD("set", rpc_handle_set, set_policy),
UBUS_METHOD("get", rpc_handle_get, get_policy),
UBUS_METHOD("unset", rpc_handle_unset, get_policy),
- UBUS_METHOD("destroy", rpc_handle_destroy, &sid_policy),
+ UBUS_METHOD("destroy", rpc_handle_destroy, sid_policy),
UBUS_METHOD("login", rpc_handle_login, login_policy),
};
UBUS_METHOD("login", rpc_handle_login, login_policy),
};
continue;
snprintf(path, sizeof(path) - 1, RPC_SESSION_DIRECTORY "/%s", ses->id);
continue;
snprintf(path, sizeof(path) - 1, RPC_SESSION_DIRECTORY "/%s", ses->id);