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}
|
@item block_passwd @var{device} @var{password}
|
||||||
@findex block_passwd
|
@findex block_passwd
|
||||||
Set the encrypted device @var{device} password to @var{password}
|
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
|
ETEXI
|
||||||
|
|
||||||
{
|
{
|
||||||
|
100
monitor.c
100
monitor.c
@ -34,6 +34,7 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "net/slirp.h"
|
#include "net/slirp.h"
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
|
#include "ui/qemu-spice.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
@ -1075,6 +1076,105 @@ static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
|||||||
return ret;
|
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)
|
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
{
|
{
|
||||||
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
|
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
|
||||||
|
@ -735,6 +735,63 @@ Example:
|
|||||||
"password": "12345" } }
|
"password": "12345" } }
|
||||||
<- { "return": {} }
|
<- { "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
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -32,6 +32,9 @@ void qemu_spice_input_init(void);
|
|||||||
void qemu_spice_audio_init(void);
|
void qemu_spice_audio_init(void);
|
||||||
void qemu_spice_display_init(DisplayState *ds);
|
void qemu_spice_display_init(DisplayState *ds);
|
||||||
int qemu_spice_add_interface(SpiceBaseInstance *sin);
|
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_print(Monitor *mon, const QObject *data);
|
||||||
void do_info_spice(Monitor *mon, QObject **ret_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 */
|
#else /* CONFIG_SPICE */
|
||||||
|
|
||||||
#define using_spice 0
|
#define using_spice 0
|
||||||
|
#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
|
||||||
|
#define qemu_spice_set_pw_expire(_e) (-1)
|
||||||
|
|
||||||
#endif /* CONFIG_SPICE */
|
#endif /* CONFIG_SPICE */
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
static SpiceServer *spice_server;
|
static SpiceServer *spice_server;
|
||||||
static const char *auth = "spice";
|
static const char *auth = "spice";
|
||||||
|
static char *auth_passwd;
|
||||||
|
static time_t auth_expires = TIME_MAX;
|
||||||
int using_spice = 0;
|
int using_spice = 0;
|
||||||
|
|
||||||
struct SpiceTimer {
|
struct SpiceTimer {
|
||||||
@ -599,6 +601,39 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
|||||||
return spice_server_add_interface(spice_server, 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)
|
static void spice_register_config(void)
|
||||||
{
|
{
|
||||||
qemu_add_opts(&qemu_spice_opts);
|
qemu_add_opts(&qemu_spice_opts);
|
||||||
|
Loading…
Reference in New Issue
Block a user