[libvirt] [PATCH 0/6] Some patches for native TLS encrypted chardev TCP support

Not fully complete yet as I need the key secret from the LUKS encryption support series; however, I figured I would post what I have that is at least "separable". This set of patches is in support of: https://bugzilla.redhat.com/show_bug.cgi?id=1300776 What's missing is the ability to provide an AES secret/key/passphrase in order to generate the qemu "passwordid=tlskey0" option. John Ferlan (6): caps: Add capability for tls-x509-creds docs: Clarify chardev protocol qemu: Refactor qemuDomainAttachChrDevice error paths conf: Add new tlsx509 attribute for tcp chardev qemu: Add support for TLS X.509 path qemu: Add the ability to hotplug the TLS X.509 environment docs/formatdomain.html.in | 36 +++++++- docs/schemas/domaincommon.rng | 12 +++ src/conf/domain_audit.c | 2 + src/conf/domain_conf.c | 15 +++ src/conf/domain_conf.h | 1 + src/conf/virchrdev.c | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 101 +++++++++++++++++++++ src/qemu/qemu_command.h | 6 ++ src/qemu/qemu_hotplug.c | 47 ++++++++-- src/qemu/qemu_monitor_json.c | 9 ++ src/security/security_dac.c | 11 ++- src/security/security_selinux.c | 10 ++ src/security/virt-aa-helper.c | 12 ++- tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + .../caps_2.6.0-gicv2.aarch64.xml | 1 + .../caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + .../qemuxml2argv-serial-tcp-tlsx509-chardev.args | 32 +++++++ .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml | 42 +++++++++ tests/qemuxml2argvtest.c | 3 + .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml | 51 +++++++++++ tests/qemuxml2xmltest.c | 1 + 25 files changed, 385 insertions(+), 15 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml -- 2.5.5

Add the capability flag and checks for the qemu object 'tls-creds-x509' Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + 7 files changed, 8 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b9f3fe0..95a21ae 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -333,6 +333,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "qxl.max_outputs", /* 225 */ "qxl-vga.max_outputs", "spice-unix", + "tls-creds-x509", ); @@ -1560,6 +1561,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "secret", QEMU_CAPS_OBJECT_SECRET }, { "pxb", QEMU_CAPS_DEVICE_PXB }, { "pxb-pcie", QEMU_CAPS_DEVICE_PXB_PCIE }, + { "tls-creds-x509", QEMU_CAPS_OBJECT_TLS_CREDS_X509 }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index d33ba00..0341d4a 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -366,6 +366,7 @@ typedef enum { QEMU_CAPS_QXL_MAX_OUTPUTS, /* -device qxl,max-outputs= */ QEMU_CAPS_QXL_VGA_MAX_OUTPUTS, /* -device qxl-vga,max-outputs= */ QEMU_CAPS_SPICE_UNIX, /* -spice unix */ + QEMU_CAPS_OBJECT_TLS_CREDS_X509, /* -object tls-creds-x509 */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml index 83f1e14..3b1b0e2 100644 --- a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml @@ -185,6 +185,7 @@ <flag name='qxl.max_outputs'/> <flag name='qxl-vga.max_outputs'/> <flag name='spice-unix'/> + <flag name='tls-creds-x509'/> <version>2005000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml index 8b68291..955c950 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml @@ -155,6 +155,7 @@ <flag name='nec-usb-xhci-ports'/> <flag name='virtio-scsi-pci.iothread'/> <flag name='name-guest'/> + <flag name='tls-creds-x509'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml index d65523e..935c82b 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml @@ -155,6 +155,7 @@ <flag name='nec-usb-xhci-ports'/> <flag name='virtio-scsi-pci.iothread'/> <flag name='name-guest'/> + <flag name='tls-creds-x509'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml index 771d209..e721147 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml @@ -149,6 +149,7 @@ <flag name='nec-usb-xhci-ports'/> <flag name='virtio-scsi-pci.iothread'/> <flag name='name-guest'/> + <flag name='tls-creds-x509'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml index c9f2965..e90e841 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml @@ -191,6 +191,7 @@ <flag name='qxl.max_outputs'/> <flag name='qxl-vga.max_outputs'/> <flag name='spice-unix'/> + <flag name='tls-creds-x509'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> -- 2.5.5

On Mon, Jun 13, 2016 at 08:40:23PM -0400, John Ferlan wrote:
Add the capability flag and checks for the qemu object 'tls-creds-x509'
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 1 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 1 + 7 files changed, 8 insertions(+)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add a slight clarification to usage of "telnet", "telnets", or "tls" as the protocol type value. Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fb3ec5e..bca9847 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5949,9 +5949,13 @@ qemu-kvm -net nic,model=? /dev/null <p> Alternatively you can use <code>telnet</code> instead - of <code>raw</code> TCP. <span class="since">Since 0.8.5</span> - you can also use <code>telnets</code> - (secure telnet) and <code>tls</code>. + of <code>raw</code> TCP in order to utilize the telnet protocol + for the connection. + </p> + <p> + <span class="since">Since 0.8.5,</span> some hypervisors support + use of either <code>telnets</code> (secure telnet) or <code>tls</code> + (via secure sockets layer) as the transport protocol for connections. </p> <pre> -- 2.5.5

On Mon, Jun 13, 2016 at 08:40:24PM -0400, John Ferlan wrote:
Add a slight clarification to usage of "telnet", "telnets", or "tls" as the protocol type value.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Refactor the error paths for attaching char device (it's about to be more complicated). Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_hotplug.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 58156c6..7d05073 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1524,17 +1524,12 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, goto cleanup; qemuDomainObjEnterMonitor(driver, vm); - if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) { - ignore_value(qemuDomainObjExitMonitor(driver, vm)); - goto audit; - } + if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) + goto failchardev; + + if (qemuMonitorAddDevice(priv->mon, devstr) < 0) + goto failadddev; - if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) { - /* detach associated chardev on error */ - qemuMonitorDetachCharDev(priv->mon, charAlias); - ignore_value(qemuDomainObjExitMonitor(driver, vm)); - goto audit; - } if (qemuDomainObjExitMonitor(driver, vm) < 0) goto audit; @@ -1550,6 +1545,13 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, VIR_FREE(charAlias); VIR_FREE(devstr); return ret; + + failadddev: + /* detach associated chardev on error */ + qemuMonitorDetachCharDev(priv->mon, charAlias); + failchardev: + ignore_value(qemuDomainObjExitMonitor(driver, vm)); + goto audit; } -- 2.5.5

On Mon, Jun 13, 2016 at 08:40:25PM -0400, John Ferlan wrote:
Refactor the error paths for attaching char device (it's about to be more complicated).
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_hotplug.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
ACK Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

Add the domain rng, parse, and format of a new XML element "tlsx509": <tlsx509 path='/tmp/x509/certdir'/> The attribute for the element will contain a path to an X.509 certificate credential directory to be passed along to the hypervisor to process. Signed-off-by: John Ferlan <jferlan@redhat.com> --- docs/formatdomain.html.in | 26 +++++++++++ docs/schemas/domaincommon.rng | 12 +++++ src/conf/domain_conf.c | 15 +++++++ src/conf/domain_conf.h | 1 + .../qemuxml2argv-serial-tcp-tlsx509-chardev.xml | 42 ++++++++++++++++++ .../qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml | 51 ++++++++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 7 files changed, 148 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index bca9847..07d5773 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5975,6 +5975,32 @@ qemu-kvm -net nic,model=? /dev/null </devices> ...</pre> + <p> + <span class="since">Since 1.3.6,</span> some hypervisors support + receiving a path to a directory containing an X.509 certificate + credentials. Configuration is handled via the + <code>tlsx509</code> element with the <code>path</code> attribute + defining the absolute directory path to the credentials. + </p> +<pre> + ... + <devices> + <serial type="tcp"> + <source mode="connect" host="0.0.0.0" service="2445"/> + <protocol type="raw"/> + <tlsx509 path='/path/to/x509/certdir'/> + <target port="1"/> + </serial> + ... + <serial type="tcp"> + <source mode="bind" host="127.0.0.1" service="2445"/> + <protocol type="raw"/> + <target port="1"/> + <tlsx509 path="/path/to/x509/certdir"/> + </serial> + </devices> + ...</pre> + <h6><a name="elementsCharUDP">UDP network console</a></h6> <p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 02078d7..1b6af6c 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -3207,6 +3207,9 @@ <ref name="qemucdevTgtDef"/> </optional> <optional> + <ref name="qemucdevTlsx509Def"/> + </optional> + <optional> <ref name="alias"/> </optional> <optional> @@ -3258,6 +3261,14 @@ </element> </define> + <define name="qemucdevTlsx509Def"> + <element name="tlsx509"> + <attribute name="path"> + <ref name="absFilePath"/> + </attribute> + </element> + </define> + <define name="qemucdevSrcTypeChoice"> <choice> <value>dev</value> @@ -3373,6 +3384,7 @@ </element> </optional> <optional> + <element name="log"> <attribute name="file"> <ref name="absFilePath"/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 10e61da..721866e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1837,6 +1837,7 @@ virDomainChrSourceDefClear(virDomainChrSourceDefPtr def) case VIR_DOMAIN_CHR_TYPE_TCP: VIR_FREE(def->data.tcp.host); VIR_FREE(def->data.tcp.service); + VIR_FREE(def->data.tcp.tlspath); break; case VIR_DOMAIN_CHR_TYPE_UNIX: @@ -1893,6 +1894,9 @@ virDomainChrSourceDefCopy(virDomainChrSourceDefPtr dest, if (VIR_STRDUP(dest->data.tcp.service, src->data.tcp.service) < 0) return -1; + + if (VIR_STRDUP(dest->data.tcp.tlspath, src->data.tcp.tlspath) < 0) + return -1; break; case VIR_DOMAIN_CHR_TYPE_UNIX: @@ -1961,6 +1965,7 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, case VIR_DOMAIN_CHR_TYPE_TCP: return src->data.tcp.listen == tgt->data.tcp.listen && src->data.tcp.protocol == tgt->data.tcp.protocol && + STREQ_NULLABLE(src->data.tcp.tlspath, tgt->data.tcp.tlspath) && STREQ_NULLABLE(src->data.tcp.host, tgt->data.tcp.host) && STREQ_NULLABLE(src->data.tcp.service, tgt->data.tcp.service); break; @@ -9849,6 +9854,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, char *master = NULL; char *slave = NULL; char *append = NULL; + char *tlsx509 = NULL; int remaining = 0; while (cur != NULL) { @@ -9938,6 +9944,9 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) { if (!protocol) protocol = virXMLPropString(cur, "type"); + } else if (xmlStrEqual(cur->name, BAD_CAST "tlsx509")) { + if (!tlsx509) + tlsx509 = virXMLPropString(cur, "path"); } else { remaining++; } @@ -10041,6 +10050,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, goto error; } + if (tlsx509) + def->data.tcp.tlspath = virFileSanitizePath(tlsx509); break; case VIR_DOMAIN_CHR_TYPE_UDP: @@ -10115,6 +10126,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, VIR_FREE(append); VIR_FREE(logappend); VIR_FREE(logfile); + VIR_FREE(tlsx509); return remaining; @@ -20965,6 +20977,9 @@ virDomainChrSourceDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "<protocol type='%s'/>\n", virDomainChrTcpProtocolTypeToString( def->data.tcp.protocol)); + if (def->data.tcp.tlspath) + virBufferEscapeString(buf, "<tlsx509 path='%s'/>\n", + def->data.tcp.tlspath); break; case VIR_DOMAIN_CHR_TYPE_UNIX: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3792562..a1cced5 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1085,6 +1085,7 @@ struct _virDomainChrSourceDef { struct { char *host; char *service; + char *tlspath; bool listen; int protocol; } tcp; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml new file mode 100644 index 0000000..edd78f1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml @@ -0,0 +1,42 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <serial type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target port='0'/> + </serial> + <serial type='tcp'> + <source mode='connect' host='127.0.0.1' service='5555'/> + <protocol type='raw'/> + <target port='0'/> + <tlsx509 path='/tmp/x509/certdir'/> + </serial> + <console type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target type='serial' port='0'/> + </console> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml new file mode 100644 index 0000000..e9e6e70 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml @@ -0,0 +1,51 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <serial type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target port='0'/> + </serial> + <serial type='tcp'> + <source mode='connect' host='127.0.0.1' service='5555'/> + <protocol type='raw'/> + <tlsx509 path='/tmp/x509/certdir'/> + <target port='0'/> + </serial> + <console type='udp'> + <source mode='bind' host='127.0.0.1' service='1111'/> + <source mode='connect' host='127.0.0.1' service='2222'/> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index ba55919..692f2c2 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -483,6 +483,7 @@ mymain(void) DO_TEST("serial-tcp"); DO_TEST("serial-udp"); DO_TEST("serial-tcp-telnet"); + DO_TEST("serial-tcp-tlsx509-chardev"); DO_TEST("serial-many"); DO_TEST("serial-spiceport"); DO_TEST("serial-spiceport-nospice"); -- 2.5.5

On Mon, Jun 13, 2016 at 08:40:26PM -0400, John Ferlan wrote:
Add the domain rng, parse, and format of a new XML element "tlsx509":
<tlsx509 path='/tmp/x509/certdir'/>
The attribute for the element will contain a path to an X.509 certificate credential directory to be passed along to the hypervisor to process.
I'm in two minds as to whether we want to add this feature to the XML. As a point of reference, we don't permit configuration of this for the VNC / SPICE graphics. In those cases we've defined cert locations in the qemu.conf file only. I tend to thing that's probably what we should do for chardevs, nbd and migration too. Providing certificates to a host is typically something that you would do when first provisioning the host. As such you'll almost certainly have a single set of certs you'll use for all VMs on a given host. It is an interesting question as to whether you'll use the same set of certs for VNC, chardev, migration and nbd, or whether each service will want separate certs. I can see value in both really - particularly if some of the services are exposed publically (vnc, chardev) while others are only exposed internally in a mgmt lan (migration, nbd). I'd suggest we add chardev_tls_x509_cert_dir migration_tls_x509_cert_dir nbd_tls_x509_cert_dir to let them be configured independantly, but *also* add a default_tls_x509_cert_dir if a service specific cert dir config opt is not set, then honour the default cert dir config opt. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 06/14/2016 05:39 AM, Daniel P. Berrange wrote:
On Mon, Jun 13, 2016 at 08:40:26PM -0400, John Ferlan wrote:
Add the domain rng, parse, and format of a new XML element "tlsx509":
<tlsx509 path='/tmp/x509/certdir'/>
The attribute for the element will contain a path to an X.509 certificate credential directory to be passed along to the hypervisor to process.
I'm in two minds as to whether we want to add this feature to the XML.
As a point of reference, we don't permit configuration of this for the VNC / SPICE graphics. In those cases we've defined cert locations in the qemu.conf file only.
I tend to thing that's probably what we should do for chardevs, nbd and migration too. Providing certificates to a host is typically something that you would do when first provisioning the host. As such you'll almost certainly have a single set of certs you'll use for all VMs on a given host.
It is an interesting question as to whether you'll use the same set of certs for VNC, chardev, migration and nbd, or whether each service will want separate certs. I can see value in both really - particularly if some of the services are exposed publically (vnc, chardev) while others are only exposed internally in a mgmt lan (migration, nbd).
I'd suggest we add
chardev_tls_x509_cert_dir migration_tls_x509_cert_dir nbd_tls_x509_cert_dir
to let them be configured independantly, but *also* add a
default_tls_x509_cert_dir
if a service specific cert dir config opt is not set, then honour the default cert dir config opt.
OK - this is certainly an area where I don't have a lot of experience/insight. My assumption on these bzs was that it could be possible for different domains on the host to use different certificate environments based on what they were being used for. Going the route of qemu.conf file just leads down the path of a singular use/definition per host. Thanks for the quick review feedback - it certainly helps! John

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. Since this is providing a new file which the domain will need to read, make the appropriate security backend adjustments to add the path to the TLS credential directory. xxx?? Do we need to add this to the private structure to recreate? xxxx Finally add the tests for the qemu command line Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/conf/domain_audit.c | 2 + src/conf/virchrdev.c | 1 + src/qemu/qemu_command.c | 72 ++++++++++++++++++++++ src/security/security_dac.c | 11 +++- src/security/security_selinux.c | 10 +++ src/security/virt-aa-helper.c | 12 +++- .../qemuxml2argv-serial-tcp-tlsx509-chardev.args | 32 ++++++++++ tests/qemuxml2argvtest.c | 3 + 8 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 36a3cf6..78bc092 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -85,6 +85,8 @@ virDomainAuditChardevPath(virDomainChrSourceDefPtr chr) return chr->data.nix.path; case VIR_DOMAIN_CHR_TYPE_TCP: + return chr->data.tcp.tlspath; + case VIR_DOMAIN_CHR_TYPE_UDP: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: diff --git a/src/conf/virchrdev.c b/src/conf/virchrdev.c index bca9c37..93bc57f 100644 --- a/src/conf/virchrdev.c +++ b/src/conf/virchrdev.c @@ -360,6 +360,7 @@ int virChrdevOpen(virChrdevsPtr devs, case VIR_DOMAIN_CHR_TYPE_UNIX: path = source->data.nix.path; break; + /* Do I have to do anything for VIR_DOMAIN_CHR_TYPE_TCP: */ default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported device type '%s'"), diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 490260f..3656683 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -701,6 +701,58 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf, } +/* qemuBuildTLSx509BackendProps: + * @tlspath: path to the TLS credentials + * @listen: boolen listen for client or server setting + * @alias: Alias for the parent (this code will add a "_tls0" to alias) + * @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, + const char *inalias, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *propsret) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + char *path = NULL; + char *alias = NULL; + int ret = -1; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("tls-creds not supported in this QEMU binary")); + return -1; + } + + qemuBufferEscapeComma(&buf, tlspath); + if (virBufferCheckError(&buf) < 0) + goto cleanup; + path = virBufferContentAndReset(&buf); + + if (virAsprintf(&alias, "obj%s_tls0", inalias) < 0) + goto cleanup; + + if (virJSONValueObjectCreate(propsret, + "s:dir", path, + "s:endpoint", (listen ? "server": "client"), + NULL) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virBufferFreeAndReset(&buf); + VIR_FREE(path); + VIR_FREE(alias); + return ret; +} + + #define QEMU_DEFAULT_NBD_PORT "10809" static char * @@ -4657,6 +4709,7 @@ qemuBuildChrChardevFileStr(virLogManagerPtr logManager, return 0; } + /* This function outputs a -chardev command line option which describes only the * host side of the character device */ static char * @@ -4668,6 +4721,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, virQEMUCapsPtr qemuCaps) { virBuffer buf = VIR_BUFFER_INITIALIZER; + virJSONValuePtr props = NULL; bool telnet; switch (dev->type) { @@ -4744,6 +4798,23 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, dev->data.tcp.service, telnet ? ",telnet" : "", dev->data.tcp.listen ? ",server,nowait" : ""); + + if (dev->data.tcp.tlspath) { + char *tmp; + if (qemuBuildTLSx509BackendStr(dev->data.tcp.tlspath, + dev->data.tcp.listen, + alias, qemuCaps, &props) < 0) + goto error; + + if (!(tmp = virQEMUBuildObjectCommandlineFromJSON("tls-creds-x509", + alias, props))) + goto error; + + virCommandAddArgList(cmd, "-object", tmp, NULL); + VIR_FREE(tmp); + + virBufferAsprintf(&buf, ",tls-creds=obj%s_tls0", alias); + } break; case VIR_DOMAIN_CHR_TYPE_UNIX: @@ -4799,6 +4870,7 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, error: virBufferFreeAndReset(&buf); + virJSONValueFree(props); return NULL; } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 442ce70..a2c971b 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -881,13 +881,22 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr, ret = 0; break; + case VIR_DOMAIN_CHR_TYPE_TCP: + if (!dev_source->data.nix.listen && dev_source->data.tcp.tlspath) { + if (virSecurityDACSetOwnership(priv, NULL, + dev_source->data.tcp.tlspath, + user, group) < 0) + goto done; + } + ret = 0; + break; + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_PTY: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_UDP: - case VIR_DOMAIN_CHR_TYPE_TCP: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: case VIR_DOMAIN_CHR_TYPE_NMDM: case VIR_DOMAIN_CHR_TYPE_LAST: diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index aa61767..1793a76 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1831,6 +1831,16 @@ virSecuritySELinuxSetChardevLabel(virSecurityManagerPtr mgr, ret = 0; break; + case VIR_DOMAIN_CHR_TYPE_TCP: + if (!dev_source->data.nix.listen && dev_source->data.tcp.tlspath) { + if (virSecuritySELinuxSetFilecon(mgr, + dev_source->data.tcp.tlspath, + imagelabel) < 0) + goto done; + } + ret = 0; + break; + case VIR_DOMAIN_CHR_TYPE_PIPE: if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) || (virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0)) diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 9eafaee..200e5ed 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -924,7 +924,7 @@ get_files(vahControl * ctl) goto cleanup; } - for (i = 0; i < ctl->def->nserials; i++) + for (i = 0; i < ctl->def->nserials; i++) { if (ctl->def->serials[i] && (ctl->def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY || ctl->def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV || @@ -938,6 +938,16 @@ get_files(vahControl * ctl) "rw", ctl->def->serials[i]->source.type) != 0) goto cleanup; + if (ctl->def->serials[i] && + ctl->def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_TCP && + ctl->def->serials[i]->source.data.tcp.tlspath && + ctl->def->serials[i]->source.data.tcp.tlspath[0] != '\0') + if (vah_add_file_chardev(&buf, + ctl->def->serials[i]->source.data.tcp.tlspath, + "rw", + ctl->def->serials[i]->source.type) != 0) + goto cleanup; + } for (i = 0; i < ctl->def->nconsoles; i++) if (ctl->def->consoles[i] && 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..83841f1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.args @@ -0,0 +1,32 @@ +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=/tmp/x509/certdir,endpoint=client \ +-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 573162f..55c58a9 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1069,6 +1069,9 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("serial-tcp-telnet-chardev", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); + DO_TEST("serial-tcp-tlsx509-chardev", + QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_OBJECT_TLS_CREDS_X509); DO_TEST("serial-many-chardev", QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("parallel-tcp-chardev", -- 2.5.5

If the incoming XML defined a path to a TLS X.509 certificate environment, add the necessary 'tls-creds-x509' object to the VIR_DOMAIN_CHR_TYPE_TCP character device. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/qemu/qemu_command.c | 69 +++++++++++++++++++++++++++++++------------- src/qemu/qemu_command.h | 6 ++++ src/qemu/qemu_hotplug.c | 27 ++++++++++++++++- src/qemu/qemu_monitor_json.c | 9 ++++++ 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3656683..c3e17cf 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -704,23 +704,21 @@ qemuBuildRBDSecinfoURI(virBufferPtr buf, /* qemuBuildTLSx509BackendProps: * @tlspath: path to the TLS credentials * @listen: boolen listen for client or server setting - * @alias: Alias for the parent (this code will add a "_tls0" to alias) + * @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 +int qemuBuildTLSx509BackendProps(const char *tlspath, bool listen, - const char *inalias, virQEMUCapsPtr qemuCaps, virJSONValuePtr *propsret) { virBuffer buf = VIR_BUFFER_INITIALIZER; char *path = NULL; - char *alias = NULL; int ret = -1; if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { @@ -734,9 +732,6 @@ qemuBuildTLSx509BackendProps(const char *tlspath, goto cleanup; path = virBufferContentAndReset(&buf); - if (virAsprintf(&alias, "obj%s_tls0", inalias) < 0) - goto cleanup; - if (virJSONValueObjectCreate(propsret, "s:dir", path, "s:endpoint", (listen ? "server": "client"), @@ -748,7 +743,51 @@ qemuBuildTLSx509BackendProps(const char *tlspath, 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 + * @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, + const char *inalias, + virQEMUCapsPtr qemuCaps) +{ + int ret = -1; + char *alias = NULL; + virJSONValuePtr props = NULL; + char *tmp = NULL; + + if (qemuBuildTLSx509BackendProps(tlspath, listen, 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; } @@ -4721,7 +4760,6 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, virQEMUCapsPtr qemuCaps) { virBuffer buf = VIR_BUFFER_INITIALIZER; - virJSONValuePtr props = NULL; bool telnet; switch (dev->type) { @@ -4800,19 +4838,11 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, dev->data.tcp.listen ? ",server,nowait" : ""); if (dev->data.tcp.tlspath) { - char *tmp; - if (qemuBuildTLSx509BackendStr(dev->data.tcp.tlspath, - dev->data.tcp.listen, - alias, qemuCaps, &props) < 0) + if (qemuBuildTLSx509CommandLine(cmd, dev->data.tcp.tlspath, + dev->data.tcp.listen, + alias, qemuCaps) < 0) goto error; - if (!(tmp = virQEMUBuildObjectCommandlineFromJSON("tls-creds-x509", - alias, props))) - goto error; - - virCommandAddArgList(cmd, "-object", tmp, NULL); - VIR_FREE(tmp); - virBufferAsprintf(&buf, ",tls-creds=obj%s_tls0", alias); } break; @@ -4870,7 +4900,6 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager, error: virBufferFreeAndReset(&buf); - virJSONValueFree(props); return NULL; } diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index f0ffe21..ea5c728 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -61,6 +61,12 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver, const char *domainLibDir) ATTRIBUTE_NONNULL(15); +/* Generate the object properties for a tls-creds-x509 */ +int qemuBuildTLSx509BackendProps(const char *tlspath, + bool listen, + virQEMUCapsPtr qemuCaps, + virJSONValuePtr *propsret); + /* Generate '-device' string for chardev device */ int qemuBuildChrDeviceStr(char **deviceStr, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 7d05073..c9e9d3b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1499,7 +1499,10 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv = vm->privateData; virDomainDefPtr vmdef = vm->def; char *devstr = NULL; + virDomainChrSourceDefPtr dev = &chr->source; char *charAlias = NULL; + virJSONValuePtr props = NULL; + char *objAlias = NULL; bool need_release = false; if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL && @@ -1523,8 +1526,25 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, if (qemuDomainChrPreInsert(vmdef, chr) < 0) goto cleanup; + if (dev->data.tcp.tlspath) { + + if (qemuBuildTLSx509BackendProps(dev->data.tcp.tlspath, + dev->data.tcp.listen, + priv->qemuCaps, + &props) < 0) + goto cleanup; + + if (virAsprintf(&objAlias, "obj%s_tls0", chr->info.alias) < 0) + goto cleanup; + } + qemuDomainObjEnterMonitor(driver, vm); - if (qemuMonitorAttachCharDev(priv->mon, charAlias, &chr->source) < 0) + + if (objAlias && qemuMonitorAddObject(priv->mon, "tls-creds-x509", + objAlias, props) < 0) + goto failobject; + + if (qemuMonitorAttachCharDev(priv->mon, charAlias, dev) < 0) goto failchardev; if (qemuMonitorAddDevice(priv->mon, devstr) < 0) @@ -1542,6 +1562,8 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, qemuDomainChrInsertPreAllocCleanup(vm->def, chr); if (ret < 0 && need_release) qemuDomainReleaseDeviceAddress(vm, &chr->info, NULL); + VIR_FREE(objAlias); + virJSONValueFree(props); VIR_FREE(charAlias); VIR_FREE(devstr); return ret; @@ -1550,6 +1572,9 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, /* detach associated chardev on error */ qemuMonitorDetachCharDev(priv->mon, charAlias); failchardev: + /* Remove the object */ + ignore_value(qemuMonitorDelObject(priv->mon, objAlias)); + failobject: ignore_value(qemuDomainObjExitMonitor(driver, vm)); goto audit; } diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 380ddab..81e89cc 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6137,6 +6137,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, virJSONValuePtr data = NULL; virJSONValuePtr addr = NULL; const char *backend_type = NULL; + char *tlsalias = NULL; bool telnet; if (!(backend = virJSONValueNewObject()) || @@ -6182,6 +6183,13 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 || virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0) goto error; + if (chr->data.tcp.tlspath) { + if (virAsprintf(&tlsalias, "obj%s_tls0", chrID) < 0) + goto error; + + if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0) + goto error; + } break; case VIR_DOMAIN_CHR_TYPE_UDP: @@ -6247,6 +6255,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, return ret; error: + VIR_FREE(tlsalias); virJSONValueFree(addr); virJSONValueFree(data); virJSONValueFree(backend); -- 2.5.5
participants (2)
-
Daniel P. Berrange
-
John Ferlan