From b0ef5c53675eeab65b9962c3b7f17d332148d173 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 9 Apr 2010 17:56:00 +0100 Subject: [PATCH] Support SPICE channel security options This extends the SPICE XML to allow channel security options Any non-specified channel uses the default, which allows both secure & insecure usage * src/conf/domain_conf.c, src/conf/domain_conf.h, src/libvirt_private.syms: Add XML syntax for specifying per channel security options for spice. * src/qemu/qemu_conf.c: Configure channel security with spice --- docs/formatdomain.html.in | 15 ++++ docs/schemas/domain.rng | 21 ++++++ src/conf/domain_conf.c | 75 ++++++++++++++++++- src/conf/domain_conf.h | 21 ++++++ src/libvirt_private.syms | 4 + src/qemu/qemu_conf.c | 13 ++++ .../qemuxml2argv-graphics-spice.args | 2 +- .../qemuxml2argv-graphics-spice.xml | 5 +- 8 files changed, 153 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a4ff500e57..8db8b52b25 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1108,6 +1108,7 @@ qemu-kvm -net nic,model=? /dev/null
"spice"
+

Starts a SPICE server. The port attribute specifies the TCP port number (with -1 as legacy syntax indicating that it should be auto-allocated), while tlsPort gives an alternative @@ -1119,6 +1120,20 @@ qemu-kvm -net nic,model=? /dev/null to use. It is possible to set a limit on the validity of the password be giving an timestamp passwdValidTo='2010-04-09T15:51:00' assumed to be in UTC. NB, this may not be supported by all hypervisors. +

+

+ When SPICE has both a normal and TLS secured TCP port configured, it + can be desirable to restrict what channels can be run on each port. + This is achieved by adding one or more <channel> elements inside + the main <graphics> element. Valid channel names include + main,display,inputs,cursor, + playback,record. +

+
+  <graphics type='spice' port='-1' tlsPort='-1' autoport='yes'>
+    <channel name='main' mode='secure'/>
+    <channel name='record' mode='insecure'/>
+  </graphics>
"rdp"
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 7903000680..5b7ecc2a9f 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1093,6 +1093,27 @@ + + + + + main + display + inputs + cursor + playback + record + + + + + any + secure + insecure + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b9e4f4c6fd..655449c7f6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -271,6 +271,21 @@ VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST, "desktop", "spice") +VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST, + "main", + "display", + "inputs", + "cursor", + "playback", + "record"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST, + "any", + "secure", + "insecure"); + VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, "subsystem", "capabilities") @@ -3274,6 +3289,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { def->data.desktop.display = virXMLPropString(node, "display"); } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + xmlNodePtr cur; char *port = virXMLPropString(node, "port"); char *tlsPort; char *autoport; @@ -3318,6 +3334,40 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { def->data.spice.keymap = virXMLPropString(node, "keymap"); if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0) goto error; + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "channel")) { + const char *name, *mode; + int nameval, modeval; + name = virXMLPropString(cur, "name"); + mode = virXMLPropString(cur, "mode"); + + if (!name || !mode) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("spice channel missing name/mode")); + goto error; + } + + if ((nameval = virDomainGraphicsSpiceChannelNameTypeFromString(name)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice channel name %s"), + name); + goto error; + } + if ((modeval = virDomainGraphicsSpiceChannelModeTypeFromString(mode)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown spice channel mode %s"), + mode); + goto error; + } + + def->data.spice.channels[nameval] = modeval; + } + } + cur = cur->next; + } } cleanup: @@ -6572,6 +6622,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, int flags) { const char *type = virDomainGraphicsTypeToString(def->type); + int children = 0; + int i; if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -6673,7 +6725,28 @@ virDomainGraphicsDefFormat(virBufferPtr buf, } - virBufferAddLit(buf, "/>\n"); + if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { + for (i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) { + int mode = def->data.spice.channels[i]; + if (mode == VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY) + continue; + + if (!children) { + virBufferAddLit(buf, ">\n"); + children = 1; + } + + virBufferVSprintf(buf, " \n", + virDomainGraphicsSpiceChannelNameTypeToString(i), + virDomainGraphicsSpiceChannelModeTypeToString(mode)); + } + } + + if (children) { + virBufferAddLit(buf, " \n"); + } else { + virBufferAddLit(buf, "/>\n"); + } return 0; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d66aaa3232..7d2d6f5edc 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -525,6 +525,24 @@ struct _virDomainGraphicsAuthDef { time_t validTo; /* seconds since epoch */ }; +enum virDomainGraphicsSpiceChannelName { + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MAIN, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_DISPLAY, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_INPUT, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_CURSOR, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_PLAYBACK, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_RECORD, + + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST +}; + +enum virDomainGraphicsSpiceChannelMode { + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE, + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE, + + VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST +}; typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; @@ -561,6 +579,7 @@ struct _virDomainGraphicsDef { char *keymap; virDomainGraphicsAuthDef auth; unsigned int autoport :1; + int channels[VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST]; } spice; } data; }; @@ -1234,6 +1253,8 @@ VIR_ENUM_DECL(virDomainHostdevSubsys) VIR_ENUM_DECL(virDomainInput) VIR_ENUM_DECL(virDomainInputBus) VIR_ENUM_DECL(virDomainGraphics) +VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName) +VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainSeclabel) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8f267f6f2a..39eb6489bd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -204,6 +204,10 @@ virDomainFindByName; virDomainFindByUUID; virDomainGetRootFilesystem; virDomainGraphicsDefFree; +virDomainGraphicsSpiceChannelModeTypeFromString; +virDomainGraphicsSpiceChannelModeTypeToString; +virDomainGraphicsSpiceChannelNameTypeFromString; +virDomainGraphicsSpiceChannelNameTypeToString; virDomainGraphicsTypeFromString; virDomainGraphicsTypeToString; virDomainHostdevDefFree; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 32b486b012..9e6e162623 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -5177,6 +5177,19 @@ int qemudBuildCommandLine(virConnectPtr conn, virBufferVSprintf(&opt, ",x509-dir=%s", driver->spiceTLSx509certdir); + for (i = 0 ; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST ; i++) { + int mode = def->graphics[0]->data.spice.channels[i]; + switch (mode) { + case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_SECURE: + virBufferVSprintf(&opt, ",tls-channel=%s", + virDomainGraphicsSpiceChannelNameTypeToString(i)); + break; + case VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_INSECURE: + virBufferVSprintf(&opt, ",plaintext-channel=%s", + virDomainGraphicsSpiceChannelNameTypeToString(i)); + break; + } + } if (virBufferError(&opt)) goto no_memory; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args index 44809b040d..87b8c0646a 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,x509-dir=/etc/pki/libvirt-spice -vga qxl -device qxl,id=video1,bus=pci.0,addr=0x4 -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,tls-channel=main,plaintext-channel=inputs -vga qxl -device qxl,id=video1,bus=pci.0,addr=0x4 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml index 6fe9a60c06..bdce04b377 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml @@ -21,7 +21,10 @@ - + + + + -- GitLab