All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Markus Armbruster" <armbru@redhat.com>,
	"Max Reitz" <mreitz@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@gmail.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>,
	"Eric Blake" <eblake@redhat.com>,
	"Daniel P. Berrange" <berrange@redhat.com>
Subject: [Qemu-devel] [PATCH v8 6/7] util: add QAuthZSimple object type for a simple access control list
Date: Thu, 14 Jul 2016 15:03:38 +0100	[thread overview]
Message-ID: <1468505019-18154-7-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1468505019-18154-1-git-send-email-berrange@redhat.com>

Add a QAuthZSimple object type that implements the QAuthZ
interface. This simple built-in implementation maintains
a trivial access control list with a sequence of match
rules and a final default policy. This replicates the
functionality currently provided by the qemu_acl module.

To create an instance of this object via the QMP monitor,
the syntax used would be

  {
    "execute": "object-add",
    "arguments": {
      "qom-type": "authz-simple",
      "id": "auth0",
      "parameters": {
        "rules": [
           { "match": "fred", "policy": "allow", "format": "exact" },
           { "match": "bob", "policy": "allow", "format": "exact" },
           { "match": "danb", "policy": "deny", "format": "glob" },
           { "match": "dan*", "policy": "allow", "format": "exact" },
        ],
        "policy": "deny"
      }
    }
  }

Or via the -object command line

  $QEMU \
     -object authz-simple,id=acl0,policy=deny,\
             rules.0.match=fred,rules.0.policy=allow,rules.0.format=exact,\
             rules.1.match=bob,rules.1.policy=allow,rules.1.format=exact,\
             rules.2.match=danb,rules.2.policy=deny,rules.2.format=glob,\
             rules.3.match=dan\*,rules.3.policy=allow,rules.3.format=exact

This sets up an authorization rule that allows 'fred',
'bob' and anyone whose name starts with 'dan', except
for 'danb'. Everyone unmatched is denied.

Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 Makefile                    |   2 +-
 include/qemu/authz-simple.h | 115 ++++++++++++++++
 qapi-schema.json            |   6 +-
 qapi/util.json              |  47 +++++++
 tests/.gitignore            |   1 +
 tests/Makefile.include      |   3 +
 tests/test-authz-simple.c   | 172 ++++++++++++++++++++++++
 util/Makefile.objs          |   1 +
 util/authz-simple.c         | 314 ++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 659 insertions(+), 2 deletions(-)
 create mode 100644 include/qemu/authz-simple.h
 create mode 100644 qapi/util.json
 create mode 100644 tests/test-authz-simple.c
 create mode 100644 util/authz-simple.c

diff --git a/Makefile b/Makefile
index b3ac210..3a1f4c1 100644
--- a/Makefile
+++ b/Makefile
@@ -292,7 +292,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
                $(SRC_PATH)/qapi/block.json $(SRC_PATH)/qapi/block-core.json \
                $(SRC_PATH)/qapi/event.json $(SRC_PATH)/qapi/introspect.json \
                $(SRC_PATH)/qapi/crypto.json $(SRC_PATH)/qapi/rocker.json \
-               $(SRC_PATH)/qapi/trace.json
+               $(SRC_PATH)/qapi/trace.json $(SRC_PATH)/qapi/util.json
 
 qapi-types.c qapi-types.h :\
 $(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
diff --git a/include/qemu/authz-simple.h b/include/qemu/authz-simple.h
new file mode 100644
index 0000000..30e78bd
--- /dev/null
+++ b/include/qemu/authz-simple.h
@@ -0,0 +1,115 @@
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2016 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/>.
+ *
+ */
+
+#ifndef QAUTHZ_SIMPLE_H__
+#define QAUTHZ_SIMPLE_H__
+
+#include "qemu/authz.h"
+
+
+#define TYPE_QAUTHZ_SIMPLE "authz-simple"
+
+#define QAUTHZ_SIMPLE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(QAuthZSimpleClass, (klass), \
+                        TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(QAuthZSimpleClass, (obj), \
+                      TYPE_QAUTHZ_SIMPLE)
+#define QAUTHZ_SIMPLE(obj) \
+     INTERFACE_CHECK(QAuthZSimple, (obj), \
+                     TYPE_QAUTHZ_SIMPLE)
+
+typedef struct QAuthZSimple QAuthZSimple;
+typedef struct QAuthZSimpleClass QAuthZSimpleClass;
+
+
+/**
+ * QAuthZSimple:
+ *
+ * This authorization driver provides a simple mechanism
+ * for granting access by matching user names against a
+ * list of globs. Each match rule has an associated policy
+ * and a catch all policy applies if no rule matches
+ *
+ * To create an instance of this class via QMP:
+ *
+ *  {
+ *    "execute": "object-add",
+ *    "arguments": {
+ *      "qom-type": "authz-simple",
+ *      "id": "auth0",
+ *      "parameters": {
+ *        "rules": [
+ *           { "match": "fred", "policy": "allow", "format": "exact" },
+ *           { "match": "bob", "policy": "allow", "format": "exact" },
+ *           { "match": "danb", "policy": "deny", "format": "exact" },
+ *           { "match": "dan*", "policy": "allow", "format": "glob" }
+ *        ],
+ *        "policy": "deny"
+ *      }
+ *    }
+ *  }
+ *
+ * Or via the CLI:
+ *
+ *   $QEMU                                                         \
+ *    -object authz-simple,id=acl0,policy=deny,                    \
+ *            match.0.name=fred,match.0.policy=allow,format=exact, \
+ *            match.1.name=bob,match.1.policy=allow,format=exact,  \
+ *            match.2.name=danb,match.2.policy=deny,format=exact,  \
+ *            match.3.name=dan\*,match.3.policy=allow,format=exact
+ *
+ */
+struct QAuthZSimple {
+    QAuthZ parent_obj;
+
+    QAuthZSimplePolicy policy;
+    QAuthZSimpleRuleList *rules;
+};
+
+
+struct QAuthZSimpleClass {
+    QAuthZClass parent_class;
+};
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+                                QAuthZSimplePolicy policy,
+                                Error **errp);
+
+ssize_t qauthz_simple_append_rule(QAuthZSimple *auth,
+                                  const char *match,
+                                  QAuthZSimplePolicy policy,
+                                  QAuthZSimpleFormat format,
+                                  Error **errp);
+
+ssize_t qauthz_simple_insert_rule(QAuthZSimple *auth,
+                                  const char *match,
+                                  QAuthZSimplePolicy policy,
+                                  QAuthZSimpleFormat format,
+                                  size_t index,
+                                  Error **errp);
+
+ssize_t qauthz_simple_delete_rule(QAuthZSimple *auth,
+                                  const char *match);
+
+
+#endif /* QAUTHZ_SIMPLE_H__ */
+
diff --git a/qapi-schema.json b/qapi-schema.json
index d2d6506..814372c 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5,6 +5,9 @@
 # QAPI common definitions
 { 'include': 'qapi/common.json' }
 
+# QAPI util definitions
+{ 'include': 'qapi/util.json' }
+
 # QAPI crypto definitions
 { 'include': 'qapi/crypto.json' }
 
@@ -3740,7 +3743,8 @@
 # Since 2.5
 ##
 { 'struct': 'DummyForceArrays',
-  'data': { 'unused': ['X86CPUFeatureWordInfo'] } }
+  'data': { 'unused1': ['X86CPUFeatureWordInfo'],
+            'unused2': ['QAuthZSimpleRule'] } }
 
 
 ##
diff --git a/qapi/util.json b/qapi/util.json
new file mode 100644
index 0000000..6652867
--- /dev/null
+++ b/qapi/util.json
@@ -0,0 +1,47 @@
+# -*- Mode: Python -*-
+#
+# QAPI util definitions
+
+##
+# QAuthZSimplePolicy:
+#
+# The authorization policy result
+#
+# @deny: deny access
+# @allow: allow access
+#
+# Since: 2.7
+##
+{ 'enum': 'QAuthZSimplePolicy',
+  'prefix': 'QAUTHZ_SIMPLE_POLICY',
+  'data': ['deny', 'allow']}
+
+##
+# QAuthZSimpleFormat:
+#
+# The authorization policy result
+#
+# @exact: an exact string match
+# @glob: string with ? and * shell wildcard support
+#
+# Since: 2.7
+##
+{ 'enum': 'QAuthZSimpleFormat',
+  'prefix': 'QAUTHZ_SIMPLE_FORMAT',
+  'data': ['exact', 'glob']}
+
+##
+# QAuthZSimpleRule:
+#
+# A single authorization rule.
+#
+# @match: a glob to match against a user identity
+# @policy: the result to return if @match evaluates to true
+# @format: (optional) the format of the @match rule (default 'exact')
+#
+# Since: 2.7
+##
+{ 'struct': 'QAuthZSimpleRule',
+  'data': {'match': 'str',
+           'policy': 'QAuthZSimplePolicy',
+           '*format': 'QAuthZSimpleFormat'}}
diff --git a/tests/.gitignore b/tests/.gitignore
index dbb5263..f0fbdb7 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -10,6 +10,7 @@ check-qom-proplist
 qht-bench
 rcutorture
 test-aio
+test-authz-simple
 test-base64
 test-bitops
 test-blockjob-txn
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2010b11..38298db 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -111,6 +111,7 @@ check-unit-y += tests/test-crypto-xts$(EXESUF)
 check-unit-y += tests/test-crypto-block$(EXESUF)
 gcov-files-test-logging-y = tests/test-logging.c
 check-unit-y += tests/test-logging$(EXESUF)
+check-unit-y += tests/test-authz-simple$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -469,6 +470,8 @@ tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
 	$(test-util-obj-y)
 tests/test-base64$(EXESUF): tests/test-base64.o \
 	libqemuutil.a libqemustub.a
+tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o \
+	libqemuutil.a libqemustub.a $(util-qom-obj-y) $(qom-obj-y)
 
 tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 
diff --git a/tests/test-authz-simple.c b/tests/test-authz-simple.c
new file mode 100644
index 0000000..e9aea6d
--- /dev/null
+++ b/tests/test-authz-simple.c
@@ -0,0 +1,172 @@
+/*
+ * QEMU simple authorization object
+ *
+ * Copyright (c) 2016 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 <glib.h>
+
+#include "qemu/authz-simple.h"
+
+static void test_authz_default_deny(void)
+{
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_DENY,
+                                           &error_abort);
+
+    g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+    object_unparent(OBJECT(auth));
+}
+
+static void test_authz_default_allow(void)
+{
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                           &error_abort);
+
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+    object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_deny(void)
+{
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                           &error_abort);
+
+    qauthz_simple_append_rule(auth, "fred", QAUTHZ_SIMPLE_POLICY_DENY,
+                              QAUTHZ_SIMPLE_FORMAT_EXACT, &error_abort);
+
+    g_assert(!qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+    object_unparent(OBJECT(auth));
+}
+
+static void test_authz_explicit_allow(void)
+{
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_DENY,
+                                           &error_abort);
+
+    qauthz_simple_append_rule(auth, "fred", QAUTHZ_SIMPLE_POLICY_ALLOW,
+                              QAUTHZ_SIMPLE_FORMAT_EXACT, &error_abort);
+
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+
+    object_unparent(OBJECT(auth));
+}
+
+
+static void test_authz_complex(void)
+{
+#ifndef CONFIG_FNMATCH
+    Error *local_err = NULL;
+#endif
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_DENY,
+                                           &error_abort);
+
+    qauthz_simple_append_rule(auth, "fred", QAUTHZ_SIMPLE_POLICY_ALLOW,
+                              QAUTHZ_SIMPLE_FORMAT_EXACT, &error_abort);
+    qauthz_simple_append_rule(auth, "bob", QAUTHZ_SIMPLE_POLICY_ALLOW,
+                              QAUTHZ_SIMPLE_FORMAT_EXACT, &error_abort);
+    qauthz_simple_append_rule(auth, "dan", QAUTHZ_SIMPLE_POLICY_DENY,
+                              QAUTHZ_SIMPLE_FORMAT_EXACT, &error_abort);
+#ifdef CONFIG_FNMATCH
+    qauthz_simple_append_rule(auth, "dan*", QAUTHZ_SIMPLE_POLICY_ALLOW,
+                              QAUTHZ_SIMPLE_FORMAT_GLOB, &error_abort);
+
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "fred", &error_abort));
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "bob", &error_abort));
+    g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "danb", &error_abort));
+#else
+    g_assert(qauthz_simple_append_rule(auth, "dan*",
+                                       QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                       QAUTHZ_SIMPLE_FORMAT_GLOB,
+                                       &local_err) < 0);
+    g_assert(local_err != NULL);
+    error_free(local_err);
+#endif
+
+    object_unparent(OBJECT(auth));
+}
+
+static void test_authz_add_remove(void)
+{
+    QAuthZSimple *auth = qauthz_simple_new("auth0",
+                                           QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                           &error_abort);
+
+    g_assert_cmpint(qauthz_simple_append_rule(auth, "fred",
+                                              QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                              QAUTHZ_SIMPLE_FORMAT_EXACT,
+                                              &error_abort),
+                    ==, 0);
+    g_assert_cmpint(qauthz_simple_append_rule(auth, "bob",
+                                              QAUTHZ_SIMPLE_POLICY_ALLOW,
+                                              QAUTHZ_SIMPLE_FORMAT_EXACT,
+                                              &error_abort),
+                    ==, 1);
+    g_assert_cmpint(qauthz_simple_append_rule(auth, "dan",
+                                              QAUTHZ_SIMPLE_POLICY_DENY,
+                                              QAUTHZ_SIMPLE_FORMAT_EXACT,
+                                              &error_abort),
+                    ==, 2);
+    g_assert_cmpint(qauthz_simple_append_rule(auth, "frank",
+                                              QAUTHZ_SIMPLE_POLICY_DENY,
+                                              QAUTHZ_SIMPLE_FORMAT_EXACT,
+                                              &error_abort),
+                    ==, 3);
+
+    g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+    g_assert_cmpint(qauthz_simple_delete_rule(auth, "dan"),
+                    ==, 2);
+
+    g_assert(qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+    g_assert_cmpint(qauthz_simple_insert_rule(auth, "dan",
+                                              QAUTHZ_SIMPLE_POLICY_DENY,
+                                              QAUTHZ_SIMPLE_FORMAT_EXACT,
+                                              2,
+                                              &error_abort),
+                    ==, 2);
+
+    g_assert(!qauthz_is_allowed(QAUTHZ(auth), "dan", &error_abort));
+
+    object_unparent(OBJECT(auth));
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    module_call_init(MODULE_INIT_QOM);
+
+    g_test_add_func("/auth/simple/default/deny", test_authz_default_deny);
+    g_test_add_func("/auth/simple/default/allow", test_authz_default_allow);
+    g_test_add_func("/auth/simple/explicit/deny", test_authz_explicit_deny);
+    g_test_add_func("/auth/simple/explicit/allow", test_authz_explicit_allow);
+    g_test_add_func("/auth/simple/complex", test_authz_complex);
+    g_test_add_func("/auth/simple/add-remove", test_authz_add_remove);
+
+    return g_test_run();
+}
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 006ac63..f71a7b6 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -37,3 +37,4 @@ util-obj-y += qht.o
 util-obj-y += range.o
 
 util-qom-obj-y += authz.o
+util-qom-obj-y += authz-simple.o
diff --git a/util/authz-simple.c b/util/authz-simple.c
new file mode 100644
index 0000000..a26177f
--- /dev/null
+++ b/util/authz-simple.c
@@ -0,0 +1,314 @@
+/*
+ * QEMU simple authorization driver
+ *
+ * Copyright (c) 2016 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 "qemu/authz-simple.h"
+#include "qom/object_interfaces.h"
+#include "qapi-visit.h"
+
+#ifdef CONFIG_FNMATCH
+#include <fnmatch.h>
+#endif
+
+static bool qauthz_simple_is_allowed(QAuthZ *authz,
+                                     const char *identity,
+                                     Error **errp)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(authz);
+    QAuthZSimpleRuleList *rules = sauthz->rules;
+
+    while (rules) {
+        QAuthZSimpleRule *rule = rules->value;
+        QAuthZSimpleFormat format = rule->has_format ? rule->format :
+            QAUTHZ_SIMPLE_FORMAT_EXACT;
+
+        switch (format) {
+        case QAUTHZ_SIMPLE_FORMAT_EXACT:
+            if (strcmp(rule->match, identity) == 0) {
+                return rule->policy == QAUTHZ_SIMPLE_POLICY_ALLOW;
+            }
+            break;
+#ifdef CONFIG_FNMATCH
+        case QAUTHZ_SIMPLE_FORMAT_GLOB:
+            if (fnmatch(rule->match, identity, 0) == 0) {
+                return rule->policy == QAUTHZ_SIMPLE_POLICY_ALLOW;
+            }
+            break;
+#else
+            return false;
+#endif
+        default:
+            return false;
+        }
+        rules = rules->next;
+    }
+
+    return sauthz->policy == QAUTHZ_SIMPLE_POLICY_ALLOW;
+}
+
+
+static void
+qauthz_simple_prop_set_policy(Object *obj,
+                              int value,
+                              Error **errp G_GNUC_UNUSED)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+    sauthz->policy = value;
+}
+
+
+static int
+qauthz_simple_prop_get_policy(Object *obj,
+                              Error **errp G_GNUC_UNUSED)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+    return sauthz->policy;
+}
+
+
+static void
+qauthz_simple_prop_get_rules(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+    visit_type_QAuthZSimpleRuleList(v, name, &sauthz->rules, errp);
+}
+
+static void
+qauthz_simple_prop_set_rules(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+    QAuthZSimpleRuleList *oldrules;
+#ifndef CONFIG_FNMATCH
+    QAuthZSimpleRuleList *rules;
+#endif
+
+    oldrules = sauthz->rules;
+    visit_type_QAuthZSimpleRuleList(v, name, &sauthz->rules, errp);
+
+#ifndef CONFIG_FNMATCH
+    rules = sauthz->rules;
+    while (rules) {
+        QAuthZSimpleRule *rule = rules->value;
+        if (rule->has_format &&
+            rule->format == QAUTHZ_SIMPLE_FORMAT_GLOB) {
+            error_setg(errp, "Glob format not supported on this platform");
+            qapi_free_QAuthZSimpleRuleList(sauthz->rules);
+            sauthz->rules = oldrules;
+            return;
+        }
+    }
+#endif
+
+    qapi_free_QAuthZSimpleRuleList(oldrules);
+}
+
+
+static void
+qauthz_simple_complete(UserCreatable *uc, Error **errp)
+{
+}
+
+
+static void
+qauthz_simple_finalize(Object *obj)
+{
+    QAuthZSimple *sauthz = QAUTHZ_SIMPLE(obj);
+
+    qapi_free_QAuthZSimpleRuleList(sauthz->rules);
+}
+
+
+static void
+qauthz_simple_class_init(ObjectClass *oc, void *data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+    QAuthZClass *authz = QAUTHZ_CLASS(oc);
+
+    ucc->complete = qauthz_simple_complete;
+    authz->is_allowed = qauthz_simple_is_allowed;
+
+    object_class_property_add_enum(oc, "policy",
+                                   "QAuthZSimplePolicy",
+                                   QAuthZSimplePolicy_lookup,
+                                   qauthz_simple_prop_get_policy,
+                                   qauthz_simple_prop_set_policy,
+                                   NULL);
+
+    object_class_property_add(oc, "rules", "QAuthZSimpleRule",
+                              qauthz_simple_prop_get_rules,
+                              qauthz_simple_prop_set_rules,
+                              NULL, NULL, NULL);
+}
+
+
+QAuthZSimple *qauthz_simple_new(const char *id,
+                                QAuthZSimplePolicy policy,
+                                Error **errp)
+{
+    return QAUTHZ_SIMPLE(
+        object_new_with_props(TYPE_QAUTHZ_SIMPLE,
+                              object_get_objects_root(),
+                              id, errp,
+                              "policy", QAuthZSimplePolicy_lookup[policy],
+                              NULL));
+}
+
+
+ssize_t qauthz_simple_append_rule(QAuthZSimple *auth,
+                                  const char *match,
+                                  QAuthZSimplePolicy policy,
+                                  QAuthZSimpleFormat format,
+                                  Error **errp)
+{
+    QAuthZSimpleRule *rule;
+    QAuthZSimpleRuleList *rules, *tmp;
+    size_t i = 0;
+
+#ifndef CONFIG_FNMATCH
+    if (format == QAUTHZ_SIMPLE_FORMAT_GLOB) {
+        error_setg(errp, "Glob format not supported on this platform");
+        return -1;
+    }
+#endif
+
+    rule = g_new0(QAuthZSimpleRule, 1);
+    rule->policy = policy;
+    rule->match = g_strdup(match);
+    rule->format = format;
+    rule->has_format = true;
+
+    tmp = g_new0(QAuthZSimpleRuleList, 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_simple_insert_rule(QAuthZSimple *auth,
+                                  const char *match,
+                                  QAuthZSimplePolicy policy,
+                                  QAuthZSimpleFormat format,
+                                  size_t index,
+                                  Error **errp)
+{
+    QAuthZSimpleRule *rule;
+    QAuthZSimpleRuleList *rules, *tmp;
+    size_t i = 0;
+
+#ifndef CONFIG_FNMATCH
+    if (format == QAUTHZ_SIMPLE_FORMAT_GLOB) {
+        error_setg(errp, "Glob format not supported on this platform");
+        return -1;
+    }
+#endif
+
+    rule = g_new0(QAuthZSimpleRule, 1);
+    rule->policy = policy;
+    rule->match = g_strdup(match);
+    rule->format = format;
+    rule->has_format = true;
+
+    tmp = g_new0(QAuthZSimpleRuleList, 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_simple_delete_rule(QAuthZSimple *auth, const char *match)
+{
+    QAuthZSimpleRule *rule;
+    QAuthZSimpleRuleList *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_QAuthZSimpleRuleList(rules);
+            return i;
+        }
+        prev = rules;
+        rules = rules->next;
+        i++;
+    }
+
+    return -1;
+}
+
+
+static const TypeInfo qauthz_simple_info = {
+    .parent = TYPE_QAUTHZ,
+    .name = TYPE_QAUTHZ_SIMPLE,
+    .instance_size = sizeof(QAuthZSimple),
+    .instance_finalize = qauthz_simple_finalize,
+    .class_size = sizeof(QAuthZSimpleClass),
+    .class_init = qauthz_simple_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+
+static void
+qauthz_simple_register_types(void)
+{
+    type_register_static(&qauthz_simple_info);
+}
+
+
+type_init(qauthz_simple_register_types);
-- 
2.7.4

  parent reply	other threads:[~2016-07-14 14:04 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-14 14:03 [Qemu-devel] [PATCH v8 0/7] Provide a QOM-based authorization API Daniel P. Berrange
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 1/7] qdict: implement a qdict_crumple method for un-flattening a dict Daniel P. Berrange
2016-07-15 15:06   ` Markus Armbruster
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 2/7] option: make parse_option_bool/number non-static Daniel P. Berrange
2016-07-15 15:13   ` Markus Armbruster
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 3/7] qapi: add a QmpInputVisitor that does string conversion Daniel P. Berrange
2016-07-15 15:36   ` Markus Armbruster
2016-07-15 16:27     ` Eric Blake
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 4/7] qom: support arbitrary non-scalar properties with -object Daniel P. Berrange
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 5/7] util: add QAuthZ object as an authorization base class Daniel P. Berrange
2016-07-14 14:03 ` Daniel P. Berrange [this message]
2016-07-14 14:03 ` [Qemu-devel] [PATCH v8 7/7] acl: delete existing ACL implementation Daniel P. Berrange

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1468505019-18154-7-git-send-email-berrange@redhat.com \
    --to=berrange@redhat.com \
    --cc=afaerber@suse.de \
    --cc=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=marcandre.lureau@gmail.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.