1c8c99887SDaniel P. Berrange /*
2c8c99887SDaniel P. Berrange * QEMU access control list authorization driver
3c8c99887SDaniel P. Berrange *
4c8c99887SDaniel P. Berrange * Copyright (c) 2018 Red Hat, Inc.
5c8c99887SDaniel P. Berrange *
6c8c99887SDaniel P. Berrange * This library is free software; you can redistribute it and/or
7c8c99887SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public
8c8c99887SDaniel P. Berrange * License as published by the Free Software Foundation; either
9036a80cdSChetan Pant * version 2.1 of the License, or (at your option) any later version.
10c8c99887SDaniel P. Berrange *
11c8c99887SDaniel P. Berrange * This library is distributed in the hope that it will be useful,
12c8c99887SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c8c99887SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c8c99887SDaniel P. Berrange * Lesser General Public License for more details.
15c8c99887SDaniel P. Berrange *
16c8c99887SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public
17c8c99887SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18c8c99887SDaniel P. Berrange *
19c8c99887SDaniel P. Berrange */
20c8c99887SDaniel P. Berrange
21c8c99887SDaniel P. Berrange #include "qemu/osdep.h"
22c8c99887SDaniel P. Berrange #include "authz/list.h"
2345b1f68cSMarkus Armbruster #include "trace.h"
24c8c99887SDaniel P. Berrange #include "qom/object_interfaces.h"
25c8c99887SDaniel P. Berrange #include "qapi/qapi-visit-authz.h"
260b8fa32fSMarkus Armbruster #include "qemu/module.h"
27c8c99887SDaniel P. Berrange
qauthz_list_is_allowed(QAuthZ * authz,const char * identity,Error ** errp)28c8c99887SDaniel P. Berrange static bool qauthz_list_is_allowed(QAuthZ *authz,
29c8c99887SDaniel P. Berrange const char *identity,
30c8c99887SDaniel P. Berrange Error **errp)
31c8c99887SDaniel P. Berrange {
32c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(authz);
33c8c99887SDaniel P. Berrange QAuthZListRuleList *rules = lauthz->rules;
34c8c99887SDaniel P. Berrange
35c8c99887SDaniel P. Berrange while (rules) {
36c8c99887SDaniel P. Berrange QAuthZListRule *rule = rules->value;
37c8c99887SDaniel P. Berrange QAuthZListFormat format = rule->has_format ? rule->format :
38c8c99887SDaniel P. Berrange QAUTHZ_LIST_FORMAT_EXACT;
39c8c99887SDaniel P. Berrange
40c8c99887SDaniel P. Berrange trace_qauthz_list_check_rule(authz, rule->match, identity,
41c8c99887SDaniel P. Berrange format, rule->policy);
42c8c99887SDaniel P. Berrange switch (format) {
43c8c99887SDaniel P. Berrange case QAUTHZ_LIST_FORMAT_EXACT:
44c8c99887SDaniel P. Berrange if (g_str_equal(rule->match, identity)) {
45c8c99887SDaniel P. Berrange return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
46c8c99887SDaniel P. Berrange }
47c8c99887SDaniel P. Berrange break;
48c8c99887SDaniel P. Berrange case QAUTHZ_LIST_FORMAT_GLOB:
49c8c99887SDaniel P. Berrange if (g_pattern_match_simple(rule->match, identity)) {
50c8c99887SDaniel P. Berrange return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
51c8c99887SDaniel P. Berrange }
52c8c99887SDaniel P. Berrange break;
53c8c99887SDaniel P. Berrange default:
54c8c99887SDaniel P. Berrange g_warn_if_reached();
55c8c99887SDaniel P. Berrange return false;
56c8c99887SDaniel P. Berrange }
57c8c99887SDaniel P. Berrange rules = rules->next;
58c8c99887SDaniel P. Berrange }
59c8c99887SDaniel P. Berrange
60c8c99887SDaniel P. Berrange trace_qauthz_list_default_policy(authz, identity, lauthz->policy);
61c8c99887SDaniel P. Berrange return lauthz->policy == QAUTHZ_LIST_POLICY_ALLOW;
62c8c99887SDaniel P. Berrange }
63c8c99887SDaniel P. Berrange
64c8c99887SDaniel P. Berrange
65c8c99887SDaniel P. Berrange static void
qauthz_list_prop_set_policy(Object * obj,int value,Error ** errp G_GNUC_UNUSED)66c8c99887SDaniel P. Berrange qauthz_list_prop_set_policy(Object *obj,
67c8c99887SDaniel P. Berrange int value,
68c8c99887SDaniel P. Berrange Error **errp G_GNUC_UNUSED)
69c8c99887SDaniel P. Berrange {
70c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(obj);
71c8c99887SDaniel P. Berrange
72c8c99887SDaniel P. Berrange lauthz->policy = value;
73c8c99887SDaniel P. Berrange }
74c8c99887SDaniel P. Berrange
75c8c99887SDaniel P. Berrange
76c8c99887SDaniel P. Berrange static int
qauthz_list_prop_get_policy(Object * obj,Error ** errp G_GNUC_UNUSED)77c8c99887SDaniel P. Berrange qauthz_list_prop_get_policy(Object *obj,
78c8c99887SDaniel P. Berrange Error **errp G_GNUC_UNUSED)
79c8c99887SDaniel P. Berrange {
80c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(obj);
81c8c99887SDaniel P. Berrange
82c8c99887SDaniel P. Berrange return lauthz->policy;
83c8c99887SDaniel P. Berrange }
84c8c99887SDaniel P. Berrange
85c8c99887SDaniel P. Berrange
86c8c99887SDaniel P. Berrange static void
qauthz_list_prop_get_rules(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)87c8c99887SDaniel P. Berrange qauthz_list_prop_get_rules(Object *obj, Visitor *v, const char *name,
88c8c99887SDaniel P. Berrange void *opaque, Error **errp)
89c8c99887SDaniel P. Berrange {
90c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(obj);
91c8c99887SDaniel P. Berrange
92c8c99887SDaniel P. Berrange visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
93c8c99887SDaniel P. Berrange }
94c8c99887SDaniel P. Berrange
95c8c99887SDaniel P. Berrange static void
qauthz_list_prop_set_rules(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)96c8c99887SDaniel P. Berrange qauthz_list_prop_set_rules(Object *obj, Visitor *v, const char *name,
97c8c99887SDaniel P. Berrange void *opaque, Error **errp)
98c8c99887SDaniel P. Berrange {
99c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(obj);
100c8c99887SDaniel P. Berrange QAuthZListRuleList *oldrules;
101c8c99887SDaniel P. Berrange
102c8c99887SDaniel P. Berrange oldrules = lauthz->rules;
103c8c99887SDaniel P. Berrange visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
104c8c99887SDaniel P. Berrange
105c8c99887SDaniel P. Berrange qapi_free_QAuthZListRuleList(oldrules);
106c8c99887SDaniel P. Berrange }
107c8c99887SDaniel P. Berrange
108c8c99887SDaniel P. Berrange
109c8c99887SDaniel P. Berrange static void
qauthz_list_finalize(Object * obj)110c8c99887SDaniel P. Berrange qauthz_list_finalize(Object *obj)
111c8c99887SDaniel P. Berrange {
112c8c99887SDaniel P. Berrange QAuthZList *lauthz = QAUTHZ_LIST(obj);
113c8c99887SDaniel P. Berrange
114c8c99887SDaniel P. Berrange qapi_free_QAuthZListRuleList(lauthz->rules);
115c8c99887SDaniel P. Berrange }
116c8c99887SDaniel P. Berrange
117c8c99887SDaniel P. Berrange
118c8c99887SDaniel P. Berrange static void
qauthz_list_class_init(ObjectClass * oc,const void * data)11912d1a768SPhilippe Mathieu-Daudé qauthz_list_class_init(ObjectClass *oc, const void *data)
120c8c99887SDaniel P. Berrange {
121c8c99887SDaniel P. Berrange QAuthZClass *authz = QAUTHZ_CLASS(oc);
122c8c99887SDaniel P. Berrange
123c8c99887SDaniel P. Berrange object_class_property_add_enum(oc, "policy",
124c8c99887SDaniel P. Berrange "QAuthZListPolicy",
125c8c99887SDaniel P. Berrange &QAuthZListPolicy_lookup,
126c8c99887SDaniel P. Berrange qauthz_list_prop_get_policy,
127d2623129SMarkus Armbruster qauthz_list_prop_set_policy);
128c8c99887SDaniel P. Berrange
129c8c99887SDaniel P. Berrange object_class_property_add(oc, "rules", "QAuthZListRule",
130c8c99887SDaniel P. Berrange qauthz_list_prop_get_rules,
131c8c99887SDaniel P. Berrange qauthz_list_prop_set_rules,
132d2623129SMarkus Armbruster NULL, NULL);
133c8c99887SDaniel P. Berrange
134c8c99887SDaniel P. Berrange authz->is_allowed = qauthz_list_is_allowed;
135c8c99887SDaniel P. Berrange }
136c8c99887SDaniel P. Berrange
137c8c99887SDaniel P. Berrange
qauthz_list_new(const char * id,QAuthZListPolicy policy,Error ** errp)138c8c99887SDaniel P. Berrange QAuthZList *qauthz_list_new(const char *id,
139c8c99887SDaniel P. Berrange QAuthZListPolicy policy,
140c8c99887SDaniel P. Berrange Error **errp)
141c8c99887SDaniel P. Berrange {
142c8c99887SDaniel P. Berrange return QAUTHZ_LIST(
143c8c99887SDaniel P. Berrange object_new_with_props(TYPE_QAUTHZ_LIST,
144c8c99887SDaniel P. Berrange object_get_objects_root(),
145c8c99887SDaniel P. Berrange id, errp,
146c8c99887SDaniel P. Berrange "policy", QAuthZListPolicy_str(policy),
147c8c99887SDaniel P. Berrange NULL));
148c8c99887SDaniel P. Berrange }
149c8c99887SDaniel P. Berrange
qauthz_list_append_rule(QAuthZList * auth,const char * match,QAuthZListPolicy policy,QAuthZListFormat format,Error ** errp)150c8c99887SDaniel P. Berrange ssize_t qauthz_list_append_rule(QAuthZList *auth,
151c8c99887SDaniel P. Berrange const char *match,
152c8c99887SDaniel P. Berrange QAuthZListPolicy policy,
153c8c99887SDaniel P. Berrange QAuthZListFormat format,
154c8c99887SDaniel P. Berrange Error **errp)
155c8c99887SDaniel P. Berrange {
156c8c99887SDaniel P. Berrange QAuthZListRule *rule;
157c8c99887SDaniel P. Berrange QAuthZListRuleList *rules, *tmp;
158c8c99887SDaniel P. Berrange size_t i = 0;
159c8c99887SDaniel P. Berrange
160c8c99887SDaniel P. Berrange rule = g_new0(QAuthZListRule, 1);
161c8c99887SDaniel P. Berrange rule->policy = policy;
162c8c99887SDaniel P. Berrange rule->match = g_strdup(match);
163c8c99887SDaniel P. Berrange rule->format = format;
164c8c99887SDaniel P. Berrange rule->has_format = true;
165c8c99887SDaniel P. Berrange
166c8c99887SDaniel P. Berrange tmp = g_new0(QAuthZListRuleList, 1);
167c8c99887SDaniel P. Berrange tmp->value = rule;
168c8c99887SDaniel P. Berrange
169c8c99887SDaniel P. Berrange rules = auth->rules;
170c8c99887SDaniel P. Berrange if (rules) {
171c8c99887SDaniel P. Berrange while (rules->next) {
172c8c99887SDaniel P. Berrange i++;
173c8c99887SDaniel P. Berrange rules = rules->next;
174c8c99887SDaniel P. Berrange }
175c8c99887SDaniel P. Berrange rules->next = tmp;
176c8c99887SDaniel P. Berrange return i + 1;
177c8c99887SDaniel P. Berrange } else {
178c8c99887SDaniel P. Berrange auth->rules = tmp;
179c8c99887SDaniel P. Berrange return 0;
180c8c99887SDaniel P. Berrange }
181c8c99887SDaniel P. Berrange }
182c8c99887SDaniel P. Berrange
183c8c99887SDaniel P. Berrange
qauthz_list_insert_rule(QAuthZList * auth,const char * match,QAuthZListPolicy policy,QAuthZListFormat format,size_t index,Error ** errp)184c8c99887SDaniel P. Berrange ssize_t qauthz_list_insert_rule(QAuthZList *auth,
185c8c99887SDaniel P. Berrange const char *match,
186c8c99887SDaniel P. Berrange QAuthZListPolicy policy,
187c8c99887SDaniel P. Berrange QAuthZListFormat format,
188c8c99887SDaniel P. Berrange size_t index,
189c8c99887SDaniel P. Berrange Error **errp)
190c8c99887SDaniel P. Berrange {
191c8c99887SDaniel P. Berrange QAuthZListRule *rule;
192c8c99887SDaniel P. Berrange QAuthZListRuleList *rules, *tmp;
193c8c99887SDaniel P. Berrange size_t i = 0;
194c8c99887SDaniel P. Berrange
195c8c99887SDaniel P. Berrange rule = g_new0(QAuthZListRule, 1);
196c8c99887SDaniel P. Berrange rule->policy = policy;
197c8c99887SDaniel P. Berrange rule->match = g_strdup(match);
198c8c99887SDaniel P. Berrange rule->format = format;
199c8c99887SDaniel P. Berrange rule->has_format = true;
200c8c99887SDaniel P. Berrange
201c8c99887SDaniel P. Berrange tmp = g_new0(QAuthZListRuleList, 1);
202c8c99887SDaniel P. Berrange tmp->value = rule;
203c8c99887SDaniel P. Berrange
204c8c99887SDaniel P. Berrange rules = auth->rules;
205c8c99887SDaniel P. Berrange if (rules && index > 0) {
206c8c99887SDaniel P. Berrange while (rules->next && i < (index - 1)) {
207c8c99887SDaniel P. Berrange i++;
208c8c99887SDaniel P. Berrange rules = rules->next;
209c8c99887SDaniel P. Berrange }
210c8c99887SDaniel P. Berrange tmp->next = rules->next;
211c8c99887SDaniel P. Berrange rules->next = tmp;
212c8c99887SDaniel P. Berrange return i + 1;
213c8c99887SDaniel P. Berrange } else {
214c8c99887SDaniel P. Berrange tmp->next = auth->rules;
215c8c99887SDaniel P. Berrange auth->rules = tmp;
216c8c99887SDaniel P. Berrange return 0;
217c8c99887SDaniel P. Berrange }
218c8c99887SDaniel P. Berrange }
219c8c99887SDaniel P. Berrange
220c8c99887SDaniel P. Berrange
qauthz_list_delete_rule(QAuthZList * auth,const char * match)221c8c99887SDaniel P. Berrange ssize_t qauthz_list_delete_rule(QAuthZList *auth, const char *match)
222c8c99887SDaniel P. Berrange {
223c8c99887SDaniel P. Berrange QAuthZListRule *rule;
224c8c99887SDaniel P. Berrange QAuthZListRuleList *rules, *prev;
225c8c99887SDaniel P. Berrange size_t i = 0;
226c8c99887SDaniel P. Berrange
227c8c99887SDaniel P. Berrange prev = NULL;
228c8c99887SDaniel P. Berrange rules = auth->rules;
229c8c99887SDaniel P. Berrange while (rules) {
230c8c99887SDaniel P. Berrange rule = rules->value;
231c8c99887SDaniel P. Berrange if (g_str_equal(rule->match, match)) {
232c8c99887SDaniel P. Berrange if (prev) {
233c8c99887SDaniel P. Berrange prev->next = rules->next;
234c8c99887SDaniel P. Berrange } else {
235c8c99887SDaniel P. Berrange auth->rules = rules->next;
236c8c99887SDaniel P. Berrange }
237c8c99887SDaniel P. Berrange rules->next = NULL;
238c8c99887SDaniel P. Berrange qapi_free_QAuthZListRuleList(rules);
239c8c99887SDaniel P. Berrange return i;
240c8c99887SDaniel P. Berrange }
241c8c99887SDaniel P. Berrange prev = rules;
242c8c99887SDaniel P. Berrange rules = rules->next;
243c8c99887SDaniel P. Berrange i++;
244c8c99887SDaniel P. Berrange }
245c8c99887SDaniel P. Berrange
246c8c99887SDaniel P. Berrange return -1;
247c8c99887SDaniel P. Berrange }
248c8c99887SDaniel P. Berrange
249c8c99887SDaniel P. Berrange
250c8c99887SDaniel P. Berrange static const TypeInfo qauthz_list_info = {
251c8c99887SDaniel P. Berrange .parent = TYPE_QAUTHZ,
252c8c99887SDaniel P. Berrange .name = TYPE_QAUTHZ_LIST,
253c8c99887SDaniel P. Berrange .instance_size = sizeof(QAuthZList),
254c8c99887SDaniel P. Berrange .instance_finalize = qauthz_list_finalize,
255c8c99887SDaniel P. Berrange .class_init = qauthz_list_class_init,
256*2cd09e47SPhilippe Mathieu-Daudé .interfaces = (const InterfaceInfo[]) {
257c8c99887SDaniel P. Berrange { TYPE_USER_CREATABLE },
258c8c99887SDaniel P. Berrange { }
259c8c99887SDaniel P. Berrange }
260c8c99887SDaniel P. Berrange };
261c8c99887SDaniel P. Berrange
262c8c99887SDaniel P. Berrange
263c8c99887SDaniel P. Berrange static void
qauthz_list_register_types(void)264c8c99887SDaniel P. Berrange qauthz_list_register_types(void)
265c8c99887SDaniel P. Berrange {
266c8c99887SDaniel P. Berrange type_register_static(&qauthz_list_info);
267c8c99887SDaniel P. Berrange }
268c8c99887SDaniel P. Berrange
269c8c99887SDaniel P. Berrange
270c8c99887SDaniel P. Berrange type_init(qauthz_list_register_types);
271