vnc/spice: add set_passwd monitor command.

This patch adds new set_password and expire_password monitor commands
which allows to change and expire the password for spice and vnc
connections.  See the doc update patch chunk for details.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2010-10-07 12:22:54 +02:00
parent 3c9405a0f7
commit 7572150c18
5 changed files with 251 additions and 0 deletions

View File

@ -1132,6 +1132,60 @@ STEXI
@item block_passwd @var{device} @var{password}
@findex block_passwd
Set the encrypted device @var{device} password to @var{password}
ETEXI
{
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.user_print = monitor_user_noop,
.mhandler.cmd_new = set_password,
},
STEXI
@item set_password [ vnc | spice ] password [ action-if-connected ]
@findex set_password
Change spice/vnc password. Use zero to make the password stay valid
forever. @var{action-if-connected} specifies what should happen in
case a connection is established: @var{fail} makes the password change
fail. @var{disconnect} changes the password and disconnects the
client. @var{keep} changes the password and keeps the connection up.
@var{keep} is the default.
ETEXI
{
.name = "expire_password",
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.user_print = monitor_user_noop,
.mhandler.cmd_new = expire_password,
},
STEXI
@item expire_password [ vnc | spice ] expire-time
@findex expire_password
Specify when a password for spice/vnc becomes
invalid. @var{expire-time} accepts:
@table @var
@item now
Invalidate password instantly.
@item never
Password stays valid forever.
@item +nsec
Password stays valid for @var{nsec} seconds starting now.
@item nsec
Password is invalidated at the given time. @var{nsec} are the seconds
passed since 1970, i.e. unix epoch.
@end table
ETEXI
{

100
monitor.c
View File

@ -34,6 +34,7 @@
#include "net.h"
#include "net/slirp.h"
#include "qemu-char.h"
#include "ui/qemu-spice.h"
#include "sysemu.h"
#include "monitor.h"
#include "readline.h"
@ -1075,6 +1076,105 @@ static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
return ret;
}
static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *protocol = qdict_get_str(qdict, "protocol");
const char *password = qdict_get_str(qdict, "password");
const char *connected = qdict_get_try_str(qdict, "connected");
int disconnect_if_connected = 0;
int fail_if_connected = 0;
int rc;
if (connected) {
if (strcmp(connected, "fail") == 0) {
fail_if_connected = 1;
} else if (strcmp(connected, "disconnect") == 0) {
disconnect_if_connected = 1;
} else if (strcmp(connected, "keep") == 0) {
/* nothing */
} else {
qerror_report(QERR_INVALID_PARAMETER, "connected");
return -1;
}
}
if (strcmp(protocol, "spice") == 0) {
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
rc = qemu_spice_set_passwd(password, fail_if_connected,
disconnect_if_connected);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
if (strcmp(protocol, "vnc") == 0) {
if (fail_if_connected || disconnect_if_connected) {
/* vnc supports "connected=keep" only */
qerror_report(QERR_INVALID_PARAMETER, "connected");
return -1;
}
rc = vnc_display_password(NULL, password);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
qerror_report(QERR_INVALID_PARAMETER, "protocol");
return -1;
}
static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *protocol = qdict_get_str(qdict, "protocol");
const char *whenstr = qdict_get_str(qdict, "time");
time_t when;
int rc;
if (strcmp(whenstr, "now")) {
when = 0;
} else if (strcmp(whenstr, "never")) {
when = TIME_MAX;
} else if (whenstr[0] == '+') {
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
} else {
when = strtoull(whenstr, NULL, 10);
}
if (strcmp(protocol, "spice") == 0) {
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
rc = qemu_spice_set_pw_expire(when);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
if (strcmp(protocol, "vnc") == 0) {
rc = vnc_display_pw_expire(NULL, when);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
qerror_report(QERR_INVALID_PARAMETER, "protocol");
return -1;
}
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));

View File

@ -735,6 +735,63 @@ Example:
"password": "12345" } }
<- { "return": {} }
EQMP
{
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.user_print = monitor_user_noop,
.mhandler.cmd_new = set_password,
},
SQMP
set_password
------------
Set the password for vnc/spice protocols.
Arguments:
- "protocol": protocol name (json-string)
- "password": password (json-string)
- "connected": [ keep | disconnect | fail ] (josn-string, optional)
Example:
-> { "execute": "set_password", "arguments": { "protocol": "vnc",
"password": "secret" } }
<- { "return": {} }
EQMP
{
.name = "expire_password",
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.user_print = monitor_user_noop,
.mhandler.cmd_new = expire_password,
},
SQMP
expire_password
---------------
Set the password expire time for vnc/spice protocols.
Arguments:
- "protocol": protocol name (json-string)
- "time": [ now | never | +secs | secs ] (json-string)
Example:
-> { "execute": "expire_password", "arguments": { "protocol": "vnc",
"time": "+60" } }
<- { "return": {} }
EQMP
{

View File

@ -32,6 +32,9 @@ void qemu_spice_input_init(void);
void qemu_spice_audio_init(void);
void qemu_spice_display_init(DisplayState *ds);
int qemu_spice_add_interface(SpiceBaseInstance *sin);
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected, bool disconnect_if_connected);
int qemu_spice_set_pw_expire(time_t expires);
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
@ -39,6 +42,8 @@ void do_info_spice(Monitor *mon, QObject **ret_data);
#else /* CONFIG_SPICE */
#define using_spice 0
#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
#define qemu_spice_set_pw_expire(_e) (-1)
#endif /* CONFIG_SPICE */

View File

@ -36,6 +36,8 @@
static SpiceServer *spice_server;
static const char *auth = "spice";
static char *auth_passwd;
static time_t auth_expires = TIME_MAX;
int using_spice = 0;
struct SpiceTimer {
@ -599,6 +601,39 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
return spice_server_add_interface(spice_server, sin);
}
static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn)
{
time_t lifetime, now = time(NULL);
char *passwd;
if (now < auth_expires) {
passwd = auth_passwd;
lifetime = (auth_expires - now);
if (lifetime > INT_MAX) {
lifetime = INT_MAX;
}
} else {
passwd = NULL;
lifetime = 1;
}
return spice_server_set_ticket(spice_server, passwd, lifetime,
fail_if_conn, disconnect_if_conn);
}
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_conn, bool disconnect_if_conn)
{
free(auth_passwd);
auth_passwd = strdup(passwd);
return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn);
}
int qemu_spice_set_pw_expire(time_t expires)
{
auth_expires = expires;
return qemu_spice_set_ticket(false, false);
}
static void spice_register_config(void)
{
qemu_add_opts(&qemu_spice_opts);