xref: /qemu/ui/vnc-auth-vencrypt.c (revision 7a4e543d)
1 /*
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 
27 #include "qemu/osdep.h"
28 #include "vnc.h"
29 #include "qemu/main-loop.h"
30 
31 static void start_auth_vencrypt_subauth(VncState *vs)
32 {
33     switch (vs->subauth) {
34     case VNC_AUTH_VENCRYPT_TLSNONE:
35     case VNC_AUTH_VENCRYPT_X509NONE:
36        VNC_DEBUG("Accept TLS auth none\n");
37        vnc_write_u32(vs, 0); /* Accept auth completion */
38        start_client_init(vs);
39        break;
40 
41     case VNC_AUTH_VENCRYPT_TLSVNC:
42     case VNC_AUTH_VENCRYPT_X509VNC:
43        VNC_DEBUG("Start TLS auth VNC\n");
44        start_auth_vnc(vs);
45        break;
46 
47 #ifdef CONFIG_VNC_SASL
48     case VNC_AUTH_VENCRYPT_TLSSASL:
49     case VNC_AUTH_VENCRYPT_X509SASL:
50       VNC_DEBUG("Start TLS auth SASL\n");
51       start_auth_sasl(vs);
52       break;
53 #endif /* CONFIG_VNC_SASL */
54 
55     default: /* Should not be possible, but just in case */
56        VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
57        vnc_write_u8(vs, 1);
58        if (vs->minor >= 8) {
59            static const char err[] = "Unsupported authentication type";
60            vnc_write_u32(vs, sizeof(err));
61            vnc_write(vs, err, sizeof(err));
62        }
63        vnc_client_error(vs);
64     }
65 }
66 
67 static void vnc_tls_handshake_done(Object *source,
68                                    Error *err,
69                                    gpointer user_data)
70 {
71     VncState *vs = user_data;
72 
73     if (err) {
74         VNC_DEBUG("Handshake failed %s\n",
75                   error_get_pretty(err));
76         vnc_client_error(vs);
77     } else {
78         vs->ioc_tag = qio_channel_add_watch(
79             vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL);
80         start_auth_vencrypt_subauth(vs);
81     }
82 }
83 
84 
85 static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
86 {
87     int auth = read_u32(data, 0);
88 
89     if (auth != vs->subauth) {
90         VNC_DEBUG("Rejecting auth %d\n", auth);
91         vnc_write_u8(vs, 0); /* Reject auth */
92         vnc_flush(vs);
93         vnc_client_error(vs);
94     } else {
95         Error *err = NULL;
96         QIOChannelTLS *tls;
97         VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth);
98         vnc_write_u8(vs, 1); /* Accept auth */
99         vnc_flush(vs);
100 
101         if (vs->ioc_tag) {
102             g_source_remove(vs->ioc_tag);
103             vs->ioc_tag = 0;
104         }
105 
106         tls = qio_channel_tls_new_server(
107             vs->ioc,
108             vs->vd->tlscreds,
109             vs->vd->tlsaclname,
110             &err);
111         if (!tls) {
112             VNC_DEBUG("Failed to setup TLS %s\n", error_get_pretty(err));
113             error_free(err);
114             vnc_client_error(vs);
115             return 0;
116         }
117 
118         VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
119         object_unref(OBJECT(vs->ioc));
120         vs->ioc = QIO_CHANNEL(tls);
121         vs->tls = qio_channel_tls_get_session(tls);
122 
123         qio_channel_tls_handshake(tls,
124                                   vnc_tls_handshake_done,
125                                   vs,
126                                   NULL);
127     }
128     return 0;
129 }
130 
131 static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
132 {
133     if (data[0] != 0 ||
134         data[1] != 2) {
135         VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
136         vnc_write_u8(vs, 1); /* Reject version */
137         vnc_flush(vs);
138         vnc_client_error(vs);
139     } else {
140         VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
141         vnc_write_u8(vs, 0); /* Accept version */
142         vnc_write_u8(vs, 1); /* Number of sub-auths */
143         vnc_write_u32(vs, vs->subauth); /* The supported auth */
144         vnc_flush(vs);
145         vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
146     }
147     return 0;
148 }
149 
150 
151 void start_auth_vencrypt(VncState *vs)
152 {
153     /* Send VeNCrypt version 0.2 */
154     vnc_write_u8(vs, 0);
155     vnc_write_u8(vs, 2);
156 
157     vnc_read_when(vs, protocol_client_vencrypt_init, 2);
158 }
159 
160