[libvirt] [PATCH v2 0/4] qemu: Allow setting sslverify option

This is a rebased version now that the <cookie> support was postponed. Peter Krempa (4): qemu: capabilities: Add capability for the sslverify curl driver option conf: Use only one temporary string in virDomainDiskSourceParse conf: Add support for modifying ssl validation for https/ftps disks qemu: command: Implement ssl verification configuration docs/formatdomain.html.in | 9 ++++ docs/schemas/domaincommon.rng | 47 ++++++++++++++++++- src/conf/domain_conf.c | 34 +++++++++++--- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 22 +++++++-- src/util/virstoragefile.h | 1 + .../generic-disk-network-http.xml | 9 ++++ tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + .../qemuxml2argv-disk-drive-network-http.args | 37 +++++++++++++++ .../qemuxml2argv-disk-drive-network-http.xml | 52 ++++++++++++++++++++++ 11 files changed, 202 insertions(+), 13 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.xml -- 2.12.2

The option allows setting verifiaction of the SSL certificate for HTTPS and FTPS based disks. --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + 3 files changed, 4 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d34790768..2536ac09d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -365,6 +365,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "block-write-threshold", "query-named-block-nodes", "cpu-cache", + "block-curl-sslverify", ); @@ -1719,6 +1720,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsUSBNECXHCI[] = { static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = { { "blockdev-add/arg-type/options/+gluster/debug-level", QEMU_CAPS_GLUSTER_DEBUG_LEVEL}, { "blockdev-add/arg-type/+gluster/debug", QEMU_CAPS_GLUSTER_DEBUG_LEVEL}, + { "blockdev-add/arg-type/+https/sslverify", QEMU_CAPS_BLOCK_CURL_SSLVERIFY}, }; struct virQEMUCapsObjectTypeProps { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 47649c945..c582f765c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -402,6 +402,7 @@ typedef enum { QEMU_CAPS_BLOCK_WRITE_THRESHOLD, /* BLOCK_WRITE_THRESHOLD event */ QEMU_CAPS_QUERY_NAMED_BLOCK_NODES, /* qmp query-named-block-nodes */ QEMU_CAPS_CPU_CACHE, /* -cpu supports host-cache-info and l3-cache properties */ + QEMU_CAPS_BLOCK_CURL_SSLVERIFY, /* sslverify and other curl driver options */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index fccb469fe..d56893d87 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -209,6 +209,7 @@ <flag name='block-write-threshold'/> <flag name='query-named-block-nodes'/> <flag name='cpu-cache'/> + <flag name='block-curl-sslverify'/> <version>2009000</version> <kvmVersion>0</kvmVersion> <package> (v2.9.0)</package> -- 2.12.2

On Fri, Apr 28, 2017 at 01:10:24PM +0200, Peter Krempa wrote:
The option allows setting verifiaction of the SSL certificate for HTTPS
verification Jan
and FTPS based disks. --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 + 3 files changed, 4 insertions(+)

--- src/conf/domain_conf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5a736c853..c40a5a7a6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7526,7 +7526,7 @@ virDomainDiskSourceParse(xmlNodePtr node, virStorageSourcePtr src) { int ret = -1; - char *protocol = NULL; + char *tmp = NULL; xmlNodePtr saveNode = ctxt->node; ctxt->node = node; @@ -7542,17 +7542,18 @@ virDomainDiskSourceParse(xmlNodePtr node, src->path = virXMLPropString(node, "dir"); break; case VIR_STORAGE_TYPE_NETWORK: - if (!(protocol = virXMLPropString(node, "protocol"))) { + if (!(tmp = virXMLPropString(node, "protocol"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("missing network source protocol type")); goto cleanup; } - if ((src->protocol = virStorageNetProtocolTypeFromString(protocol)) <= 0) { + if ((src->protocol = virStorageNetProtocolTypeFromString(tmp)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown protocol type '%s'"), protocol); + _("unknown protocol type '%s'"), tmp); goto cleanup; } + VIR_FREE(tmp); if (!(src->path = virXMLPropString(node, "name")) && src->protocol != VIR_STORAGE_NET_PROTOCOL_NBD) { @@ -7565,7 +7566,6 @@ virDomainDiskSourceParse(xmlNodePtr node, * as a part of the path. This is hard to work with when dealing with * relative names. Split out the volume into a separate variable */ if (src->path && src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) { - char *tmp; if (!(tmp = strchr(src->path, '/')) || tmp == src->path) { virReportError(VIR_ERR_XML_ERROR, @@ -7580,6 +7580,7 @@ virDomainDiskSourceParse(xmlNodePtr node, goto cleanup; tmp[0] = '\0'; + tmp = NULL; } /* snapshot currently works only for remote disks */ @@ -7612,7 +7613,7 @@ virDomainDiskSourceParse(xmlNodePtr node, ret = 0; cleanup: - VIR_FREE(protocol); + VIR_FREE(tmp); ctxt->node = saveNode; return ret; } -- 2.12.2

On Fri, Apr 28, 2017 at 01:10:25PM +0200, Peter Krempa wrote:
--- src/conf/domain_conf.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
@@ -7565,7 +7566,6 @@ virDomainDiskSourceParse(xmlNodePtr node, * as a part of the path. This is hard to work with when dealing with * relative names. Split out the volume into a separate variable */ if (src->path && src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) { - char *tmp;
This is not a temporary string, just a pointer into a different string and should not be mixed up with the virXMLPropString usage. (Maybe this code would look nicer with virStringSplit?) Jan
if (!(tmp = strchr(src->path, '/')) || tmp == src->path) { virReportError(VIR_ERR_XML_ERROR,

To allow turning of verification of SSL cerificates add a new element <ssl> to the disk source XML which will allow configuring the validation process using the 'verify' attribute. --- docs/formatdomain.html.in | 9 +++++ docs/schemas/domaincommon.rng | 47 +++++++++++++++++++++- src/conf/domain_conf.c | 21 +++++++++- src/util/virstoragefile.h | 1 + .../generic-disk-network-http.xml | 9 +++++ 5 files changed, 84 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 03961fb4b..f3bf63d6c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2288,6 +2288,7 @@ <driver name='qemu' type='raw'/> <source protocol="https" name="url_path"> <host name="hostname" port="443"/> + <ssl verify="no"/> </source> <target dev='hdf' bus='ide' tray='open'/> <readonly/> @@ -2628,6 +2629,14 @@ protocol. Supported for 'rbd' <span class="since">since 1.2.11 (QEMU only).</span> </dd> + <dt><code>ssl</code></dt> + <dd> + For <code>https</code> and <code>ftps</code> accessed storage it's + possible to tweak the SSL transport parameters with this element. + The <code>verify</code> attribute allows to turn on or of SSL + certificate validation. Supported values are <code>yes</code> and + <code>no</code>. <span class="since">Since 3.3.0</span> + </dd> </dl> <p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 6367c059c..ef09fa831 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1556,12 +1556,37 @@ </element> </define> + <define name="diskSourceNetworkProtocolSSLVerify"> + <element name="ssl"> + <attribute name="verify"> + <ref name="virYesNo"/> + </attribute> + <empty/> + </element> + </define> + + <define name="diskSourceNetworkProtocolHTTPS"> + <element name="source"> + <interleave> + <attribute name="protocol"> + <choice> + <value>https</value> + </choice> + </attribute> + <attribute name="name"/> + <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="diskSourceNetworkProtocolSSLVerify"/> + </optional> + </interleave> + </element> + </define> + <define name="diskSourceNetworkProtocolHTTP"> <element name="source"> <attribute name="protocol"> <choice> <value>http</value> - <value>https</value> </choice> </attribute> <attribute name="name"/> @@ -1569,6 +1594,23 @@ </element> </define> + <define name="diskSourceNetworkProtocolFTPS"> + <element name="source"> + <interleave> + <attribute name="protocol"> + <choice> + <value>ftps</value> + </choice> + </attribute> + <attribute name="name"/> + <ref name="diskSourceNetworkHost"/> + <optional> + <ref name="diskSourceNetworkProtocolSSLVerify"/> + </optional> + </interleave> + </element> + </define> + <define name="diskSourceNetworkProtocolSimple"> <element name="source"> <attribute name="protocol"> @@ -1576,7 +1618,6 @@ <value>sheepdog</value> <value>iscsi</value> <value>ftp</value> - <value>ftps</value> <value>tftp</value> </choice> </attribute> @@ -1622,6 +1663,8 @@ <ref name="diskSourceNetworkProtocolGluster"/> <ref name="diskSourceNetworkProtocolRBD"/> <ref name="diskSourceNetworkProtocolHTTP"/> + <ref name="diskSourceNetworkProtocolHTTPS"/> + <ref name="diskSourceNetworkProtocolFTPS"/> <ref name="diskSourceNetworkProtocolSimple"/> </choice> </define> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index c40a5a7a6..ec45d89b7 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7591,6 +7591,20 @@ virDomainDiskSourceParse(xmlNodePtr node, if (virDomainStorageHostParse(node, &src->hosts, &src->nhosts) < 0) goto cleanup; + + if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS || + src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS) && + (tmp = virXPathString("string(./ssl/@verify)", ctxt))) { + int verify; + if ((verify = virTristateBoolTypeFromString(tmp)) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid ssl verify mode '%s'"), tmp); + goto cleanup; + } + VIR_FREE(tmp); + + src->sslverify = verify; + } break; case VIR_STORAGE_TYPE_VOLUME: if (virDomainDiskSourcePoolDefParse(node, &src->srcpool) < 0) @@ -20788,7 +20802,8 @@ virDomainDiskSourceFormatNetwork(virBufferPtr buf, VIR_FREE(path); - if (src->nhosts == 0 && !src->snapshot && !src->configFile) { + if (src->nhosts == 0 && !src->snapshot && !src->configFile && + src->sslverify == VIR_TRISTATE_BOOL_ABSENT) { virBufferAddLit(buf, "/>\n"); } else { virBufferAddLit(buf, ">\n"); @@ -20810,6 +20825,10 @@ virDomainDiskSourceFormatNetwork(virBufferPtr buf, virBufferEscapeString(buf, "<snapshot name='%s'/>\n", src->snapshot); virBufferEscapeString(buf, "<config file='%s'/>\n", src->configFile); + if (src->sslverify != VIR_TRISTATE_BOOL_ABSENT) + virBufferAsprintf(buf, "<ssl verify='%s'/>\n", + virTristateBoolTypeToString(src->sslverify)); + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</source>\n"); } diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 9ebfc1108..e995b97fe 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -238,6 +238,7 @@ struct _virStorageSource { virStorageSourcePoolDefPtr srcpool; virStorageAuthDefPtr auth; virStorageEncryptionPtr encryption; + virTristateBool sslverify; char *driverName; int format; /* virStorageFileFormat in domain backing chains, but diff --git a/tests/genericxml2xmlindata/generic-disk-network-http.xml b/tests/genericxml2xmlindata/generic-disk-network-http.xml index 51c779502..2448af727 100644 --- a/tests/genericxml2xmlindata/generic-disk-network-http.xml +++ b/tests/genericxml2xmlindata/generic-disk-network-http.xml @@ -25,6 +25,7 @@ <driver name='qemu' type='raw'/> <source protocol='https' name='test2.img'> <host name='example.org'/> + <ssl verify='no'/> </source> <target dev='vdb' bus='virtio'/> </disk> @@ -35,6 +36,14 @@ </source> <target dev='vdc' bus='virtio'/> </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='https' name='test4.img'> + <host name='example.org' port='1234'/> + <ssl verify='yes'/> + </source> + <target dev='vdd' bus='virtio'/> + </disk> <controller type='usb' index='0'/> <controller type='pci' index='0' model='pci-root'/> <input type='mouse' bus='ps2'/> -- 2.12.2

On Fri, Apr 28, 2017 at 01:10:26PM +0200, Peter Krempa wrote:
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 03961fb4b..f3bf63d6c 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2288,6 +2288,7 @@ <driver name='qemu' type='raw'/> <source protocol="https" name="url_path"> <host name="hostname" port="443"/> + <ssl verify="no"/> </source> <target dev='hdf' bus='ide' tray='open'/> <readonly/> @@ -2628,6 +2629,14 @@ protocol. Supported for 'rbd' <span class="since">since 1.2.11 (QEMU only).</span> </dd> + <dt><code>ssl</code></dt> + <dd> + For <code>https</code> and <code>ftps</code> accessed storage it's + possible to tweak the SSL transport parameters with this element. + The <code>verify</code> attribute allows to turn on or of SSL
on or off
+ certificate validation. Supported values are <code>yes</code> and + <code>no</code>. <span class="since">Since 3.3.0</span>
3.4.0 Jan

Allow disabling of SSL certificate validation for HTTPS and FTPS drives in qemu. --- src/qemu/qemu_command.c | 22 +++++++-- .../qemuxml2argv-disk-drive-network-http.args | 37 +++++++++++++++ .../qemuxml2argv-disk-drive-network-http.xml | 52 ++++++++++++++++++++++ 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.xml diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 196716a6f..2c4704aa6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1528,10 +1528,24 @@ qemuBuildDriveSourceStr(virDomainDiskDefPtr disk, } virBufferAddLit(buf, ","); - if (disk->src->type == VIR_STORAGE_TYPE_NETWORK && - disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) { - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_GLUSTER_DEBUG_LEVEL)) - virBufferAsprintf(buf, "file.debug=%d,", cfg->glusterDebugLevel); + if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { + if ((disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS || + disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS) && + disk->src->sslverify != VIR_TRISTATE_BOOL_ABSENT) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCK_CURL_SSLVERIFY)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("can't set SSL verification for https/ftps disks")); + goto cleanup; + } + + virBufferAsprintf(buf, "file.sslverify=%s,", + virTristateSwitchTypeToString(disk->src->sslverify)); + } + + if (disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER) { + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_GLUSTER_DEBUG_LEVEL)) + virBufferAsprintf(buf, "file.debug=%d,", cfg->glusterDebugLevel); + } } if (secinfo && secinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.args new file mode 100644 index 000000000..e1bfd42a8 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.args @@ -0,0 +1,37 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-i686 \ +-name QEMUGuest1 \ +-S \ +-M pc \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-usb \ +-drive file=http://example.org:80/test.img,format=raw,if=none,\ +id=drive-virtio-disk0 \ +-device virtio-blk-pci,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,\ +id=virtio-disk0 \ +-drive file=https://example.org:443/test2.img,format=raw,if=none,\ +id=drive-virtio-disk1 \ +-device virtio-blk-pci,bus=pci.0,addr=0x4,drive=drive-virtio-disk1,\ +id=virtio-disk1 \ +-drive 'file=http://example.org:1234/test3.img,\ +file.cookie=test=testcookievalue; test2=blurb,format=raw,if=none,\ +id=drive-virtio-disk2' \ +-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk2,\ +id=virtio-disk2 \ +-drive 'file=https://example.org:1234/test4.img,file.sslverify=off,\ +file.cookie=test=testcookievalue; test2=blurb,format=raw,if=none,\ +id=drive-virtio-disk3' \ +-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk3,\ +id=virtio-disk3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.xml new file mode 100644 index 000000000..50bd6a0e0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-network-http.xml @@ -0,0 +1,52 @@ +<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-system-i686</emulator> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='http' name='test.img'> + <host name='example.org'/> + </source> + <target dev='vda' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='https' name='test2.img'> + <host name='example.org'/> + </source> + <target dev='vdb' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='http' name='test3.img'> + <host name='example.org' port='1234'/> + </source> + <target dev='vdc' bus='virtio'/> + </disk> + <disk type='network' device='disk'> + <driver name='qemu' type='raw'/> + <source protocol='https' name='test4.img'> + <host name='example.org' port='1234'/> + <ssl verify='no'/> + </source> + <target dev='vdd' bus='virtio'/> + </disk> + <controller type='usb' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> -- 2.12.2
participants (2)
-
Ján Tomko
-
Peter Krempa