271 lines
7.2 KiB
C
271 lines
7.2 KiB
C
/*
|
|
* QEMU access control list authorization driver
|
|
*
|
|
* Copyright (c) 2018 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "authz/list.h"
|
|
#include "trace.h"
|
|
#include "qom/object_interfaces.h"
|
|
#include "qapi/qapi-visit-authz.h"
|
|
#include "qemu/module.h"
|
|
|
|
static bool qauthz_list_is_allowed(QAuthZ *authz,
|
|
const char *identity,
|
|
Error **errp)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(authz);
|
|
QAuthZListRuleList *rules = lauthz->rules;
|
|
|
|
while (rules) {
|
|
QAuthZListRule *rule = rules->value;
|
|
QAuthZListFormat format = rule->has_format ? rule->format :
|
|
QAUTHZ_LIST_FORMAT_EXACT;
|
|
|
|
trace_qauthz_list_check_rule(authz, rule->match, identity,
|
|
format, rule->policy);
|
|
switch (format) {
|
|
case QAUTHZ_LIST_FORMAT_EXACT:
|
|
if (g_str_equal(rule->match, identity)) {
|
|
return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
|
|
}
|
|
break;
|
|
case QAUTHZ_LIST_FORMAT_GLOB:
|
|
if (g_pattern_match_simple(rule->match, identity)) {
|
|
return rule->policy == QAUTHZ_LIST_POLICY_ALLOW;
|
|
}
|
|
break;
|
|
default:
|
|
g_warn_if_reached();
|
|
return false;
|
|
}
|
|
rules = rules->next;
|
|
}
|
|
|
|
trace_qauthz_list_default_policy(authz, identity, lauthz->policy);
|
|
return lauthz->policy == QAUTHZ_LIST_POLICY_ALLOW;
|
|
}
|
|
|
|
|
|
static void
|
|
qauthz_list_prop_set_policy(Object *obj,
|
|
int value,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(obj);
|
|
|
|
lauthz->policy = value;
|
|
}
|
|
|
|
|
|
static int
|
|
qauthz_list_prop_get_policy(Object *obj,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(obj);
|
|
|
|
return lauthz->policy;
|
|
}
|
|
|
|
|
|
static void
|
|
qauthz_list_prop_get_rules(Object *obj, Visitor *v, const char *name,
|
|
void *opaque, Error **errp)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(obj);
|
|
|
|
visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
|
|
}
|
|
|
|
static void
|
|
qauthz_list_prop_set_rules(Object *obj, Visitor *v, const char *name,
|
|
void *opaque, Error **errp)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(obj);
|
|
QAuthZListRuleList *oldrules;
|
|
|
|
oldrules = lauthz->rules;
|
|
visit_type_QAuthZListRuleList(v, name, &lauthz->rules, errp);
|
|
|
|
qapi_free_QAuthZListRuleList(oldrules);
|
|
}
|
|
|
|
|
|
static void
|
|
qauthz_list_finalize(Object *obj)
|
|
{
|
|
QAuthZList *lauthz = QAUTHZ_LIST(obj);
|
|
|
|
qapi_free_QAuthZListRuleList(lauthz->rules);
|
|
}
|
|
|
|
|
|
static void
|
|
qauthz_list_class_init(ObjectClass *oc, void *data)
|
|
{
|
|
QAuthZClass *authz = QAUTHZ_CLASS(oc);
|
|
|
|
object_class_property_add_enum(oc, "policy",
|
|
"QAuthZListPolicy",
|
|
&QAuthZListPolicy_lookup,
|
|
qauthz_list_prop_get_policy,
|
|
qauthz_list_prop_set_policy);
|
|
|
|
object_class_property_add(oc, "rules", "QAuthZListRule",
|
|
qauthz_list_prop_get_rules,
|
|
qauthz_list_prop_set_rules,
|
|
NULL, NULL);
|
|
|
|
authz->is_allowed = qauthz_list_is_allowed;
|
|
}
|
|
|
|
|
|
QAuthZList *qauthz_list_new(const char *id,
|
|
QAuthZListPolicy policy,
|
|
Error **errp)
|
|
{
|
|
return QAUTHZ_LIST(
|
|
object_new_with_props(TYPE_QAUTHZ_LIST,
|
|
object_get_objects_root(),
|
|
id, errp,
|
|
"policy", QAuthZListPolicy_str(policy),
|
|
NULL));
|
|
}
|
|
|
|
ssize_t qauthz_list_append_rule(QAuthZList *auth,
|
|
const char *match,
|
|
QAuthZListPolicy policy,
|
|
QAuthZListFormat format,
|
|
Error **errp)
|
|
{
|
|
QAuthZListRule *rule;
|
|
QAuthZListRuleList *rules, *tmp;
|
|
size_t i = 0;
|
|
|
|
rule = g_new0(QAuthZListRule, 1);
|
|
rule->policy = policy;
|
|
rule->match = g_strdup(match);
|
|
rule->format = format;
|
|
rule->has_format = true;
|
|
|
|
tmp = g_new0(QAuthZListRuleList, 1);
|
|
tmp->value = rule;
|
|
|
|
rules = auth->rules;
|
|
if (rules) {
|
|
while (rules->next) {
|
|
i++;
|
|
rules = rules->next;
|
|
}
|
|
rules->next = tmp;
|
|
return i + 1;
|
|
} else {
|
|
auth->rules = tmp;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
ssize_t qauthz_list_insert_rule(QAuthZList *auth,
|
|
const char *match,
|
|
QAuthZListPolicy policy,
|
|
QAuthZListFormat format,
|
|
size_t index,
|
|
Error **errp)
|
|
{
|
|
QAuthZListRule *rule;
|
|
QAuthZListRuleList *rules, *tmp;
|
|
size_t i = 0;
|
|
|
|
rule = g_new0(QAuthZListRule, 1);
|
|
rule->policy = policy;
|
|
rule->match = g_strdup(match);
|
|
rule->format = format;
|
|
rule->has_format = true;
|
|
|
|
tmp = g_new0(QAuthZListRuleList, 1);
|
|
tmp->value = rule;
|
|
|
|
rules = auth->rules;
|
|
if (rules && index > 0) {
|
|
while (rules->next && i < (index - 1)) {
|
|
i++;
|
|
rules = rules->next;
|
|
}
|
|
tmp->next = rules->next;
|
|
rules->next = tmp;
|
|
return i + 1;
|
|
} else {
|
|
tmp->next = auth->rules;
|
|
auth->rules = tmp;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
ssize_t qauthz_list_delete_rule(QAuthZList *auth, const char *match)
|
|
{
|
|
QAuthZListRule *rule;
|
|
QAuthZListRuleList *rules, *prev;
|
|
size_t i = 0;
|
|
|
|
prev = NULL;
|
|
rules = auth->rules;
|
|
while (rules) {
|
|
rule = rules->value;
|
|
if (g_str_equal(rule->match, match)) {
|
|
if (prev) {
|
|
prev->next = rules->next;
|
|
} else {
|
|
auth->rules = rules->next;
|
|
}
|
|
rules->next = NULL;
|
|
qapi_free_QAuthZListRuleList(rules);
|
|
return i;
|
|
}
|
|
prev = rules;
|
|
rules = rules->next;
|
|
i++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
static const TypeInfo qauthz_list_info = {
|
|
.parent = TYPE_QAUTHZ,
|
|
.name = TYPE_QAUTHZ_LIST,
|
|
.instance_size = sizeof(QAuthZList),
|
|
.instance_finalize = qauthz_list_finalize,
|
|
.class_size = sizeof(QAuthZListClass),
|
|
.class_init = qauthz_list_class_init,
|
|
.interfaces = (InterfaceInfo[]) {
|
|
{ TYPE_USER_CREATABLE },
|
|
{ }
|
|
}
|
|
};
|
|
|
|
|
|
static void
|
|
qauthz_list_register_types(void)
|
|
{
|
|
type_register_static(&qauthz_list_info);
|
|
}
|
|
|
|
|
|
type_init(qauthz_list_register_types);
|