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