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 9c8c99887SDaniel P. Berrange * version 2 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 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 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 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 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 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 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 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, 127*d2623129SMarkus 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, 132*d2623129SMarkus 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 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 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 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 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_size = sizeof(QAuthZListClass), 256c8c99887SDaniel P. Berrange .class_init = qauthz_list_class_init, 257c8c99887SDaniel P. Berrange .interfaces = (InterfaceInfo[]) { 258c8c99887SDaniel P. Berrange { TYPE_USER_CREATABLE }, 259c8c99887SDaniel P. Berrange { } 260c8c99887SDaniel P. Berrange } 261c8c99887SDaniel P. Berrange }; 262c8c99887SDaniel P. Berrange 263c8c99887SDaniel P. Berrange 264c8c99887SDaniel P. Berrange static void 265c8c99887SDaniel P. Berrange qauthz_list_register_types(void) 266c8c99887SDaniel P. Berrange { 267c8c99887SDaniel P. Berrange type_register_static(&qauthz_list_info); 268c8c99887SDaniel P. Berrange } 269c8c99887SDaniel P. Berrange 270c8c99887SDaniel P. Berrange 271c8c99887SDaniel P. Berrange type_init(qauthz_list_register_types); 272