xref: /qemu/authz/list.c (revision 036a80cd)
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
9*036a80cdSChetan 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,void * data)119c8c99887SDaniel P. Berrange qauthz_list_class_init(ObjectClass *oc, 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,
256c8c99887SDaniel P. Berrange     .interfaces = (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