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.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
  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
 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
 138QAuthZList *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
 150ssize_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
 184ssize_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
 221ssize_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
 250static 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
 263static void
 264qauthz_list_register_types(void)
 265{
 266    type_register_static(&qauthz_list_info);
 267}
 268
 269
 270type_init(qauthz_list_register_types);
 271