Commit b76806d4 authored by Daniel P. Berrangé's avatar Daniel P. Berrangé
Browse files

authz: delete existing ACL implementation



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.

Reviewed-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: default avatarPhilippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: default avatarDaniel P. Berrange <berrange@redhat.com>
parent 8953caf3
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -3205,20 +3205,6 @@ if test "$xkbcommon" != "no" ; then
  fi
fi

##########################################
# fnmatch() probe, used for ACL routines
fnmatch="no"
cat > $TMPC << EOF
#include <fnmatch.h>
int main(void)
{
    fnmatch("foo", "foo", 0);
    return 0;
}
EOF
if compile_prog "" "" ; then
   fnmatch="yes"
fi

##########################################
# xfsctl() probe, used for file-posix.c
@@ -6416,9 +6402,6 @@ if test "$xkbcommon" = "yes" ; then
  echo "XKBCOMMON_CFLAGS=$xkbcommon_cflags" >> $config_host_mak
  echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak
fi
if test "$fnmatch" = "yes" ; then
  echo "CONFIG_FNMATCH=y" >> $config_host_mak
fi
if test "$xfs" = "yes" ; then
  echo "CONFIG_XFS=y" >> $config_host_mak
fi
+17 −18
Original line number Diff line number Diff line
@@ -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);
}
@@ -95,7 +95,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)
{
@@ -105,13 +105,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));
@@ -262,6 +262,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)) {
@@ -349,19 +350,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;
                }
@@ -555,7 +554,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)
{
+1 −1
Original line number Diff line number Diff line
@@ -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"

include/qemu/acl.h

deleted100644 → 0
+0 −66
Original line number Diff line number Diff line
/*
 * 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 */
+119 −60
Original line number Diff line number Diff line
@@ -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"
@@ -2016,93 +2017,148 @@ 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;
    QAuthZList *auth = find_auth(mon, aclname);
    QAuthZListRuleList *rules;
    size_t i = 0;

    if (!auth) {
        return;
    }

    if (acl) {
    monitor_printf(mon, "policy: %s\n",
                       acl->defaultDeny ? "deny" : "allow");
        QTAILQ_FOREACH(entry, &acl->entries, next) {
                   QAuthZListPolicy_str(auth->policy));

    rules = auth->rules;
    while (rules) {
        QAuthZListRule *rule = rules->value;
        i++;
            monitor_printf(mon, "%d: %s %s\n", i,
                           entry->deny ? "deny" : "allow", entry->match);
        }
        monitor_printf(mon, "%zu: %s %s\n", i,
                       QAuthZListPolicy_str(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;
            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 {
    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 {
            monitor_printf(mon, "acl: policy set to 'deny'\n");
        }
    }
}

static QAuthZListFormat hmp_acl_get_format(const char *match)
{
    if (strchr(match, '*')) {
        return QAUTHZ_LIST_FORMAT_GLOB;
    } else {
        return QAUTHZ_LIST_FORMAT_EXACT;
    }
}

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 {
    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", policy);
                       "expected 'deny' or 'allow'\n", policystr);
        return;
    }
        if (has_index)
            ret = qemu_acl_insert(acl, deny, match, index);
        else
            ret = qemu_acl_append(acl, deny, match);
        if (ret < 0)

    format = hmp_acl_get_format(match);

    if (has_index && index == 0) {
        monitor_printf(mon, "acl: unable to add acl entry\n");
        else
            monitor_printf(mon, "acl: added rule at position %d\n", ret);
        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);
    }
}

@@ -2110,15 +2166,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)
    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");
        else
            monitor_printf(mon, "acl: removed rule at position %d\n", ret);
    }
}

Loading