From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
We try to use that command first when setting a VNC/SPICE password. If
that doesn't work we fallback to the legacy VNC only password
Allow an expiry time to be set, if that doesn't work, throw an error
if they try to use SPICE.
Change since v1:
- moved qemuInitGraphicsPasswords to qemu_hotplug, renamed
to qemuDomainChangeGraphicsPasswords.
- updated what looks like a typo (that appears to work anyway) in
initial patch from Daniel:
- ret = qemuInitGraphicsPasswords(driver, vm,
- VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
- &vm->def->graphics[0]->data.vnc.auth,
- driver->vncPassword);
+ ret = qemuInitGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+
&vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
Based on patch by Daniel P. Berrange <berrange(a)redhat.com>.
---
src/qemu/qemu_driver.c | 22 +++++----
src/qemu/qemu_hotplug.c | 114 +++++++++++++++++++++++++++++++++++++++++++---
src/qemu/qemu_hotplug.h | 5 ++
3 files changed, 123 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e915705..2f1e741 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1999,16 +1999,18 @@ qemuInitPasswords(virConnectPtr conn,
int ret = 0;
qemuDomainObjPrivatePtr priv = vm->privateData;
- if ((vm->def->ngraphics == 1) &&
- vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
- (vm->def->graphics[0]->data.vnc.auth.passwd || driver->vncPassword))
{
-
- qemuDomainObjEnterMonitorWithDriver(driver, vm);
- ret = qemuMonitorSetVNCPassword(priv->mon,
-
vm->def->graphics[0]->data.vnc.auth.passwd ?
-
vm->def->graphics[0]->data.vnc.auth.passwd :
- driver->vncPassword);
- qemuDomainObjExitMonitorWithDriver(driver, vm);
+ if (vm->def->ngraphics == 1) {
+ if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_VNC,
+
&vm->def->graphics[0]->data.vnc.auth,
+ driver->vncPassword);
+ } else if (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE)
{
+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
+ VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+
&vm->def->graphics[0]->data.spice.auth,
+ driver->spicePassword);
+ }
}
if (ret < 0)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 827bcaf..d153c0d 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1038,7 +1038,6 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
virDomainGraphicsDefPtr dev)
{
virDomainGraphicsDefPtr olddev = qemuDomainFindGraphics(vm, dev);
- qemuDomainObjPrivatePtr priv = vm->privateData;
int ret = -1;
if (!olddev) {
@@ -1066,24 +1065,65 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
return -1;
}
- if (STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd,
dev->data.vnc.auth.passwd)) {
+ /* If a password lifetime was, or is set, then we must always run,
+ * even if new password matches old password */
+ if (olddev->data.vnc.auth.expires ||
+ dev->data.vnc.auth.expires ||
+ STRNEQ_NULLABLE(olddev->data.vnc.auth.passwd,
dev->data.vnc.auth.passwd)) {
VIR_DEBUG("Updating password on VNC server %p %p",
dev->data.vnc.auth.passwd, driver->vncPassword);
- qemuDomainObjEnterMonitorWithDriver(driver, vm);
- ret = qemuMonitorSetVNCPassword(priv->mon,
- dev->data.vnc.auth.passwd ?
- dev->data.vnc.auth.passwd :
- driver->vncPassword);
- qemuDomainObjExitMonitorWithDriver(driver, vm);
+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
VIR_DOMAIN_GRAPHICS_TYPE_VNC,
+ &dev->data.vnc.auth,
driver->vncPassword);
/* Steal the new dev's char * reference */
VIR_FREE(olddev->data.vnc.auth.passwd);
olddev->data.vnc.auth.passwd = dev->data.vnc.auth.passwd;
dev->data.vnc.auth.passwd = NULL;
+ olddev->data.vnc.auth.validTo = dev->data.vnc.auth.validTo;
+ olddev->data.vnc.auth.expires = dev->data.vnc.auth.expires;
} else {
ret = 0;
}
break;
+ case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
+ if ((olddev->data.spice.autoport != dev->data.spice.autoport) ||
+ (!dev->data.spice.autoport && (olddev->data.spice.port !=
dev->data.spice.port)) ||
+ (!dev->data.spice.autoport && (olddev->data.spice.tlsPort !=
dev->data.spice.tlsPort))) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot change port settings on spice
graphics"));
+ return -1;
+ }
+ if (STRNEQ_NULLABLE(olddev->data.spice.listenAddr,
dev->data.spice.listenAddr)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot change listen address setting on spice
graphics"));
+ return -1;
+ }
+ if (STRNEQ_NULLABLE(olddev->data.spice.keymap, dev->data.spice.keymap)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot change keymap setting on spice
graphics"));
+ return -1;
+ }
+
+ /* If a password lifetime was, or is set, then we must always run,
+ * even if new password matches old password */
+ if (olddev->data.spice.auth.expires ||
+ dev->data.spice.auth.expires ||
+ STRNEQ_NULLABLE(olddev->data.spice.auth.passwd,
dev->data.spice.auth.passwd)) {
+ VIR_DEBUG("Updating password on SPICE server %p %p",
dev->data.spice.auth.passwd, driver->spicePassword);
+ ret = qemuDomainChangeGraphicsPasswords(driver, vm,
VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+ &dev->data.spice.auth,
driver->spicePassword);
+
+ /* Steal the new dev's char * reference */
+ VIR_FREE(olddev->data.spice.auth.passwd);
+ olddev->data.spice.auth.passwd = dev->data.spice.auth.passwd;
+ dev->data.spice.auth.passwd = NULL;
+ olddev->data.spice.auth.validTo = dev->data.spice.auth.validTo;
+ olddev->data.spice.auth.expires = dev->data.spice.auth.expires;
+ } else {
+ VIR_DEBUG0("Not updating since password didn't change");
+ ret = 0;
+ }
+
default:
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to change config on '%s' graphics
type"),
@@ -1707,3 +1747,61 @@ int qemuDomainDetachHostDevice(struct qemud_driver *driver,
return ret;
}
+
+int
+qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ int type,
+ virDomainGraphicsAuthDefPtr auth,
+ const char *defaultPasswd)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ time_t now = time(NULL);
+ char expire_time [64];
+ int ret;
+
+ if (!auth->passwd && !driver->vncPassword)
+ return 0;
+
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ ret = qemuMonitorSetPassword(priv->mon,
+ type,
+ auth->passwd ? auth->passwd : defaultPasswd,
+ NULL);
+
+ if (ret == -2) {
+ if (type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Only VNC graphics are supported"));
+ ret = -1;
+ } else {
+ ret = qemuMonitorSetVNCPassword(priv->mon,
+ auth->passwd ? auth->passwd :
defaultPasswd);
+ }
+ }
+
+ if (auth->expires) {
+ time_t lifetime = auth->validTo - now;
+ if (lifetime <= 0)
+ snprintf(expire_time, sizeof (expire_time), "now");
+ else
+ snprintf(expire_time, sizeof (expire_time), "%lu", (long
unsigned)auth->validTo);
+ } else {
+ snprintf(expire_time, sizeof (expire_time), "never");
+ }
+
+ ret = qemuMonitorExpirePassword(priv->mon, type, expire_time);
+
+ if (ret == -2) {
+ /* XXX we could fake this with a timer */
+ if (auth->expires) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Expiry of passwords is not supported"));
+ ret = -1;
+ }
+ }
+
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 0e7ca8e..217785d 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -70,6 +70,11 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver,
int qemuDomainChangeGraphics(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainGraphicsDefPtr dev);
+int qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
+ virDomainObjPtr vm,
+ int type,
+ virDomainGraphicsAuthDefPtr auth,
+ const char *defaultPasswd);
int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev,
--
1.7.3.4