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: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2016-02-18 18:40:24 +00:00 committed by Daniel P. Berrangé
parent 8953caf3cd
commit b76806d4ec
16 changed files with 207 additions and 376 deletions

17
configure vendored
View File

@ -3205,20 +3205,6 @@ if test "$xkbcommon" != "no" ; then
fi fi
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 # 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_CFLAGS=$xkbcommon_cflags" >> $config_host_mak
echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak echo "XKBCOMMON_LIBS=$xkbcommon_libs" >> $config_host_mak
fi fi
if test "$fnmatch" = "yes" ; then
echo "CONFIG_FNMATCH=y" >> $config_host_mak
fi
if test "$xfs" = "yes" ; then if test "$xfs" = "yes" ; then
echo "CONFIG_XFS=y" >> $config_host_mak echo "CONFIG_XFS=y" >> $config_host_mak
fi fi

View File

@ -24,7 +24,7 @@
#include "crypto/tlscredspsk.h" #include "crypto/tlscredspsk.h"
#include "crypto/tlscredsx509.h" #include "crypto/tlscredsx509.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/acl.h" #include "authz/base.h"
#include "trace.h" #include "trace.h"
#ifdef CONFIG_GNUTLS #ifdef CONFIG_GNUTLS
@ -37,7 +37,7 @@ struct QCryptoTLSSession {
QCryptoTLSCreds *creds; QCryptoTLSCreds *creds;
gnutls_session_t handle; gnutls_session_t handle;
char *hostname; char *hostname;
char *aclname; char *authzid;
bool handshakeComplete; bool handshakeComplete;
QCryptoTLSSessionWriteFunc writeFunc; QCryptoTLSSessionWriteFunc writeFunc;
QCryptoTLSSessionReadFunc readFunc; QCryptoTLSSessionReadFunc readFunc;
@ -56,7 +56,7 @@ qcrypto_tls_session_free(QCryptoTLSSession *session)
gnutls_deinit(session->handle); gnutls_deinit(session->handle);
g_free(session->hostname); g_free(session->hostname);
g_free(session->peername); g_free(session->peername);
g_free(session->aclname); g_free(session->authzid);
object_unref(OBJECT(session->creds)); object_unref(OBJECT(session->creds));
g_free(session); g_free(session);
} }
@ -95,7 +95,7 @@ qcrypto_tls_session_pull(void *opaque, void *buf, size_t len)
QCryptoTLSSession * QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds, qcrypto_tls_session_new(QCryptoTLSCreds *creds,
const char *hostname, const char *hostname,
const char *aclname, const char *authzid,
QCryptoTLSCredsEndpoint endpoint, QCryptoTLSCredsEndpoint endpoint,
Error **errp) Error **errp)
{ {
@ -105,13 +105,13 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds,
session = g_new0(QCryptoTLSSession, 1); session = g_new0(QCryptoTLSSession, 1);
trace_qcrypto_tls_session_new( trace_qcrypto_tls_session_new(
session, creds, hostname ? hostname : "<none>", session, creds, hostname ? hostname : "<none>",
aclname ? aclname : "<none>", endpoint); authzid ? authzid : "<none>", endpoint);
if (hostname) { if (hostname) {
session->hostname = g_strdup(hostname); session->hostname = g_strdup(hostname);
} }
if (aclname) { if (authzid) {
session->aclname = g_strdup(aclname); session->authzid = g_strdup(authzid);
} }
session->creds = creds; session->creds = creds;
object_ref(OBJECT(creds)); object_ref(OBJECT(creds));
@ -262,6 +262,7 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
unsigned int nCerts, i; unsigned int nCerts, i;
time_t now; time_t now;
gnutls_x509_crt_t cert = NULL; gnutls_x509_crt_t cert = NULL;
Error *err = NULL;
now = time(NULL); now = time(NULL);
if (now == ((time_t)-1)) { if (now == ((time_t)-1)) {
@ -349,19 +350,17 @@ qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
gnutls_strerror(ret)); gnutls_strerror(ret));
goto error; goto error;
} }
if (session->aclname) { if (session->authzid) {
qemu_acl *acl = qemu_acl_find(session->aclname); bool allow;
int allow;
if (!acl) { allow = qauthz_is_allowed_by_id(session->authzid,
error_setg(errp, "Cannot find ACL %s", session->peername, &err);
session->aclname); if (err) {
error_propagate(errp, err);
goto error; goto error;
} }
allow = qemu_acl_party_is_allowed(acl, session->peername);
if (!allow) { 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); session->peername);
goto error; goto error;
} }
@ -555,7 +554,7 @@ qcrypto_tls_session_get_peer_name(QCryptoTLSSession *session)
QCryptoTLSSession * QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED, qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED,
const char *hostname 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, QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,
Error **errp) Error **errp)
{ {

View File

@ -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" 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 # 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" qcrypto_tls_session_check_creds(void *session, const char *status) "TLS session check creds session=%p status=%s"

View File

@ -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 */

175
monitor.c
View File

@ -51,7 +51,8 @@
#include "sysemu/balloon.h" #include "sysemu/balloon.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/hw_accel.h" #include "sysemu/hw_accel.h"
#include "qemu/acl.h" #include "authz/list.h"
#include "qapi/util.h"
#include "sysemu/tpm.h" #include "sysemu/tpm.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.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); 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); 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) static void hmp_acl_show(Monitor *mon, const QDict *qdict)
{ {
const char *aclname = qdict_get_str(qdict, "aclname"); const char *aclname = qdict_get_str(qdict, "aclname");
qemu_acl *acl = find_acl(mon, aclname); QAuthZList *auth = find_auth(mon, aclname);
qemu_acl_entry *entry; QAuthZListRuleList *rules;
int i = 0; size_t i = 0;
if (acl) { if (!auth) {
monitor_printf(mon, "policy: %s\n", return;
acl->defaultDeny ? "deny" : "allow"); }
QTAILQ_FOREACH(entry, &acl->entries, next) {
i++; monitor_printf(mon, "policy: %s\n",
monitor_printf(mon, "%d: %s %s\n", i, QAuthZListPolicy_str(auth->policy));
entry->deny ? "deny" : "allow", entry->match);
} rules = auth->rules;
while (rules) {
QAuthZListRule *rule = rules->value;
i++;
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) static void hmp_acl_reset(Monitor *mon, const QDict *qdict)
{ {
const char *aclname = qdict_get_str(qdict, "aclname"); const char *aclname = qdict_get_str(qdict, "aclname");
qemu_acl *acl = find_acl(mon, aclname); QAuthZList *auth = find_auth(mon, aclname);
if (acl) { if (!auth) {
qemu_acl_reset(acl); return;
monitor_printf(mon, "acl: removed all rules\n");
} }
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) static void hmp_acl_policy(Monitor *mon, const QDict *qdict)
{ {
const char *aclname = qdict_get_str(qdict, "aclname"); const char *aclname = qdict_get_str(qdict, "aclname");
const char *policy = qdict_get_str(qdict, "policy"); 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 (!auth) {
if (strcmp(policy, "allow") == 0) { return;
acl->defaultDeny = 0; }
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"); 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 { } else {
monitor_printf(mon, "acl: unknown policy '%s', " monitor_printf(mon, "acl: policy set to 'deny'\n");
"expected 'deny' or 'allow'\n", policy);
} }
} }
} }
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) static void hmp_acl_add(Monitor *mon, const QDict *qdict)
{ {
const char *aclname = qdict_get_str(qdict, "aclname"); const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match"); 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 has_index = qdict_haskey(qdict, "index");
int index = qdict_get_try_int(qdict, "index", -1); int index = qdict_get_try_int(qdict, "index", -1);
qemu_acl *acl = find_acl(mon, aclname); QAuthZList *auth = find_auth(mon, aclname);
int deny, ret; Error *err = NULL;
QAuthZListPolicy policy;
QAuthZListFormat format;
size_t i = 0;
if (acl) { if (!auth) {
if (strcmp(policy, "allow") == 0) { return;
deny = 0; }
} else if (strcmp(policy, "deny") == 0) {
deny = 1; policy = qapi_enum_parse(&QAuthZListPolicy_lookup,
} else { policystr,
monitor_printf(mon, "acl: unknown policy '%s', " QAUTHZ_LIST_POLICY_DENY,
"expected 'deny' or 'allow'\n", policy); &err);
return; if (err) {
} error_free(err);
if (has_index) monitor_printf(mon, "acl: unknown policy '%s', "
ret = qemu_acl_insert(acl, deny, match, index); "expected 'deny' or 'allow'\n", policystr);
else return;
ret = qemu_acl_append(acl, deny, match); }
if (ret < 0)
monitor_printf(mon, "acl: unable to add acl entry\n"); format = hmp_acl_get_format(match);
else
monitor_printf(mon, "acl: added rule at position %d\n", ret); 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);
} }
} }
@ -2110,15 +2166,18 @@ static void hmp_acl_remove(Monitor *mon, const QDict *qdict)
{ {
const char *aclname = qdict_get_str(qdict, "aclname"); const char *aclname = qdict_get_str(qdict, "aclname");
const char *match = qdict_get_str(qdict, "match"); const char *match = qdict_get_str(qdict, "match");
qemu_acl *acl = find_acl(mon, aclname); QAuthZList *auth = find_auth(mon, aclname);
int ret; ssize_t i = 0;
if (acl) { if (!auth) {
ret = qemu_acl_remove(acl, match); return;
if (ret < 0) }
monitor_printf(mon, "acl: no matching acl entry\n");
else i = qauthz_list_delete_rule(auth, match);
monitor_printf(mon, "acl: removed rule at position %d\n", ret); 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");
} }
} }

View File

@ -537,8 +537,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 \ test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
tests/test-qapi-introspect.o \ tests/test-qapi-introspect.o \
$(test-qom-obj-y) $(test-qom-obj-y)
benchmark-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 = $(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-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
test-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y) test-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y)
test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o

View File

@ -28,7 +28,7 @@
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "qemu/acl.h" #include "authz/list.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
@ -229,7 +229,7 @@ static void test_crypto_tls_session_x509(const void *opaque)
QCryptoTLSCreds *serverCreds; QCryptoTLSCreds *serverCreds;
QCryptoTLSSession *clientSess = NULL; QCryptoTLSSession *clientSess = NULL;
QCryptoTLSSession *serverSess = NULL; QCryptoTLSSession *serverSess = NULL;
qemu_acl *acl; QAuthZList *auth;
const char * const *wildcards; const char * const *wildcards;
int channel[2]; int channel[2];
bool clientShake = false; bool clientShake = false;
@ -285,11 +285,15 @@ static void test_crypto_tls_session_x509(const void *opaque)
SERVER_CERT_DIR); SERVER_CERT_DIR);
g_assert(serverCreds != NULL); g_assert(serverCreds != NULL);
acl = qemu_acl_init("tlssessionacl"); auth = qauthz_list_new("tlssessionacl",
qemu_acl_reset(acl); QAUTHZ_LIST_POLICY_DENY,
&error_abort);
wildcards = data->wildcards; wildcards = data->wildcards;
while (wildcards && *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++; wildcards++;
} }
@ -377,6 +381,7 @@ static void test_crypto_tls_session_x509(const void *opaque)
object_unparent(OBJECT(serverCreds)); object_unparent(OBJECT(serverCreds));
object_unparent(OBJECT(clientCreds)); object_unparent(OBJECT(clientCreds));
object_unparent(OBJECT(auth));
qcrypto_tls_session_free(serverSess); qcrypto_tls_session_free(serverSess);
qcrypto_tls_session_free(clientSess); qcrypto_tls_session_free(clientSess);

View File

@ -29,8 +29,8 @@
#include "io-channel-helpers.h" #include "io-channel-helpers.h"
#include "crypto/init.h" #include "crypto/init.h"
#include "crypto/tlscredsx509.h" #include "crypto/tlscredsx509.h"
#include "qemu/acl.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "authz/list.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT #ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
@ -113,7 +113,7 @@ static void test_io_channel_tls(const void *opaque)
QIOChannelTLS *serverChanTLS; QIOChannelTLS *serverChanTLS;
QIOChannelSocket *clientChanSock; QIOChannelSocket *clientChanSock;
QIOChannelSocket *serverChanSock; QIOChannelSocket *serverChanSock;
qemu_acl *acl; QAuthZList *auth;
const char * const *wildcards; const char * const *wildcards;
int channel[2]; int channel[2];
struct QIOChannelTLSHandshakeData clientHandshake = { false, false }; struct QIOChannelTLSHandshakeData clientHandshake = { false, false };
@ -161,11 +161,15 @@ static void test_io_channel_tls(const void *opaque)
SERVER_CERT_DIR); SERVER_CERT_DIR);
g_assert(serverCreds != NULL); g_assert(serverCreds != NULL);
acl = qemu_acl_init("channeltlsacl"); auth = qauthz_list_new("channeltlsacl",
qemu_acl_reset(acl); QAUTHZ_LIST_POLICY_DENY,
&error_abort);
wildcards = data->wildcards; wildcards = data->wildcards;
while (wildcards && *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++; wildcards++;
} }
@ -253,6 +257,8 @@ static void test_io_channel_tls(const void *opaque)
object_unref(OBJECT(serverChanSock)); object_unref(OBJECT(serverChanSock));
object_unref(OBJECT(clientChanSock)); object_unref(OBJECT(clientChanSock));
object_unparent(OBJECT(auth));
close(channel[0]); close(channel[0]);
close(channel[1]); close(channel[1]);
} }

View File

@ -24,6 +24,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "authz/base.h"
#include "vnc.h" #include "vnc.h"
#include "trace.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) static int vnc_auth_sasl_check_access(VncState *vs)
{ {
const void *val; const void *val;
int err; int rv;
int allow; Error *err = NULL;
bool allow;
err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val); rv = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
if (err != SASL_OK) { if (rv != SASL_OK) {
trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username", trace_vnc_auth_fail(vs, vs->auth, "Cannot fetch SASL username",
sasl_errstring(err, NULL, NULL)); sasl_errstring(rv, NULL, NULL));
return -1; return -1;
} }
if (val == NULL) { if (val == NULL) {
@ -163,12 +165,19 @@ static int vnc_auth_sasl_check_access(VncState *vs)
vs->sasl.username = g_strdup((const char*)val); vs->sasl.username = g_strdup((const char*)val);
trace_vnc_auth_sasl_username(vs, vs->sasl.username); 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); trace_vnc_auth_sasl_acl(vs, 1);
return 0; 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); trace_vnc_auth_sasl_acl(vs, allow);
return allow ? 0 : -1; return allow ? 0 : -1;

View File

@ -30,8 +30,8 @@
typedef struct VncStateSASL VncStateSASL; typedef struct VncStateSASL VncStateSASL;
typedef struct VncDisplaySASL VncDisplaySASL; typedef struct VncDisplaySASL VncDisplaySASL;
#include "qemu/acl.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "authz/base.h"
struct VncStateSASL { struct VncStateSASL {
sasl_conn_t *conn; sasl_conn_t *conn;
@ -60,7 +60,8 @@ struct VncStateSASL {
}; };
struct VncDisplaySASL { struct VncDisplaySASL {
qemu_acl *acl; QAuthZ *authz;
char *authzid;
}; };
void vnc_sasl_client_cleanup(VncState *vs); void vnc_sasl_client_cleanup(VncState *vs);

View File

@ -109,7 +109,7 @@ static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len
tls = qio_channel_tls_new_server( tls = qio_channel_tls_new_server(
vs->ioc, vs->ioc,
vs->vd->tlscreds, vs->vd->tlscreds,
vs->vd->tlsaclname, vs->vd->tlsauthzid,
&err); &err);
if (!tls) { if (!tls) {
trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed", trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",

View File

@ -62,7 +62,7 @@ gboolean vncws_tls_handshake_io(QIOChannel *ioc G_GNUC_UNUSED,
tls = qio_channel_tls_new_server( tls = qio_channel_tls_new_server(
vs->ioc, vs->ioc,
vs->vd->tlscreds, vs->vd->tlscreds,
vs->vd->tlsaclname, vs->vd->tlsauthzid,
&err); &err);
if (!tls) { if (!tls) {
VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err)); VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));

View File

@ -33,7 +33,7 @@
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/acl.h" #include "authz/list.h"
#include "qemu/config-file.h" #include "qemu/config-file.h"
#include "qapi/qapi-emit-events.h" #include "qapi/qapi-emit-events.h"
#include "qapi/qapi-events-ui.h" #include "qapi/qapi-events-ui.h"
@ -3229,12 +3229,24 @@ static void vnc_display_close(VncDisplay *vd)
object_unparent(OBJECT(vd->tlscreds)); object_unparent(OBJECT(vd->tlscreds));
vd->tlscreds = NULL; vd->tlscreds = NULL;
} }
g_free(vd->tlsaclname); if (vd->tlsauthz) {
vd->tlsaclname = NULL; object_unparent(OBJECT(vd->tlsauthz));
vd->tlsauthz = NULL;
}
g_free(vd->tlsauthzid);
vd->tlsauthzid = NULL;
if (vd->lock_key_sync) { if (vd->lock_key_sync) {
qemu_remove_led_event_handler(vd->led); qemu_remove_led_event_handler(vd->led);
vd->led = NULL; 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) int vnc_display_password(const char *id, const char *password)
@ -3887,23 +3899,24 @@ void vnc_display_open(const char *id, Error **errp)
if (acl) { if (acl) {
if (strcmp(vd->id, "default") == 0) { if (strcmp(vd->id, "default") == 0) {
vd->tlsaclname = g_strdup("vnc.x509dname"); vd->tlsauthzid = g_strdup("vnc.x509dname");
} else { } 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 #ifdef CONFIG_VNC_SASL
if (acl && sasl) { if (acl && sasl) {
char *aclname;
if (strcmp(vd->id, "default") == 0) { if (strcmp(vd->id, "default") == 0) {
aclname = g_strdup("vnc.username"); vd->sasl.authzid = g_strdup("vnc.username");
} else { } 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); vd->sasl.authz = QAUTHZ(qauthz_list_new(vd->sasl.authzid,
g_free(aclname); QAUTHZ_LIST_POLICY_DENY,
&error_abort));
} }
#endif #endif

View File

@ -39,6 +39,7 @@
#include "io/channel-socket.h" #include "io/channel-socket.h"
#include "io/channel-tls.h" #include "io/channel-tls.h"
#include "io/net-listener.h" #include "io/net-listener.h"
#include "authz/base.h"
#include <zlib.h> #include <zlib.h>
#include "keymaps.h" #include "keymaps.h"
@ -178,7 +179,8 @@ struct VncDisplay
bool lossy; bool lossy;
bool non_adaptive; bool non_adaptive;
QCryptoTLSCreds *tlscreds; QCryptoTLSCreds *tlscreds;
char *tlsaclname; QAuthZ *tlsauthz;
char *tlsauthzid;
#ifdef CONFIG_VNC_SASL #ifdef CONFIG_VNC_SASL
VncDisplaySASL sasl; VncDisplaySASL sasl;
#endif #endif

View File

@ -20,7 +20,6 @@ util-obj-y += envlist.o path.o module.o
util-obj-y += host-utils.o util-obj-y += host-utils.o
util-obj-y += bitmap.o bitops.o hbitmap.o util-obj-y += bitmap.o bitops.o hbitmap.o
util-obj-y += fifo8.o util-obj-y += fifo8.o
util-obj-y += acl.o
util-obj-y += cacheinfo.o util-obj-y += cacheinfo.o
util-obj-y += error.o qemu-error.o util-obj-y += error.o qemu-error.o
util-obj-y += id.o util-obj-y += id.o

View File

@ -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;
}