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:
parent
3c9405a0f7
commit
7572150c18
@ -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
100
monitor.c
@ -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"));
|
||||
|
@ -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
|
||||
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user