xref: /openbmc/qemu/authz/list.c (revision 4966c5bd)
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 "authz/trace.h"
24 #include "qom/object_interfaces.h"
25 #include "qapi/qapi-visit-authz.h"
26 
27 static bool qauthz_list_is_allowed(QAuthZ *authz,
28                                    const char *identity,
29                                    Error **errp)
30 {
31     QAuthZList *lauthz = QAUTHZ_LIST(authz);
32     QAuthZListRuleList *rules = lauthz->rules;
33 
34     while (rules) {
35         QAuthZListRule *rule = rules->value;
36         QAuthZListFormat format = rule->has_format ? rule->format :
37             QAUTHZ_LIST_FORMAT_EXACT;
38 
39         trace_qauthz_list_check_rule(authz, rule->match, identity,
40                                      format, rule->policy);
41         switch (format) {
42         case QAUTHZ_LIST_FORMAT_EXACT:
43             if (g_str_equal(rule->match, identity)) {
44                 return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
45             }
46             break;
47         case QAUTHZ_LIST_FORMAT_GLOB:
48             if (g_pattern_match_simple(rule->match, identity)) {
49                 return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
50             }
51             break;
52         default:
53             g_warn_if_reached();
54             return false;
55         }
56         rules = rules->next;
57     }
58 
59     trace_qauthz_list_default_policy(authz, identity, lauthz->policy);
60     return lauthz->policy == QAUTHZ_LIST_POLICY_ALLOW;
61 }
62 
63 
64 static void
65 qauthz_list_prop_set_policy(Object *obj,
66                             int value,
67                             Error **errp G_GNUC_UNUSED)
68 {
69     QAuthZList *lauthz = QAUTHZ_LIST(obj);
70 
71     lauthz->policy = value;
72 }
73 
74 
75 static int
76 qauthz_list_prop_get_policy(Object *obj,
77                             Error **errp G_GNUC_UNUSED)
78 {
79     QAuthZList *lauthz = QAUTHZ_LIST(obj);
80 
81     return lauthz->policy;
82 }
83 
84 
85 static void
86 qauthz_list_prop_get_rules(Object *obj, Visitor *v, const char *name,
87                            void *opaque, Error **errp)
88 {
89     QAuthZList *lauthz = QAUTHZ_LIST(obj);
90 
91     visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
92 }
93 
94 static void
95 qauthz_list_prop_set_rules(Object *obj, Visitor *v, const char *name,
96                            void *opaque, Error **errp)
97 {
98     QAuthZList *lauthz = QAUTHZ_LIST(obj);
99     QAuthZListRuleList *oldrules;
100 
101     oldrules = lauthz->rules;
102     visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
103 
104     qapi_free_QAuthZListRuleList(oldrules);
105 }
106 
107 
108 static void
109 qauthz_list_finalize(Object *obj)
110 {
111     QAuthZList *lauthz = QAUTHZ_LIST(obj);
112 
113     qapi_free_QAuthZListRuleList(lauthz->rules);
114 }
115 
116 
117 static void
118 qauthz_list_class_init(ObjectClass *oc, void *data)
119 {
120     QAuthZClass *authz = QAUTHZ_CLASS(oc);
121 
122     object_class_property_add_enum(oc, "policy",
123                                    "QAuthZListPolicy",
124                                    &QAuthZListPolicy_lookup,
125                                    qauthz_list_prop_get_policy,
126                                    qauthz_list_prop_set_policy,
127                                    NULL);
128 
129     object_class_property_add(oc, "rules", "QAuthZListRule",
130                               qauthz_list_prop_get_rules,
131                               qauthz_list_prop_set_rules,
132                               NULL, NULL, NULL);
133 
134     authz->is_allowed = qauthz_list_is_allowed;
135 }
136 
137 
138 QAuthZList *qauthz_list_new(const char *id,
139                             QAuthZListPolicy policy,
140                             Error **errp)
141 {
142     return QAUTHZ_LIST(
143         object_new_with_props(TYPE_QAUTHZ_LIST,
144                               object_get_objects_root(),
145                               id, errp,
146                               "policy", QAuthZListPolicy_str(policy),
147                               NULL));
148 }
149 
150 ssize_t qauthz_list_append_rule(QAuthZList *auth,
151                                 const char *match,
152                                 QAuthZListPolicy policy,
153                                 QAuthZListFormat format,
154                                 Error **errp)
155 {
156     QAuthZListRule *rule;
157     QAuthZListRuleList *rules, *tmp;
158     size_t i = 0;
159 
160     rule = g_new0(QAuthZListRule, 1);
161     rule->policy = policy;
162     rule->match = g_strdup(match);
163     rule->format = format;
164     rule->has_format = true;
165 
166     tmp = g_new0(QAuthZListRuleList, 1);
167     tmp->value = rule;
168 
169     rules = auth->rules;
170     if (rules) {
171         while (rules->next) {
172             i++;
173             rules = rules->next;
174         }
175         rules->next = tmp;
176         return i + 1;
177     } else {
178         auth->rules = tmp;
179         return 0;
180     }
181 }
182 
183 
184 ssize_t qauthz_list_insert_rule(QAuthZList *auth,
185                                 const char *match,
186                                 QAuthZListPolicy policy,
187                                 QAuthZListFormat format,
188                                 size_t index,
189                                 Error **errp)
190 {
191     QAuthZListRule *rule;
192     QAuthZListRuleList *rules, *tmp;
193     size_t i = 0;
194 
195     rule = g_new0(QAuthZListRule, 1);
196     rule->policy = policy;
197     rule->match = g_strdup(match);
198     rule->format = format;
199     rule->has_format = true;
200 
201     tmp = g_new0(QAuthZListRuleList, 1);
202     tmp->value = rule;
203 
204     rules = auth->rules;
205     if (rules && index > 0) {
206         while (rules->next && i < (index - 1)) {
207             i++;
208             rules = rules->next;
209         }
210         tmp->next = rules->next;
211         rules->next = tmp;
212         return i + 1;
213     } else {
214         tmp->next = auth->rules;
215         auth->rules = tmp;
216         return 0;
217     }
218 }
219 
220 
221 ssize_t qauthz_list_delete_rule(QAuthZList *auth, const char *match)
222 {
223     QAuthZListRule *rule;
224     QAuthZListRuleList *rules, *prev;
225     size_t i = 0;
226 
227     prev = NULL;
228     rules = auth->rules;
229     while (rules) {
230         rule = rules->value;
231         if (g_str_equal(rule->match, match)) {
232             if (prev) {
233                 prev->next = rules->next;
234             } else {
235                 auth->rules = rules->next;
236             }
237             rules->next = NULL;
238             qapi_free_QAuthZListRuleList(rules);
239             return i;
240         }
241         prev = rules;
242         rules = rules->next;
243         i++;
244     }
245 
246     return -1;
247 }
248 
249 
250 static const TypeInfo qauthz_list_info = {
251     .parent = TYPE_QAUTHZ,
252     .name = TYPE_QAUTHZ_LIST,
253     .instance_size = sizeof(QAuthZList),
254     .instance_finalize = qauthz_list_finalize,
255     .class_size = sizeof(QAuthZListClass),
256     .class_init = qauthz_list_class_init,
257     .interfaces = (InterfaceInfo[]) {
258         { TYPE_USER_CREATABLE },
259         { }
260     }
261 };
262 
263 
264 static void
265 qauthz_list_register_types(void)
266 {
267     type_register_static(&qauthz_list_info);
268 }
269 
270 
271 type_init(qauthz_list_register_types);
272