[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/2] qemu: Update password support in the QEMU driver



From: Marc-André Lureau <marcandre lureau redhat com>

Use the new set_password and expire_password monitor commands
to set password.

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.

Based on patch by Daniel P. Berrange <berrange redhat com>.
---
 src/qemu/qemu_driver.c |  138 +++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 120 insertions(+), 18 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4877692..b4017af 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2516,6 +2516,65 @@ qemudInitCpuAffinity(virDomainObjPtr vm)
 
 
 static int
+qemuInitGraphicsPasswords(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;
+}
+
+
+static int
 qemuInitPasswords(virConnectPtr conn,
                   struct qemud_driver *driver,
                   virDomainObjPtr vm,
@@ -2523,16 +2582,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 = qemuInitGraphicsPasswords(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 = qemuInitGraphicsPasswords(driver, vm,
+                                            VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
+                                            &vm->def->graphics[0]->data.vnc.auth,
+                                            driver->vncPassword);
+        }
     }
 
     if (ret < 0)
@@ -8922,7 +8983,6 @@ qemuDomainChangeGraphics(struct qemud_driver *driver,
                          virDomainGraphicsDefPtr dev)
 {
     virDomainGraphicsDefPtr olddev = qemuDomainFindGraphics(vm, dev);
-    qemuDomainObjPrivatePtr priv = vm->privateData;
     int ret = -1;
 
     if (!olddev) {
@@ -8950,24 +9010,66 @@ 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 = qemuInitGraphicsPasswords(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 {
+            VIR_DEBUG0("Not updating since password didn't change");
             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 = qemuInitGraphicsPasswords(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"),
-- 
1.7.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]