blob: d9c212ff3286c7b45977f3ddf7e0422f78c9867d [file] [log] [blame]
aliguori274b6fc2009-03-06 23:44:29 +00001/*
2 * QEMU VNC display driver: VeNCrypt authentication setup
3 *
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
6 * Copyright (C) 2009 Red Hat, Inc
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Peter Maydelle16f4c82016-01-29 17:49:51 +000027#include "qemu/osdep.h"
aliguori274b6fc2009-03-06 23:44:29 +000028#include "vnc.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010029#include "qapi/error.h"
Alex Bligh6a1751b2013-08-21 16:02:47 +010030#include "qemu/main-loop.h"
Daniel P. Berrangead6374c2017-09-21 13:15:27 +010031#include "trace.h"
aliguori274b6fc2009-03-06 23:44:29 +000032
33static void start_auth_vencrypt_subauth(VncState *vs)
34{
Daniel P. Berrange7e7e2eb2011-06-23 13:31:41 +010035 switch (vs->subauth) {
aliguori274b6fc2009-03-06 23:44:29 +000036 case VNC_AUTH_VENCRYPT_TLSNONE:
37 case VNC_AUTH_VENCRYPT_X509NONE:
aliguori274b6fc2009-03-06 23:44:29 +000038 vnc_write_u32(vs, 0); /* Accept auth completion */
39 start_client_init(vs);
40 break;
41
42 case VNC_AUTH_VENCRYPT_TLSVNC:
43 case VNC_AUTH_VENCRYPT_X509VNC:
aliguori274b6fc2009-03-06 23:44:29 +000044 start_auth_vnc(vs);
45 break;
46
47#ifdef CONFIG_VNC_SASL
48 case VNC_AUTH_VENCRYPT_TLSSASL:
49 case VNC_AUTH_VENCRYPT_X509SASL:
Blue Swirl0ed8b6f2012-07-08 06:56:53 +000050 start_auth_sasl(vs);
51 break;
aliguori274b6fc2009-03-06 23:44:29 +000052#endif /* CONFIG_VNC_SASL */
53
54 default: /* Should not be possible, but just in case */
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010055 trace_vnc_auth_fail(vs, vs->auth, "Unhandled VeNCrypt subauth", "");
aliguori274b6fc2009-03-06 23:44:29 +000056 vnc_write_u8(vs, 1);
57 if (vs->minor >= 8) {
58 static const char err[] = "Unsupported authentication type";
59 vnc_write_u32(vs, sizeof(err));
60 vnc_write(vs, err, sizeof(err));
61 }
62 vnc_client_error(vs);
63 }
64}
65
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010066static void vnc_tls_handshake_done(QIOTask *task,
Daniel P. Berrange2cc45222015-03-02 19:01:05 +000067 gpointer user_data)
Chih-Min Chao494cb812015-04-09 02:04:11 +080068{
Daniel P. Berrange2cc45222015-03-02 19:01:05 +000069 VncState *vs = user_data;
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010070 Error *err = NULL;
aliguori274b6fc2009-03-06 23:44:29 +000071
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010072 if (qio_task_propagate_error(task, &err)) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010073 trace_vnc_auth_fail(vs, vs->auth, "TLS handshake failed",
74 error_get_pretty(err));
Daniel P. Berrange2cc45222015-03-02 19:01:05 +000075 vnc_client_error(vs);
Daniel P. Berrange60e705c2016-08-11 15:20:58 +010076 error_free(err);
Daniel P. Berrange2cc45222015-03-02 19:01:05 +000077 } else {
Brandon Carpentera75d6f02017-09-12 08:21:47 -070078 if (vs->ioc_tag) {
79 g_source_remove(vs->ioc_tag);
80 }
Daniel P. Berrange04d25292015-02-27 16:20:57 +000081 vs->ioc_tag = qio_channel_add_watch(
Ding Hui2ddafce2020-10-29 11:22:41 +080082 vs->ioc, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_OUT,
83 vnc_client_io, vs, NULL);
Daniel P. Berrange3e305e42015-08-06 14:39:32 +010084 start_auth_vencrypt_subauth(vs);
aliguori274b6fc2009-03-06 23:44:29 +000085 }
aliguori274b6fc2009-03-06 23:44:29 +000086}
87
88
aliguori274b6fc2009-03-06 23:44:29 +000089static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
90{
91 int auth = read_u32(data, 0);
92
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010093 trace_vnc_auth_vencrypt_subauth(vs, auth);
Daniel P. Berrange7e7e2eb2011-06-23 13:31:41 +010094 if (auth != vs->subauth) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010095 trace_vnc_auth_fail(vs, vs->auth, "Unsupported sub-auth version", "");
aliguori274b6fc2009-03-06 23:44:29 +000096 vnc_write_u8(vs, 0); /* Reject auth */
97 vnc_flush(vs);
98 vnc_client_error(vs);
99 } else {
Daniel P. Berrange3e305e42015-08-06 14:39:32 +0100100 Error *err = NULL;
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000101 QIOChannelTLS *tls;
aliguori274b6fc2009-03-06 23:44:29 +0000102 vnc_write_u8(vs, 1); /* Accept auth */
103 vnc_flush(vs);
104
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000105 if (vs->ioc_tag) {
106 g_source_remove(vs->ioc_tag);
107 vs->ioc_tag = 0;
108 }
109
110 tls = qio_channel_tls_new_server(
111 vs->ioc,
112 vs->vd->tlscreds,
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +0000113 vs->vd->tlsauthzid,
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000114 &err);
115 if (!tls) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100116 trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
117 error_get_pretty(err));
Daniel P. Berrange3e305e42015-08-06 14:39:32 +0100118 error_free(err);
119 vnc_client_error(vs);
aliguori274b6fc2009-03-06 23:44:29 +0000120 return 0;
121 }
122
Daniel P. Berrange10bcfe52016-09-30 11:57:14 +0100123 qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000124 object_unref(OBJECT(vs->ioc));
125 vs->ioc = QIO_CHANNEL(tls);
Daniel P. Berrangead6374c2017-09-21 13:15:27 +0100126 trace_vnc_client_io_wrap(vs, vs->ioc, "tls");
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000127 vs->tls = qio_channel_tls_get_session(tls);
128
129 qio_channel_tls_handshake(tls,
130 vnc_tls_handshake_done,
131 vs,
Peter Xu1939ccd2018-03-05 14:43:24 +0800132 NULL,
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000133 NULL);
aliguori274b6fc2009-03-06 23:44:29 +0000134 }
135 return 0;
136}
137
138static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
139{
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100140 trace_vnc_auth_vencrypt_version(vs, (int)data[0], (int)data[1]);
aliguori274b6fc2009-03-06 23:44:29 +0000141 if (data[0] != 0 ||
142 data[1] != 2) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100143 trace_vnc_auth_fail(vs, vs->auth, "Unsupported version", "");
aliguori274b6fc2009-03-06 23:44:29 +0000144 vnc_write_u8(vs, 1); /* Reject version */
145 vnc_flush(vs);
146 vnc_client_error(vs);
147 } else {
aliguori274b6fc2009-03-06 23:44:29 +0000148 vnc_write_u8(vs, 0); /* Accept version */
149 vnc_write_u8(vs, 1); /* Number of sub-auths */
Daniel P. Berrange7e7e2eb2011-06-23 13:31:41 +0100150 vnc_write_u32(vs, vs->subauth); /* The supported auth */
aliguori274b6fc2009-03-06 23:44:29 +0000151 vnc_flush(vs);
152 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
153 }
154 return 0;
155}
156
157
158void start_auth_vencrypt(VncState *vs)
159{
160 /* Send VeNCrypt version 0.2 */
161 vnc_write_u8(vs, 0);
162 vnc_write_u8(vs, 2);
163
164 vnc_read_when(vs, protocol_client_vencrypt_init, 2);
165}
166