qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/5] VNC-related HMP/QMP fixes
@ 2021-10-20 13:54 Stefan Reiter
  2021-10-20 13:54 ` [PATCH v6 1/5] monitor/hmp: add support for flag argument with value Stefan Reiter
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:54 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

Since the removal of the generic 'qmp_change' command, one can no longer replace
the 'default' VNC display listen address at runtime (AFAIK). For our users who
need to set up a secondary VNC access port, this means configuring a second VNC
display (in addition to our standard one for web-access), but it turns out one
cannot set a password on this second display at the moment, as the
'set_password' call only operates on the 'default' display.

Additionally, using secret objects, the password is only read once at startup.
This could be considered a bug too, but is not touched in this series and left
for a later date.

v5 -> v6:
* consider feedback from Markus' review, mainly:
  * fix crash bug in patch 1 (sorry, artifact of patch-splitting)
  * rely on '!has_param => param == NULL' to shorten code
  * add note to 'docs/about/deprecated.rst' and touch up comments a bit
* go back to g_free instead of qapi_free_* since the latter apparently tries to
  free the passed in pointer which lives on the stack...
* fix bug in HMP parsing (see patch 1)

v4 -> v5:
* add comment to patch 1 in "monitor-internal.h"
* use qapi_free_SetPasswordOptions and friends, don't leak strdups
* split QAPI change into 3 seperate patches

v3 -> v4:
* drop previously patch 1, this was fixed here instead:
  https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg02529.html
* patch 1: add Eric's R-b
* patch 2: remove if-assignment, use 'deprecated' feature in schema

v2 -> v3:
* refactor QMP schema for set/expire_password as suggested by Eric Blake and
  Markus Armbruster

v1 -> v2:
* add Marc-André's R-b on patch 1
* use '-d' flag as suggested by Eric Blake and Gerd Hoffmann
  * I didn't see a way to do this yet, so I added a "flags with values" arg type


Stefan Reiter (5):
  monitor/hmp: add support for flag argument with value
  qapi/monitor: refactor set/expire_password with enums
  qapi/monitor: allow VNC display id in set/expire_password
  qapi/monitor: only allow 'keep' SetPasswordAction for VNC and
    deprecate
  docs: add deprecation note about 'set_password' param 'connected'

 docs/about/deprecated.rst  |   6 ++
 hmp-commands.hx            |  24 +++---
 monitor/hmp-cmds.c         |  54 ++++++++++++-
 monitor/hmp.c              |  19 ++++-
 monitor/monitor-internal.h |   3 +-
 monitor/qmp-cmds.c         |  54 ++++---------
 qapi/ui.json               | 156 ++++++++++++++++++++++++++++++++-----
 7 files changed, 242 insertions(+), 74 deletions(-)

-- 
2.30.2



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v6 1/5] monitor/hmp: add support for flag argument with value
  2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
@ 2021-10-20 13:54 ` Stefan Reiter
  2021-10-29 19:50   ` Eric Blake
  2021-10-20 13:54 ` [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums Stefan Reiter
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:54 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

Adds support for the "-xV" parameter type, where "-x" denotes a flag
name and the "V" suffix indicates that this flag is supposed to take an
arbitrary string parameter.

These parameters are always optional, the entry in the qdict will be
omitted if the flag is not given.

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---

v6:
It wasn't possible to pass the 'connected' parameter to set_password, since the
code to handle optional parameters couldn't live with a different param (not
starting with '-') coming up instead - fix that by advancing over the 'value
flag' modifier in case `*p != '-'`.

Also change the modifier to 'V' instead of 'S' so it can be distinguished from
an actual trailing 'S' type param.

Discovered in testing. I dropped Eric's R-b due to the code change.

 monitor/hmp.c              | 19 ++++++++++++++++++-
 monitor/monitor-internal.h |  3 ++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/monitor/hmp.c b/monitor/hmp.c
index d50c3124e1..899e0c990f 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -980,6 +980,7 @@ static QDict *monitor_parse_arguments(Monitor *mon,
             {
                 const char *tmp = p;
                 int skip_key = 0;
+                int ret;
                 /* option */
 
                 c = *typestr++;
@@ -1002,11 +1003,27 @@ static QDict *monitor_parse_arguments(Monitor *mon,
                     }
                     if (skip_key) {
                         p = tmp;
+                    } else if (*typestr == 'V') {
+                        /* has option with string value */
+                        typestr++;
+                        tmp = p++;
+                        while (qemu_isspace(*p)) {
+                            p++;
+                        }
+                        ret = get_str(buf, sizeof(buf), &p);
+                        if (ret < 0) {
+                            monitor_printf(mon, "%s: value expected for -%c\n",
+                                           cmd->name, *tmp);
+                            goto fail;
+                        }
+                        qdict_put_str(qdict, key, buf);
                     } else {
-                        /* has option */
+                        /* has boolean option */
                         p++;
                         qdict_put_bool(qdict, key, true);
                     }
+                } else if (*typestr == 'V') {
+                    typestr++;
                 }
             }
             break;
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 9c3a09cb01..9e708b329d 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -63,7 +63,8 @@
  * '.'          other form of optional type (for 'i' and 'l')
  * 'b'          boolean
  *              user mode accepts "on" or "off"
- * '-'          optional parameter (eg. '-f')
+ * '-'          optional parameter (eg. '-f'); if followed by an 'V', it
+ *              specifies an optional string param (e.g. '-fV' allows '-f foo')
  *
  */
 
-- 
2.30.2




^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums
  2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
  2021-10-20 13:54 ` [PATCH v6 1/5] monitor/hmp: add support for flag argument with value Stefan Reiter
@ 2021-10-20 13:54 ` Stefan Reiter
  2021-10-21  4:38   ` Markus Armbruster
  2021-10-20 13:54 ` [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password Stefan Reiter
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:54 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

'protocol' and 'connected' are better suited as enums than as strings,
make use of that. No functional change intended.

Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
 monitor/hmp-cmds.c | 29 +++++++++++++++++++++++++++--
 monitor/qmp-cmds.c | 37 ++++++++++++-------------------------
 qapi/ui.json       | 37 +++++++++++++++++++++++++++++++++++--
 3 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index bcaa41350e..b8abe69609 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1453,8 +1453,24 @@ void hmp_set_password(Monitor *mon, const QDict *qdict)
     const char *password  = qdict_get_str(qdict, "password");
     const char *connected = qdict_get_try_str(qdict, "connected");
     Error *err = NULL;
+    DisplayProtocol proto;
+    SetPasswordAction conn;
 
-    qmp_set_password(protocol, password, !!connected, connected, &err);
+    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
+                            DISPLAY_PROTOCOL_VNC, &err);
+    if (err) {
+        goto out;
+    }
+
+    conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
+                           SET_PASSWORD_ACTION_KEEP, &err);
+    if (err) {
+        goto out;
+    }
+
+    qmp_set_password(proto, password, !!connected, conn, &err);
+
+out:
     hmp_handle_error(mon, err);
 }
 
@@ -1463,8 +1479,17 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
     const char *protocol  = qdict_get_str(qdict, "protocol");
     const char *whenstr = qdict_get_str(qdict, "time");
     Error *err = NULL;
+    DisplayProtocol proto;
 
-    qmp_expire_password(protocol, whenstr, &err);
+    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
+                            DISPLAY_PROTOCOL_VNC, &err);
+    if (err) {
+        goto out;
+    }
+
+    qmp_expire_password(proto, whenstr, &err);
+
+out:
     hmp_handle_error(mon, err);
 }
 
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 5c0d5e116b..0654d7289a 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -163,33 +163,27 @@ void qmp_system_wakeup(Error **errp)
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
 }
 
-void qmp_set_password(const char *protocol, const char *password,
-                      bool has_connected, const char *connected, Error **errp)
+void qmp_set_password(DisplayProtocol protocol, const char *password,
+                      bool has_connected, SetPasswordAction 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_setg(errp, QERR_INVALID_PARAMETER, "connected");
-            return;
-        }
+        fail_if_connected = connected == SET_PASSWORD_ACTION_FAIL;
+        disconnect_if_connected = connected == SET_PASSWORD_ACTION_DISCONNECT;
     }
 
-    if (strcmp(protocol, "spice") == 0) {
+    if (protocol == DISPLAY_PROTOCOL_SPICE) {
         if (!qemu_using_spice(errp)) {
             return;
         }
         rc = qemu_spice.set_passwd(password, fail_if_connected,
                                    disconnect_if_connected);
-    } else if (strcmp(protocol, "vnc") == 0) {
+    } else {
+        assert(protocol == DISPLAY_PROTOCOL_VNC);
         if (fail_if_connected || disconnect_if_connected) {
             /* vnc supports "connected=keep" only */
             error_setg(errp, QERR_INVALID_PARAMETER, "connected");
@@ -198,10 +192,6 @@ void qmp_set_password(const char *protocol, const char *password,
         /* Note that setting an empty password will not disable login through
          * this interface. */
         rc = vnc_display_password(NULL, password);
-    } else {
-        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
-                   "'vnc' or 'spice'");
-        return;
     }
 
     if (rc != 0) {
@@ -209,7 +199,7 @@ void qmp_set_password(const char *protocol, const char *password,
     }
 }
 
-void qmp_expire_password(const char *protocol, const char *whenstr,
+void qmp_expire_password(DisplayProtocol protocol, const char *whenstr,
                          Error **errp)
 {
     time_t when;
@@ -225,17 +215,14 @@ void qmp_expire_password(const char *protocol, const char *whenstr,
         when = strtoull(whenstr, NULL, 10);
     }
 
-    if (strcmp(protocol, "spice") == 0) {
+    if (protocol == DISPLAY_PROTOCOL_SPICE) {
         if (!qemu_using_spice(errp)) {
             return;
         }
         rc = qemu_spice.set_pw_expire(when);
-    } else if (strcmp(protocol, "vnc") == 0) {
-        rc = vnc_display_pw_expire(NULL, when);
     } else {
-        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "protocol",
-                   "'vnc' or 'spice'");
-        return;
+        assert(protocol == DISPLAY_PROTOCOL_VNC);
+        rc = vnc_display_pw_expire(NULL, when);
     }
 
     if (rc != 0) {
diff --git a/qapi/ui.json b/qapi/ui.json
index d7567ac866..15cc19dcc5 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -9,6 +9,35 @@
 { 'include': 'common.json' }
 { 'include': 'sockets.json' }
 
+##
+# @DisplayProtocol:
+#
+# Display protocols which support changing password options.
+#
+# Since: 6.2
+#
+##
+{ 'enum': 'DisplayProtocol',
+  'data': [ { 'name': 'vnc', 'if': 'CONFIG_VNC' },
+            { 'name': 'spice', 'if': 'CONFIG_SPICE' } ] }
+
+##
+# @SetPasswordAction:
+#
+# An action to take on changing a password on a connection with active clients.
+#
+# @fail: fail the command if clients are connected
+#
+# @disconnect: disconnect existing clients
+#
+# @keep: maintain existing clients
+#
+# Since: 6.2
+#
+##
+{ 'enum': 'SetPasswordAction',
+  'data': [ 'fail', 'disconnect', 'keep' ] }
+
 ##
 # @set_password:
 #
@@ -38,7 +67,9 @@
 #
 ##
 { 'command': 'set_password',
-  'data': {'protocol': 'str', 'password': 'str', '*connected': 'str'} }
+  'data': { 'protocol': 'DisplayProtocol',
+            'password': 'str',
+            '*connected': 'SetPasswordAction' } }
 
 ##
 # @expire_password:
@@ -71,7 +102,9 @@
 # <- { "return": {} }
 #
 ##
-{ 'command': 'expire_password', 'data': {'protocol': 'str', 'time': 'str'} }
+{ 'command': 'expire_password',
+  'data': { 'protocol': 'DisplayProtocol',
+            'time': 'str' } }
 
 ##
 # @screendump:
-- 
2.30.2




^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password
  2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
  2021-10-20 13:54 ` [PATCH v6 1/5] monitor/hmp: add support for flag argument with value Stefan Reiter
  2021-10-20 13:54 ` [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums Stefan Reiter
@ 2021-10-20 13:54 ` Stefan Reiter
  2021-10-21  5:05   ` Markus Armbruster
  2021-10-20 13:54 ` [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate Stefan Reiter
  2021-10-20 13:55 ` [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected' Stefan Reiter
  4 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:54 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

It is possible to specify more than one VNC server on the command line,
either with an explicit ID or the auto-generated ones à la "default",
"vnc2", "vnc3", ...

It is not possible to change the password on one of these extra VNC
displays though. Fix this by adding a "display" parameter to the
"set_password" and "expire_password" QMP and HMP commands.

For HMP, the display is specified using the "-d" value flag.

For QMP, the schema is updated to explicitly express the supported
variants of the commands with protocol-discriminated unions.

Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
 hmp-commands.hx    |  24 +++++-----
 monitor/hmp-cmds.c |  51 +++++++++++++++------
 monitor/qmp-cmds.c |  36 ++++++---------
 qapi/ui.json       | 112 +++++++++++++++++++++++++++++++++++----------
 4 files changed, 154 insertions(+), 69 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index cf723c69ac..9fbb207b35 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1514,33 +1514,35 @@ ERST
 
     {
         .name       = "set_password",
-        .args_type  = "protocol:s,password:s,connected:s?",
-        .params     = "protocol password action-if-connected",
+        .args_type  = "protocol:s,password:s,display:-dV,connected:s?",
+        .params     = "protocol password [-d display] [action-if-connected]",
         .help       = "set spice/vnc password",
         .cmd        = hmp_set_password,
     },
 
 SRST
-``set_password [ vnc | spice ] password [ action-if-connected ]``
-  Change spice/vnc password.  *action-if-connected* specifies what
-  should happen in case a connection is established: *fail* makes the
-  password change fail.  *disconnect* changes the password and
+``set_password [ vnc | spice ] password [ -d display ] [ action-if-connected ]``
+  Change spice/vnc password.  *display* can be used with 'vnc' to specify
+  which display to set the password on.  *action-if-connected* specifies
+  what should happen in case a connection is established: *fail* makes
+  the password change fail.  *disconnect* changes the password and
   disconnects the client.  *keep* changes the password and keeps the
   connection up.  *keep* is the default.
 ERST
 
     {
         .name       = "expire_password",
-        .args_type  = "protocol:s,time:s",
-        .params     = "protocol time",
+        .args_type  = "protocol:s,time:s,display:-dV",
+        .params     = "protocol time [-d display]",
         .help       = "set spice/vnc password expire-time",
         .cmd        = hmp_expire_password,
     },
 
 SRST
-``expire_password [ vnc | spice ]`` *expire-time*
-  Specify when a password for spice/vnc becomes
-  invalid. *expire-time* accepts:
+``expire_password [ vnc | spice ] expire-time [ -d display ]``
+  Specify when a password for spice/vnc becomes invalid.
+  *display* behaves the same as in ``set_password``.
+  *expire-time* accepts:
 
   ``now``
     Invalidate password instantly.
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index b8abe69609..daa4a8e106 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1451,26 +1451,39 @@ 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 *display = qdict_get_try_str(qdict, "display");
     const char *connected = qdict_get_try_str(qdict, "connected");
     Error *err = NULL;
-    DisplayProtocol proto;
-    SetPasswordAction conn;
 
-    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
-                            DISPLAY_PROTOCOL_VNC, &err);
+    SetPasswordOptions opts = {
+        .password = g_strdup(password),
+        .u.vnc.display = NULL,
+    };
+
+    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
+                                    DISPLAY_PROTOCOL_VNC, &err);
     if (err) {
         goto out;
     }
 
-    conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
-                           SET_PASSWORD_ACTION_KEEP, &err);
-    if (err) {
-        goto out;
+    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
+        opts.u.vnc.has_display = !!display;
+        opts.u.vnc.display = g_strdup(display);
+    } else if (opts.protocol == DISPLAY_PROTOCOL_SPICE) {
+        opts.u.spice.has_connected = !!connected;
+        opts.u.spice.connected =
+            qapi_enum_parse(&SetPasswordAction_lookup, connected,
+                            SET_PASSWORD_ACTION_KEEP, &err);
+        if (err) {
+            goto out;
+        }
     }
 
-    qmp_set_password(proto, password, !!connected, conn, &err);
+    qmp_set_password(&opts, &err);
 
 out:
+    g_free(opts.password);
+    g_free(opts.u.vnc.display);
     hmp_handle_error(mon, err);
 }
 
@@ -1478,18 +1491,30 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
 {
     const char *protocol  = qdict_get_str(qdict, "protocol");
     const char *whenstr = qdict_get_str(qdict, "time");
+    const char *display = qdict_get_try_str(qdict, "display");
     Error *err = NULL;
-    DisplayProtocol proto;
 
-    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
-                            DISPLAY_PROTOCOL_VNC, &err);
+    ExpirePasswordOptions opts = {
+        .time = g_strdup(whenstr),
+        .u.vnc.display = NULL,
+    };
+
+    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
+                                    DISPLAY_PROTOCOL_VNC, &err);
     if (err) {
         goto out;
     }
 
-    qmp_expire_password(proto, whenstr, &err);
+    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
+        opts.u.vnc.has_display = !!display;
+        opts.u.vnc.display = g_strdup(display);
+    }
+
+    qmp_expire_password(&opts, &err);
 
 out:
+    g_free(opts.time);
+    g_free(opts.u.vnc.display);
     hmp_handle_error(mon, err);
 }
 
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 0654d7289a..5637bd70b6 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -163,35 +163,27 @@ void qmp_system_wakeup(Error **errp)
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
 }
 
-void qmp_set_password(DisplayProtocol protocol, const char *password,
-                      bool has_connected, SetPasswordAction connected,
-                      Error **errp)
+void qmp_set_password(SetPasswordOptions *opts, Error **errp)
 {
-    int disconnect_if_connected = 0;
-    int fail_if_connected = 0;
-    int rc;
+    int rc = 0;
 
-    if (has_connected) {
-        fail_if_connected = connected == SET_PASSWORD_ACTION_FAIL;
-        disconnect_if_connected = connected == SET_PASSWORD_ACTION_DISCONNECT;
-    }
-
-    if (protocol == DISPLAY_PROTOCOL_SPICE) {
+    if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
         if (!qemu_using_spice(errp)) {
             return;
         }
-        rc = qemu_spice.set_passwd(password, fail_if_connected,
-                                   disconnect_if_connected);
+        rc = qemu_spice.set_passwd(opts->password,
+                opts->u.spice.connected == SET_PASSWORD_ACTION_FAIL,
+                opts->u.spice.connected == SET_PASSWORD_ACTION_DISCONNECT);
     } else {
-        assert(protocol == DISPLAY_PROTOCOL_VNC);
-        if (fail_if_connected || disconnect_if_connected) {
+        assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
+        if (opts->u.vnc.connected != SET_PASSWORD_ACTION_KEEP) {
             /* vnc supports "connected=keep" only */
             error_setg(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);
+        rc = vnc_display_password(opts->u.vnc.display, opts->password);
     }
 
     if (rc != 0) {
@@ -199,11 +191,11 @@ void qmp_set_password(DisplayProtocol protocol, const char *password,
     }
 }
 
-void qmp_expire_password(DisplayProtocol protocol, const char *whenstr,
-                         Error **errp)
+void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp)
 {
     time_t when;
     int rc;
+    const char *whenstr = opts->time;
 
     if (strcmp(whenstr, "now") == 0) {
         when = 0;
@@ -215,14 +207,14 @@ void qmp_expire_password(DisplayProtocol protocol, const char *whenstr,
         when = strtoull(whenstr, NULL, 10);
     }
 
-    if (protocol == DISPLAY_PROTOCOL_SPICE) {
+    if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
         if (!qemu_using_spice(errp)) {
             return;
         }
         rc = qemu_spice.set_pw_expire(when);
     } else {
-        assert(protocol == DISPLAY_PROTOCOL_VNC);
-        rc = vnc_display_pw_expire(NULL, when);
+        assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
+        rc = vnc_display_pw_expire(opts->u.vnc.display, when);
     }
 
     if (rc != 0) {
diff --git a/qapi/ui.json b/qapi/ui.json
index 15cc19dcc5..99ac29ad9c 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -39,20 +39,61 @@
   'data': [ 'fail', 'disconnect', 'keep' ] }
 
 ##
-# @set_password:
+# @SetPasswordOptions:
 #
-# Sets the password of a remote display session.
+# General options for set_password.
 #
 # @protocol: - 'vnc' to modify the VNC server password
 #            - 'spice' to modify the Spice server password
 #
 # @password: the new password
 #
-# @connected: 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
+# Since: 6.2
+#
+##
+{ 'union': 'SetPasswordOptions',
+  'base': { 'protocol': 'DisplayProtocol',
+            'password': 'str' },
+  'discriminator': 'protocol',
+  'data': { 'vnc': 'SetPasswordOptionsVnc',
+            'spice': 'SetPasswordOptionsSpice' } }
+
+##
+# @SetPasswordOptionsSpice:
+#
+# Options for set_password specific to the SPICE procotol.
+#
+# @connected: How to handle existing clients when changing the
+#             password. If nothing is specified, defaults to 'keep'.
+#
+# Since: 6.2
+#
+##
+{ 'struct': 'SetPasswordOptionsSpice',
+  'data': { '*connected': 'SetPasswordAction' } }
+
+##
+# @SetPasswordOptionsVnc:
+#
+# Options for set_password specific to the VNC procotol.
+#
+# @display: The id of the display where the password should be changed.
+#           Defaults to the first.
+#
+# @connected: How to handle existing clients when changing the
+#             password.
+#
+# Since: 6.2
+#
+##
+{ 'struct': 'SetPasswordOptionsVnc',
+  'data': { '*display': 'str',
+            '*connected': 'SetPasswordAction' }}
+
+##
+# @set_password:
+#
+# Set the password of a remote display server.
 #
 # Returns: - Nothing on success
 #          - If Spice is not enabled, DeviceNotFound
@@ -66,18 +107,16 @@
 # <- { "return": {} }
 #
 ##
-{ 'command': 'set_password',
-  'data': { 'protocol': 'DisplayProtocol',
-            'password': 'str',
-            '*connected': 'SetPasswordAction' } }
+{ 'command': 'set_password', 'boxed': true, 'data': 'SetPasswordOptions' }
 
 ##
-# @expire_password:
+# @ExpirePasswordOptions:
 #
-# Expire the password of a remote display server.
-#
-# @protocol: the name of the remote display protocol 'vnc' or 'spice'
+# General options for expire_password.
 #
+# @protocol: - 'vnc' to modify the VNC server expiration
+#            - 'spice' to modify the Spice server expiration
+
 # @time: when to expire the password.
 #
 #        - 'now' to expire the password immediately
@@ -85,16 +124,45 @@
 #        - '+INT' where INT is the number of seconds from now (integer)
 #        - 'INT' where INT is the absolute time in seconds
 #
-# Returns: - Nothing on success
-#          - If @protocol is 'spice' and Spice is not active, DeviceNotFound
-#
-# Since: 0.14
-#
 # Notes: Time is relative to the server and currently there is no way to
 #        coordinate server time with client time.  It is not recommended to
 #        use the absolute time version of the @time parameter unless you're
 #        sure you are on the same machine as the QEMU instance.
 #
+# Since: 6.2
+#
+##
+{ 'union': 'ExpirePasswordOptions',
+  'base': { 'protocol': 'DisplayProtocol',
+            'time': 'str' },
+  'discriminator': 'protocol',
+  'data': { 'vnc': 'ExpirePasswordOptionsVnc' } }
+
+##
+# @ExpirePasswordOptionsVnc:
+#
+# Options for expire_password specific to the VNC procotol.
+#
+# @display: The id of the display where the expiration should be changed.
+#           Defaults to the first.
+#
+# Since: 6.2
+#
+##
+
+{ 'struct': 'ExpirePasswordOptionsVnc',
+  'data': { '*display': 'str' } }
+
+##
+# @expire_password:
+#
+# Expire the password of a remote display server.
+#
+# Returns: - Nothing on success
+#          - If @protocol is 'spice' and Spice is not active, DeviceNotFound
+#
+# Since: 0.14
+#
 # Example:
 #
 # -> { "execute": "expire_password", "arguments": { "protocol": "vnc",
@@ -102,9 +170,7 @@
 # <- { "return": {} }
 #
 ##
-{ 'command': 'expire_password',
-  'data': { 'protocol': 'DisplayProtocol',
-            'time': 'str' } }
+{ 'command': 'expire_password', 'boxed': true, 'data': 'ExpirePasswordOptions' }
 
 ##
 # @screendump:
-- 
2.30.2




^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate
  2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
                   ` (2 preceding siblings ...)
  2021-10-20 13:54 ` [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password Stefan Reiter
@ 2021-10-20 13:54 ` Stefan Reiter
  2021-10-21  5:16   ` Markus Armbruster
  2021-10-20 13:55 ` [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected' Stefan Reiter
  4 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:54 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

VNC only supports 'keep' here, enforce this via a seperate
SetPasswordActionVnc enum and mark the option 'deprecated' (as it is
useless with only one value possible).

Suggested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---
 monitor/qmp-cmds.c |  5 -----
 qapi/ui.json       | 21 ++++++++++++++++++++-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 5637bd70b6..4825d0cbea 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -176,11 +176,6 @@ void qmp_set_password(SetPasswordOptions *opts, Error **errp)
                 opts->u.spice.connected == SET_PASSWORD_ACTION_DISCONNECT);
     } else {
         assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
-        if (opts->u.vnc.connected != SET_PASSWORD_ACTION_KEEP) {
-            /* vnc supports "connected=keep" only */
-            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
-            return;
-        }
         /* Note that setting an empty password will not disable login through
          * this interface. */
         rc = vnc_display_password(opts->u.vnc.display, opts->password);
diff --git a/qapi/ui.json b/qapi/ui.json
index 99ac29ad9c..5292617b44 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -38,6 +38,20 @@
 { 'enum': 'SetPasswordAction',
   'data': [ 'fail', 'disconnect', 'keep' ] }
 
+##
+# @SetPasswordActionVnc:
+#
+# See @SetPasswordAction. VNC only supports the keep action. 'connection'
+# should just be omitted for VNC, this is kept for backwards compatibility.
+#
+# @keep: maintain existing clients
+#
+# Since: 6.2
+#
+##
+{ 'enum': 'SetPasswordActionVnc',
+  'data': [ 'keep' ] }
+
 ##
 # @SetPasswordOptions:
 #
@@ -83,12 +97,17 @@
 # @connected: How to handle existing clients when changing the
 #             password.
 #
+# Features:
+# @deprecated: For VNC, @connected will always be 'keep', parameter should be
+#              omitted.
+#
 # Since: 6.2
 #
 ##
 { 'struct': 'SetPasswordOptionsVnc',
   'data': { '*display': 'str',
-            '*connected': 'SetPasswordAction' }}
+            '*connected': { 'type': 'SetPasswordActionVnc',
+                            'features': ['deprecated'] } } }
 
 ##
 # @set_password:
-- 
2.30.2




^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected'
  2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
                   ` (3 preceding siblings ...)
  2021-10-20 13:54 ` [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate Stefan Reiter
@ 2021-10-20 13:55 ` Stefan Reiter
  2021-10-21  5:16   ` Markus Armbruster
  4 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-20 13:55 UTC (permalink / raw)
  To: Marc-André Lureau, Marc-André Lureau,
	Dr. David Alan Gilbert, Markus Armbruster, Paolo Bonzini,
	Eric Blake, Gerd Hoffmann, Wolfgang Bumiller, Thomas Lamprecht
  Cc: qemu-devel

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
---

Seperate patch since it read a bit unsure in the review, feel free to either
drop or squash this.

 docs/about/deprecated.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 0bed6ecb1d..1ad08e57d2 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -228,6 +228,12 @@ Use the more generic commands ``block-export-add`` and ``block-export-del``
 instead.  As part of this deprecation, where ``nbd-server-add`` used a
 single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``.
 
+``set_password`` argument ``connected`` for VNC protocol (since 6.2)
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Only the value ``keep`` is and was ever supported for VNC. It is recommended to
+just drop the argument.
+
 System accelerators
 -------------------
 
-- 
2.30.2




^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums
  2021-10-20 13:54 ` [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums Stefan Reiter
@ 2021-10-21  4:38   ` Markus Armbruster
  0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2021-10-21  4:38 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

Stefan Reiter <s.reiter@proxmox.com> writes:

> 'protocol' and 'connected' are better suited as enums than as strings,
> make use of that. No functional change intended.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>

Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password
  2021-10-20 13:54 ` [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password Stefan Reiter
@ 2021-10-21  5:05   ` Markus Armbruster
  2021-10-21  8:42     ` Stefan Reiter
  0 siblings, 1 reply; 13+ messages in thread
From: Markus Armbruster @ 2021-10-21  5:05 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

Stefan Reiter <s.reiter@proxmox.com> writes:

> It is possible to specify more than one VNC server on the command line,
> either with an explicit ID or the auto-generated ones à la "default",
> "vnc2", "vnc3", ...
>
> It is not possible to change the password on one of these extra VNC
> displays though. Fix this by adding a "display" parameter to the
> "set_password" and "expire_password" QMP and HMP commands.
>
> For HMP, the display is specified using the "-d" value flag.
>
> For QMP, the schema is updated to explicitly express the supported
> variants of the commands with protocol-discriminated unions.
>
> Suggested-by: Markus Armbruster <armbru@redhat.com>
> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
> ---
>  hmp-commands.hx    |  24 +++++-----
>  monitor/hmp-cmds.c |  51 +++++++++++++++------
>  monitor/qmp-cmds.c |  36 ++++++---------
>  qapi/ui.json       | 112 +++++++++++++++++++++++++++++++++++----------
>  4 files changed, 154 insertions(+), 69 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index cf723c69ac..9fbb207b35 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1514,33 +1514,35 @@ ERST
>  
>      {
>          .name       = "set_password",
> -        .args_type  = "protocol:s,password:s,connected:s?",
> -        .params     = "protocol password action-if-connected",
> +        .args_type  = "protocol:s,password:s,display:-dV,connected:s?",
> +        .params     = "protocol password [-d display] [action-if-connected]",
>          .help       = "set spice/vnc password",
>          .cmd        = hmp_set_password,
>      },
>  
>  SRST
> -``set_password [ vnc | spice ] password [ action-if-connected ]``
> -  Change spice/vnc password.  *action-if-connected* specifies what
> -  should happen in case a connection is established: *fail* makes the
> -  password change fail.  *disconnect* changes the password and
> +``set_password [ vnc | spice ] password [ -d display ] [ action-if-connected ]``
> +  Change spice/vnc password.  *display* can be used with 'vnc' to specify
> +  which display to set the password on.  *action-if-connected* specifies
> +  what should happen in case a connection is established: *fail* makes
> +  the password change fail.  *disconnect* changes the password and
>    disconnects the client.  *keep* changes the password and keeps the
>    connection up.  *keep* is the default.
>  ERST
>  
>      {
>          .name       = "expire_password",
> -        .args_type  = "protocol:s,time:s",
> -        .params     = "protocol time",
> +        .args_type  = "protocol:s,time:s,display:-dV",
> +        .params     = "protocol time [-d display]",
>          .help       = "set spice/vnc password expire-time",
>          .cmd        = hmp_expire_password,
>      },
>  
>  SRST
> -``expire_password [ vnc | spice ]`` *expire-time*
> -  Specify when a password for spice/vnc becomes
> -  invalid. *expire-time* accepts:
> +``expire_password [ vnc | spice ] expire-time [ -d display ]``
> +  Specify when a password for spice/vnc becomes invalid.
> +  *display* behaves the same as in ``set_password``.
> +  *expire-time* accepts:
>  
>    ``now``
>      Invalidate password instantly.
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index b8abe69609..daa4a8e106 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -1451,26 +1451,39 @@ 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 *display = qdict_get_try_str(qdict, "display");
>      const char *connected = qdict_get_try_str(qdict, "connected");
>      Error *err = NULL;
> -    DisplayProtocol proto;
> -    SetPasswordAction conn;
>  
> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> -                            DISPLAY_PROTOCOL_VNC, &err);
> +    SetPasswordOptions opts = {
> +        .password = g_strdup(password),
> +        .u.vnc.display = NULL,
> +    };
> +
> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> +                                    DISPLAY_PROTOCOL_VNC, &err);
>      if (err) {
>          goto out;
>      }
>  
> -    conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
> -                           SET_PASSWORD_ACTION_KEEP, &err);
> -    if (err) {
> -        goto out;
> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
> +        opts.u.vnc.has_display = !!display;
> +        opts.u.vnc.display = g_strdup(display);
> +    } else if (opts.protocol == DISPLAY_PROTOCOL_SPICE) {
> +        opts.u.spice.has_connected = !!connected;
> +        opts.u.spice.connected =
> +            qapi_enum_parse(&SetPasswordAction_lookup, connected,
> +                            SET_PASSWORD_ACTION_KEEP, &err);
> +        if (err) {
> +            goto out;
> +        }
>      }
>  
> -    qmp_set_password(proto, password, !!connected, conn, &err);
> +    qmp_set_password(&opts, &err);
>  
>  out:
> +    g_free(opts.password);
> +    g_free(opts.u.vnc.display);

Uh-oh...

For DISPLAY_PROTOCOL_SPICE, we execute

           .u.vnc.display = NULL,
           opts.u.spice.has_connected = !!connected;
           opts.u.spice.connected =
               qapi_enum_parse(&SetPasswordAction_lookup, connected,
                               SET_PASSWORD_ACTION_KEEP, &err);
           opts.u.vnc.has_display = !!display;
       g_free(opts.u.vnc.display);

The assignments to opts.u.spice.has_connected and opts.u.spice_connected
clobber opts.u.vnc.display.

The simplest fix is to pass @display directly.  Precedence:
hmp_drive_mirror().

Do the same for @password, of course.

>      hmp_handle_error(mon, err);
>  }
>  
> @@ -1478,18 +1491,30 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
>  {
>      const char *protocol  = qdict_get_str(qdict, "protocol");
>      const char *whenstr = qdict_get_str(qdict, "time");
> +    const char *display = qdict_get_try_str(qdict, "display");
>      Error *err = NULL;
> -    DisplayProtocol proto;
>  
> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> -                            DISPLAY_PROTOCOL_VNC, &err);
> +    ExpirePasswordOptions opts = {
> +        .time = g_strdup(whenstr),
> +        .u.vnc.display = NULL,
> +    };
> +
> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
> +                                    DISPLAY_PROTOCOL_VNC, &err);
>      if (err) {
>          goto out;
>      }
>  
> -    qmp_expire_password(proto, whenstr, &err);
> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
> +        opts.u.vnc.has_display = !!display;
> +        opts.u.vnc.display = g_strdup(display);
> +    }

Use of -d with spice are silently ignored.  Do we care?  Same for
hmp_set_password() above.

> +
> +    qmp_expire_password(&opts, &err);
>  
>  out:
> +    g_free(opts.time);
> +    g_free(opts.u.vnc.display);

No uh-oh here, since opts.u.vnc is actually the only member of opts.u.
Still, let's pass @time and @display directly for consistency and
robustness.

>      hmp_handle_error(mon, err);
>  }
>  

[...]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected'
  2021-10-20 13:55 ` [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected' Stefan Reiter
@ 2021-10-21  5:16   ` Markus Armbruster
  0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2021-10-21  5:16 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

Stefan Reiter <s.reiter@proxmox.com> writes:

> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
> ---
>
> Seperate patch since it read a bit unsure in the review, feel free to either
> drop or squash this.
>
>  docs/about/deprecated.rst | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 0bed6ecb1d..1ad08e57d2 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -228,6 +228,12 @@ Use the more generic commands ``block-export-add`` and ``block-export-del``
>  instead.  As part of this deprecation, where ``nbd-server-add`` used a
>  single ``bitmap``, the new ``block-export-add`` uses a list of ``bitmaps``.
>  
> +``set_password`` argument ``connected`` for VNC protocol (since 6.2)
> +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
> +
> +Only the value ``keep`` is and was ever supported for VNC. It is recommended to
> +just drop the argument.
> +
>  System accelerators
>  -------------------

This is okay.  Possibly clearer:

   Only the value ``keep`` is and was ever supported for VNC.  The
   (useless) argument will be dropped in a future version of QEMU.

Either phrasing is
Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate
  2021-10-20 13:54 ` [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate Stefan Reiter
@ 2021-10-21  5:16   ` Markus Armbruster
  0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2021-10-21  5:16 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

Stefan Reiter <s.reiter@proxmox.com> writes:

> VNC only supports 'keep' here, enforce this via a seperate
> SetPasswordActionVnc enum and mark the option 'deprecated' (as it is
> useless with only one value possible).
>
> Suggested-by: Eric Blake <eblake@redhat.com>
> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>

With the next patch squashed in:
Reviewed-by: Markus Armbruster <armbru@redhat.com>



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password
  2021-10-21  5:05   ` Markus Armbruster
@ 2021-10-21  8:42     ` Stefan Reiter
  2021-10-21  9:35       ` Markus Armbruster
  0 siblings, 1 reply; 13+ messages in thread
From: Stefan Reiter @ 2021-10-21  8:42 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

On 10/21/21 7:05 AM, Markus Armbruster wrote:
> Stefan Reiter <s.reiter@proxmox.com> writes:
> 
>> It is possible to specify more than one VNC server on the command line,
>> either with an explicit ID or the auto-generated ones à la "default",
>> "vnc2", "vnc3", ...
>>
>> It is not possible to change the password on one of these extra VNC
>> displays though. Fix this by adding a "display" parameter to the
>> "set_password" and "expire_password" QMP and HMP commands.
>>
>> For HMP, the display is specified using the "-d" value flag.
>>
>> For QMP, the schema is updated to explicitly express the supported
>> variants of the commands with protocol-discriminated unions.
>>
>> Suggested-by: Markus Armbruster <armbru@redhat.com>
>> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
>> ---
>>   hmp-commands.hx    |  24 +++++-----
>>   monitor/hmp-cmds.c |  51 +++++++++++++++------
>>   monitor/qmp-cmds.c |  36 ++++++---------
>>   qapi/ui.json       | 112 +++++++++++++++++++++++++++++++++++----------
>>   4 files changed, 154 insertions(+), 69 deletions(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index cf723c69ac..9fbb207b35 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -1514,33 +1514,35 @@ ERST
>>   
>>       {
>>           .name       = "set_password",
>> -        .args_type  = "protocol:s,password:s,connected:s?",
>> -        .params     = "protocol password action-if-connected",
>> +        .args_type  = "protocol:s,password:s,display:-dV,connected:s?",
>> +        .params     = "protocol password [-d display] [action-if-connected]",
>>           .help       = "set spice/vnc password",
>>           .cmd        = hmp_set_password,
>>       },
>>   
>>   SRST
>> -``set_password [ vnc | spice ] password [ action-if-connected ]``
>> -  Change spice/vnc password.  *action-if-connected* specifies what
>> -  should happen in case a connection is established: *fail* makes the
>> -  password change fail.  *disconnect* changes the password and
>> +``set_password [ vnc | spice ] password [ -d display ] [ action-if-connected ]``
>> +  Change spice/vnc password.  *display* can be used with 'vnc' to specify
>> +  which display to set the password on.  *action-if-connected* specifies
>> +  what should happen in case a connection is established: *fail* makes
>> +  the password change fail.  *disconnect* changes the password and
>>     disconnects the client.  *keep* changes the password and keeps the
>>     connection up.  *keep* is the default.
>>   ERST
>>   
>>       {
>>           .name       = "expire_password",
>> -        .args_type  = "protocol:s,time:s",
>> -        .params     = "protocol time",
>> +        .args_type  = "protocol:s,time:s,display:-dV",
>> +        .params     = "protocol time [-d display]",
>>           .help       = "set spice/vnc password expire-time",
>>           .cmd        = hmp_expire_password,
>>       },
>>   
>>   SRST
>> -``expire_password [ vnc | spice ]`` *expire-time*
>> -  Specify when a password for spice/vnc becomes
>> -  invalid. *expire-time* accepts:
>> +``expire_password [ vnc | spice ] expire-time [ -d display ]``
>> +  Specify when a password for spice/vnc becomes invalid.
>> +  *display* behaves the same as in ``set_password``.
>> +  *expire-time* accepts:
>>   
>>     ``now``
>>       Invalidate password instantly.
>> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
>> index b8abe69609..daa4a8e106 100644
>> --- a/monitor/hmp-cmds.c
>> +++ b/monitor/hmp-cmds.c
>> @@ -1451,26 +1451,39 @@ 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 *display = qdict_get_try_str(qdict, "display");
>>       const char *connected = qdict_get_try_str(qdict, "connected");
>>       Error *err = NULL;
>> -    DisplayProtocol proto;
>> -    SetPasswordAction conn;
>>   
>> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>> -                            DISPLAY_PROTOCOL_VNC, &err);
>> +    SetPasswordOptions opts = {
>> +        .password = g_strdup(password),
>> +        .u.vnc.display = NULL,
>> +    };
>> +
>> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>> +                                    DISPLAY_PROTOCOL_VNC, &err);
>>       if (err) {
>>           goto out;
>>       }
>>   
>> -    conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
>> -                           SET_PASSWORD_ACTION_KEEP, &err);
>> -    if (err) {
>> -        goto out;
>> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
>> +        opts.u.vnc.has_display = !!display;
>> +        opts.u.vnc.display = g_strdup(display);
>> +    } else if (opts.protocol == DISPLAY_PROTOCOL_SPICE) {
>> +        opts.u.spice.has_connected = !!connected;
>> +        opts.u.spice.connected =
>> +            qapi_enum_parse(&SetPasswordAction_lookup, connected,
>> +                            SET_PASSWORD_ACTION_KEEP, &err);
>> +        if (err) {
>> +            goto out;
>> +        }
>>       }
>>   
>> -    qmp_set_password(proto, password, !!connected, conn, &err);
>> +    qmp_set_password(&opts, &err);
>>   
>>   out:
>> +    g_free(opts.password);
>> +    g_free(opts.u.vnc.display);
> 
> Uh-oh...
> 
> For DISPLAY_PROTOCOL_SPICE, we execute
> 
>             .u.vnc.display = NULL,
>             opts.u.spice.has_connected = !!connected;
>             opts.u.spice.connected =
>                 qapi_enum_parse(&SetPasswordAction_lookup, connected,
>                                 SET_PASSWORD_ACTION_KEEP, &err);
>             opts.u.vnc.has_display = !!display;
>         g_free(opts.u.vnc.display);
> 
> The assignments to opts.u.spice.has_connected and opts.u.spice_connected
> clobber opts.u.vnc.display.
> 
> The simplest fix is to pass @display directly.  Precedence:
> hmp_drive_mirror().

With "directly", I assume you mean without g_strdup, so:

   opts.u.vnc.display = (char *)display;

right? Does it matter that we drop the 'const'?

> 
> Do the same for @password, of course.
> 
>>       hmp_handle_error(mon, err);
>>   }
>>   
>> @@ -1478,18 +1491,30 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
>>   {
>>       const char *protocol  = qdict_get_str(qdict, "protocol");
>>       const char *whenstr = qdict_get_str(qdict, "time");
>> +    const char *display = qdict_get_try_str(qdict, "display");
>>       Error *err = NULL;
>> -    DisplayProtocol proto;
>>   
>> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>> -                            DISPLAY_PROTOCOL_VNC, &err);
>> +    ExpirePasswordOptions opts = {
>> +        .time = g_strdup(whenstr),
>> +        .u.vnc.display = NULL,
>> +    };
>> +
>> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>> +                                    DISPLAY_PROTOCOL_VNC, &err);
>>       if (err) {
>>           goto out;
>>       }
>>   
>> -    qmp_expire_password(proto, whenstr, &err);
>> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
>> +        opts.u.vnc.has_display = !!display;
>> +        opts.u.vnc.display = g_strdup(display);
>> +    }
> 
> Use of -d with spice are silently ignored.  Do we care?  Same for
> hmp_set_password() above.

Depends on you, I don't. I think it's not worth catching even more
in HMP, since it's clear there's only one SPICE display anyway, and
it's all documented.

> 
>> +
>> +    qmp_expire_password(&opts, &err);
>>   
>>   out:
>> +    g_free(opts.time);
>> +    g_free(opts.u.vnc.display);
> 
> No uh-oh here, since opts.u.vnc is actually the only member of opts.u.
> Still, let's pass @time and @display directly for consistency and
> robustness.
> 
>>       hmp_handle_error(mon, err);
>>   }
>>   
> 
> [...]
> 
> 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password
  2021-10-21  8:42     ` Stefan Reiter
@ 2021-10-21  9:35       ` Markus Armbruster
  0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2021-10-21  9:35 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, Dr. David Alan Gilbert, qemu-devel,
	Marc-André Lureau, Gerd Hoffmann, Paolo Bonzini,
	Marc-André Lureau, Eric Blake, Thomas Lamprecht

Stefan Reiter <s.reiter@proxmox.com> writes:

> On 10/21/21 7:05 AM, Markus Armbruster wrote:
>> Stefan Reiter <s.reiter@proxmox.com> writes:
>> 
>>> It is possible to specify more than one VNC server on the command line,
>>> either with an explicit ID or the auto-generated ones à la "default",
>>> "vnc2", "vnc3", ...
>>>
>>> It is not possible to change the password on one of these extra VNC
>>> displays though. Fix this by adding a "display" parameter to the
>>> "set_password" and "expire_password" QMP and HMP commands.
>>>
>>> For HMP, the display is specified using the "-d" value flag.
>>>
>>> For QMP, the schema is updated to explicitly express the supported
>>> variants of the commands with protocol-discriminated unions.
>>>
>>> Suggested-by: Markus Armbruster <armbru@redhat.com>
>>> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
>>> ---

[...]

>>> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
>>> index b8abe69609..daa4a8e106 100644
>>> --- a/monitor/hmp-cmds.c
>>> +++ b/monitor/hmp-cmds.c
>>> @@ -1451,26 +1451,39 @@ 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 *display = qdict_get_try_str(qdict, "display");
>>>       const char *connected = qdict_get_try_str(qdict, "connected");
>>>       Error *err = NULL;
>>> -    DisplayProtocol proto;
>>> -    SetPasswordAction conn;
>>>   
>>> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>>> -                            DISPLAY_PROTOCOL_VNC, &err);
>>> +    SetPasswordOptions opts = {
>>> +        .password = g_strdup(password),
>>> +        .u.vnc.display = NULL,
>>> +    };
>>> +
>>> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>>> +                                    DISPLAY_PROTOCOL_VNC, &err);
>>>       if (err) {
>>>           goto out;
>>>       }
>>>   
>>> -    conn = qapi_enum_parse(&SetPasswordAction_lookup, connected,
>>> -                           SET_PASSWORD_ACTION_KEEP, &err);
>>> -    if (err) {
>>> -        goto out;
>>> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
>>> +        opts.u.vnc.has_display = !!display;
>>> +        opts.u.vnc.display = g_strdup(display);
>>> +    } else if (opts.protocol == DISPLAY_PROTOCOL_SPICE) {
>>> +        opts.u.spice.has_connected = !!connected;
>>> +        opts.u.spice.connected =
>>> +            qapi_enum_parse(&SetPasswordAction_lookup, connected,
>>> +                            SET_PASSWORD_ACTION_KEEP, &err);
>>> +        if (err) {
>>> +            goto out;
>>> +        }
>>>       }
>>>   
>>> -    qmp_set_password(proto, password, !!connected, conn, &err);
>>> +    qmp_set_password(&opts, &err);
>>>   
>>>   out:
>>> +    g_free(opts.password);
>>> +    g_free(opts.u.vnc.display);
>> 
>> Uh-oh...
>> 
>> For DISPLAY_PROTOCOL_SPICE, we execute
>> 
>>             .u.vnc.display = NULL,
>>             opts.u.spice.has_connected = !!connected;
>>             opts.u.spice.connected =
>>                 qapi_enum_parse(&SetPasswordAction_lookup, connected,
>>                                 SET_PASSWORD_ACTION_KEEP, &err);
>>             opts.u.vnc.has_display = !!display;
>>         g_free(opts.u.vnc.display);
>> 
>> The assignments to opts.u.spice.has_connected and opts.u.spice_connected
>> clobber opts.u.vnc.display.
>> 
>> The simplest fix is to pass @display directly.  Precedence:
>> hmp_drive_mirror().
>
> With "directly", I assume you mean without g_strdup, so:
>
>    opts.u.vnc.display = (char *)display;
>
> right?

Right.

>        Does it matter that we drop the 'const'?

It's ugly, but harmless.

qdict_get_try_str() returns const char * to discourage you from messing
with the string while it's in the QDict.

qmp_set_password() does not actually mess with its argument.

>> Do the same for @password, of course.
>> 
>>>       hmp_handle_error(mon, err);
>>>   }
>>>   
>>> @@ -1478,18 +1491,30 @@ void hmp_expire_password(Monitor *mon, const QDict *qdict)
>>>   {
>>>       const char *protocol  = qdict_get_str(qdict, "protocol");
>>>       const char *whenstr = qdict_get_str(qdict, "time");
>>> +    const char *display = qdict_get_try_str(qdict, "display");
>>>       Error *err = NULL;
>>> -    DisplayProtocol proto;
>>>   
>>> -    proto = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>>> -                            DISPLAY_PROTOCOL_VNC, &err);
>>> +    ExpirePasswordOptions opts = {
>>> +        .time = g_strdup(whenstr),
>>> +        .u.vnc.display = NULL,
>>> +    };
>>> +
>>> +    opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
>>> +                                    DISPLAY_PROTOCOL_VNC, &err);
>>>       if (err) {
>>>           goto out;
>>>       }
>>>   
>>> -    qmp_expire_password(proto, whenstr, &err);
>>> +    if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
>>> +        opts.u.vnc.has_display = !!display;
>>> +        opts.u.vnc.display = g_strdup(display);
>>> +    }
>> 
>> Use of -d with spice are silently ignored.  Do we care?  Same for
>> hmp_set_password() above.
>
> Depends on you, I don't. I think it's not worth catching even more
> in HMP, since it's clear there's only one SPICE display anyway, and
> it's all documented.

Up to the HMP maintainer, and we'll take silence as tacit agreement with
you :)

>>> +
>>> +    qmp_expire_password(&opts, &err);
>>>   
>>>   out:
>>> +    g_free(opts.time);
>>> +    g_free(opts.u.vnc.display);
>> 
>> No uh-oh here, since opts.u.vnc is actually the only member of opts.u.
>> Still, let's pass @time and @display directly for consistency and
>> robustness.
>> 
>>>       hmp_handle_error(mon, err);
>>>   }
>>>   
>> 
>> [...]



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v6 1/5] monitor/hmp: add support for flag argument with value
  2021-10-20 13:54 ` [PATCH v6 1/5] monitor/hmp: add support for flag argument with value Stefan Reiter
@ 2021-10-29 19:50   ` Eric Blake
  0 siblings, 0 replies; 13+ messages in thread
From: Eric Blake @ 2021-10-29 19:50 UTC (permalink / raw)
  To: Stefan Reiter
  Cc: Wolfgang Bumiller, qemu-devel, Dr. David Alan Gilbert,
	Markus Armbruster, Marc-André Lureau, Gerd Hoffmann,
	Paolo Bonzini, Marc-André Lureau, Thomas Lamprecht

On Wed, Oct 20, 2021 at 03:54:56PM +0200, Stefan Reiter wrote:
> Adds support for the "-xV" parameter type, where "-x" denotes a flag
> name and the "V" suffix indicates that this flag is supposed to take an
> arbitrary string parameter.
> 
> These parameters are always optional, the entry in the qdict will be
> omitted if the flag is not given.
> 
> Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
> ---
> 
> v6:
> It wasn't possible to pass the 'connected' parameter to set_password, since the
> code to handle optional parameters couldn't live with a different param (not
> starting with '-') coming up instead - fix that by advancing over the 'value
> flag' modifier in case `*p != '-'`.
> 
> Also change the modifier to 'V' instead of 'S' so it can be distinguished from
> an actual trailing 'S' type param.
> 
> Discovered in testing. I dropped Eric's R-b due to the code change.

Good that you caught it, and correct in dropping my earlier R-b.  But
now that I've read this version:

> +++ b/monitor/monitor-internal.h
> @@ -63,7 +63,8 @@
>   * '.'          other form of optional type (for 'i' and 'l')
>   * 'b'          boolean
>   *              user mode accepts "on" or "off"
> - * '-'          optional parameter (eg. '-f')
> + * '-'          optional parameter (eg. '-f'); if followed by an 'V', it

s/an/a/

> + *              specifies an optional string param (e.g. '-fV' allows '-f foo')
>   *

With the typo fix,
Reviewed-by: Eric Blake <eblake@redhat.com>

[Hmm, I see that you posted v7 in the meantime, and it still has the
typo, but I already typed this mail]

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2021-10-29 20:23 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-20 13:54 [PATCH v6 0/5] VNC-related HMP/QMP fixes Stefan Reiter
2021-10-20 13:54 ` [PATCH v6 1/5] monitor/hmp: add support for flag argument with value Stefan Reiter
2021-10-29 19:50   ` Eric Blake
2021-10-20 13:54 ` [PATCH v6 2/5] qapi/monitor: refactor set/expire_password with enums Stefan Reiter
2021-10-21  4:38   ` Markus Armbruster
2021-10-20 13:54 ` [PATCH v6 3/5] qapi/monitor: allow VNC display id in set/expire_password Stefan Reiter
2021-10-21  5:05   ` Markus Armbruster
2021-10-21  8:42     ` Stefan Reiter
2021-10-21  9:35       ` Markus Armbruster
2021-10-20 13:54 ` [PATCH v6 4/5] qapi/monitor: only allow 'keep' SetPasswordAction for VNC and deprecate Stefan Reiter
2021-10-21  5:16   ` Markus Armbruster
2021-10-20 13:55 ` [PATCH v6 5/5] docs: add deprecation note about 'set_password' param 'connected' Stefan Reiter
2021-10-21  5:16   ` Markus Armbruster

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).