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