[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v5 11/11] authz: delete existing ACL implementat
From: |
Philippe Mathieu-Daudé |
Subject: |
Re: [Qemu-devel] [PATCH v5 11/11] authz: delete existing ACL implementation |
Date: |
Fri, 19 Oct 2018 08:10:28 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 |
On 09/10/2018 15:04, Daniel P. Berrangé wrote:
> From: "Daniel P. Berrange" <address@hidden>
>
> The 'qemu_acl' type was a previous non-QOM based attempt to provide an
> authorization facility in QEMU. Because it is non-QOM based it cannot be
> created via the command line and requires special monitor commands to
> manipulate it.
>
> The new QAuthZ subclasses provide a superset of the functionality in
> qemu_acl, so the latter can now be deleted. The HMP 'acl_*' monitor
> commands are converted to use the new QAuthZSimple data type instead
> in order to provide temporary backwards compatibility.
>
> Signed-off-by: Daniel P. Berrange <address@hidden>
> ---
> crypto/tlssession.c | 35 ++++---
> crypto/trace-events | 2 +-
> include/qemu/acl.h | 66 ------------
> monitor.c | 180 ++++++++++++++++++++++-----------
> tests/Makefile.include | 4 +-
> tests/test-crypto-tlssession.c | 15 ++-
> tests/test-io-channel-tls.c | 16 ++-
> ui/vnc-auth-sasl.c | 23 +++--
> ui/vnc-auth-sasl.h | 5 +-
> ui/vnc-auth-vencrypt.c | 2 +-
> ui/vnc-ws.c | 2 +-
> ui/vnc.c | 37 ++++---
> ui/vnc.h | 4 +-
> util/Makefile.objs | 1 -
> util/acl.c | 179 --------------------------------
> 15 files changed, 210 insertions(+), 361 deletions(-)
> delete mode 100644 include/qemu/acl.h
> delete mode 100644 util/acl.c
>
> diff --git a/crypto/tlssession.c b/crypto/tlssession.c
> index 66a6fbe19c..23842aa95d 100644
> --- a/crypto/tlssession.c
> +++ b/crypto/tlssession.c
> @@ -24,7 +24,7 @@
> #include "crypto/tlscredspsk.h"
> #include "crypto/tlscredsx509.h"
> #include "qapi/error.h"
> -#include "qemu/acl.h"
> +#include "authz/base.h"
> #include "trace.h"
>
> #ifdef CONFIG_GNUTLS
> @@ -37,7 +37,7 @@ struct QCryptoTLSSession {
> QCryptoTLSCreds *creds;
> gnutls_session_t handle;
> char *hostname;
> - char *aclname;
> + char *authzid;
> bool handshakeComplete;
> QCryptoTLSSessionWriteFunc writeFunc;
> QCryptoTLSSessionReadFunc readFunc;
> @@ -56,7 +56,7 @@ qcrypto_tls_session_free(QCryptoTLSSession *session)
> gnutls_deinit(session->handle);
> g_free(session->hostname);
> g_free(session->peername);
> - g_free(session->aclname);
> + g_free(session->authzid);
> object_unref(OBJECT(session->creds));
> g_free(session);
> }
> @@ -101,7 +101,7 @@ qcrypto_tls_session_pull(void *opaque, void *buf, size_t
> len)
> QCryptoTLSSession *
> qcrypto_tls_session_new(QCryptoTLSCreds *creds,
> const char *hostname,
> - const char *aclname,
> + const char *authzid,
> QCryptoTLSCredsEndpoint endpoint,
> Error **errp)
> {
> @@ -111,13 +111,13 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
> session = g_new0(QCryptoTLSSession, 1);
> trace_qcrypto_tls_session_new(
> session, creds, hostname ? hostname : "<none>",
> - aclname ? aclname : "<none>", endpoint);
> + authzid ? authzid : "<none>", endpoint);
>
> if (hostname) {
> session->hostname = g_strdup(hostname);
> }
> - if (aclname) {
> - session->aclname = g_strdup(aclname);
> + if (authzid) {
> + session->authzid = g_strdup(authzid);
> }
> session->creds = creds;
> object_ref(OBJECT(creds));
> @@ -268,6 +268,7 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession
> *session,
> unsigned int nCerts, i;
> time_t now;
> gnutls_x509_crt_t cert = NULL;
> + Error *err = NULL;
>
> now = time(NULL);
> if (now == ((time_t)-1)) {
> @@ -355,19 +356,17 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession
> *session,
> gnutls_strerror(ret));
> goto error;
> }
> - if (session->aclname) {
> - qemu_acl *acl = qemu_acl_find(session->aclname);
> - int allow;
> - if (!acl) {
> - error_setg(errp, "Cannot find ACL %s",
> - session->aclname);
> + if (session->authzid) {
> + bool allow;
> +
> + allow = qauthz_is_allowed_by_id(session->authzid,
> + session->peername, &err);
> + if (err) {
> + error_propagate(errp, err);
> goto error;
> }
> -
> - allow = qemu_acl_party_is_allowed(acl, session->peername);
> -
> if (!allow) {
> - error_setg(errp, "TLS x509 ACL check for %s is denied",
> + error_setg(errp, "TLS x509 authz check for %s is denied",
> session->peername);
> goto error;
> }
> @@ -558,7 +557,7 @@ qcrypto_tls_session_get_peer_name(QCryptoTLSSession
> *session)
> QCryptoTLSSession *
> qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED,
> const char *hostname G_GNUC_UNUSED,
> - const char *aclname G_GNUC_UNUSED,
> + const char *authzid G_GNUC_UNUSED,
> QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,
> Error **errp)
> {
> diff --git a/crypto/trace-events b/crypto/trace-events
> index 597389b73c..a38ad7b787 100644
> --- a/crypto/trace-events
> +++ b/crypto/trace-events
> @@ -19,5 +19,5 @@ qcrypto_tls_creds_x509_load_cert(void *creds, int isServer,
> const char *file) "T
> qcrypto_tls_creds_x509_load_cert_list(void *creds, const char *file) "TLS
> creds x509 load cert list creds=%p file=%s"
>
> # crypto/tlssession.c
> -qcrypto_tls_session_new(void *session, void *creds, const char *hostname,
> const char *aclname, int endpoint) "TLS session new session=%p creds=%p
> hostname=%s aclname=%s endpoint=%d"
> +qcrypto_tls_session_new(void *session, void *creds, const char *hostname,
> const char *authzid, int endpoint) "TLS session new session=%p creds=%p
> hostname=%s authzid=%s endpoint=%d"
> qcrypto_tls_session_check_creds(void *session, const char *status) "TLS
> session check creds session=%p status=%s"
> diff --git a/include/qemu/acl.h b/include/qemu/acl.h
> deleted file mode 100644
> index 7c44119a47..0000000000
> --- a/include/qemu/acl.h
> +++ /dev/null
> @@ -1,66 +0,0 @@
> -/*
> - * QEMU access control list management
> - *
> - * Copyright (C) 2009 Red Hat, Inc
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> copy
> - * of this software and associated documentation files (the "Software"), to
> deal
> - * in the Software without restriction, including without limitation the
> rights
> - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> - * copies of the Software, and to permit persons to whom the Software is
> - * furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice shall be included in
> - * all copies or substantial portions of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> - * THE SOFTWARE.
> - */
> -
> -#ifndef QEMU_ACL_H
> -#define QEMU_ACL_H
> -
> -#include "qemu/queue.h"
> -
> -typedef struct qemu_acl_entry qemu_acl_entry;
> -typedef struct qemu_acl qemu_acl;
> -
> -struct qemu_acl_entry {
> - char *match;
> - int deny;
> -
> - QTAILQ_ENTRY(qemu_acl_entry) next;
> -};
> -
> -struct qemu_acl {
> - char *aclname;
> - unsigned int nentries;
> - QTAILQ_HEAD(,qemu_acl_entry) entries;
> - int defaultDeny;
> -};
> -
> -qemu_acl *qemu_acl_init(const char *aclname);
> -
> -qemu_acl *qemu_acl_find(const char *aclname);
> -
> -int qemu_acl_party_is_allowed(qemu_acl *acl,
> - const char *party);
> -
> -void qemu_acl_reset(qemu_acl *acl);
> -
> -int qemu_acl_append(qemu_acl *acl,
> - int deny,
> - const char *match);
> -int qemu_acl_insert(qemu_acl *acl,
> - int deny,
> - const char *match,
> - int index);
> -int qemu_acl_remove(qemu_acl *acl,
> - const char *match);
> -
> -#endif /* QEMU_ACL_H */
> diff --git a/monitor.c b/monitor.c
> index b9258a7438..abedc6263f 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -51,7 +51,8 @@
> #include "sysemu/balloon.h"
> #include "qemu/timer.h"
> #include "sysemu/hw_accel.h"
> -#include "qemu/acl.h"
> +#include "authz/list.h"
> +#include "qapi/util.h"
> #include "sysemu/tpm.h"
> #include "qapi/qmp/qdict.h"
> #include "qapi/qmp/qerror.h"
> @@ -2040,61 +2041,87 @@ static void hmp_wavcapture(Monitor *mon, const QDict
> *qdict)
> QLIST_INSERT_HEAD (&capture_head, s, entries);
> }
>
> -static qemu_acl *find_acl(Monitor *mon, const char *name)
> +static QAuthZList *find_auth(Monitor *mon, const char *name)
> {
> - qemu_acl *acl = qemu_acl_find(name);
> + Object *obj;
> + Object *container;
>
> - if (!acl) {
> + container = object_get_objects_root();
> + obj = object_resolve_path_component(container, name);
> + if (!obj) {
> monitor_printf(mon, "acl: unknown list '%s'\n", name);
> + return NULL;
> }
> - return acl;
> +
> + return QAUTHZ_LIST(obj);
> }
>
> static void hmp_acl_show(Monitor *mon, const QDict *qdict)
> {
> const char *aclname = qdict_get_str(qdict, "aclname");
> - qemu_acl *acl = find_acl(mon, aclname);
> - qemu_acl_entry *entry;
> - int i = 0;
> -
> - if (acl) {
> - monitor_printf(mon, "policy: %s\n",
> - acl->defaultDeny ? "deny" : "allow");
> - QTAILQ_FOREACH(entry, &acl->entries, next) {
> - i++;
> - monitor_printf(mon, "%d: %s %s\n", i,
> - entry->deny ? "deny" : "allow", entry->match);
> - }
> + QAuthZList *auth = find_auth(mon, aclname);
> + QAuthZListRuleList *rules;
> + size_t i = 0;
> +
> + if (!auth) {
> + return;
> + }
> +
> + monitor_printf(mon, "policy: %s\n",
> + QAuthZListPolicy_lookup.array[auth->policy]);
> +
> + rules = auth->rules;
> + while (rules) {
> + QAuthZListRule *rule = rules->value;
> + i++;
> + monitor_printf(mon, "%zu: %s %s\n", i,
> + QAuthZListPolicy_lookup.array[rule->policy],
> + rule->match);
> + rules = rules->next;
> }
> }
>
> static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
> {
> const char *aclname = qdict_get_str(qdict, "aclname");
> - qemu_acl *acl = find_acl(mon, aclname);
> + QAuthZList *auth = find_auth(mon, aclname);
>
> - if (acl) {
> - qemu_acl_reset(acl);
> - monitor_printf(mon, "acl: removed all rules\n");
> + if (!auth) {
> + return;
> }
> +
> + auth->policy = QAUTHZ_LIST_POLICY_DENY;
> + qapi_free_QAuthZListRuleList(auth->rules);
> + auth->rules = NULL;
> + monitor_printf(mon, "acl: removed all rules\n");
> }
>
> static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
> {
> const char *aclname = qdict_get_str(qdict, "aclname");
> const char *policy = qdict_get_str(qdict, "policy");
> - qemu_acl *acl = find_acl(mon, aclname);
> + QAuthZList *auth = find_auth(mon, aclname);
> + int val;
> + Error *err = NULL;
>
> - if (acl) {
> - if (strcmp(policy, "allow") == 0) {
> - acl->defaultDeny = 0;
> + if (!auth) {
> + return;
> + }
> +
> + val = qapi_enum_parse(&QAuthZListPolicy_lookup,
> + policy,
> + QAUTHZ_LIST_POLICY_DENY,
> + &err);
> + if (err) {
> + error_free(err);
> + monitor_printf(mon, "acl: unknown policy '%s', "
> + "expected 'deny' or 'allow'\n", policy);
> + } else {
> + auth->policy = val;
> + if (auth->policy == QAUTHZ_LIST_POLICY_ALLOW) {
> monitor_printf(mon, "acl: policy set to 'allow'\n");
> - } else if (strcmp(policy, "deny") == 0) {
> - acl->defaultDeny = 1;
> - monitor_printf(mon, "acl: policy set to 'deny'\n");
> } else {
> - monitor_printf(mon, "acl: unknown policy '%s', "
> - "expected 'deny' or 'allow'\n", policy);
> + monitor_printf(mon, "acl: policy set to 'deny'\n");
> }
> }
> }
> @@ -2103,30 +2130,60 @@ static void hmp_acl_add(Monitor *mon, const QDict
> *qdict)
> {
> const char *aclname = qdict_get_str(qdict, "aclname");
> const char *match = qdict_get_str(qdict, "match");
> - const char *policy = qdict_get_str(qdict, "policy");
> + const char *policystr = qdict_get_str(qdict, "policy");
> int has_index = qdict_haskey(qdict, "index");
> int index = qdict_get_try_int(qdict, "index", -1);
> - qemu_acl *acl = find_acl(mon, aclname);
> - int deny, ret;
> -
> - if (acl) {
> - if (strcmp(policy, "allow") == 0) {
> - deny = 0;
> - } else if (strcmp(policy, "deny") == 0) {
> - deny = 1;
> - } else {
> - monitor_printf(mon, "acl: unknown policy '%s', "
> - "expected 'deny' or 'allow'\n", policy);
> - return;
> - }
> - if (has_index)
> - ret = qemu_acl_insert(acl, deny, match, index);
> - else
> - ret = qemu_acl_append(acl, deny, match);
> - if (ret < 0)
> - monitor_printf(mon, "acl: unable to add acl entry\n");
> - else
> - monitor_printf(mon, "acl: added rule at position %d\n", ret);
> + QAuthZList *auth = find_auth(mon, aclname);
> + Error *err = NULL;
> + QAuthZListPolicy policy;
> + QAuthZListFormat format;
> + size_t i = 0;
> +
> + if (!auth) {
> + return;
> + }
> +
> + policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
> + policystr,
> + QAUTHZ_LIST_POLICY_DENY,
> + &err);
> + if (err) {
> + error_free(err);
> + monitor_printf(mon, "acl: unknown policy '%s', "
> + "expected 'deny' or 'allow'\n", policystr);
> + return;
> + }
> +
> +#ifdef CONFIG_FNMATCH
> + if (strchr(match, '*')) {
> + format = QAUTHZ_LIST_FORMAT_GLOB;
> + } else {
> + format = QAUTHZ_LIST_FORMAT_EXACT;
> + }
> +#else
> + /* Historically we silently degraded to plain strcmp
> + * when fnmatch() was missing */
> + format = QAUTHZ_LIST_FORMAT_EXACT;
> +#endif
Only one comment in this patch, I'd prefer this ifdeffery moved to some
get_format(match) function.
Reviewed-by: Philippe Mathieu-Daudé <address@hidden>
> +
> + if (has_index && index == 0) {
> + monitor_printf(mon, "acl: unable to add acl entry\n");
> + return;
> + }
> +
> + if (has_index) {
> + i = qauthz_list_insert_rule(auth, match, policy,
> + format, index - 1, &err);
> + } else {
> + i = qauthz_list_append_rule(auth, match, policy,
> + format, &err);
> + }
> + if (err) {
> + monitor_printf(mon, "acl: unable to add rule: %s",
> + error_get_pretty(err));
> + error_free(err);
> + } else {
> + monitor_printf(mon, "acl: added rule at position %zu\n", i + 1);
> }
> }
>
> @@ -2134,15 +2191,18 @@ static void hmp_acl_remove(Monitor *mon, const QDict
> *qdict)
> {
> const char *aclname = qdict_get_str(qdict, "aclname");
> const char *match = qdict_get_str(qdict, "match");
> - qemu_acl *acl = find_acl(mon, aclname);
> - int ret;
> + QAuthZList *auth = find_auth(mon, aclname);
> + ssize_t i = 0;
>
> - if (acl) {
> - ret = qemu_acl_remove(acl, match);
> - if (ret < 0)
> - monitor_printf(mon, "acl: no matching acl entry\n");
> - else
> - monitor_printf(mon, "acl: removed rule at position %d\n", ret);
> + if (!auth) {
> + return;
> + }
> +
> + i = qauthz_list_delete_rule(auth, match);
> + if (i >= 0) {
> + monitor_printf(mon, "acl: removed rule at position %zu\n", i + 1);
> + } else {
> + monitor_printf(mon, "acl: no matching acl entry\n");
> }
> }
>
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 4bd67cd53f..b4df52cf12 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -626,8 +626,8 @@ test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
> test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
> tests/test-qapi-events.o tests/test-qapi-introspect.o \
> $(test-qom-obj-y)
> -benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
> -test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
> +benchmark-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
> +test-crypto-obj-y = $(authz-obj-y) $(crypto-obj-y) $(test-qom-obj-y)
> test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
> test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
>
> diff --git a/tests/test-crypto-tlssession.c b/tests/test-crypto-tlssession.c
> index 6fa9950afb..15212ec276 100644
> --- a/tests/test-crypto-tlssession.c
> +++ b/tests/test-crypto-tlssession.c
> @@ -28,7 +28,7 @@
> #include "qom/object_interfaces.h"
> #include "qapi/error.h"
> #include "qemu/sockets.h"
> -#include "qemu/acl.h"
> +#include "authz/list.h"
>
> #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
>
> @@ -229,7 +229,7 @@ static void test_crypto_tls_session_x509(const void
> *opaque)
> QCryptoTLSCreds *serverCreds;
> QCryptoTLSSession *clientSess = NULL;
> QCryptoTLSSession *serverSess = NULL;
> - qemu_acl *acl;
> + QAuthZList *auth;
> const char * const *wildcards;
> int channel[2];
> bool clientShake = false;
> @@ -285,11 +285,15 @@ static void test_crypto_tls_session_x509(const void
> *opaque)
> SERVER_CERT_DIR);
> g_assert(serverCreds != NULL);
>
> - acl = qemu_acl_init("tlssessionacl");
> - qemu_acl_reset(acl);
> + auth = qauthz_list_new("tlssessionacl",
> + QAUTHZ_LIST_POLICY_DENY,
> + &error_abort);
> wildcards = data->wildcards;
> while (wildcards && *wildcards) {
> - qemu_acl_append(acl, 0, *wildcards);
> + qauthz_list_append_rule(auth, *wildcards,
> + QAUTHZ_LIST_POLICY_ALLOW,
> + QAUTHZ_LIST_FORMAT_GLOB,
> + &error_abort);
> wildcards++;
> }
>
> @@ -377,6 +381,7 @@ static void test_crypto_tls_session_x509(const void
> *opaque)
>
> object_unparent(OBJECT(serverCreds));
> object_unparent(OBJECT(clientCreds));
> + object_unparent(OBJECT(auth));
>
> qcrypto_tls_session_free(serverSess);
> qcrypto_tls_session_free(clientSess);
> diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c
> index 4900c6d433..43b707eba7 100644
> --- a/tests/test-io-channel-tls.c
> +++ b/tests/test-io-channel-tls.c
> @@ -29,8 +29,8 @@
> #include "io-channel-helpers.h"
> #include "crypto/init.h"
> #include "crypto/tlscredsx509.h"
> -#include "qemu/acl.h"
> #include "qapi/error.h"
> +#include "authz/list.h"
> #include "qom/object_interfaces.h"
>
> #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
> @@ -113,7 +113,7 @@ static void test_io_channel_tls(const void *opaque)
> QIOChannelTLS *serverChanTLS;
> QIOChannelSocket *clientChanSock;
> QIOChannelSocket *serverChanSock;
> - qemu_acl *acl;
> + QAuthZList *auth;
> const char * const *wildcards;
> int channel[2];
> struct QIOChannelTLSHandshakeData clientHandshake = { false, false };
> @@ -161,11 +161,15 @@ static void test_io_channel_tls(const void *opaque)
> SERVER_CERT_DIR);
> g_assert(serverCreds != NULL);
>
> - acl = qemu_acl_init("channeltlsacl");
> - qemu_acl_reset(acl);
> + auth = qauthz_list_new("channeltlsacl",
> + QAUTHZ_LIST_POLICY_DENY,
> + &error_abort);
> wildcards = data->wildcards;
> while (wildcards && *wildcards) {
> - qemu_acl_append(acl, 0, *wildcards);
> + qauthz_list_append_rule(auth, *wildcards,
> + QAUTHZ_LIST_POLICY_ALLOW,
> + QAUTHZ_LIST_FORMAT_GLOB,
> + &error_abort);
> wildcards++;
> }
>
> @@ -253,6 +257,8 @@ static void test_io_channel_tls(const void *opaque)
> object_unref(OBJECT(serverChanSock));
> object_unref(OBJECT(clientChanSock));
>
> + object_unparent(OBJECT(auth));
> +
> close(channel[0]);
> close(channel[1]);
> }
> diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
> index 3751a777a4..7b2b09f242 100644
> --- a/ui/vnc-auth-sasl.c
> +++ b/ui/vnc-auth-sasl.c
> @@ -24,6 +24,7 @@
>
> #include "qemu/osdep.h"
> #include "qapi/error.h"
> +#include "authz/base.h"
> #include "vnc.h"
> #include "trace.h"
>
> @@ -146,13 +147,14 @@ size_t vnc_client_read_sasl(VncState *vs)
> static int vnc_auth_sasl_check_access(VncState *vs)
> {
> const void *val;
> - int err;
> - int allow;
> + int rv;
> + Error *err = NULL;
> + bool allow;
>
> - err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
> - if (err != SASL_OK) {
> + rv = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
> + if (rv != SASL_OK) {
> trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username",
> - sasl_errstring(err, NULL, NULL));
> + sasl_errstring(rv, NULL, NULL));
> return -1;
> }
> if (val == NULL) {
> @@ -163,12 +165,19 @@ static int vnc_auth_sasl_check_access(VncState *vs)
> vs->sasl.username = g_strdup((const char*)val);
> trace_vnc_auth_sasl_username(vs, vs->sasl.username);
>
> - if (vs->vd->sasl.acl == NULL) {
> + if (vs->vd->sasl.authzid == NULL) {
> trace_vnc_auth_sasl_acl(vs, 1);
> return 0;
> }
>
> - allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username);
> + allow = qauthz_is_allowed_by_id(vs->vd->sasl.authzid,
> + vs->sasl.username, &err);
> + if (err) {
> + trace_vnc_auth_fail(vs, vs->auth, "Error from authz",
> + error_get_pretty(err));
> + error_free(err);
> + return -1;
> + }
>
> trace_vnc_auth_sasl_acl(vs, allow);
> return allow ? 0 : -1;
> diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h
> index 2ae224ee3a..fb55fe04ca 100644
> --- a/ui/vnc-auth-sasl.h
> +++ b/ui/vnc-auth-sasl.h
> @@ -30,8 +30,8 @@
> typedef struct VncStateSASL VncStateSASL;
> typedef struct VncDisplaySASL VncDisplaySASL;
>
> -#include "qemu/acl.h"
> #include "qemu/main-loop.h"
> +#include "authz/base.h"
>
> struct VncStateSASL {
> sasl_conn_t *conn;
> @@ -60,7 +60,8 @@ struct VncStateSASL {
> };
>
> struct VncDisplaySASL {
> - qemu_acl *acl;
> + QAuthZ *authz;
> + char *authzid;
> };
>
> void vnc_sasl_client_cleanup(VncState *vs);
> diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
> index d99ea362c1..f072e16ace 100644
> --- a/ui/vnc-auth-vencrypt.c
> +++ b/ui/vnc-auth-vencrypt.c
> @@ -109,7 +109,7 @@ static int protocol_client_vencrypt_auth(VncState *vs,
> uint8_t *data, size_t len
> tls = qio_channel_tls_new_server(
> vs->ioc,
> vs->vd->tlscreds,
> - vs->vd->tlsaclname,
> + vs->vd->tlsauthzid,
> &err);
> if (!tls) {
> trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
> diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
> index 950f1cd2ac..95c9703c72 100644
> --- a/ui/vnc-ws.c
> +++ b/ui/vnc-ws.c
> @@ -62,7 +62,7 @@ gboolean vncws_tls_handshake_io(QIOChannel *ioc
> G_GNUC_UNUSED,
> tls = qio_channel_tls_new_server(
> vs->ioc,
> vs->vd->tlscreds,
> - vs->vd->tlsaclname,
> + vs->vd->tlsauthzid,
> &err);
> if (!tls) {
> VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
> diff --git a/ui/vnc.c b/ui/vnc.c
> index cf221c83cc..60cb7c2d3d 100644
> --- a/ui/vnc.c
> +++ b/ui/vnc.c
> @@ -33,7 +33,7 @@
> #include "qemu/option.h"
> #include "qemu/sockets.h"
> #include "qemu/timer.h"
> -#include "qemu/acl.h"
> +#include "authz/list.h"
> #include "qemu/config-file.h"
> #include "qapi/qapi-events.h"
> #include "qapi/error.h"
> @@ -3267,12 +3267,24 @@ static void vnc_display_close(VncDisplay *vd)
> object_unparent(OBJECT(vd->tlscreds));
> vd->tlscreds = NULL;
> }
> - g_free(vd->tlsaclname);
> - vd->tlsaclname = NULL;
> + if (vd->tlsauthz) {
> + object_unparent(OBJECT(vd->tlsauthz));
> + vd->tlsauthz = NULL;
> + }
> + g_free(vd->tlsauthzid);
> + vd->tlsauthzid = NULL;
> if (vd->lock_key_sync) {
> qemu_remove_led_event_handler(vd->led);
> vd->led = NULL;
> }
> +#ifdef CONFIG_VNC_SASL
> + if (vd->sasl.authz) {
> + object_unparent(OBJECT(vd->sasl.authz));
> + vd->sasl.authz = NULL;
> + }
> + g_free(vd->sasl.authzid);
> + vd->sasl.authzid = NULL;
> +#endif
> }
>
> int vnc_display_password(const char *id, const char *password)
> @@ -3925,23 +3937,24 @@ void vnc_display_open(const char *id, Error **errp)
>
> if (acl) {
> if (strcmp(vd->id, "default") == 0) {
> - vd->tlsaclname = g_strdup("vnc.x509dname");
> + vd->tlsauthzid = g_strdup("vnc.x509dname");
> } else {
> - vd->tlsaclname = g_strdup_printf("vnc.%s.x509dname", vd->id);
> + vd->tlsauthzid = g_strdup_printf("vnc.%s.x509dname", vd->id);
> }
> - qemu_acl_init(vd->tlsaclname);
> + vd->tlsauthz = QAUTHZ(qauthz_list_new(vd->tlsauthzid,
> + QAUTHZ_LIST_POLICY_DENY,
> + &error_abort));
> }
> #ifdef CONFIG_VNC_SASL
> if (acl && sasl) {
> - char *aclname;
> -
> if (strcmp(vd->id, "default") == 0) {
> - aclname = g_strdup("vnc.username");
> + vd->sasl.authzid = g_strdup("vnc.username");
> } else {
> - aclname = g_strdup_printf("vnc.%s.username", vd->id);
> + vd->sasl.authzid = g_strdup_printf("vnc.%s.username", vd->id);
> }
> - vd->sasl.acl = qemu_acl_init(aclname);
> - g_free(aclname);
> + vd->sasl.authz = QAUTHZ(qauthz_list_new(vd->sasl.authzid,
> + QAUTHZ_LIST_POLICY_DENY,
> + &error_abort));
> }
> #endif
>
> diff --git a/ui/vnc.h b/ui/vnc.h
> index a86e0610e8..29ee1738a5 100644
> --- a/ui/vnc.h
> +++ b/ui/vnc.h
> @@ -39,6 +39,7 @@
> #include "io/channel-socket.h"
> #include "io/channel-tls.h"
> #include "io/net-listener.h"
> +#include "authz/base.h"
> #include <zlib.h>
>
> #include "keymaps.h"
> @@ -177,7 +178,8 @@ struct VncDisplay
> bool lossy;
> bool non_adaptive;
> QCryptoTLSCreds *tlscreds;
> - char *tlsaclname;
> + QAuthZ *tlsauthz;
> + char *tlsauthzid;
> #ifdef CONFIG_VNC_SASL
> VncDisplaySASL sasl;
> #endif
> diff --git a/util/Makefile.objs b/util/Makefile.objs
> index 4d7675d6e7..ca99e7e90d 100644
> --- a/util/Makefile.objs
> +++ b/util/Makefile.objs
> @@ -20,7 +20,6 @@ util-obj-y += envlist.o path.o module.o
> util-obj-y += host-utils.o
> util-obj-y += bitmap.o bitops.o hbitmap.o
> util-obj-y += fifo8.o
> -util-obj-y += acl.o
> util-obj-y += cacheinfo.o
> util-obj-y += error.o qemu-error.o
> util-obj-y += id.o
> diff --git a/util/acl.c b/util/acl.c
> deleted file mode 100644
> index c105addadc..0000000000
> --- a/util/acl.c
> +++ /dev/null
> @@ -1,179 +0,0 @@
> -/*
> - * QEMU access control list management
> - *
> - * Copyright (C) 2009 Red Hat, Inc
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> copy
> - * of this software and associated documentation files (the "Software"), to
> deal
> - * in the Software without restriction, including without limitation the
> rights
> - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> - * copies of the Software, and to permit persons to whom the Software is
> - * furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice shall be included in
> - * all copies or substantial portions of the Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> FROM,
> - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> - * THE SOFTWARE.
> - */
> -
> -
> -#include "qemu/osdep.h"
> -#include "qemu-common.h"
> -#include "qemu/acl.h"
> -
> -#ifdef CONFIG_FNMATCH
> -#include <fnmatch.h>
> -#endif
> -
> -
> -static unsigned int nacls = 0;
> -static qemu_acl **acls = NULL;
> -
> -
> -
> -qemu_acl *qemu_acl_find(const char *aclname)
> -{
> - int i;
> - for (i = 0 ; i < nacls ; i++) {
> - if (strcmp(acls[i]->aclname, aclname) == 0)
> - return acls[i];
> - }
> -
> - return NULL;
> -}
> -
> -qemu_acl *qemu_acl_init(const char *aclname)
> -{
> - qemu_acl *acl;
> -
> - acl = qemu_acl_find(aclname);
> - if (acl)
> - return acl;
> -
> - acl = g_malloc(sizeof(*acl));
> - acl->aclname = g_strdup(aclname);
> - /* Deny by default, so there is no window of "open
> - * access" between QEMU starting, and the user setting
> - * up ACLs in the monitor */
> - acl->defaultDeny = 1;
> -
> - acl->nentries = 0;
> - QTAILQ_INIT(&acl->entries);
> -
> - acls = g_realloc(acls, sizeof(*acls) * (nacls +1));
> - acls[nacls] = acl;
> - nacls++;
> -
> - return acl;
> -}
> -
> -int qemu_acl_party_is_allowed(qemu_acl *acl,
> - const char *party)
> -{
> - qemu_acl_entry *entry;
> -
> - QTAILQ_FOREACH(entry, &acl->entries, next) {
> -#ifdef CONFIG_FNMATCH
> - if (fnmatch(entry->match, party, 0) == 0)
> - return entry->deny ? 0 : 1;
> -#else
> - /* No fnmatch, so fallback to exact string matching
> - * instead of allowing wildcards */
> - if (strcmp(entry->match, party) == 0)
> - return entry->deny ? 0 : 1;
> -#endif
> - }
> -
> - return acl->defaultDeny ? 0 : 1;
> -}
> -
> -
> -void qemu_acl_reset(qemu_acl *acl)
> -{
> - qemu_acl_entry *entry, *next_entry;
> -
> - /* Put back to deny by default, so there is no window
> - * of "open access" while the user re-initializes the
> - * access control list */
> - acl->defaultDeny = 1;
> - QTAILQ_FOREACH_SAFE(entry, &acl->entries, next, next_entry) {
> - QTAILQ_REMOVE(&acl->entries, entry, next);
> - g_free(entry->match);
> - g_free(entry);
> - }
> - acl->nentries = 0;
> -}
> -
> -
> -int qemu_acl_append(qemu_acl *acl,
> - int deny,
> - const char *match)
> -{
> - qemu_acl_entry *entry;
> -
> - entry = g_malloc(sizeof(*entry));
> - entry->match = g_strdup(match);
> - entry->deny = deny;
> -
> - QTAILQ_INSERT_TAIL(&acl->entries, entry, next);
> - acl->nentries++;
> -
> - return acl->nentries;
> -}
> -
> -
> -int qemu_acl_insert(qemu_acl *acl,
> - int deny,
> - const char *match,
> - int index)
> -{
> - qemu_acl_entry *tmp;
> - int i = 0;
> -
> - if (index <= 0)
> - return -1;
> - if (index > acl->nentries) {
> - return qemu_acl_append(acl, deny, match);
> - }
> -
> - QTAILQ_FOREACH(tmp, &acl->entries, next) {
> - i++;
> - if (i == index) {
> - qemu_acl_entry *entry;
> - entry = g_malloc(sizeof(*entry));
> - entry->match = g_strdup(match);
> - entry->deny = deny;
> -
> - QTAILQ_INSERT_BEFORE(tmp, entry, next);
> - acl->nentries++;
> - break;
> - }
> - }
> -
> - return i;
> -}
> -
> -int qemu_acl_remove(qemu_acl *acl,
> - const char *match)
> -{
> - qemu_acl_entry *entry;
> - int i = 0;
> -
> - QTAILQ_FOREACH(entry, &acl->entries, next) {
> - i++;
> - if (strcmp(entry->match, match) == 0) {
> - QTAILQ_REMOVE(&acl->entries, entry, next);
> - acl->nentries--;
> - g_free(entry->match);
> - g_free(entry);
> - return i;
> - }
> - }
> - return -1;
> -}
>
Re: [Qemu-devel] [PATCH v5 00/11] Add a standard authorization framework, Daniel P . Berrangé, 2018/10/18