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 "authz/trace.h"
  24#include "qom/object_interfaces.h"
  25#include "qapi/qapi-visit-authz.h"
  26
  27static 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
  64static void
  65qauthz_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
  75static int
  76qauthz_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
  85static void
  86qauthz_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
  94static void
  95qauthz_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
 108static void
 109qauthz_list_finalize(Object *obj)
 110{
 111    QAuthZList *lauthz = QAUTHZ_LIST(obj);
 112
 113    qapi_free_QAuthZListRuleList(lauthz->rules);
 114}
 115
 116
 117static void
 118qauthz_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
 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_size = sizeof(QAuthZListClass),
 256    .class_init = qauthz_list_class_init,
 257    .interfaces = (InterfaceInfo[]) {
 258        { TYPE_USER_CREATABLE },
 259        { }
 260    }
 261};
 262
 263
 264static void
 265qauthz_list_register_types(void)
 266{
 267    type_register_static(&qauthz_list_info);
 268}
 269
 270
 271type_init(qauthz_list_register_types);
 272