]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/extra/0003-monitor-refactor-set-expire_password-and-allow-VNC-d.patch
bump version to 6.2.0-11
[pve-qemu.git] / debian / patches / extra / 0003-monitor-refactor-set-expire_password-and-allow-VNC-d.patch
CommitLineData
f376b2b9
SR
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Stefan Reiter <s.reiter@proxmox.com>
3Date: Wed, 25 Aug 2021 11:14:13 +0200
4Subject: [PATCH] monitor: refactor set/expire_password and allow VNC display
5 id
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10It is possible to specify more than one VNC server on the command line,
11either with an explicit ID or the auto-generated ones à la "default",
12"vnc2", "vnc3", ...
13
14It is not possible to change the password on one of these extra VNC
15displays though. Fix this by adding a "display" parameter to the
16"set_password" and "expire_password" QMP and HMP commands.
17
18For HMP, the display is specified using the "-d" value flag.
19
20For QMP, the schema is updated to explicitly express the supported
21variants of the commands with protocol-discriminated unions.
22
23Suggested-by: Eric Blake <eblake@redhat.com>
24Suggested-by: Markus Armbruster <armbru@redhat.com>
25Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
ddbf7a87 26Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
4567474e 27Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
f376b2b9 28---
4567474e 29 hmp-commands.hx | 24 ++++---
f376b2b9
SR
30 monitor/hmp-cmds.c | 57 +++++++++++++++-
31 monitor/qmp-cmds.c | 62 ++++++-----------
ddbf7a87 32 qapi/ui.json | 165 ++++++++++++++++++++++++++++++++++++++-------
4567474e 33 4 files changed, 231 insertions(+), 77 deletions(-)
f376b2b9
SR
34
35diff --git a/hmp-commands.hx b/hmp-commands.hx
4567474e 36index 70a9136ac2..5efb47fc32 100644
f376b2b9
SR
37--- a/hmp-commands.hx
38+++ b/hmp-commands.hx
4567474e 39@@ -1514,33 +1514,35 @@ ERST
f376b2b9
SR
40
41 {
42 .name = "set_password",
43- .args_type = "protocol:s,password:s,connected:s?",
44- .params = "protocol password action-if-connected",
45+ .args_type = "protocol:s,password:s,display:-dS,connected:s?",
46+ .params = "protocol password [-d display] [action-if-connected]",
47 .help = "set spice/vnc password",
48 .cmd = hmp_set_password,
49 },
50
51 SRST
52-``set_password [ vnc | spice ] password [ action-if-connected ]``
4567474e
FE
53- Change spice/vnc password. *action-if-connected* specifies what
54- should happen in case a connection is established: *fail* makes the
55- password change fail. *disconnect* changes the password and
f376b2b9
SR
56+``set_password [ vnc | spice ] password [ -d display ] [ action-if-connected ]``
57+ Change spice/vnc password. *display* can be used with 'vnc' to specify
58+ which display to set the password on. *action-if-connected* specifies
59+ what should happen in case a connection is established: *fail* makes
60+ the password change fail. *disconnect* changes the password and
4567474e
FE
61 disconnects the client. *keep* changes the password and keeps the
62 connection up. *keep* is the default.
f376b2b9
SR
63 ERST
64
65 {
66 .name = "expire_password",
67- .args_type = "protocol:s,time:s",
68- .params = "protocol time",
69+ .args_type = "protocol:s,time:s,display:-dS",
70+ .params = "protocol time [-d display]",
71 .help = "set spice/vnc password expire-time",
72 .cmd = hmp_expire_password,
73 },
74
75 SRST
76-``expire_password [ vnc | spice ]`` *expire-time*
77- Specify when a password for spice/vnc becomes
78- invalid. *expire-time* accepts:
79+``expire_password [ vnc | spice ] expire-time [ -d display ]``
80+ Specify when a password for spice/vnc becomes invalid.
81+ *display* behaves the same as in ``set_password``.
82+ *expire-time* accepts:
83
84 ``now``
85 Invalidate password instantly.
86diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
4567474e 87index 9c91bf93e9..2e91ccb738 100644
f376b2b9
SR
88--- a/monitor/hmp-cmds.c
89+++ b/monitor/hmp-cmds.c
4567474e 90@@ -1384,10 +1384,41 @@ void hmp_set_password(Monitor *mon, const QDict *qdict)
f376b2b9
SR
91 {
92 const char *protocol = qdict_get_str(qdict, "protocol");
93 const char *password = qdict_get_str(qdict, "password");
94+ const char *display = qdict_get_try_str(qdict, "display");
95 const char *connected = qdict_get_try_str(qdict, "connected");
96 Error *err = NULL;
97+ DisplayProtocol proto;
98
99- qmp_set_password(protocol, password, !!connected, connected, &err);
100+ SetPasswordOptions opts = {
101+ .password = g_strdup(password),
102+ .u.vnc.display = NULL,
103+ };
104+
105+ proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
106+ DISPLAY_PROTOCOL_VNC, &err);
107+ if (err) {
108+ hmp_handle_error(mon, err);
109+ return;
110+ }
111+ opts.protocol = proto;
112+
113+ if (proto == DISPLAY_PROTOCOL_VNC) {
114+ opts.u.vnc.has_display = !!display;
115+ opts.u.vnc.display = g_strdup(display);
116+ } else if (proto == DISPLAY_PROTOCOL_SPICE) {
117+ opts.u.spice.has_connected = !!connected;
118+ opts.u.spice.connected =
119+ qapi_enum_parse(&SetPasswordAction_lookup, connected,
120+ SET_PASSWORD_ACTION_KEEP, &err);
121+ if (err) {
122+ hmp_handle_error(mon, err);
123+ return;
124+ }
125+ }
126+
127+ qmp_set_password(&opts, &err);
128+ g_free(opts.password);
129+ g_free(opts.u.vnc.display);
130 hmp_handle_error(mon, err);
131 }
132
4567474e 133@@ -1395,9 +1426,31 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
f376b2b9
SR
134 {
135 const char *protocol = qdict_get_str(qdict, "protocol");
136 const char *whenstr = qdict_get_str(qdict, "time");
137+ const char *display = qdict_get_try_str(qdict, "display");
138 Error *err = NULL;
139+ DisplayProtocol proto;
ddbf7a87
TL
140
141- qmp_expire_password(protocol, whenstr, &err);
f376b2b9
SR
142+ ExpirePasswordOptions opts = {
143+ .time = g_strdup(whenstr),
144+ .u.vnc.display = NULL,
145+ };
146+
147+ proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
148+ DISPLAY_PROTOCOL_VNC, &err);
149+ if (err) {
150+ hmp_handle_error(mon, err);
151+ return;
152+ }
153+ opts.protocol = proto;
154+
155+ if (proto == DISPLAY_PROTOCOL_VNC) {
156+ opts.u.vnc.has_display = !!display;
157+ opts.u.vnc.display = g_strdup(display);
158+ }
ddbf7a87 159+
f376b2b9
SR
160+ qmp_expire_password(&opts, &err);
161+ g_free(opts.time);
162+ g_free(opts.u.vnc.display);
163 hmp_handle_error(mon, err);
164 }
165
166diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
4567474e 167index 343353e27a..729ca7cceb 100644
f376b2b9
SR
168--- a/monitor/qmp-cmds.c
169+++ b/monitor/qmp-cmds.c
4567474e 170@@ -167,45 +167,30 @@ void qmp_system_wakeup(Error **errp)
f376b2b9
SR
171 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
172 }
173
174-void qmp_set_password(const char *protocol, const char *password,
175- bool has_connected, const char *connected, Error **errp)
176+void qmp_set_password(SetPasswordOptions *opts, Error **errp)
177 {
178- int disconnect_if_connected = 0;
179- int fail_if_connected = 0;
180- int rc;
ddbf7a87
TL
181+ bool disconnect_if_connected = false;
182+ bool fail_if_connected = false;
183+ int rc = 0;
184
f376b2b9
SR
185- if (has_connected) {
186- if (strcmp(connected, "fail") == 0) {
187- fail_if_connected = 1;
188- } else if (strcmp(connected, "disconnect") == 0) {
189- disconnect_if_connected = 1;
190- } else if (strcmp(connected, "keep") == 0) {
191- /* nothing */
192- } else {
193- error_setg(errp, QERR_INVALID_PARAMETER, "connected");
194- return;
195- }
196- }
ddbf7a87 197-
f376b2b9
SR
198- if (strcmp(protocol, "spice") == 0) {
199+ if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
200 if (!qemu_using_spice(errp)) {
201 return;
202 }
203- rc = qemu_spice.set_passwd(password, fail_if_connected,
f376b2b9
SR
204+ if (opts->u.spice.has_connected) {
205+ fail_if_connected =
206+ opts->u.spice.connected == SET_PASSWORD_ACTION_FAIL;
207+ disconnect_if_connected =
208+ opts->u.spice.connected == SET_PASSWORD_ACTION_DISCONNECT;
ddbf7a87 209+ }
f376b2b9 210+ rc = qemu_spice.set_passwd(opts->password, fail_if_connected,
ddbf7a87
TL
211 disconnect_if_connected);
212- } else if (strcmp(protocol, "vnc") == 0) {
213- if (fail_if_connected || disconnect_if_connected) {
214- /* vnc supports "connected=keep" only */
215- error_setg(errp, QERR_INVALID_PARAMETER, "connected");
216- return;
217- }
f376b2b9
SR
218+ } else if (opts->protocol == DISPLAY_PROTOCOL_VNC) {
219 /* Note that setting an empty password will not disable login through
220 * this interface. */
221- rc = vnc_display_password(NULL, password);
222- } else {
223- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
224- "'vnc' or 'spice'");
225- return;
226+ rc = vnc_display_password(
227+ opts->u.vnc.has_display ? opts->u.vnc.display : NULL,
228+ opts->password);
229 }
230
231 if (rc != 0) {
4567474e 232@@ -213,11 +198,11 @@ void qmp_set_password(const char *protocol, const char *password,
f376b2b9
SR
233 }
234 }
235
236-void qmp_expire_password(const char *protocol, const char *whenstr,
237- Error **errp)
238+void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp)
239 {
240 time_t when;
241 int rc;
242+ const char* whenstr = opts->time;
243
244 if (strcmp(whenstr, "now") == 0) {
245 when = 0;
4567474e 246@@ -229,17 +214,14 @@ void qmp_expire_password(const char *protocol, const char *whenstr,
f376b2b9
SR
247 when = strtoull(whenstr, NULL, 10);
248 }
249
250- if (strcmp(protocol, "spice") == 0) {
251+ if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
252 if (!qemu_using_spice(errp)) {
253 return;
254 }
255 rc = qemu_spice.set_pw_expire(when);
256- } else if (strcmp(protocol, "vnc") == 0) {
257- rc = vnc_display_pw_expire(NULL, when);
258- } else {
259- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
260- "'vnc' or 'spice'");
261- return;
262+ } else if (opts->protocol == DISPLAY_PROTOCOL_VNC) {
263+ rc = vnc_display_pw_expire(
264+ opts->u.vnc.has_display ? opts->u.vnc.display : NULL, when);
265 }
266
267 if (rc != 0) {
268diff --git a/qapi/ui.json b/qapi/ui.json
4567474e 269index d7567ac866..4244c62c30 100644
f376b2b9
SR
270--- a/qapi/ui.json
271+++ b/qapi/ui.json
ddbf7a87
TL
272@@ -9,22 +9,23 @@
273 { 'include': 'common.json' }
f376b2b9
SR
274 { 'include': 'sockets.json' }
275
ddbf7a87 276+##
f376b2b9 277+# @DisplayProtocol:
ddbf7a87 278+#
f376b2b9 279+# Display protocols which support changing password options.
ddbf7a87 280+#
f376b2b9 281+# Since: 6.2
ddbf7a87 282+#
f376b2b9
SR
283+##
284+{ 'enum': 'DisplayProtocol',
4567474e
FE
285+ 'data': [ { 'name': 'vnc', 'if': 'CONFIG_VNC' },
286+ { 'name': 'spice', 'if': 'CONFIG_SPICE' } ] }
f376b2b9 287+
ddbf7a87
TL
288 ##
289 # @set_password:
f376b2b9 290 #
ddbf7a87
TL
291 # Sets the password of a remote display session.
292 #
293-# @protocol: - 'vnc' to modify the VNC server password
294-# - 'spice' to modify the Spice server password
295-#
296-# @password: the new password
297-#
f376b2b9
SR
298-# @connected: how to handle existing clients when changing the
299-# password. If nothing is specified, defaults to 'keep'
300-# 'fail' to fail the command if clients are connected
301-# 'disconnect' to disconnect existing clients
302-# 'keep' to maintain existing clients
ddbf7a87 303-#
f376b2b9
SR
304 # Returns: - Nothing on success
305 # - If Spice is not enabled, DeviceNotFound
ddbf7a87 306 #
f376b2b9
SR
307@@ -37,16 +38,123 @@
308 # <- { "return": {} }
309 #
310 ##
311-{ 'command': 'set_password',
312- 'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }
313+{ 'command': 'set_password', 'boxed': true, 'data': 'SetPasswordOptions' }
314+
315+##
316+# @SetPasswordOptions:
317+#
318+# Data required to set a new password on a display server protocol.
319+#
320+# @protocol: - 'vnc' to modify the VNC server password
321+# - 'spice' to modify the Spice server password
322+#
323+# @password: the new password
324+#
325+# Since: 6.2
326+#
327+##
328+{ 'union': 'SetPasswordOptions',
329+ 'base': { 'protocol': 'DisplayProtocol',
330+ 'password': 'str' },
331+ 'discriminator': 'protocol',
332+ 'data': { 'vnc': 'SetPasswordOptionsVnc',
333+ 'spice': 'SetPasswordOptionsSpice' } }
334+
335+##
336+# @SetPasswordAction:
337+#
338+# An action to take on changing a password on a connection with active clients.
339+#
340+# @fail: fail the command if clients are connected
341+#
342+# @disconnect: disconnect existing clients
343+#
344+# @keep: maintain existing clients
345+#
346+# Since: 6.2
347+#
348+##
349+{ 'enum': 'SetPasswordAction',
350+ 'data': [ 'fail', 'disconnect', 'keep' ] }
351+
352+##
353+# @SetPasswordActionVnc:
354+#
355+# See @SetPasswordAction. VNC only supports the keep action. 'connection'
356+# should just be omitted for VNC, this is kept for backwards compatibility.
357+#
358+# @keep: maintain existing clients
359+#
360+# Since: 6.2
361+#
362+##
363+{ 'enum': 'SetPasswordActionVnc',
364+ 'data': [ 'keep' ] }
365+
366+##
367+# @SetPasswordOptionsSpice:
368+#
369+# Options for set_password specific to the VNC procotol.
370+#
371+# @connected: How to handle existing clients when changing the
372+# password. If nothing is specified, defaults to 'keep'.
373+#
374+# Since: 6.2
375+#
376+##
377+{ 'struct': 'SetPasswordOptionsSpice',
378+ 'data': { '*connected': 'SetPasswordAction' } }
379+
380+##
381+# @SetPasswordOptionsVnc:
382+#
383+# Options for set_password specific to the VNC procotol.
384+#
385+# @display: The id of the display where the password should be changed.
386+# Defaults to the first.
387+#
388+# @connected: How to handle existing clients when changing the
389+# password.
390+#
391+# Features:
392+# @deprecated: For VNC, @connected will always be 'keep', parameter should be
393+# omitted.
394+#
395+# Since: 6.2
396+#
397+##
398+{ 'struct': 'SetPasswordOptionsVnc',
399+ 'data': { '*display': 'str',
400+ '*connected': { 'type': 'SetPasswordActionVnc',
401+ 'features': ['deprecated'] } } }
402
403 ##
404 # @expire_password:
405 #
406 # Expire the password of a remote display server.
407 #
408-# @protocol: the name of the remote display protocol 'vnc' or 'spice'
409+# Returns: - Nothing on success
410+# - If @protocol is 'spice' and Spice is not active, DeviceNotFound
ddbf7a87 411 #
f376b2b9
SR
412+# Since: 0.14
413+#
414+# Example:
415+#
416+# -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
417+# "time": "+60" } }
418+# <- { "return": {} }
419+#
420+##
421+{ 'command': 'expire_password', 'boxed': true, 'data': 'ExpirePasswordOptions' }
422+
423+##
424+# @ExpirePasswordOptions:
425+#
426+# Data required to set password expiration on a display server protocol.
ddbf7a87 427+#
f376b2b9
SR
428+# @protocol: - 'vnc' to modify the VNC server expiration
429+# - 'spice' to modify the Spice server expiration
430+
431 # @time: when to expire the password.
432 #
433 # - 'now' to expire the password immediately
434@@ -54,24 +162,33 @@
435 # - '+INT' where INT is the number of seconds from now (integer)
436 # - 'INT' where INT is the absolute time in seconds
437 #
438-# Returns: - Nothing on success
439-# - If @protocol is 'spice' and Spice is not active, DeviceNotFound
440-#
441-# Since: 0.14
442-#
443 # Notes: Time is relative to the server and currently there is no way to
444 # coordinate server time with client time. It is not recommended to
445 # use the absolute time version of the @time parameter unless you're
446 # sure you are on the same machine as the QEMU instance.
447 #
448-# Example:
449+# Since: 6.2
450 #
451-# -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
452-# "time": "+60" } }
453-# <- { "return": {} }
454+##
455+{ 'union': 'ExpirePasswordOptions',
456+ 'base': { 'protocol': 'DisplayProtocol',
457+ 'time': 'str' },
458+ 'discriminator': 'protocol',
459+ 'data': { 'vnc': 'ExpirePasswordOptionsVnc' } }
460+
461+##
462+# @ExpirePasswordOptionsVnc:
463+#
464+# Options for expire_password specific to the VNC procotol.
465+#
466+# @display: The id of the display where the expiration should be changed.
467+# Defaults to the first.
468+#
469+# Since: 6.2
470 #
471 ##
472-{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }
473+{ 'struct': 'ExpirePasswordOptionsVnc',
474+ 'data': { '*display': 'str' } }
475
476 ##
477 # @screendump: