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