2 * luci-io - LuCI non-RPC helper
4 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 static const struct blobmsg_policy ses_new_policy[__SES_NEW_MAX] = {
28 [SES_NEW_SID] = { .name = "sid", .type = BLOBMSG_TYPE_STRING },
32 parse_acl_scope(struct blob_attr *acl_perm, struct blob_attr *acl_scope,
35 struct blob_attr *acl_obj, *acl_func;
39 if (!strcmp(blobmsg_name(acl_scope), "ubus") &&
40 blob_id(acl_scope) == BLOBMSG_TYPE_TABLE)
42 blobmsg_add_string(req, "scope", blobmsg_name(acl_scope));
43 c = blobmsg_open_array(req, "objects");
45 blobmsg_for_each_attr(acl_obj, acl_scope, rem)
47 if (blob_id(acl_obj) != BLOBMSG_TYPE_ARRAY)
50 blobmsg_for_each_attr(acl_func, acl_obj, rem2)
52 if (blob_id(acl_func) != BLOBMSG_TYPE_STRING)
55 d = blobmsg_open_array(req, NULL);
56 blobmsg_add_string(req, NULL, blobmsg_name(acl_obj));
57 blobmsg_add_string(req, NULL, blobmsg_data(acl_func));
58 blobmsg_close_array(req, d);
62 blobmsg_close_array(req, c);
65 else if ((!strcmp(blobmsg_name(acl_scope), "uci") ||
66 !strcmp(blobmsg_name(acl_scope), "luci-io")) &&
67 blob_id(acl_scope) == BLOBMSG_TYPE_ARRAY)
69 blobmsg_add_string(req, "scope", blobmsg_name(acl_scope));
70 c = blobmsg_open_array(req, "objects");
72 blobmsg_for_each_attr(acl_obj, acl_scope, rem)
74 if (blob_id(acl_obj) != BLOBMSG_TYPE_STRING)
77 d = blobmsg_open_array(req, NULL);
78 blobmsg_add_string(req, NULL, blobmsg_data(acl_obj));
79 blobmsg_add_string(req, NULL, blobmsg_name(acl_perm));
80 blobmsg_close_array(req, d);
83 blobmsg_close_array(req, c);
90 static struct uci_section *
91 test_user_access(struct uci_context *uci, const char *user)
93 struct uci_package *p;
94 struct uci_section *s;
95 struct uci_element *e;
96 struct uci_ptr ptr = { .package = "luci", .option = "user" };
98 uci_load(uci, ptr.package, &p);
103 uci_foreach_element(&p->sections, e)
105 s = uci_to_section(e);
107 if (strcmp(s->type, "access"))
110 ptr.section = s->e.name;
114 if (uci_lookup_ptr(uci, &ptr, NULL, true))
117 if (ptr.o->type != UCI_TYPE_STRING)
120 if (strcmp(ptr.o->v.string, user))
130 test_group_access(struct uci_section *s, const char *perm, const char *group)
132 struct uci_option *o;
133 struct uci_element *e, *l;
135 uci_foreach_element(&s->options, e)
137 o = uci_to_option(e);
139 if (o->type != UCI_TYPE_LIST)
142 if (strcmp(o->e.name, perm))
145 uci_foreach_element(&o->v.list, l)
146 if (l->name && !fnmatch(l->name, group, 0))
150 if (!strcmp(perm, "read"))
151 return test_group_access(s, "write", group);
157 setup_session_cb(struct ubus_request *req, int type, struct blob_attr *msg)
159 struct blob_attr *tb[__SES_NEW_MAX];
160 const char **sid = req->priv;
165 blobmsg_parse(ses_new_policy, __SES_NEW_MAX, tb,
166 blob_data(msg), blob_len(msg));
169 *sid = strdup(blobmsg_data(tb[SES_NEW_SID]));
173 setup_session(const char *user)
176 struct blob_buf req = { 0 }, acl = { 0 };
177 struct blob_attr *acl_group, *acl_perm, *acl_scope;
178 struct ubus_context *ctx = NULL;
179 struct uci_context *uci = NULL;
180 struct uci_section *access;
181 const char *sid = NULL;
182 int i, rem, rem2, rem3;
186 uci = uci_alloc_context();
191 access = test_user_access(uci, user);
193 /* continue without access group if user is root (backward compat) */
194 if (!access && strcmp(user, "root"))
197 ctx = ubus_connect(NULL);
199 if (!ctx || ubus_lookup_id(ctx, "session", &id))
202 blob_buf_init(&req, 0);
203 blobmsg_add_u32(&req, "timeout", 3600);
204 ubus_invoke(ctx, id, "create", req.head, setup_session_cb, &sid, 500);
209 blob_buf_init(&req, 0);
210 blobmsg_add_string(&req, "sid", sid);
211 c = blobmsg_open_table(&req, "values");
212 blobmsg_add_string(&req, "user", user);
213 blobmsg_close_table(&req, c);
214 ubus_invoke(ctx, id, "set", req.head, NULL, NULL, 500);
216 if (glob("/usr/share/luci2/acl.d/*.json", 0, NULL, &gl))
219 for (i = 0; i < gl.gl_pathc; i++)
221 blob_buf_init(&acl, 0);
223 if (!blobmsg_add_json_from_file(&acl, gl.gl_pathv[i]))
225 fprintf(stderr, "Failed to parse %s\n", gl.gl_pathv[i]);
229 blob_for_each_attr(acl_group, acl.head, rem)
231 blobmsg_for_each_attr(acl_perm, acl_group, rem2)
233 if (blob_id(acl_perm) != BLOBMSG_TYPE_TABLE)
236 if (strcmp(blobmsg_name(acl_perm), "read") &&
237 strcmp(blobmsg_name(acl_perm), "write"))
240 if (access != NULL &&
241 !test_group_access(access, blobmsg_name(acl_perm),
242 blobmsg_name(acl_group)))
245 blobmsg_for_each_attr(acl_scope, acl_perm, rem3)
247 blob_buf_init(&req, 0);
249 if (!parse_acl_scope(acl_perm, acl_scope, &req))
252 blobmsg_add_string(&req, "sid", sid);
253 ubus_invoke(ctx, id, "grant", req.head, NULL, NULL, 500);
256 blob_buf_init(&req, 0);
257 blobmsg_add_string(&req, "sid", sid);
258 blobmsg_add_string(&req, "scope", "luci-ui");
259 c = blobmsg_open_array(&req, "objects");
260 d = blobmsg_open_array(&req, NULL);
261 blobmsg_add_string(&req, NULL, blobmsg_name(acl_group));
262 blobmsg_add_string(&req, NULL, blobmsg_name(acl_perm));
263 blobmsg_close_array(&req, d);
264 blobmsg_close_array(&req, c);
265 ubus_invoke(ctx, id, "grant", req.head, NULL, NULL, 500);
275 uci_free_context(uci);