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:
parent
8953caf3cd
commit
b76806d4ec
17
configure
vendored
17
configure
vendored
@ -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
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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"
|
||||||
|
@ -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
175
monitor.c
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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",
|
||||||
|
@ -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));
|
||||||
|
37
ui/vnc.c
37
ui/vnc.c
@ -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
|
||||||
|
|
||||||
|
4
ui/vnc.h
4
ui/vnc.h
@ -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
|
||||||
|
@ -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
|
||||||
|
179
util/acl.c
179
util/acl.c
@ -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;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user