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
##########################################
# 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

View file

@ -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)
{

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"
# 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"

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 "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 (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);
}
if (!auth) {
return;
}
monitor_printf(mon, "policy: %s\n",
QAuthZListPolicy_str(auth->policy));
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)
{
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");
}
}
}
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;
QAuthZList *auth = find_auth(mon, aclname);
Error *err = NULL;
QAuthZListPolicy policy;
QAuthZListFormat format;
size_t i = 0;
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);
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;
}
format = hmp_acl_get_format(match);
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 *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");
}
}

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 \
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-authz-obj-y = $(test-qom-obj-y) $(authz-obj-y)
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 "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);

View file

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

View file

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

View file

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

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(
vs->ioc,
vs->vd->tlscreds,
vs->vd->tlsaclname,
vs->vd->tlsauthzid,
&err);
if (!tls) {
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(
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));

View file

@ -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-emit-events.h"
#include "qapi/qapi-events-ui.h"
@ -3229,12 +3229,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)
@ -3887,23 +3899,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

View file

@ -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"
@ -178,7 +179,8 @@ struct VncDisplay
bool lossy;
bool non_adaptive;
QCryptoTLSCreds *tlscreds;
char *tlsaclname;
QAuthZ *tlsauthz;
char *tlsauthzid;
#ifdef CONFIG_VNC_SASL
VncDisplaySASL sasl;
#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 += 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

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