[libvirt] [PATCH v3 3/4] qemu: Add support for TLS X.509 path to TCP chardev backend

John Ferlan jferlan at redhat.com
Thu Jun 16 16:26:44 UTC 2016


When building a chardev device string for tcp, add the necessary pieces to
access provide the TLS X.509 path to qemu.  This includes generating the
'tls-creds-x509' object and then adding the 'tls-creds' parameter to the
VIR_DOMAIN_CHR_TYPE_TCP command line.

Finally add the tests for the qemu command line. This test will make use
of the "new(ish)" /etc/pki/qemu setting for a TLS certificate environment
by *not* "resetting" the chardevTLSx509certdir prior to running the test.
Also use the default "verify" option (which is "no").

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/qemu/qemu_command.c                            | 109 ++++++++++++++++++++-
 .../qemuxml2argv-serial-tcp-tlsx509-chardev.args   |  33 +++++++
 tests/qemuxml2argvtest.c                           |   6 ++
 3 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 4a8def1..0ee07a9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -701,6 +701,103 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf,
 }
 
 
+/* qemuBuildTLSx509BackendProps:
+ * @tlspath: path to the TLS credentials
+ * @listen: boolen listen for client or server setting
+ * @verifypeer: boolean to enable peer verification (form of authorization)
+ * @qemuCaps: capabilities
+ * @propsret: json properties to return
+ *
+ * Create a backend string for the tls-creds-x509 object.
+ *
+ * Returns 0 on success, -1 on failure with error set.
+ */
+static int
+qemuBuildTLSx509BackendProps(const char *tlspath,
+                             bool listen,
+                             bool verifypeer,
+                             virQEMUCapsPtr qemuCaps,
+                             virJSONValuePtr *propsret)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *path = NULL;
+    int ret = -1;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("tls-creds-x509 not supported in this QEMU binary"));
+        return -1;
+    }
+
+    qemuBufferEscapeComma(&buf, tlspath);
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+    path = virBufferContentAndReset(&buf);
+
+    if (virJSONValueObjectCreate(propsret,
+                                 "s:dir", path,
+                                 "s:endpoint", (listen ? "server": "client"),
+                                 "b:verify-peer", verifypeer,
+                                 NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    VIR_FREE(path);
+    return ret;
+}
+
+
+/* qemuBuildTLSx509CommandLine:
+ * @cmd: Pointer to command
+ * @tlspath: path to the TLS credentials
+ * @listen: boolen listen for client or server setting
+ * @verifypeer: boolean to enable peer verification (form of authorization)
+ * @inalias: Alias for the parent (this code will add a "_tls0" to alias)
+ * @qemuCaps: capabilities
+ *
+ * Create the command line for a TLS object
+ *
+ * Returns 0 on success, -1 on failure with error set.
+ */
+static int
+qemuBuildTLSx509CommandLine(virCommandPtr cmd,
+                            const char *tlspath,
+                            bool listen,
+                            bool verifypeer,
+                            const char *inalias,
+                            virQEMUCapsPtr qemuCaps)
+{
+    int ret = -1;
+    char *alias = NULL;
+    virJSONValuePtr props = NULL;
+    char *tmp = NULL;
+
+    if (qemuBuildTLSx509BackendProps(tlspath, listen, verifypeer,
+                                     qemuCaps, &props) < 0)
+        return -1;
+
+    if (virAsprintf(&alias, "obj%s_tls0", inalias) < 0)
+        goto cleanup;
+
+    if (!(tmp = virQEMUBuildObjectCommandlineFromJSON("tls-creds-x509",
+                                                      alias, props)))
+        goto cleanup;
+
+    virCommandAddArgList(cmd, "-object", tmp, NULL);
+
+    ret = 0;
+
+ cleanup:
+    virJSONValueFree(props);
+    VIR_FREE(alias);
+    VIR_FREE(tmp);
+    return ret;
+}
+
+
 #define QEMU_DEFAULT_NBD_PORT "10809"
 
 static char *
@@ -4685,7 +4782,7 @@ qemuBuildChrChardevFileStr(virLogManagerPtr logManager,
 static char *
 qemuBuildChrChardevStr(virLogManagerPtr logManager,
                        virCommandPtr cmd,
-                       virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
+                       virQEMUDriverConfigPtr cfg,
                        const virDomainDef *def,
                        const virDomainChrSourceDef *dev,
                        const char *alias,
@@ -4768,6 +4865,16 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager,
                           dev->data.tcp.service,
                           telnet ? ",telnet" : "",
                           dev->data.tcp.listen ? ",server,nowait" : "");
+
+            if (cfg->chardevTLS) {
+                if (qemuBuildTLSx509CommandLine(cmd, cfg->chardevTLSx509certdir,
+                                                dev->data.tcp.listen,
+                                                cfg->chardevTLSx509verify,
+                                                alias, qemuCaps) < 0)
+                    goto error;
+
+                virBufferAsprintf(&buf, ",tls-creds=obj%s_tls0", alias);
+            }
         break;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
new file mode 100644
index 0000000..5b3016d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args
@@ -0,0 +1,33 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-chardev udp,id=charserial0,host=127.0.0.1,port=2222,localaddr=127.0.0.1,\
+localport=1111 \
+-device isa-serial,chardev=charserial0,id=serial0 \
+-object tls-creds-x509,id=objserial1_tls0,dir=/etc/pki/qemu,endpoint=client,\
+verify-peer=no \
+-chardev socket,id=charserial1,host=127.0.0.1,port=5555,\
+tls-creds=objserial1_tls0 \
+-device isa-serial,chardev=charserial1,id=serial1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c406b64..7c04f56 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1072,6 +1072,12 @@ mymain(void)
             QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
     DO_TEST("serial-tcp-telnet-chardev",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
+    driver.config->chardevTLS = 1;
+    DO_TEST("serial-tcp-tlsx509-chardev",
+            QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG,
+            QEMU_CAPS_OBJECT_TLS_CREDS_X509);
+    driver.config->chardevTLS = 0;
+    VIR_FREE(driver.config->chardevTLSx509certdir);
     DO_TEST("serial-many-chardev",
             QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
     DO_TEST("parallel-tcp-chardev",
-- 
2.5.5




More information about the libvir-list mailing list