peterdelevoryas / rpms / qemu

Forked from rpms/qemu 2 years ago
Clone

Blame qemu-sasl-08-vnc-acl-mgmt.patch

Daniel P. Berrange 42af21
This patch introduces a generic internal API for access control lists
Daniel P. Berrange 42af21
to be used by network servers in QEMU. It adds support for checking
Daniel P. Berrange 42af21
these ACL in the VNC server, in two places. The first ACL is for the
Daniel P. Berrange 42af21
SASL authentication mechanism, checking the SASL username. This ACL
Daniel P. Berrange 42af21
is called 'vnc.username'. The second is for the TLS authentication
Daniel P. Berrange 42af21
mechanism, when x509 client certificates are turned on, checking against
Daniel P. Berrange 42af21
the Distinguished Name of the client. This ACL is called 'vnc.x509dname'
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
The internal API provides for an ACL with the following characteristics
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
 - A unique name, eg  vnc.username, and vnc.x509dname.
Daniel P. Berrange 42af21
 - A default policy, allow or deny
Daniel P. Berrange 42af21
 - An ordered series of match rules, with allow or deny policy
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
If none of the match rules apply, then the default policy is
Daniel P. Berrange 42af21
used.
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
There is a monitor API to manipulate the ACLs, which I'll describe via
Daniel P. Berrange 42af21
examples
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
  (qemu) acl show vnc.username
Daniel P. Berrange 42af21
  policy: allow
Daniel P. Berrange 42af21
  (qemu) acl policy vnc.username denya
Daniel P. Berrange 42af21
  acl: policy set to 'deny'
Daniel P. Berrange 42af21
  (qemu) acl allow vnc.username fred
Daniel P. Berrange 42af21
  acl: added rule at position 1
Daniel P. Berrange 42af21
  (qemu) acl allow vnc.username bob
Daniel P. Berrange 42af21
  acl: added rule at position 2
Daniel P. Berrange 42af21
  (qemu) acl allow vnc.username joe 1
Daniel P. Berrange 42af21
  acl: added rule at position 1
Daniel P. Berrange 42af21
  (qemu) acl show vnc.username
Daniel P. Berrange 42af21
  policy: deny
Daniel P. Berrange 42af21
  0: allow fred
Daniel P. Berrange 42af21
  1: allow joe
Daniel P. Berrange 42af21
  2: allow bob
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
  (qemu) acl show vnc.x509dname
Daniel P. Berrange 42af21
  policy: allow
Daniel P. Berrange 42af21
  (qemu) acl policy vnc.x509dname deny
Daniel P. Berrange 42af21
  acl: policy set to 'deny'
Daniel P. Berrange 42af21
  (qemu) acl allow vnc.x509dname C=GB,O=ACME,L=London,CN=*
Daniel P. Berrange 42af21
  acl: added rule at position 1
Daniel P. Berrange 42af21
  (qemu) acl allow vnc.x509dname C=GB,O=ACME,L=Boston,CN=bob
Daniel P. Berrange 42af21
  acl: added rule at position 2
Daniel P. Berrange 42af21
  (qemu) acl show vnc.x509dname
Daniel P. Berrange 42af21
  policy: deny
Daniel P. Berrange 42af21
  0: allow C=GB,O=ACME,L=London,CN=*
Daniel P. Berrange 42af21
  1: allow C=GB,O=ACME,L=Boston,CN=bob
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
By default the VNC server will not use any ACLs, allowing access to
Daniel P. Berrange 42af21
the server if the user successfully authenticates. To enable use of
Daniel P. Berrange 42af21
ACLs to restrict user access, the ',acl' flag should be given when
Daniel P. Berrange 42af21
starting QEMU. The initial ACL activated will be a 'deny all' policy
Daniel P. Berrange 42af21
and should be customized using monitor commands.
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
eg enable SASL auth and ACLs
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
    qemu ....  -vnc localhost:1,sasl,acl
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
The next patch will provide a way to load a pre-defined ACL when
Daniel P. Berrange 42af21
starting up
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
 Makefile        |    6 +
Daniel P. Berrange 42af21
 b/acl.c         |  185 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Daniel P. Berrange 42af21
 b/acl.h         |   74 ++++++++++++++++++++++
Daniel P. Berrange 42af21
 configure       |   18 +++++
Daniel P. Berrange 42af21
 monitor.c       |   95 ++++++++++++++++++++++++++++
Daniel P. Berrange 42af21
 qemu-doc.texi   |   49 ++++++++++++++
Daniel P. Berrange 42af21
 vnc-auth-sasl.c |   16 +++-
Daniel P. Berrange 42af21
 vnc-auth-sasl.h |    7 ++
Daniel P. Berrange 42af21
 vnc-tls.c       |   19 +++++
Daniel P. Berrange 42af21
 vnc-tls.h       |    3 
Daniel P. Berrange 42af21
 vnc.c           |   21 ++++++
Daniel P. Berrange 42af21
 vnc.h           |    3 
Daniel P. Berrange 42af21
 12 files changed, 491 insertions(+), 5 deletions(-)
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
   Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Daniel P. Berrange 42af21
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 Makefile
Daniel P. Berrange 42af21
--- a/Makefile	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/Makefile	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -144,7 +144,7 @@ endif
Daniel P. Berrange 42af21
 ifdef CONFIG_CURSES
Daniel P. Berrange 42af21
 OBJS+=curses.o
Daniel P. Berrange 42af21
 endif
Daniel P. Berrange 42af21
-OBJS+=vnc.o d3des.o
Daniel P. Berrange 42af21
+OBJS+=vnc.o acl.o d3des.o
Daniel P. Berrange 42af21
 ifdef CONFIG_VNC_TLS
Daniel P. Berrange 42af21
 OBJS+=vnc-tls.o vnc-auth-vencrypt.o
Daniel P. Berrange 42af21
 endif
Daniel P. Berrange 42af21
@@ -174,9 +174,11 @@ sdl.o: sdl.c keymaps.h sdl_keysym.h
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 sdl.o audio/sdlaudio.o: CFLAGS += $(SDL_CFLAGS)
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+acl.o: acl.h acl.c
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 vnc.h: vnc-tls.h vnc-auth-vencrypt.h vnc-auth-sasl.h keymaps.h
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
-vnc.o: vnc.c vnc.h vnc_keysym.h vnchextile.h d3des.c d3des.h
Daniel P. Berrange 42af21
+vnc.o: vnc.c vnc.h vnc_keysym.h vnchextile.h d3des.c d3des.h acl.h
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 vnc.o: CFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 acl.c
Daniel P. Berrange 42af21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
Daniel P. Berrange 42af21
+++ b/acl.c	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -0,0 +1,185 @@
Daniel P. Berrange 42af21
+/*
Daniel P. Berrange 42af21
+ * QEMU access control list management
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * Copyright (C) 2009 Red Hat, Inc
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
Daniel P. Berrange 42af21
+ * of this software and associated documentation files (the "Software"), to deal
Daniel P. Berrange 42af21
+ * in the Software without restriction, including without limitation the rights
Daniel P. Berrange 42af21
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Daniel P. Berrange 42af21
+ * copies of the Software, and to permit persons to whom the Software is
Daniel P. Berrange 42af21
+ * furnished to do so, subject to the following conditions:
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * The above copyright notice and this permission notice shall be included in
Daniel P. Berrange 42af21
+ * all copies or substantial portions of the Software.
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Daniel P. Berrange 42af21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Daniel P. Berrange 42af21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Daniel P. Berrange 42af21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Daniel P. Berrange 42af21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Daniel P. Berrange 42af21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Daniel P. Berrange 42af21
+ * THE SOFTWARE.
Daniel P. Berrange 42af21
+ */
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#include "qemu-common.h"
Daniel P. Berrange 42af21
+#include "sysemu.h"
Daniel P. Berrange 42af21
+#include "acl.h"
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#ifdef HAVE_FNMATCH_H
Daniel P. Berrange 42af21
+#include <fnmatch.h>
Daniel P. Berrange 42af21
+#endif
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+static unsigned int nacls = 0;
Daniel P. Berrange 42af21
+static qemu_acl **acls = NULL;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+qemu_acl *qemu_acl_find(const char *aclname)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    int i;
Daniel P. Berrange 42af21
+    for (i = 0 ; i < nacls ; i++) {
Daniel P. Berrange 42af21
+	if (strcmp(acls[i]->aclname, aclname) == 0)
Daniel P. Berrange 42af21
+	    return acls[i];
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    return NULL;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+qemu_acl *qemu_acl_init(const char *aclname)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl *acl;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    acl = qemu_acl_find(aclname);
Daniel P. Berrange 42af21
+    if (acl)
Daniel P. Berrange 42af21
+	return acl;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    acl = qemu_malloc(sizeof(*acl));
Daniel P. Berrange 42af21
+    acl->aclname = qemu_strdup(aclname);
Daniel P. Berrange 42af21
+    /* Deny by default, so there is no window of "open
Daniel P. Berrange 42af21
+     * access" between QEMU starting, and the user setting
Daniel P. Berrange 42af21
+     * up ACLs in the monitor */
Daniel P. Berrange 42af21
+    acl->defaultDeny = 1;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    acl->nentries = 0;
Daniel P. Berrange 42af21
+    TAILQ_INIT(&acl->entries);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    acls = qemu_realloc(acls, sizeof(*acls) * (nacls +1));
Daniel P. Berrange 42af21
+    acls[nacls] = acl;
Daniel P. Berrange 42af21
+    nacls++;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    return acl;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_party_is_allowed(qemu_acl *acl,
Daniel P. Berrange 42af21
+			      const char *party)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    TAILQ_FOREACH(entry, &acl->entries, next) {
Daniel P. Berrange 42af21
+#ifdef HAVE_FNMATCH_H
Daniel P. Berrange 42af21
+	if (fnmatch(entry->match, party, 0) == 0)
Daniel P. Berrange 42af21
+	    return entry->deny ? 0 : 1;
Daniel P. Berrange 42af21
+#else
Daniel P. Berrange 42af21
+	/* No fnmatch, so fallback to exact string matching
Daniel P. Berrange 42af21
+	 * instead of allowing wildcards */
Daniel P. Berrange 42af21
+	if (strcmp(entry->match, party) == 0)
Daniel P. Berrange 42af21
+	    return entry->deny ? 0 : 1;
Daniel P. Berrange 42af21
+#endif
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    return acl->defaultDeny ? 0 : 1;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+void qemu_acl_reset(qemu_acl *acl)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    /* Put back to deny by default, so there is no window
Daniel P. Berrange 42af21
+     * of "open access" while the user re-initializes the
Daniel P. Berrange 42af21
+     * access control list */
Daniel P. Berrange 42af21
+    acl->defaultDeny = 1;
Daniel P. Berrange 42af21
+    TAILQ_FOREACH(entry, &acl->entries, next) {
Daniel P. Berrange 42af21
+	TAILQ_REMOVE(&acl->entries, entry, next);
Daniel P. Berrange 42af21
+	free(entry->match);
Daniel P. Berrange 42af21
+	free(entry);
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+    acl->nentries = 0;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_append(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    int deny,
Daniel P. Berrange 42af21
+		    const char *match)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    entry = qemu_malloc(sizeof(*entry));
Daniel P. Berrange 42af21
+    entry->match = qemu_strdup(match);
Daniel P. Berrange 42af21
+    entry->deny = deny;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    TAILQ_INSERT_TAIL(&acl->entries, entry, next);
Daniel P. Berrange 42af21
+    acl->nentries++;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    return acl->nentries;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_insert(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    int deny,
Daniel P. Berrange 42af21
+		    const char *match,
Daniel P. Berrange 42af21
+		    int index)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+    qemu_acl_entry *tmp;
Daniel P. Berrange 42af21
+    int i = 0;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    if (index <= 0)
Daniel P. Berrange 42af21
+	return -1;
Daniel P. Berrange 42af21
+    if (index >= acl->nentries)
Daniel P. Berrange 42af21
+	return qemu_acl_append(acl, deny, match);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    entry = qemu_malloc(sizeof(*entry));
Daniel P. Berrange 42af21
+    entry->match = qemu_strdup(match);
Daniel P. Berrange 42af21
+    entry->deny = deny;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    TAILQ_FOREACH(tmp, &acl->entries, next) {
Daniel P. Berrange 42af21
+	i++;
Daniel P. Berrange 42af21
+	if (i == index) {
Daniel P. Berrange 42af21
+	    TAILQ_INSERT_BEFORE(tmp, entry, next);
Daniel P. Berrange 42af21
+	    acl->nentries++;
Daniel P. Berrange 42af21
+	    break;
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    return i;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_remove(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    const char *match)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+    int i = 0;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    TAILQ_FOREACH(entry, &acl->entries, next) {
Daniel P. Berrange 42af21
+	i++;
Daniel P. Berrange 42af21
+	if (strcmp(entry->match, match) == 0) {
Daniel P. Berrange 42af21
+	    TAILQ_REMOVE(&acl->entries, entry, next);
Daniel P. Berrange 42af21
+	    return i;
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+    return -1;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+/*
Daniel P. Berrange 42af21
+ * Local variables:
Daniel P. Berrange 42af21
+ *  c-indent-level: 4
Daniel P. Berrange 42af21
+ *  c-basic-offset: 4
Daniel P. Berrange 42af21
+ *  tab-width: 8
Daniel P. Berrange 42af21
+ * End:
Daniel P. Berrange 42af21
+ */
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 acl.h
Daniel P. Berrange 42af21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
Daniel P. Berrange 42af21
+++ b/acl.h	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -0,0 +1,74 @@
Daniel P. Berrange 42af21
+/*
Daniel P. Berrange 42af21
+ * QEMU access control list management
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * Copyright (C) 2009 Red Hat, Inc
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
Daniel P. Berrange 42af21
+ * of this software and associated documentation files (the "Software"), to deal
Daniel P. Berrange 42af21
+ * in the Software without restriction, including without limitation the rights
Daniel P. Berrange 42af21
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Daniel P. Berrange 42af21
+ * copies of the Software, and to permit persons to whom the Software is
Daniel P. Berrange 42af21
+ * furnished to do so, subject to the following conditions:
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * The above copyright notice and this permission notice shall be included in
Daniel P. Berrange 42af21
+ * all copies or substantial portions of the Software.
Daniel P. Berrange 42af21
+ *
Daniel P. Berrange 42af21
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Daniel P. Berrange 42af21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Daniel P. Berrange 42af21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Daniel P. Berrange 42af21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Daniel P. Berrange 42af21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Daniel P. Berrange 42af21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Daniel P. Berrange 42af21
+ * THE SOFTWARE.
Daniel P. Berrange 42af21
+ */
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#ifndef __QEMU_ACL_H__
Daniel P. Berrange 42af21
+#define __QEMU_ACL_H__
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#include "sys-queue.h"
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+typedef struct qemu_acl_entry qemu_acl_entry;
Daniel P. Berrange 42af21
+typedef struct qemu_acl qemu_acl;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+struct qemu_acl_entry {
Daniel P. Berrange 42af21
+    char *match;
Daniel P. Berrange 42af21
+    int deny;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    TAILQ_ENTRY(qemu_acl_entry) next;
Daniel P. Berrange 42af21
+};
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+struct qemu_acl {
Daniel P. Berrange 42af21
+    char *aclname;
Daniel P. Berrange 42af21
+    unsigned int nentries;
Daniel P. Berrange 42af21
+    TAILQ_HEAD(,qemu_acl_entry) entries;
Daniel P. Berrange 42af21
+    int defaultDeny;
Daniel P. Berrange 42af21
+};
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+qemu_acl *qemu_acl_init(const char *aclname);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+qemu_acl *qemu_acl_find(const char *aclname);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_party_is_allowed(qemu_acl *acl,
Daniel P. Berrange 42af21
+			      const char *party);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+void qemu_acl_reset(qemu_acl *acl);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+int qemu_acl_append(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    int deny,
Daniel P. Berrange 42af21
+		    const char *match);
Daniel P. Berrange 42af21
+int qemu_acl_insert(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    int deny,
Daniel P. Berrange 42af21
+		    const char *match,
Daniel P. Berrange 42af21
+		    int index);
Daniel P. Berrange 42af21
+int qemu_acl_remove(qemu_acl *acl,
Daniel P. Berrange 42af21
+		    const char *match);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#endif /* __QEMU_ACL_H__ */
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+/*
Daniel P. Berrange 42af21
+ * Local variables:
Daniel P. Berrange 42af21
+ *  c-indent-level: 4
Daniel P. Berrange 42af21
+ *  c-basic-offset: 4
Daniel P. Berrange 42af21
+ *  tab-width: 8
Daniel P. Berrange 42af21
+ * End:
Daniel P. Berrange 42af21
+ */
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 configure
Daniel P. Berrange 42af21
--- a/configure	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/configure	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -846,6 +846,21 @@ EOF
Daniel P. Berrange 42af21
 fi
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 ##########################################
Daniel P. Berrange 42af21
+# fnmatch() probe, used for ACL routines
Daniel P. Berrange 42af21
+fnmatch="no"
Daniel P. Berrange 42af21
+cat > $TMPC << EOF
Daniel P. Berrange 42af21
+#include <fnmatch.h>
Daniel P. Berrange 42af21
+int main(void)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    fnmatch("foo", "foo", 0);
Daniel P. Berrange 42af21
+    return 0;
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+EOF
Daniel P. Berrange 42af21
+if $cc $ARCH_CFLAGS -o $TMPE $TMPC > /dev/null 2> /dev/null ; then
Daniel P. Berrange 42af21
+   fnmatch="yes"
Daniel P. Berrange 42af21
+fi
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+##########################################
Daniel P. Berrange 42af21
 # vde libraries probe
Daniel P. Berrange 42af21
 if test "$vde" = "yes" ; then
Daniel P. Berrange 42af21
   cat > $TMPC << EOF
Daniel P. Berrange 42af21
@@ -1405,6 +1420,9 @@ if test "$vnc_sasl" = "yes" ; then
Daniel P. Berrange 42af21
   echo "CONFIG_VNC_SASL_LIBS=$vnc_sasl_libs" >> $config_mak
Daniel P. Berrange 42af21
   echo "#define CONFIG_VNC_SASL 1" >> $config_h
Daniel P. Berrange 42af21
 fi
Daniel P. Berrange 42af21
+if test "$fnmatch" = "yes" ; then
Daniel P. Berrange 42af21
+  echo "#define HAVE_FNMATCH_H 1" >> $config_h
Daniel P. Berrange 42af21
+fi
Daniel P. Berrange 42af21
 qemu_version=`head $source_path/VERSION`
Daniel P. Berrange 42af21
 echo "VERSION=$qemu_version" >>$config_mak
Daniel P. Berrange 42af21
 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 monitor.c
Daniel P. Berrange 42af21
--- a/monitor.c	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/monitor.c	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -39,6 +39,7 @@
Daniel P. Berrange 42af21
 #include "qemu-timer.h"
Daniel P. Berrange 42af21
 #include "migration.h"
Daniel P. Berrange 42af21
 #include "kvm.h"
Daniel P. Berrange 42af21
+#include "acl.h"
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 //#define DEBUG
Daniel P. Berrange 42af21
 //#define DEBUG_COMPLETION
Daniel P. Berrange 42af21
@@ -1425,6 +1426,85 @@ static void do_info_balloon(void)
Daniel P. Berrange 42af21
         term_printf("balloon: actual=%d\n", (int)(actual >> 20));
Daniel P. Berrange 42af21
 }
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+static void do_acl(const char *command,
Daniel P. Berrange 42af21
+		   const char *aclname,
Daniel P. Berrange 42af21
+		   const char *match,
Daniel P. Berrange 42af21
+		   int has_index,
Daniel P. Berrange 42af21
+		   int index)
Daniel P. Berrange 42af21
+{
Daniel P. Berrange 42af21
+    qemu_acl *acl;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    acl = qemu_acl_find(aclname);
Daniel P. Berrange 42af21
+    if (!acl) {
Daniel P. Berrange 42af21
+	term_printf("acl: unknown list '%s'\n", aclname);
Daniel P. Berrange 42af21
+	return;
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    if (strcmp(command, "show") == 0) {
Daniel P. Berrange 42af21
+	int i = 0;
Daniel P. Berrange 42af21
+	qemu_acl_entry *entry;
Daniel P. Berrange 42af21
+	term_printf("policy: %s\n",
Daniel P. Berrange 42af21
+		    acl->defaultDeny ? "deny" : "allow");
Daniel P. Berrange 42af21
+	TAILQ_FOREACH(entry, &acl->entries, next) {
Daniel P. Berrange 42af21
+	    i++;
Daniel P. Berrange 42af21
+	    term_printf("%d: %s %s\n", i,
Daniel P. Berrange 42af21
+			entry->deny ? "deny" : "allow",
Daniel P. Berrange 42af21
+			entry->match);
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    } else if (strcmp(command, "reset") == 0) {
Daniel P. Berrange 42af21
+	qemu_acl_reset(acl);
Daniel P. Berrange 42af21
+	term_printf("acl: removed all rules\n");
Daniel P. Berrange 42af21
+    } else if (strcmp(command, "policy") == 0) {
Daniel P. Berrange 42af21
+	if (!match) {
Daniel P. Berrange 42af21
+	    term_printf("acl: missing policy parameter\n");
Daniel P. Berrange 42af21
+	    return;
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	if (strcmp(match, "allow") == 0) {
Daniel P. Berrange 42af21
+	    acl->defaultDeny = 0;
Daniel P. Berrange 42af21
+	    term_printf("acl: policy set to 'allow'\n");
Daniel P. Berrange 42af21
+	} else if (strcmp(match, "deny") == 0) {
Daniel P. Berrange 42af21
+	    acl->defaultDeny = 1;
Daniel P. Berrange 42af21
+	    term_printf("acl: policy set to 'deny'\n");
Daniel P. Berrange 42af21
+	} else {
Daniel P. Berrange 42af21
+	    term_printf("acl: unknown policy '%s', expected 'deny' or 'allow'\n", match);
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    } else if ((strcmp(command, "allow") == 0) ||
Daniel P. Berrange 42af21
+	       (strcmp(command, "deny") == 0)) {
Daniel P. Berrange 42af21
+	int deny = strcmp(command, "deny") == 0 ? 1 : 0;
Daniel P. Berrange 42af21
+	int ret;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	if (!match) {
Daniel P. Berrange 42af21
+	    term_printf("acl: missing match parameter\n");
Daniel P. Berrange 42af21
+	    return;
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	if (has_index)
Daniel P. Berrange 42af21
+	    ret = qemu_acl_insert(acl, deny, match, index);
Daniel P. Berrange 42af21
+	else
Daniel P. Berrange 42af21
+	    ret = qemu_acl_append(acl, deny, match);
Daniel P. Berrange 42af21
+	if (ret < 0)
Daniel P. Berrange 42af21
+	    term_printf("acl: unable to add acl entry\n");
Daniel P. Berrange 42af21
+	else
Daniel P. Berrange 42af21
+	    term_printf("acl: added rule at position %d\n", ret);
Daniel P. Berrange 42af21
+    } else if (strcmp(command, "remove") == 0) {
Daniel P. Berrange 42af21
+	int ret;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	if (!match) {
Daniel P. Berrange 42af21
+	    term_printf("acl: missing match parameter\n");
Daniel P. Berrange 42af21
+	    return;
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	ret = qemu_acl_remove(acl, match);
Daniel P. Berrange 42af21
+	if (ret < 0)
Daniel P. Berrange 42af21
+	    term_printf("acl: no matching acl entry\n");
Daniel P. Berrange 42af21
+	else
Daniel P. Berrange 42af21
+	    term_printf("acl: removed rule at position %d\n", ret);
Daniel P. Berrange 42af21
+    } else {
Daniel P. Berrange 42af21
+	term_printf("acl: unknown command '%s'\n", command);
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 /* Please update qemu-doc.texi when adding or changing commands */
Daniel P. Berrange 42af21
 static const term_cmd_t term_cmds[] = {
Daniel P. Berrange 42af21
     { "help|?", "s?", do_help,
Daniel P. Berrange 42af21
@@ -1529,6 +1609,12 @@ static const term_cmd_t term_cmds[] = {
Daniel P. Berrange 42af21
       "target", "request VM to change it's memory allocation (in MB)" },
Daniel P. Berrange 42af21
     { "set_link", "ss", do_set_link,
Daniel P. Berrange 42af21
       "name [up|down]", "change the link status of a network adapter" },
Daniel P. Berrange 42af21
+    { "acl", "sss?i?", do_acl, "<command> <aclname> [<match>] [<index>]\n",
Daniel P. Berrange 42af21
+                               "acl show vnc.username\n"
Daniel P. Berrange 42af21
+                               "acl policy vnc.username deny\n"
Daniel P. Berrange 42af21
+                               "acl allow vnc.username fred\n"
Daniel P. Berrange 42af21
+                               "acl deny vnc.username bob\n"
Daniel P. Berrange 42af21
+                               "acl reset vnc.username\n" },
Daniel P. Berrange 42af21
     { NULL, NULL, },
Daniel P. Berrange 42af21
 };
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
@@ -2891,3 +2977,12 @@ void monitor_readline(const char *prompt
Daniel P. Berrange 42af21
                 monitor_hd[i]->focus = old_focus[i];
Daniel P. Berrange 42af21
     }
Daniel P. Berrange 42af21
 }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+/*
Daniel P. Berrange 42af21
+ * Local variables:
Daniel P. Berrange 42af21
+ *  c-indent-level: 4
Daniel P. Berrange 42af21
+ *  c-basic-offset: 4
Daniel P. Berrange 42af21
+ *  tab-width: 8
Daniel P. Berrange 42af21
+ * End:
Daniel P. Berrange 42af21
+ */
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 qemu-doc.texi
Daniel P. Berrange 42af21
--- a/qemu-doc.texi	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/qemu-doc.texi	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -631,6 +631,19 @@ ensures a data encryption preventing com
Daniel P. Berrange 42af21
 credentials. See the @ref{vnc_security} section for details on using
Daniel P. Berrange 42af21
 SASL authentication.
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+@item acl
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+Turn on access control lists for checking of the x509 client certificate
Daniel P. Berrange 42af21
+and SASL party. For x509 certs, the ACL check is made against the
Daniel P. Berrange 42af21
+certificate's distinguished name. This is something that looks like
Daniel P. Berrange 42af21
+@code{C=GB,O=ACME,L=Boston,CN=bob}. For SASL party, the ACL check is
Daniel P. Berrange 42af21
+made against the username, which depending on the SASL plugin, may
Daniel P. Berrange 42af21
+include a realm component, eg @code{bob} or @code{bob\@EXAMPLE.COM}.
Daniel P. Berrange 42af21
+When the @option{acl} flag is set, the initial access list will be
Daniel P. Berrange 42af21
+empty, with a @code{deny} policy. Thus no one will be allowed to
Daniel P. Berrange 42af21
+use the VNC server until the ACLs have been loaded. This can be
Daniel P. Berrange 42af21
+achieved using the @code{acl} monitor command.
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 @end table
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 @end table
Daniel P. Berrange 42af21
@@ -1392,6 +1405,42 @@ Password: ********
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 @end table
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+@item acl @var{subcommand} @var{aclname} @var{match} @var{index}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+Manage access control lists for network services. There are currently
Daniel P. Berrange 42af21
+two named access control lists, @var{vnc.x509dname} and @var{vnc.username}
Daniel P. Berrange 42af21
+matching on the x509 client certificate distinguished name, and SASL
Daniel P. Berrange 42af21
+username respectively.
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+@table @option
Daniel P. Berrange 42af21
+@item acl show <aclname>
Daniel P. Berrange 42af21
+list all the match rules in the access control list, and the default
Daniel P. Berrange 42af21
+policy
Daniel P. Berrange 42af21
+@item acl policy <aclname> @code{allow|deny}
Daniel P. Berrange 42af21
+set the default access control list policy, used in the event that
Daniel P. Berrange 42af21
+none of the explicit rules match. The default policy at startup is
Daniel P. Berrange 42af21
+always @code{deny}
Daniel P. Berrange 42af21
+@item acl allow <aclname> <match> [<index>]
Daniel P. Berrange 42af21
+add a match to the access control list, allowing access. The match will
Daniel P. Berrange 42af21
+normally be an exact username or x509 distinguished name, but can
Daniel P. Berrange 42af21
+optionally include wildcard globs. eg @code{*\@EXAMPLE.COM} to allow
Daniel P. Berrange 42af21
+all users in the @code{EXAMPLE.COM} kerberos realm. The match will
Daniel P. Berrange 42af21
+normally be appended to the end of the ACL, but can be inserted
Daniel P. Berrange 42af21
+earlier in the list if the optional @code{index} parameter is supplied.
Daniel P. Berrange 42af21
+@item acl deny <aclname> <match> [<index>]
Daniel P. Berrange 42af21
+add a match to the access control list, denying access. The match will
Daniel P. Berrange 42af21
+normally be an exact username or x509 distinguished name, but can
Daniel P. Berrange 42af21
+optionally include wildcard globs. eg @code{*\@EXAMPLE.COM} to allow
Daniel P. Berrange 42af21
+all users in the @code{EXAMPLE.COM} kerberos realm. The match will
Daniel P. Berrange 42af21
+normally be appended to the end of the ACL, but can be inserted
Daniel P. Berrange 42af21
+earlier in the list if the optional @code{index} parameter is supplied.
Daniel P. Berrange 42af21
+@item acl remove <aclname> <match>
Daniel P. Berrange 42af21
+remove the specified match rule from the access control list.
Daniel P. Berrange 42af21
+@item acl reset <aclname>
Daniel P. Berrange 42af21
+remove all matches from the access control list, and set the default
Daniel P. Berrange 42af21
+policy back to @code{deny}.
Daniel P. Berrange 42af21
+@end table
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 @item screendump @var{filename}
Daniel P. Berrange 42af21
 Save screen into PPM image @var{filename}.
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc-auth-sasl.c
Daniel P. Berrange 42af21
--- a/vnc-auth-sasl.c	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc-auth-sasl.c	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -120,22 +120,32 @@ static int vnc_auth_sasl_check_access(Vn
Daniel P. Berrange 42af21
 {
Daniel P. Berrange 42af21
     const void *val;
Daniel P. Berrange 42af21
     int err;
Daniel P. Berrange 42af21
+    int allow;
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
     err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val;;
Daniel P. Berrange 42af21
     if (err != SASL_OK) {
Daniel P. Berrange 42af21
-	VNC_DEBUG("cannot query SASL username on connection %d (%s)\n",
Daniel P. Berrange 42af21
+	VNC_DEBUG("cannot query SASL username on connection %d (%s), denying access\n",
Daniel P. Berrange 42af21
 		  err, sasl_errstring(err, NULL, NULL));
Daniel P. Berrange 42af21
 	return -1;
Daniel P. Berrange 42af21
     }
Daniel P. Berrange 42af21
     if (val == NULL) {
Daniel P. Berrange 42af21
-	VNC_DEBUG("no client username was found\n");
Daniel P. Berrange 42af21
+	VNC_DEBUG("no client username was found, denying access\n");
Daniel P. Berrange 42af21
 	return -1;
Daniel P. Berrange 42af21
     }
Daniel P. Berrange 42af21
     VNC_DEBUG("SASL client username %s\n", (const char *)val);
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
     vs->sasl.username = qemu_strdup((const char*)val);
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
-    return 0;
Daniel P. Berrange 42af21
+    if (vs->vd->sasl.acl == NULL) {
Daniel P. Berrange 42af21
+	VNC_DEBUG("no ACL activated, allowing access\n");
Daniel P. Berrange 42af21
+	return 0;
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+    VNC_DEBUG("SASL client %s %s by ACL\n", vs->sasl.username,
Daniel P. Berrange 42af21
+	      allow ? "allowed" : "denied");
Daniel P. Berrange 42af21
+    return allow ? 0 : -1;
Daniel P. Berrange 42af21
 }
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 static int vnc_auth_sasl_check_ssf(VncState *vs)
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc-auth-sasl.h
Daniel P. Berrange 42af21
--- a/vnc-auth-sasl.h	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc-auth-sasl.h	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -30,6 +30,9 @@
Daniel P. Berrange 42af21
 #include <sasl/sasl.h>
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 typedef struct VncStateSASL VncStateSASL;
Daniel P. Berrange 42af21
+typedef struct VncDisplaySASL VncDisplaySASL;
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+#include "acl.h"
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 struct VncStateSASL {
Daniel P. Berrange 42af21
     sasl_conn_t *conn;
Daniel P. Berrange 42af21
@@ -56,6 +59,10 @@ struct VncStateSASL {
Daniel P. Berrange 42af21
     char *mechlist;
Daniel P. Berrange 42af21
 };
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+struct VncDisplaySASL {
Daniel P. Berrange 42af21
+    qemu_acl *acl;
Daniel P. Berrange 42af21
+};
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 void vnc_sasl_client_cleanup(VncState *vs);
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 long vnc_client_read_sasl(VncState *vs);
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc-tls.c
Daniel P. Berrange 42af21
--- a/vnc-tls.c	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc-tls.c	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -255,6 +255,25 @@ int vnc_tls_validate_certificate(struct 
Daniel P. Berrange 42af21
 			  gnutls_strerror (ret));
Daniel P. Berrange 42af21
 		return -1;
Daniel P. Berrange 42af21
 	    }
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+	    if (vs->vd->tls.x509verify) {
Daniel P. Berrange 42af21
+		int allow;
Daniel P. Berrange 42af21
+		if (!vs->vd->tls.acl) {
Daniel P. Berrange 42af21
+		    VNC_DEBUG("no ACL activated, allowing access");
Daniel P. Berrange 42af21
+		    gnutls_x509_crt_deinit (cert);
Daniel P. Berrange 42af21
+		    continue;
Daniel P. Berrange 42af21
+		}
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+		allow = qemu_acl_party_is_allowed(vs->vd->tls.acl,
Daniel P. Berrange 42af21
+						  vs->tls.dname);
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
+		VNC_DEBUG("TLS x509 ACL check for %s is %s\n",
Daniel P. Berrange 42af21
+			  vs->tls.dname, allow ? "allowed" : "denied");
Daniel P. Berrange 42af21
+		if (!allow) {
Daniel P. Berrange 42af21
+		    gnutls_x509_crt_deinit (cert);
Daniel P. Berrange 42af21
+		    return -1;
Daniel P. Berrange 42af21
+		}
Daniel P. Berrange 42af21
+	    }
Daniel P. Berrange 42af21
 	}
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 	gnutls_x509_crt_deinit (cert);
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc-tls.h
Daniel P. Berrange 42af21
--- a/vnc-tls.h	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc-tls.h	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -31,6 +31,8 @@
Daniel P. Berrange 42af21
 #include <gnutls/gnutls.h>
Daniel P. Berrange 42af21
 #include <gnutls/x509.h>
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+#include "acl.h"
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
 enum {
Daniel P. Berrange 42af21
     VNC_WIREMODE_CLEAR,
Daniel P. Berrange 42af21
     VNC_WIREMODE_TLS,
Daniel P. Berrange 42af21
@@ -42,6 +44,7 @@ typedef struct VncStateTLS VncStateTLS;
Daniel P. Berrange 42af21
 /* Server state */
Daniel P. Berrange 42af21
 struct VncDisplayTLS {
Daniel P. Berrange 42af21
     int x509verify; /* Non-zero if server requests & validates client cert */
Daniel P. Berrange 42af21
+    qemu_acl *acl;
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
     /* Paths to x509 certs/keys */
Daniel P. Berrange 42af21
     char *x509cacert;
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc.c
Daniel P. Berrange 42af21
--- a/vnc.c	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc.c	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -28,6 +28,7 @@
Daniel P. Berrange 42af21
 #include "sysemu.h"
Daniel P. Berrange 42af21
 #include "qemu_socket.h"
Daniel P. Berrange 42af21
 #include "qemu-timer.h"
Daniel P. Berrange 42af21
+#include "acl.h"
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 #define VNC_REFRESH_INTERVAL (1000 / 30)
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
@@ -2082,6 +2083,7 @@ int vnc_display_open(DisplayState *ds, c
Daniel P. Berrange 42af21
     int sasl = 0;
Daniel P. Berrange 42af21
     int saslErr;
Daniel P. Berrange 42af21
 #endif
Daniel P. Berrange 42af21
+    int acl = 0;
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
     if (!vnc_display)
Daniel P. Berrange 42af21
         return -1;
Daniel P. Berrange 42af21
@@ -2138,9 +2140,28 @@ int vnc_display_open(DisplayState *ds, c
Daniel P. Berrange 42af21
 		return -1;
Daniel P. Berrange 42af21
 	    }
Daniel P. Berrange 42af21
 #endif
Daniel P. Berrange 42af21
+	} else if (strncmp(options, "acl", 3) == 0) {
Daniel P. Berrange 42af21
+	    acl = 1;
Daniel P. Berrange 42af21
 	}
Daniel P. Berrange 42af21
     }
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
+#ifdef CONFIG_VNC_TLS
Daniel P. Berrange 42af21
+    if (acl && x509 && vs->tls.x509verify) {
Daniel P. Berrange 42af21
+	if (!(vs->tls.acl = qemu_acl_init("vnc.x509dname"))) {
Daniel P. Berrange 42af21
+	    fprintf(stderr, "Failed to create x509 dname ACL\n");
Daniel P. Berrange 42af21
+	    exit(1);
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+#endif
Daniel P. Berrange 42af21
+#ifdef CONFIG_VNC_SASL
Daniel P. Berrange 42af21
+    if (acl && sasl) {
Daniel P. Berrange 42af21
+	if (!(vs->sasl.acl = qemu_acl_init("vnc.username"))) {
Daniel P. Berrange 42af21
+	    fprintf(stderr, "Failed to create username ACL\n");
Daniel P. Berrange 42af21
+	    exit(1);
Daniel P. Berrange 42af21
+	}
Daniel P. Berrange 42af21
+    }
Daniel P. Berrange 42af21
+#endif
Daniel P. Berrange 42af21
+
Daniel P. Berrange 42af21
     /*
Daniel P. Berrange 42af21
      * Combinations we support here:
Daniel P. Berrange 42af21
      *
Daniel P. Berrange 42af21
diff -r b1008c5c6c16 vnc.h
Daniel P. Berrange 42af21
--- a/vnc.h	Mon Mar 02 11:13:40 2009 +0000
Daniel P. Berrange 42af21
+++ b/vnc.h	Mon Mar 02 12:11:04 2009 +0000
Daniel P. Berrange 42af21
@@ -98,6 +98,9 @@ struct VncDisplay
Daniel P. Berrange 42af21
     int subauth; /* Used by VeNCrypt */
Daniel P. Berrange 42af21
     VncDisplayTLS tls;
Daniel P. Berrange 42af21
 #endif
Daniel P. Berrange 42af21
+#ifdef CONFIG_VNC_SASL
Daniel P. Berrange 42af21
+    VncDisplaySASL sasl;
Daniel P. Berrange 42af21
+#endif
Daniel P. Berrange 42af21
 };
Daniel P. Berrange 42af21
 
Daniel P. Berrange 42af21
 struct VncState