[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 6/9] Add SPICE support for QEMU driver configuration file



In common with VNC, the QEMU driver configuration file is used
specify the host level TLS certificate location and a default
password / listen address

* src/qemu/qemu.conf: Add spice_listen, spice_tls,
  spice_tls_x509_cert_dir & spice_password config params
* src/qemu/qemu_conf.c, src/qemu/qemu_conf.h: Parsing of
  spice config parameters and updating -spice arg generation
  to use them
* tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-rhel6.args,
  tests/qemuxml2argvtest.c: Expand test case to cover driver
  level configuration
---
 src/qemu/qemu.conf                                 |   40 +++++++++++++
 src/qemu/qemu_conf.c                               |   62 +++++++++++++++++++-
 src/qemu/qemu_conf.h                               |    4 +
 src/qemu/qemu_driver.c                             |   15 ++++-
 .../qemuxml2argv-graphics-spice.args               |    2 +-
 tests/qemuxml2argvtest.c                           |    5 ++
 6 files changed, 123 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index e2c581e..f4f965e 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -80,6 +80,46 @@
 
 
 
+# SPICE is configured to listen on 127.0.0.1 by default.
+# To make it listen on all public interfaces, uncomment
+# this next option.
+#
+# NB, strong recommendation to enable TLS + x509 certificate
+# verification when allowing public access
+#
+# spice_listen = "0.0.0.0"
+
+
+# Enable use of TLS encryption on the SPICE server.
+#
+# It is necessary to setup CA and issue a server certificate
+# before enabling this.
+#
+# spice_tls = 1
+
+
+# Use of TLS requires that x509 certificates be issued. The
+# default it to keep them in /etc/pki/libvirt-spice. This directory
+# must contain
+#
+#  ca-cert.pem - the CA master certificate
+#  server-cert.pem - the server certificate signed with ca-cert.pem
+#  server-key.pem  - the server private key
+#
+# This option allows the certificate directory to be changed
+#
+# spice_tls_x509_cert_dir = "/etc/pki/libvirt-spice"
+
+
+# The default SPICE password. This parameter is only used if the
+# per-domain XML config does not already provide a password. To
+# allow access without passwords, leave this commented out. An
+# empty string will still enable passwords, but be rejected by
+# QEMU effectively preventing any use of SPICE. Obviously change
+# this example here before you set this
+#
+# spice_password = "XYZ12345"
+
 
 # The default security driver is SELinux. If SELinux is disabled
 # on the host, then the security driver will automatically disable
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index cd09db2..e4a4db3 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -116,6 +116,15 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
         return -1;
     }
 
+    if (!(driver->spiceListen = strdup("127.0.0.1"))) {
+        virReportOOMError();
+        return -1;
+    }
+    if (!(driver->spiceTLSx509certdir = strdup(SYSCONF_DIR "/pki/libvirt-spice"))) {
+        virReportOOMError();
+        return -1;
+    }
+
 #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
     /* For privileged driver, try and find hugepage mount automatically.
      * Non-privileged driver requires admin to create a dir for the
@@ -219,6 +228,43 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
         }
     }
 
+    p = virConfGetValue (conf, "spice_tls");
+    CHECK_TYPE ("spice_tls", VIR_CONF_LONG);
+    if (p) driver->spiceTLS = p->l;
+
+    p = virConfGetValue (conf, "spice_tls_x509_cert_dir");
+    CHECK_TYPE ("spice_tls_x509_cert_dir", VIR_CONF_STRING);
+    if (p && p->str) {
+        VIR_FREE(driver->spiceTLSx509certdir);
+        if (!(driver->spiceTLSx509certdir = strdup(p->str))) {
+            virReportOOMError();
+            virConfFree(conf);
+            return -1;
+        }
+    }
+
+    p = virConfGetValue (conf, "spice_listen");
+    CHECK_TYPE ("spice_listen", VIR_CONF_STRING);
+    if (p && p->str) {
+        VIR_FREE(driver->spiceListen);
+        if (!(driver->spiceListen = strdup(p->str))) {
+            virReportOOMError();
+            virConfFree(conf);
+            return -1;
+        }
+    }
+
+    p = virConfGetValue (conf, "spice_password");
+    CHECK_TYPE ("spice_password", VIR_CONF_STRING);
+    if (p && p->str) {
+        VIR_FREE(driver->spicePassword);
+        if (!(driver->spicePassword = strdup(p->str))) {
+            virReportOOMError();
+            virConfFree(conf);
+            return -1;
+        }
+    }
+
     p = virConfGetValue (conf, "user");
     CHECK_TYPE ("user", VIR_CONF_STRING);
     if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) {
@@ -5082,11 +5128,25 @@ int qemudBuildCommandLine(virConnectPtr conn,
 
         virBufferVSprintf(&opt, "port=%u", def->graphics[0]->data.spice.port);
 
-        if (def->graphics[0]->data.spice.tlsPort)
+        if (driver->spiceTLS && def->graphics[0]->data.spice.tlsPort != -1)
             virBufferVSprintf(&opt, ",tls-port=%u", def->graphics[0]->data.spice.tlsPort);
 
         if (def->graphics[0]->data.spice.listenAddr)
             virBufferVSprintf(&opt, ",addr=%s", def->graphics[0]->data.spice.listenAddr);
+        else if (driver->spiceListen)
+            virBufferVSprintf(&opt, ",addr=%s", driver->spiceListen);
+
+        /* In the password case we set it via monitor command, to avoid
+         * making it visible on CLI, so there's no use of password=XXX
+         * in this bit of the code */
+        if (!def->graphics[0]->data.spice.passwd &&
+            !driver->spicePassword)
+            virBufferAddLit(&opt, ",disable-ticketing");
+
+        if (driver->spiceTLS)
+            virBufferVSprintf(&opt, ",x509-dir=%s",
+                              driver->spiceTLSx509certdir);
+
 
         if (virBufferError(&opt))
             goto no_memory;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index e00c83d..790ce98 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -141,6 +141,10 @@ struct qemud_driver {
     char *vncListen;
     char *vncPassword;
     char *vncSASLdir;
+    unsigned int spiceTLS : 1;
+    char *spiceTLSx509certdir;
+    char *spiceListen;
+    char *spicePassword;
     char *hugetlbfs_mount;
     char *hugepage_path;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c9f5e47..766de66 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3942,13 +3942,22 @@ static int qemudStartVMDaemon(virConnectPtr conn,
         } else if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
                    vm->def->graphics[0]->data.spice.autoport) {
             int port = qemudNextFreePort(driver, 5900);
-            int tlsPort = port == -1 ? -1 : qemudNextFreePort(driver, port + 1);
-            if (port < 0 || tlsPort < 0) {
+            int tlsPort = -1;
+            if (port < 0) {
                 qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                                "%s", _("Unable to find unused SPICE ports"));
+                                "%s", _("Unable to find an unused SPICE port"));
                 goto cleanup;
             }
 
+            if (driver->spiceTLS) {
+                tlsPort = qemudNextFreePort(driver, port + 1);
+                if (tlsPort < 0) {
+                    qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                                    "%s", _("Unable to find an unused SPICE TLS port"));
+                    goto cleanup;
+                }
+            }
+
             vm->def->graphics[0]->data.spice.port = port;
             vm->def->graphics[0]->data.spice.tlsPort = tlsPort;
         }
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
index 8d195e5..e412fdb 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
@@ -1 +1 @@
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1 -vga qxl -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,x509-dir=/etc/pki/libvirt-spice -vga qxl -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c314b2c..b149ef4 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -214,6 +214,11 @@ mymain(int argc, char **argv)
         return EXIT_FAILURE;
     if ((driver.hugepage_path = strdup("/dev/hugepages/libvirt/qemu")) == NULL)
         return EXIT_FAILURE;
+    driver.spiceTLS = 1;
+    if (!(driver.spiceTLSx509certdir = strdup("/etc/pki/libvirt-spice")))
+        return EXIT_FAILURE;
+    if (!(driver.spicePassword = strdup("123456")))
+        return EXIT_FAILURE;
 
 # define DO_TEST_FULL(name, extraFlags, migrateFrom, expectError)       \
     do {                                                                \
-- 
1.7.2.3


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]