qemu/authz/list.c
<<
>>
Prefs
   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
  28static 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
  65static void
  66qauthz_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
  76static int
  77qauthz_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
  86static void
  87qauthz_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
  95static void
  96qauthz_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
 109static void
 110qauthz_list_finalize(Object *obj)
 111{
 112    QAuthZList *lauthz = QAUTHZ_LIST(obj);
 113
 114    qapi_free_QAuthZListRuleList(lauthz->rules);
 115}
 116
 117
 118static void
 119qauthz_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
 139QAuthZList *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
 151ssize_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
 185ssize_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
 222ssize_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
 251static 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
 265static void
 266qauthz_list_register_types(void)
 267{
 268    type_register_static(&qauthz_list_info);
 269}
 270
 271
 272type_init(qauthz_list_register_types);
 273