xref: /qemu/authz/list.c (revision 05a248715cef192336a594afed812871a52efc1f)
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.1 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  
129      object_class_property_add(oc, "rules", "QAuthZListRule",
130                                qauthz_list_prop_get_rules,
131                                qauthz_list_prop_set_rules,
132                                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_init = qauthz_list_class_init,
256      .interfaces = (InterfaceInfo[]) {
257          { TYPE_USER_CREATABLE },
258          { }
259      }
260  };
261  
262  
263  static void
264  qauthz_list_register_types(void)
265  {
266      type_register_static(&qauthz_list_info);
267  }
268  
269  
270  type_init(qauthz_list_register_types);
271