diff --git a/hmp-commands.hx b/hmp-commands.hx index a586498495..4355a6f1e4 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1219,8 +1219,7 @@ ETEXI .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, + .mhandler.cmd = hmp_set_password, }, STEXI diff --git a/hmp.c b/hmp.c index 8a777804de..888e1b96ce 100644 --- a/hmp.c +++ b/hmp.c @@ -681,3 +681,14 @@ void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict) int64_t value = qdict_get_int(qdict, "value"); qmp_migrate_set_speed(value, NULL); } + +void hmp_set_password(Monitor *mon, const QDict *qdict) +{ + 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"); + Error *err = NULL; + + qmp_set_password(protocol, password, !!connected, connected, &err); + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 093242d626..4ed0feea66 100644 --- a/hmp.h +++ b/hmp.h @@ -49,5 +49,6 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); +void hmp_set_password(Monitor *mon, const QDict *qdict); #endif diff --git a/monitor.c b/monitor.c index 759c1335c3..1f5d343d07 100644 --- a/monitor.c +++ b/monitor.c @@ -884,63 +884,6 @@ 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; - } - /* Note that setting an empty password will not disable login through - * this interface. */ - 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"); diff --git a/qapi-schema.json b/qapi-schema.json index 44cf764ec3..092ff6eac2 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1275,3 +1275,32 @@ { 'command': 'qom-set', 'data': { 'path': 'str', 'property': 'str', 'value': 'visitor' }, 'gen': 'no' } + +## +# @set_password: +# +# Sets the password of a remote display session. +# +# @protocol: `vnc' to modify the VNC server password +# `spice' to modify the Spice server password +# +# @password: the new password +# +# @connected: #optional how to handle existing clients when changing the +# password. If nothing is specified, defaults to `keep' +# `fail' to fail the command if clients are connected +# `disconnect' to disconnect existing clients +# `keep' to maintain existing clients +# +# Returns: Nothing on success +# If Spice is not enabled, DeviceNotFound +# If @protocol does not support connected, InvalidParameter +# If @protocol is invalid, InvalidParameter +# If any other error occurs, SetPasswdFailed +# +# Notes: If VNC is not enabled, SetPasswdFailed is returned. +# +# Since: 0.14.0 +## +{ 'command': 'set_password', + 'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} } diff --git a/qmp-commands.hx b/qmp-commands.hx index 7e3f4b9a59..eadad054cb 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -851,10 +851,7 @@ 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, + .mhandler.cmd_new = qmp_marshal_input_set_password, }, SQMP diff --git a/qmp.c b/qmp.c index c74dde6c90..9ef43a857c 100644 --- a/qmp.c +++ b/qmp.c @@ -16,6 +16,8 @@ #include "qemu-common.h" #include "sysemu.h" #include "qmp-commands.h" +#include "ui/qemu-spice.h" +#include "ui/vnc.h" #include "kvm.h" #include "arch_init.h" #include "hw/qdev.h" @@ -249,3 +251,55 @@ out: return 0; } + +void qmp_set_password(const char *protocol, const char *password, + bool has_connected, const char *connected, Error **errp) +{ + int disconnect_if_connected = 0; + int fail_if_connected = 0; + int rc; + + if (has_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 { + error_set(errp, QERR_INVALID_PARAMETER, "connected"); + return; + } + } + + if (strcmp(protocol, "spice") == 0) { + if (!using_spice) { + /* correct one? spice isn't a device ,,, */ + error_set(errp, QERR_DEVICE_NOT_ACTIVE, "spice"); + return; + } + rc = qemu_spice_set_passwd(password, fail_if_connected, + disconnect_if_connected); + if (rc != 0) { + error_set(errp, QERR_SET_PASSWD_FAILED); + } + return; + } + + if (strcmp(protocol, "vnc") == 0) { + if (fail_if_connected || disconnect_if_connected) { + /* vnc supports "connected=keep" only */ + error_set(errp, QERR_INVALID_PARAMETER, "connected"); + return; + } + /* Note that setting an empty password will not disable login through + * this interface. */ + rc = vnc_display_password(NULL, password); + if (rc < 0) { + error_set(errp, QERR_SET_PASSWD_FAILED); + } + return; + } + + error_set(errp, QERR_INVALID_PARAMETER, "protocol"); +}