This extends the XML syntax for <graphics> to allow a password expiry time to be set eg <graphics type='vnc' port='5900' autoport='yes' keymap='en-us' passwd='12345' passwdValidTo='2010-04-09T15:51:00'/> The timestamp is in UTC. * src/conf/domain_conf.h: Pull passwd out into separate struct virDomainGraphicsAuthDef to allow sharing between VNC & SPICE * src/conf/domain_conf.c: Add parsing/formatting of new passwdValidTo argument * src/opennebula/one_conf.c, src/qemu/qemu_conf.c, src/qemu/qemu_driver.c, src/xen/xend_internal.c, src/xen/xm_internal.c: Update for changed struct containing VNC password --- src/conf/domain_conf.c | 102 +++++++++++++++++++++++++++++++++++++++----- src/conf/domain_conf.h | 13 +++++- src/esx/esx_vmx.c | 6 +- src/opennebula/one_conf.c | 4 +- src/qemu/qemu_conf.c | 4 +- src/qemu/qemu_driver.c | 20 ++++---- src/xen/xend_internal.c | 12 +++--- src/xen/xm_internal.c | 12 +++--- 8 files changed, 130 insertions(+), 43 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a3ea217..04829e9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -423,6 +423,17 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms, #endif /* !PROXY */ +static void +virDomainGraphicsAuthDefClear(virDomainGraphicsAuthDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->passwd); + + /* Don't free def */ +} + void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) { if (!def) @@ -432,7 +443,7 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) case VIR_DOMAIN_GRAPHICS_TYPE_VNC: VIR_FREE(def->data.vnc.listenAddr); VIR_FREE(def->data.vnc.keymap); - VIR_FREE(def->data.vnc.passwd); + virDomainGraphicsAuthDefClear(&def->data.vnc.auth); break; case VIR_DOMAIN_GRAPHICS_TYPE_SDL: @@ -451,7 +462,7 @@ void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def) case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: VIR_FREE(def->data.spice.listenAddr); VIR_FREE(def->data.spice.keymap); - VIR_FREE(def->data.spice.passwd); + virDomainGraphicsAuthDefClear(&def->data.spice.auth); break; } @@ -3068,6 +3079,56 @@ error: goto cleanup; } + +static int +virDomainGraphicsAuthDefParseXML(xmlNodePtr node, virDomainGraphicsAuthDefPtr def) +{ + char *validTo = NULL; + + def->passwd = virXMLPropString(node, "passwd"); + + if (!def->passwd) + return 0; + + validTo = virXMLPropString(node, "passwdValidTo"); + if (validTo) { + char *tmp; + struct tm tm; + memset(&tm, 0, sizeof(tm)); + /* Expect: YYYY-MM-DDTHH:MM:SS (%d-%d-%dT%d:%d:%d) eg 2010-11-28T14:29:01 */ + if (/* year */ + virStrToLong_i(validTo, &tmp, 10, &tm.tm_year) < 0 || *tmp != '-' || + /* month */ + virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_mon) < 0 || *tmp != '-' || + /* day */ + virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_mday) < 0 || *tmp != 'T' || + /* hour */ + virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_hour) < 0 || *tmp != ':' || + /* minute */ + virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_min) < 0 || *tmp != ':' || + /* second */ + virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_sec) < 0 || *tmp != '\0') { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse password validity time '%s', expect YYYY-MM-DDTHH:MM:SS"), + validTo); + VIR_FREE(validTo); + VIR_FREE(def->passwd); + return -1; + } + VIR_FREE(validTo); + + tm.tm_year -= 1900; /* Human epoch starts at 0 BC, not 1900BC */ + tm.tm_mon--; /* Humans start months at 1, computers at 0 */ + + /* XXX this is broken it needs to be UTC not localtime */ + def->validTo = timegm(&tm); + def->expires = 1; + } + + return 0; +} + + /* Parse the XML definition for a graphics device */ static virDomainGraphicsDefPtr virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { @@ -3126,8 +3187,10 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } def->data.vnc.listenAddr = virXMLPropString(node, "listen"); - def->data.vnc.passwd = virXMLPropString(node, "passwd"); def->data.vnc.keymap = virXMLPropString(node, "keymap"); + + if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0) + goto error; } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) { char *fullscreen = virXMLPropString(node, "fullscreen"); @@ -3251,8 +3314,9 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) { } def->data.spice.listenAddr = virXMLPropString(node, "listen"); - def->data.spice.passwd = virXMLPropString(node, "passwd"); def->data.spice.keymap = virXMLPropString(node, "keymap"); + if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth) < 0) + goto error; } cleanup: @@ -6320,6 +6384,24 @@ virDomainTimerDefFormat(virBufferPtr buf, return 0; } +static void +virDomainGraphicsAuthDefFormatAttr(virBufferPtr buf, + virDomainGraphicsAuthDefPtr def) +{ + if (!def->passwd) + return; + + virBufferEscapeString(buf, " passwd='%s'", + def->passwd); + if (def->expires) { + char strbuf[100]; + struct tm tmbuf, *tm; + tm = gmtime_r(&def->validTo, &tmbuf); + strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm); + virBufferVSprintf(buf, " passwdValidTo='%s'", strbuf); + } +} + static int virDomainGraphicsDefFormat(virBufferPtr buf, virDomainGraphicsDefPtr def, @@ -6355,10 +6437,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " keymap='%s'", def->data.vnc.keymap); - if (def->data.vnc.passwd && - (flags & VIR_DOMAIN_XML_SECURE)) - virBufferEscapeString(buf, " passwd='%s'", - def->data.vnc.passwd); + if (flags & VIR_DOMAIN_XML_SECURE) + virDomainGraphicsAuthDefFormatAttr(buf, &def->data.vnc.auth); break; @@ -6426,10 +6506,8 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " keymap='%s'", def->data.spice.keymap); - if (def->data.spice.passwd && - (flags & VIR_DOMAIN_XML_SECURE)) - virBufferEscapeString(buf, " passwd='%s'", - def->data.spice.passwd); + if (flags & VIR_DOMAIN_XML_SECURE) + virDomainGraphicsAuthDefFormatAttr(buf, &def->data.spice.auth); break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 0238f92..34a3904 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -516,6 +516,15 @@ enum virDomainGraphicsType { VIR_DOMAIN_GRAPHICS_TYPE_LAST, }; +typedef struct _virDomainGraphicsAuthDef virDomainGraphicsAuthDef; +typedef virDomainGraphicsAuthDef *virDomainGraphicsAuthDefPtr; +struct _virDomainGraphicsAuthDef { + char *passwd; + unsigned int expires: 1; /* Whether there is an expiry time set */ + time_t validTo; /* seconds since epoch */ +}; + + typedef struct _virDomainGraphicsDef virDomainGraphicsDef; typedef virDomainGraphicsDef *virDomainGraphicsDefPtr; struct _virDomainGraphicsDef { @@ -526,7 +535,7 @@ struct _virDomainGraphicsDef { unsigned int autoport :1; char *listenAddr; char *keymap; - char *passwd; + virDomainGraphicsAuthDef auth; } vnc; struct { char *display; @@ -549,7 +558,7 @@ struct _virDomainGraphicsDef { int tlsPort; char *listenAddr; char *keymap; - char *passwd; + virDomainGraphicsAuthDef auth; unsigned int autoport :1; } spice; } data; diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index 0a26614..fcaf5e9 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -1431,7 +1431,7 @@ esxVMX_ParseVNC(virConfPtr conf, virDomainGraphicsDefPtr *def) esxUtil_GetConfigString(conf, "RemoteDisplay.vnc.keymap", &(*def)->data.vnc.keymap, true) < 0 || esxUtil_GetConfigString(conf, "RemoteDisplay.vnc.password", - &(*def)->data.vnc.passwd, true) < 0) { + &(*def)->data.vnc.auth.passwd, true) < 0) { goto failure; } @@ -2831,9 +2831,9 @@ esxVMX_FormatVNC(virDomainGraphicsDefPtr def, virBufferPtr buffer) def->data.vnc.keymap); } - if (def->data.vnc.passwd != NULL) { + if (def->data.vnc.auth.passwd != NULL) { virBufferVSprintf(buffer, "RemoteDisplay.vnc.password = \"%s\"\n", - def->data.vnc.passwd); + def->data.vnc.auth.passwd); } return 0; diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c index 2079c51..0b0a08a 100644 --- a/src/opennebula/one_conf.c +++ b/src/opennebula/one_conf.c @@ -262,9 +262,9 @@ char* xmlOneTemplate(virDomainDefPtr def) virBufferVSprintf(&buf,",\n port = \"%d\"", def->graphics[i]->data.vnc.port); - if (def->graphics[i]->data.vnc.passwd != NULL) + if (def->graphics[i]->data.vnc.auth.passwd != NULL) virBufferVSprintf(&buf,",\n passwd = \"%s\"", - def->graphics[i]->data.vnc.passwd); + def->graphics[i]->data.vnc.auth.passwd); virBufferAddLit(&buf," ]\n"); diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index c76893c..f0b4296 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -4906,7 +4906,7 @@ int qemudBuildCommandLine(virConnectPtr conn, virBufferVSprintf(&opt, ":%d", def->graphics[0]->data.vnc.port - 5900); - if (def->graphics[0]->data.vnc.passwd || + if (def->graphics[0]->data.vnc.auth.passwd || driver->vncPassword) virBufferAddLit(&opt, ",password"); @@ -5016,7 +5016,7 @@ int qemudBuildCommandLine(virConnectPtr conn, /* In the password case we set it via monitor command, to avoid * making it visible on CLI, so there's no use of password=XXX * in this bit of the code */ - if (!def->graphics[0]->data.spice.passwd && + if (!def->graphics[0]->data.spice.auth.passwd && !driver->spicePassword) virBufferAddLit(&opt, ",disable-ticketing"); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5854c44..24e2367 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2515,12 +2515,12 @@ qemuInitPasswords(virConnectPtr conn, if ((vm->def->ngraphics == 1) && vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && - (vm->def->graphics[0]->data.vnc.passwd || driver->vncPassword)) { + (vm->def->graphics[0]->data.vnc.auth.passwd || driver->vncPassword)) { qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetVNCPassword(priv->mon, - vm->def->graphics[0]->data.vnc.passwd ? - vm->def->graphics[0]->data.vnc.passwd : + vm->def->graphics[0]->data.vnc.auth.passwd ? + vm->def->graphics[0]->data.vnc.auth.passwd : driver->vncPassword); qemuDomainObjExitMonitorWithDriver(driver, vm); } @@ -8829,19 +8829,19 @@ qemuDomainChangeGraphics(struct qemud_driver *driver, return -1; } - if (STRNEQ_NULLABLE(olddev->data.vnc.passwd, dev->data.vnc.passwd)) { - VIR_DEBUG("Updating password on VNC server %p %p", dev->data.vnc.passwd, driver->vncPassword); + if (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.passwd ? - dev->data.vnc.passwd : + dev->data.vnc.auth.passwd ? + dev->data.vnc.auth.passwd : driver->vncPassword); qemuDomainObjExitMonitorWithDriver(driver, vm); /* Steal the new dev's char * reference */ - VIR_FREE(olddev->data.vnc.passwd); - olddev->data.vnc.passwd = dev->data.vnc.passwd; - dev->data.vnc.passwd = NULL; + VIR_FREE(olddev->data.vnc.auth.passwd); + olddev->data.vnc.auth.passwd = dev->data.vnc.auth.passwd; + dev->data.vnc.auth.passwd = NULL; } else { ret = 0; } diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index 614c036..ee7f0e1 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -1808,7 +1808,7 @@ xenDaemonParseSxprGraphicsOld(virConnectPtr conn, goto no_memory; if (vncPasswd && - !(graphics->data.vnc.passwd = strdup(vncPasswd))) + !(graphics->data.vnc.auth.passwd = strdup(vncPasswd))) goto no_memory; if (keymap && @@ -1930,7 +1930,7 @@ xenDaemonParseSxprGraphicsNew(virConnectPtr conn, goto no_memory; if (vncPasswd && - !(graphics->data.vnc.passwd = strdup(vncPasswd))) + !(graphics->data.vnc.auth.passwd = strdup(vncPasswd))) goto no_memory; if (keymap && @@ -5251,8 +5251,8 @@ xenDaemonFormatSxprGraphicsNew(virDomainGraphicsDefPtr def, if (def->data.vnc.listenAddr) virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); - if (def->data.vnc.passwd) - virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd); + if (def->data.vnc.auth.passwd) + virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd); if (def->data.vnc.keymap) virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap); } @@ -5294,8 +5294,8 @@ xenDaemonFormatSxprGraphicsOld(virDomainGraphicsDefPtr def, if (def->data.vnc.listenAddr) virBufferVSprintf(buf, "(vnclisten '%s')", def->data.vnc.listenAddr); - if (def->data.vnc.passwd) - virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.passwd); + if (def->data.vnc.auth.passwd) + virBufferVSprintf(buf, "(vncpasswd '%s')", def->data.vnc.auth.passwd); if (def->data.vnc.keymap) virBufferVSprintf(buf, "(keymap '%s')", def->data.vnc.keymap); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 6c5df0f..4dd0641 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1304,7 +1304,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { } if (xenXMConfigCopyStringOpt(conf, "vnclisten", &graphics->data.vnc.listenAddr) < 0) goto cleanup; - if (xenXMConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.passwd) < 0) + if (xenXMConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.auth.passwd) < 0) goto cleanup; if (xenXMConfigCopyStringOpt(conf, "keymap", &graphics->data.vnc.keymap) < 0) goto cleanup; @@ -1376,7 +1376,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { if (!(graphics->data.vnc.listenAddr = strdup(key + 10))) goto no_memory; } else if (STRPREFIX(key, "vncpasswd=")) { - if (!(graphics->data.vnc.passwd = strdup(key + 10))) + if (!(graphics->data.vnc.auth.passwd = strdup(key + 10))) goto no_memory; } else if (STRPREFIX(key, "keymap=")) { if (!(graphics->data.vnc.keymap = strdup(key + 7))) @@ -2538,9 +2538,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, xenXMConfigSetString(conf, "vnclisten", def->graphics[0]->data.vnc.listenAddr) < 0) goto no_memory; - if (def->graphics[0]->data.vnc.passwd && + if (def->graphics[0]->data.vnc.auth.passwd && xenXMConfigSetString(conf, "vncpasswd", - def->graphics[0]->data.vnc.passwd) < 0) + def->graphics[0]->data.vnc.auth.passwd) < 0) goto no_memory; if (def->graphics[0]->data.vnc.keymap && xenXMConfigSetString(conf, "keymap", @@ -2569,9 +2569,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, if (def->graphics[0]->data.vnc.listenAddr) virBufferVSprintf(&buf, ",vnclisten=%s", def->graphics[0]->data.vnc.listenAddr); - if (def->graphics[0]->data.vnc.passwd) + if (def->graphics[0]->data.vnc.auth.passwd) virBufferVSprintf(&buf, ",vncpasswd=%s", - def->graphics[0]->data.vnc.passwd); + def->graphics[0]->data.vnc.auth.passwd); if (def->graphics[0]->data.vnc.keymap) virBufferVSprintf(&buf, ",keymap=%s", def->graphics[0]->data.vnc.keymap); -- 1.7.2.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list