blob: f072e16aceb1c58de48e70ac3cfd69013653da71 [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(
82 vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL);
Daniel P. Berrange3e305e42015-08-06 14:39:32 +010083 start_auth_vencrypt_subauth(vs);
aliguori274b6fc2009-03-06 23:44:29 +000084 }
aliguori274b6fc2009-03-06 23:44:29 +000085}
86
87
aliguori274b6fc2009-03-06 23:44:29 +000088static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
89{
90 int auth = read_u32(data, 0);
91
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010092 trace_vnc_auth_vencrypt_subauth(vs, auth);
Daniel P. Berrange7e7e2eb2011-06-23 13:31:41 +010093 if (auth != vs->subauth) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +010094 trace_vnc_auth_fail(vs, vs->auth, "Unsupported sub-auth version", "");
aliguori274b6fc2009-03-06 23:44:29 +000095 vnc_write_u8(vs, 0); /* Reject auth */
96 vnc_flush(vs);
97 vnc_client_error(vs);
98 } else {
Daniel P. Berrange3e305e42015-08-06 14:39:32 +010099 Error *err = NULL;
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000100 QIOChannelTLS *tls;
aliguori274b6fc2009-03-06 23:44:29 +0000101 vnc_write_u8(vs, 1); /* Accept auth */
102 vnc_flush(vs);
103
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000104 if (vs->ioc_tag) {
105 g_source_remove(vs->ioc_tag);
106 vs->ioc_tag = 0;
107 }
108
109 tls = qio_channel_tls_new_server(
110 vs->ioc,
111 vs->vd->tlscreds,
Daniel P. Berrangeb76806d2016-02-18 18:40:24 +0000112 vs->vd->tlsauthzid,
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000113 &err);
114 if (!tls) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100115 trace_vnc_auth_fail(vs, vs->auth, "TLS setup failed",
116 error_get_pretty(err));
Daniel P. Berrange3e305e42015-08-06 14:39:32 +0100117 error_free(err);
118 vnc_client_error(vs);
aliguori274b6fc2009-03-06 23:44:29 +0000119 return 0;
120 }
121
Daniel P. Berrange10bcfe52016-09-30 11:57:14 +0100122 qio_channel_set_name(QIO_CHANNEL(tls), "vnc-server-tls");
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000123 object_unref(OBJECT(vs->ioc));
124 vs->ioc = QIO_CHANNEL(tls);
Daniel P. Berrangead6374c2017-09-21 13:15:27 +0100125 trace_vnc_client_io_wrap(vs, vs->ioc, "tls");
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000126 vs->tls = qio_channel_tls_get_session(tls);
127
128 qio_channel_tls_handshake(tls,
129 vnc_tls_handshake_done,
130 vs,
Peter Xu1939ccd2018-03-05 14:43:24 +0800131 NULL,
Daniel P. Berrange2cc45222015-03-02 19:01:05 +0000132 NULL);
aliguori274b6fc2009-03-06 23:44:29 +0000133 }
134 return 0;
135}
136
137static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
138{
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100139 trace_vnc_auth_vencrypt_version(vs, (int)data[0], (int)data[1]);
aliguori274b6fc2009-03-06 23:44:29 +0000140 if (data[0] != 0 ||
141 data[1] != 2) {
Daniel P. Berrange7364dbd2017-09-21 13:15:28 +0100142 trace_vnc_auth_fail(vs, vs->auth, "Unsupported version", "");
aliguori274b6fc2009-03-06 23:44:29 +0000143 vnc_write_u8(vs, 1); /* Reject version */
144 vnc_flush(vs);
145 vnc_client_error(vs);
146 } else {
aliguori274b6fc2009-03-06 23:44:29 +0000147 vnc_write_u8(vs, 0); /* Accept version */
148 vnc_write_u8(vs, 1); /* Number of sub-auths */
Daniel P. Berrange7e7e2eb2011-06-23 13:31:41 +0100149 vnc_write_u32(vs, vs->subauth); /* The supported auth */
aliguori274b6fc2009-03-06 23:44:29 +0000150 vnc_flush(vs);
151 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
152 }
153 return 0;
154}
155
156
157void start_auth_vencrypt(VncState *vs)
158{
159 /* Send VeNCrypt version 0.2 */
160 vnc_write_u8(vs, 0);
161 vnc_write_u8(vs, 2);
162
163 vnc_read_when(vs, protocol_client_vencrypt_init, 2);
164}
165