ui: fix reporting of VNC auth in query-vnc-servers

Currently the VNC authentication info is emitted at the
top level of the query-vnc-servers data. This is wrong
because the authentication scheme differs between plain
and websockets when TLS is enabled. We should instead
report auth against the individual servers. e.g.

(QEMU) query-vnc-servers
{
    "return": [
        {
            "clients": [],
            "id": "default",
            "auth": "vencrypt",
            "vencrypt": "x509-vnc",
            "server": [
                {
                    "host": "127.0.0.1"
                    "service": "5901",
                    "websocket": false,
                    "family": "ipv4",
                    "auth": "vencrypt",
                    "vencrypt": "x509-vnc"
                },
                {
                    "host": "127.0.0.1",
                    "service": "5902",
                    "websocket": true,
                    "family": "ipv4",
                    "auth": "vnc"
                }
            ]
        }
    ]
}

This also future proofs the QMP schema so that we can
cope with multiple VNC server instances, listening on
different interfaces or ports, with different auth
setup.

Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-id: 20170203120649.15637-3-berrange@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
master
Daniel P. Berrange 2017-02-03 12:06:43 +00:00 committed by Gerd Hoffmann
parent 1b1aeb5828
commit 2a7e6857cd
2 changed files with 74 additions and 39 deletions

View File

@ -1506,7 +1506,8 @@
# #
# The network connection information for server # The network connection information for server
# #
# @auth: #optional authentication method # @auth: #optional authentication method used for
# the plain (non-websocket) VNC server
# #
# Since: 2.1 # Since: 2.1
## ##
@ -1597,6 +1598,25 @@
'tls-plain', 'x509-plain', 'tls-plain', 'x509-plain',
'tls-sasl', 'x509-sasl' ] } 'tls-sasl', 'x509-sasl' ] }
##
# @VncServerInfo2:
#
# The network connection information for server
#
# @auth: The current authentication type used by the servers
#
# @vencrypt: #optional The vencrypt sub authentication type used by the
# servers, only specified in case auth == vencrypt.
#
# Since: 2.9
##
{ 'struct': 'VncServerInfo2',
'base': 'VncBasicInfo',
'data': { 'auth' : 'VncPrimaryAuth',
'*vencrypt' : 'VncVencryptSubAuth' } }
## ##
# @VncInfo2: # @VncInfo2:
# #
@ -1612,9 +1632,9 @@
# @clients: A list of @VncClientInfo of all currently connected clients. # @clients: A list of @VncClientInfo of all currently connected clients.
# The list can be empty, for obvious reasons. # The list can be empty, for obvious reasons.
# #
# @auth: The current authentication type used by the server # @auth: The current authentication type used by the non-websockets servers
# #
# @vencrypt: #optional The vencrypt sub authentication type used by the server, # @vencrypt: #optional The vencrypt authentication type used by the servers,
# only specified in case auth == vencrypt. # only specified in case auth == vencrypt.
# #
# @display: #optional The display device the vnc server is linked to. # @display: #optional The display device the vnc server is linked to.
@ -1623,7 +1643,7 @@
## ##
{ 'struct': 'VncInfo2', { 'struct': 'VncInfo2',
'data': { 'id' : 'str', 'data': { 'id' : 'str',
'server' : ['VncBasicInfo'], 'server' : ['VncServerInfo2'],
'clients' : ['VncClientInfo'], 'clients' : ['VncClientInfo'],
'auth' : 'VncPrimaryAuth', 'auth' : 'VncPrimaryAuth',
'*vencrypt' : 'VncVencryptSubAuth', '*vencrypt' : 'VncVencryptSubAuth',

View File

@ -429,12 +429,20 @@ out_error:
return NULL; return NULL;
} }
static VncBasicInfoList *qmp_query_server_entry(QIOChannelSocket *ioc,
bool websocket, static void qmp_query_auth(int auth, int subauth,
VncBasicInfoList *prev) VncPrimaryAuth *qmp_auth,
VncVencryptSubAuth *qmp_vencrypt,
bool *qmp_has_vencrypt);
static VncServerInfo2List *qmp_query_server_entry(QIOChannelSocket *ioc,
bool websocket,
int auth,
int subauth,
VncServerInfo2List *prev)
{ {
VncBasicInfoList *list; VncServerInfo2List *list;
VncBasicInfo *info; VncServerInfo2 *info;
Error *err = NULL; Error *err = NULL;
SocketAddress *addr; SocketAddress *addr;
@ -444,85 +452,91 @@ static VncBasicInfoList *qmp_query_server_entry(QIOChannelSocket *ioc,
return prev; return prev;
} }
info = g_new0(VncBasicInfo, 1); info = g_new0(VncServerInfo2, 1);
vnc_init_basic_info(addr, info, &err); vnc_init_basic_info(addr, qapi_VncServerInfo2_base(info), &err);
qapi_free_SocketAddress(addr); qapi_free_SocketAddress(addr);
if (err) { if (err) {
qapi_free_VncBasicInfo(info); qapi_free_VncServerInfo2(info);
error_free(err); error_free(err);
return prev; return prev;
} }
info->websocket = websocket; info->websocket = websocket;
list = g_new0(VncBasicInfoList, 1); qmp_query_auth(auth, subauth, &info->auth,
&info->vencrypt, &info->has_vencrypt);
list = g_new0(VncServerInfo2List, 1);
list->value = info; list->value = info;
list->next = prev; list->next = prev;
return list; return list;
} }
static void qmp_query_auth(VncDisplay *vd, VncInfo2 *info) static void qmp_query_auth(int auth, int subauth,
VncPrimaryAuth *qmp_auth,
VncVencryptSubAuth *qmp_vencrypt,
bool *qmp_has_vencrypt)
{ {
switch (vd->auth) { switch (auth) {
case VNC_AUTH_VNC: case VNC_AUTH_VNC:
info->auth = VNC_PRIMARY_AUTH_VNC; *qmp_auth = VNC_PRIMARY_AUTH_VNC;
break; break;
case VNC_AUTH_RA2: case VNC_AUTH_RA2:
info->auth = VNC_PRIMARY_AUTH_RA2; *qmp_auth = VNC_PRIMARY_AUTH_RA2;
break; break;
case VNC_AUTH_RA2NE: case VNC_AUTH_RA2NE:
info->auth = VNC_PRIMARY_AUTH_RA2NE; *qmp_auth = VNC_PRIMARY_AUTH_RA2NE;
break; break;
case VNC_AUTH_TIGHT: case VNC_AUTH_TIGHT:
info->auth = VNC_PRIMARY_AUTH_TIGHT; *qmp_auth = VNC_PRIMARY_AUTH_TIGHT;
break; break;
case VNC_AUTH_ULTRA: case VNC_AUTH_ULTRA:
info->auth = VNC_PRIMARY_AUTH_ULTRA; *qmp_auth = VNC_PRIMARY_AUTH_ULTRA;
break; break;
case VNC_AUTH_TLS: case VNC_AUTH_TLS:
info->auth = VNC_PRIMARY_AUTH_TLS; *qmp_auth = VNC_PRIMARY_AUTH_TLS;
break; break;
case VNC_AUTH_VENCRYPT: case VNC_AUTH_VENCRYPT:
info->auth = VNC_PRIMARY_AUTH_VENCRYPT; *qmp_auth = VNC_PRIMARY_AUTH_VENCRYPT;
info->has_vencrypt = true; *qmp_has_vencrypt = true;
switch (vd->subauth) { switch (subauth) {
case VNC_AUTH_VENCRYPT_PLAIN: case VNC_AUTH_VENCRYPT_PLAIN:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_PLAIN;
break; break;
case VNC_AUTH_VENCRYPT_TLSNONE: case VNC_AUTH_VENCRYPT_TLSNONE:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_NONE;
break; break;
case VNC_AUTH_VENCRYPT_TLSVNC: case VNC_AUTH_VENCRYPT_TLSVNC:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_VNC;
break; break;
case VNC_AUTH_VENCRYPT_TLSPLAIN: case VNC_AUTH_VENCRYPT_TLSPLAIN:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_PLAIN;
break; break;
case VNC_AUTH_VENCRYPT_X509NONE: case VNC_AUTH_VENCRYPT_X509NONE:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_NONE;
break; break;
case VNC_AUTH_VENCRYPT_X509VNC: case VNC_AUTH_VENCRYPT_X509VNC:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_VNC;
break; break;
case VNC_AUTH_VENCRYPT_X509PLAIN: case VNC_AUTH_VENCRYPT_X509PLAIN:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_PLAIN;
break; break;
case VNC_AUTH_VENCRYPT_TLSSASL: case VNC_AUTH_VENCRYPT_TLSSASL:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_TLS_SASL;
break; break;
case VNC_AUTH_VENCRYPT_X509SASL: case VNC_AUTH_VENCRYPT_X509SASL:
info->vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL; *qmp_vencrypt = VNC_VENCRYPT_SUB_AUTH_X509_SASL;
break; break;
default: default:
info->has_vencrypt = false; *qmp_has_vencrypt = false;
break; break;
} }
break; break;
case VNC_AUTH_SASL: case VNC_AUTH_SASL:
info->auth = VNC_PRIMARY_AUTH_SASL; *qmp_auth = VNC_PRIMARY_AUTH_SASL;
break; break;
case VNC_AUTH_NONE: case VNC_AUTH_NONE:
default: default:
info->auth = VNC_PRIMARY_AUTH_NONE; *qmp_auth = VNC_PRIMARY_AUTH_NONE;
break; break;
} }
} }
@ -538,7 +552,8 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
info = g_new0(VncInfo2, 1); info = g_new0(VncInfo2, 1);
info->id = g_strdup(vd->id); info->id = g_strdup(vd->id);
info->clients = qmp_query_client_list(vd); info->clients = qmp_query_client_list(vd);
qmp_query_auth(vd, info); qmp_query_auth(vd->auth, vd->subauth, &info->auth,
&info->vencrypt, &info->has_vencrypt);
if (vd->dcl.con) { if (vd->dcl.con) {
dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con), dev = DEVICE(object_property_get_link(OBJECT(vd->dcl.con),
"device", NULL)); "device", NULL));
@ -547,11 +562,11 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp)
} }
if (vd->lsock != NULL) { if (vd->lsock != NULL) {
info->server = qmp_query_server_entry( info->server = qmp_query_server_entry(
vd->lsock, false, info->server); vd->lsock, false, vd->auth, vd->subauth, info->server);
} }
if (vd->lwebsock != NULL) { if (vd->lwebsock != NULL) {
info->server = qmp_query_server_entry( info->server = qmp_query_server_entry(
vd->lwebsock, true, info->server); vd->lwebsock, true, vd->ws_auth, vd->ws_subauth, info->server);
} }
item = g_new0(VncInfo2List, 1); item = g_new0(VncInfo2List, 1);