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