root / ui / vnc-auth-vencrypt.c @ 834574ea
History | View | Annotate | Download (5.6 kB)
1 | 274b6fcc | aliguori | /*
|
---|---|---|---|
2 | 274b6fcc | aliguori | * QEMU VNC display driver: VeNCrypt authentication setup
|
3 | 274b6fcc | aliguori | *
|
4 | 274b6fcc | aliguori | * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
|
5 | 274b6fcc | aliguori | * Copyright (C) 2006 Fabrice Bellard
|
6 | 274b6fcc | aliguori | * Copyright (C) 2009 Red Hat, Inc
|
7 | 274b6fcc | aliguori | *
|
8 | 274b6fcc | aliguori | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 | 274b6fcc | aliguori | * of this software and associated documentation files (the "Software"), to deal
|
10 | 274b6fcc | aliguori | * in the Software without restriction, including without limitation the rights
|
11 | 274b6fcc | aliguori | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12 | 274b6fcc | aliguori | * copies of the Software, and to permit persons to whom the Software is
|
13 | 274b6fcc | aliguori | * furnished to do so, subject to the following conditions:
|
14 | 274b6fcc | aliguori | *
|
15 | 274b6fcc | aliguori | * The above copyright notice and this permission notice shall be included in
|
16 | 274b6fcc | aliguori | * all copies or substantial portions of the Software.
|
17 | 274b6fcc | aliguori | *
|
18 | 274b6fcc | aliguori | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19 | 274b6fcc | aliguori | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20 | 274b6fcc | aliguori | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
21 | 274b6fcc | aliguori | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22 | 274b6fcc | aliguori | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 | 274b6fcc | aliguori | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24 | 274b6fcc | aliguori | * THE SOFTWARE.
|
25 | 274b6fcc | aliguori | */
|
26 | 274b6fcc | aliguori | |
27 | 274b6fcc | aliguori | #include "vnc.h" |
28 | 274b6fcc | aliguori | |
29 | 274b6fcc | aliguori | |
30 | 274b6fcc | aliguori | static void start_auth_vencrypt_subauth(VncState *vs) |
31 | 274b6fcc | aliguori | { |
32 | 7e7e2ebc | Daniel P. Berrange | switch (vs->subauth) {
|
33 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_TLSNONE:
|
34 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_X509NONE:
|
35 | 274b6fcc | aliguori | VNC_DEBUG("Accept TLS auth none\n");
|
36 | 274b6fcc | aliguori | vnc_write_u32(vs, 0); /* Accept auth completion */ |
37 | 274b6fcc | aliguori | start_client_init(vs); |
38 | 274b6fcc | aliguori | break;
|
39 | 274b6fcc | aliguori | |
40 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_TLSVNC:
|
41 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_X509VNC:
|
42 | 274b6fcc | aliguori | VNC_DEBUG("Start TLS auth VNC\n");
|
43 | 274b6fcc | aliguori | start_auth_vnc(vs); |
44 | 274b6fcc | aliguori | break;
|
45 | 274b6fcc | aliguori | |
46 | 274b6fcc | aliguori | #ifdef CONFIG_VNC_SASL
|
47 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_TLSSASL:
|
48 | 274b6fcc | aliguori | case VNC_AUTH_VENCRYPT_X509SASL:
|
49 | 274b6fcc | aliguori | VNC_DEBUG("Start TLS auth SASL\n");
|
50 | 0ed8b6f6 | Blue Swirl | start_auth_sasl(vs); |
51 | 0ed8b6f6 | Blue Swirl | break;
|
52 | 274b6fcc | aliguori | #endif /* CONFIG_VNC_SASL */ |
53 | 274b6fcc | aliguori | |
54 | 274b6fcc | aliguori | default: /* Should not be possible, but just in case */ |
55 | 7e7e2ebc | Daniel P. Berrange | VNC_DEBUG("Reject subauth %d server bug\n", vs->auth);
|
56 | 274b6fcc | aliguori | vnc_write_u8(vs, 1);
|
57 | 274b6fcc | aliguori | if (vs->minor >= 8) { |
58 | 274b6fcc | aliguori | static const char err[] = "Unsupported authentication type"; |
59 | 274b6fcc | aliguori | vnc_write_u32(vs, sizeof(err));
|
60 | 274b6fcc | aliguori | vnc_write(vs, err, sizeof(err));
|
61 | 274b6fcc | aliguori | } |
62 | 274b6fcc | aliguori | vnc_client_error(vs); |
63 | 274b6fcc | aliguori | } |
64 | 274b6fcc | aliguori | } |
65 | 274b6fcc | aliguori | |
66 | 274b6fcc | aliguori | static void vnc_tls_handshake_io(void *opaque); |
67 | 274b6fcc | aliguori | |
68 | 274b6fcc | aliguori | static int vnc_start_vencrypt_handshake(struct VncState *vs) { |
69 | 274b6fcc | aliguori | int ret;
|
70 | 274b6fcc | aliguori | |
71 | 274b6fcc | aliguori | if ((ret = gnutls_handshake(vs->tls.session)) < 0) { |
72 | 274b6fcc | aliguori | if (!gnutls_error_is_fatal(ret)) {
|
73 | 274b6fcc | aliguori | VNC_DEBUG("Handshake interrupted (blocking)\n");
|
74 | 274b6fcc | aliguori | if (!gnutls_record_get_direction(vs->tls.session))
|
75 | 274b6fcc | aliguori | qemu_set_fd_handler(vs->csock, vnc_tls_handshake_io, NULL, vs);
|
76 | 274b6fcc | aliguori | else
|
77 | 274b6fcc | aliguori | qemu_set_fd_handler(vs->csock, NULL, vnc_tls_handshake_io, vs);
|
78 | 274b6fcc | aliguori | return 0; |
79 | 274b6fcc | aliguori | } |
80 | 274b6fcc | aliguori | VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
|
81 | 274b6fcc | aliguori | vnc_client_error(vs); |
82 | 274b6fcc | aliguori | return -1; |
83 | 274b6fcc | aliguori | } |
84 | 274b6fcc | aliguori | |
85 | 274b6fcc | aliguori | if (vs->vd->tls.x509verify) {
|
86 | 274b6fcc | aliguori | if (vnc_tls_validate_certificate(vs) < 0) { |
87 | 274b6fcc | aliguori | VNC_DEBUG("Client verification failed\n");
|
88 | 274b6fcc | aliguori | vnc_client_error(vs); |
89 | 274b6fcc | aliguori | return -1; |
90 | 274b6fcc | aliguori | } else {
|
91 | 274b6fcc | aliguori | VNC_DEBUG("Client verification passed\n");
|
92 | 274b6fcc | aliguori | } |
93 | 274b6fcc | aliguori | } |
94 | 274b6fcc | aliguori | |
95 | 274b6fcc | aliguori | VNC_DEBUG("Handshake done, switching to TLS data mode\n");
|
96 | 274b6fcc | aliguori | vs->tls.wiremode = VNC_WIREMODE_TLS; |
97 | 274b6fcc | aliguori | qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
|
98 | 274b6fcc | aliguori | |
99 | 274b6fcc | aliguori | start_auth_vencrypt_subauth(vs); |
100 | 274b6fcc | aliguori | |
101 | 274b6fcc | aliguori | return 0; |
102 | 274b6fcc | aliguori | } |
103 | 274b6fcc | aliguori | |
104 | 274b6fcc | aliguori | static void vnc_tls_handshake_io(void *opaque) { |
105 | 274b6fcc | aliguori | struct VncState *vs = (struct VncState *)opaque; |
106 | 274b6fcc | aliguori | |
107 | 274b6fcc | aliguori | VNC_DEBUG("Handshake IO continue\n");
|
108 | 274b6fcc | aliguori | vnc_start_vencrypt_handshake(vs); |
109 | 274b6fcc | aliguori | } |
110 | 274b6fcc | aliguori | |
111 | 274b6fcc | aliguori | |
112 | 274b6fcc | aliguori | |
113 | 274b6fcc | aliguori | #define NEED_X509_AUTH(vs) \
|
114 | 7e7e2ebc | Daniel P. Berrange | ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ |
115 | 7e7e2ebc | Daniel P. Berrange | (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ |
116 | 7e7e2ebc | Daniel P. Berrange | (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN || \ |
117 | 7e7e2ebc | Daniel P. Berrange | (vs)->subauth == VNC_AUTH_VENCRYPT_X509SASL) |
118 | 274b6fcc | aliguori | |
119 | 274b6fcc | aliguori | |
120 | 274b6fcc | aliguori | static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len) |
121 | 274b6fcc | aliguori | { |
122 | 274b6fcc | aliguori | int auth = read_u32(data, 0); |
123 | 274b6fcc | aliguori | |
124 | 7e7e2ebc | Daniel P. Berrange | if (auth != vs->subauth) {
|
125 | 274b6fcc | aliguori | VNC_DEBUG("Rejecting auth %d\n", auth);
|
126 | 274b6fcc | aliguori | vnc_write_u8(vs, 0); /* Reject auth */ |
127 | 274b6fcc | aliguori | vnc_flush(vs); |
128 | 274b6fcc | aliguori | vnc_client_error(vs); |
129 | 274b6fcc | aliguori | } else {
|
130 | 274b6fcc | aliguori | VNC_DEBUG("Accepting auth %d, setting up TLS for handshake\n", auth);
|
131 | 274b6fcc | aliguori | vnc_write_u8(vs, 1); /* Accept auth */ |
132 | 274b6fcc | aliguori | vnc_flush(vs); |
133 | 274b6fcc | aliguori | |
134 | 274b6fcc | aliguori | if (vnc_tls_client_setup(vs, NEED_X509_AUTH(vs)) < 0) { |
135 | 274b6fcc | aliguori | VNC_DEBUG("Failed to setup TLS\n");
|
136 | 274b6fcc | aliguori | return 0; |
137 | 274b6fcc | aliguori | } |
138 | 274b6fcc | aliguori | |
139 | 274b6fcc | aliguori | VNC_DEBUG("Start TLS VeNCrypt handshake process\n");
|
140 | 274b6fcc | aliguori | if (vnc_start_vencrypt_handshake(vs) < 0) { |
141 | 274b6fcc | aliguori | VNC_DEBUG("Failed to start TLS handshake\n");
|
142 | 274b6fcc | aliguori | return 0; |
143 | 274b6fcc | aliguori | } |
144 | 274b6fcc | aliguori | } |
145 | 274b6fcc | aliguori | return 0; |
146 | 274b6fcc | aliguori | } |
147 | 274b6fcc | aliguori | |
148 | 274b6fcc | aliguori | static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len) |
149 | 274b6fcc | aliguori | { |
150 | 274b6fcc | aliguori | if (data[0] != 0 || |
151 | 274b6fcc | aliguori | data[1] != 2) { |
152 | 274b6fcc | aliguori | VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]); |
153 | 274b6fcc | aliguori | vnc_write_u8(vs, 1); /* Reject version */ |
154 | 274b6fcc | aliguori | vnc_flush(vs); |
155 | 274b6fcc | aliguori | vnc_client_error(vs); |
156 | 274b6fcc | aliguori | } else {
|
157 | 7e7e2ebc | Daniel P. Berrange | VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
|
158 | 274b6fcc | aliguori | vnc_write_u8(vs, 0); /* Accept version */ |
159 | 274b6fcc | aliguori | vnc_write_u8(vs, 1); /* Number of sub-auths */ |
160 | 7e7e2ebc | Daniel P. Berrange | vnc_write_u32(vs, vs->subauth); /* The supported auth */
|
161 | 274b6fcc | aliguori | vnc_flush(vs); |
162 | 274b6fcc | aliguori | vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
|
163 | 274b6fcc | aliguori | } |
164 | 274b6fcc | aliguori | return 0; |
165 | 274b6fcc | aliguori | } |
166 | 274b6fcc | aliguori | |
167 | 274b6fcc | aliguori | |
168 | 274b6fcc | aliguori | void start_auth_vencrypt(VncState *vs)
|
169 | 274b6fcc | aliguori | { |
170 | 274b6fcc | aliguori | /* Send VeNCrypt version 0.2 */
|
171 | 274b6fcc | aliguori | vnc_write_u8(vs, 0);
|
172 | 274b6fcc | aliguori | vnc_write_u8(vs, 2);
|
173 | 274b6fcc | aliguori | |
174 | 274b6fcc | aliguori | vnc_read_when(vs, protocol_client_vencrypt_init, 2);
|
175 | 274b6fcc | aliguori | } |