1 /* 2 * QEMU VNC display driver: Websockets support 3 * 4 * Copyright (C) 2010 Joel Martin 5 * Copyright (C) 2012 Tim Hardeck 6 * 7 * This is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This software is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this software; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "vnc.h" 22 #include "qemu/main-loop.h" 23 24 #ifdef CONFIG_VNC_TLS 25 #include "qemu/sockets.h" 26 27 static int vncws_start_tls_handshake(struct VncState *vs) 28 { 29 int ret = gnutls_handshake(vs->tls.session); 30 31 if (ret < 0) { 32 if (!gnutls_error_is_fatal(ret)) { 33 VNC_DEBUG("Handshake interrupted (blocking)\n"); 34 if (!gnutls_record_get_direction(vs->tls.session)) { 35 qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, 36 NULL, vs); 37 } else { 38 qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, 39 vs); 40 } 41 return 0; 42 } 43 VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); 44 vnc_client_error(vs); 45 return -1; 46 } 47 48 if (vs->vd->tls.x509verify) { 49 if (vnc_tls_validate_certificate(vs) < 0) { 50 VNC_DEBUG("Client verification failed\n"); 51 vnc_client_error(vs); 52 return -1; 53 } else { 54 VNC_DEBUG("Client verification passed\n"); 55 } 56 } 57 58 VNC_DEBUG("Handshake done, switching to TLS data mode\n"); 59 qemu_set_fd_handler2(vs->csock, NULL, vncws_handshake_read, NULL, vs); 60 61 return 0; 62 } 63 64 void vncws_tls_handshake_io(void *opaque) 65 { 66 struct VncState *vs = (struct VncState *)opaque; 67 68 if (!vs->tls.session) { 69 VNC_DEBUG("TLS Websocket setup\n"); 70 if (vnc_tls_client_setup(vs, vs->vd->tls.x509cert != NULL) < 0) { 71 return; 72 } 73 } 74 VNC_DEBUG("Handshake IO continue\n"); 75 vncws_start_tls_handshake(vs); 76 } 77 #endif /* CONFIG_VNC_TLS */ 78 79 void vncws_handshake_read(void *opaque) 80 { 81 VncState *vs = opaque; 82 uint8_t *handshake_end; 83 long ret; 84 /* Typical HTTP headers from novnc are 512 bytes, so limiting 85 * total header size to 4096 is easily enough. */ 86 size_t want = 4096 - vs->ws_input.offset; 87 buffer_reserve(&vs->ws_input, want); 88 ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), want); 89 90 if (!ret) { 91 if (vs->csock == -1) { 92 vnc_disconnect_finish(vs); 93 } 94 return; 95 } 96 vs->ws_input.offset += ret; 97 98 handshake_end = (uint8_t *)g_strstr_len((char *)vs->ws_input.buffer, 99 vs->ws_input.offset, WS_HANDSHAKE_END); 100 if (handshake_end) { 101 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 102 vncws_process_handshake(vs, vs->ws_input.buffer, vs->ws_input.offset); 103 buffer_advance(&vs->ws_input, handshake_end - vs->ws_input.buffer + 104 strlen(WS_HANDSHAKE_END)); 105 } else if (vs->ws_input.offset >= 4096) { 106 VNC_DEBUG("End of headers not found in first 4096 bytes\n"); 107 vnc_client_error(vs); 108 } 109 } 110 111 112 long vnc_client_read_ws(VncState *vs) 113 { 114 int ret, err; 115 uint8_t *payload; 116 size_t payload_size, header_size; 117 VNC_DEBUG("Read websocket %p size %zd offset %zd\n", vs->ws_input.buffer, 118 vs->ws_input.capacity, vs->ws_input.offset); 119 buffer_reserve(&vs->ws_input, 4096); 120 ret = vnc_client_read_buf(vs, buffer_end(&vs->ws_input), 4096); 121 if (!ret) { 122 return 0; 123 } 124 vs->ws_input.offset += ret; 125 126 ret = 0; 127 /* consume as much of ws_input buffer as possible */ 128 do { 129 if (vs->ws_payload_remain == 0) { 130 err = vncws_decode_frame_header(&vs->ws_input, 131 &header_size, 132 &vs->ws_payload_remain, 133 &vs->ws_payload_mask); 134 if (err <= 0) { 135 return err; 136 } 137 138 buffer_advance(&vs->ws_input, header_size); 139 } 140 if (vs->ws_payload_remain != 0) { 141 err = vncws_decode_frame_payload(&vs->ws_input, 142 &vs->ws_payload_remain, 143 &vs->ws_payload_mask, 144 &payload, 145 &payload_size); 146 if (err < 0) { 147 return err; 148 } 149 if (err == 0) { 150 return ret; 151 } 152 ret += err; 153 154 buffer_reserve(&vs->input, payload_size); 155 buffer_append(&vs->input, payload, payload_size); 156 157 buffer_advance(&vs->ws_input, payload_size); 158 } 159 } while (vs->ws_input.offset > 0); 160 161 return ret; 162 } 163 164 long vnc_client_write_ws(VncState *vs) 165 { 166 long ret; 167 VNC_DEBUG("Write WS: Pending output %p size %zd offset %zd\n", 168 vs->output.buffer, vs->output.capacity, vs->output.offset); 169 vncws_encode_frame(&vs->ws_output, vs->output.buffer, vs->output.offset); 170 buffer_reset(&vs->output); 171 ret = vnc_client_write_buf(vs, vs->ws_output.buffer, vs->ws_output.offset); 172 if (!ret) { 173 return 0; 174 } 175 176 buffer_advance(&vs->ws_output, ret); 177 178 if (vs->ws_output.offset == 0) { 179 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs); 180 } 181 182 return ret; 183 } 184 185 static char *vncws_extract_handshake_entry(const char *handshake, 186 size_t handshake_len, const char *name) 187 { 188 char *begin, *end, *ret = NULL; 189 char *line = g_strdup_printf("%s%s: ", WS_HANDSHAKE_DELIM, name); 190 begin = g_strstr_len(handshake, handshake_len, line); 191 if (begin != NULL) { 192 begin += strlen(line); 193 end = g_strstr_len(begin, handshake_len - (begin - handshake), 194 WS_HANDSHAKE_DELIM); 195 if (end != NULL) { 196 ret = g_strndup(begin, end - begin); 197 } 198 } 199 g_free(line); 200 return ret; 201 } 202 203 static void vncws_send_handshake_response(VncState *vs, const char* key) 204 { 205 char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; 206 unsigned char hash[SHA1_DIGEST_LEN]; 207 size_t hash_size = sizeof(hash); 208 char *accept = NULL, *response = NULL; 209 gnutls_datum_t in; 210 int ret; 211 212 g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); 213 g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); 214 215 /* hash and encode it */ 216 in.data = (void *)combined_key; 217 in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN; 218 ret = gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size); 219 if (ret == GNUTLS_E_SUCCESS && hash_size <= SHA1_DIGEST_LEN) { 220 accept = g_base64_encode(hash, hash_size); 221 } 222 if (accept == NULL) { 223 VNC_DEBUG("Hashing Websocket combined key failed\n"); 224 vnc_client_error(vs); 225 return; 226 } 227 228 response = g_strdup_printf(WS_HANDSHAKE, accept); 229 vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response)); 230 231 g_free(accept); 232 g_free(response); 233 234 vs->encode_ws = 1; 235 vnc_init_state(vs); 236 } 237 238 void vncws_process_handshake(VncState *vs, uint8_t *line, size_t size) 239 { 240 char *protocols = vncws_extract_handshake_entry((const char *)line, size, 241 "Sec-WebSocket-Protocol"); 242 char *version = vncws_extract_handshake_entry((const char *)line, size, 243 "Sec-WebSocket-Version"); 244 char *key = vncws_extract_handshake_entry((const char *)line, size, 245 "Sec-WebSocket-Key"); 246 247 if (protocols && version && key 248 && g_strrstr(protocols, "binary") 249 && !strcmp(version, WS_SUPPORTED_VERSION) 250 && strlen(key) == WS_CLIENT_KEY_LEN) { 251 vncws_send_handshake_response(vs, key); 252 } else { 253 VNC_DEBUG("Defective Websockets header or unsupported protocol\n"); 254 vnc_client_error(vs); 255 } 256 257 g_free(protocols); 258 g_free(version); 259 g_free(key); 260 } 261 262 void vncws_encode_frame(Buffer *output, const void *payload, 263 const size_t payload_size) 264 { 265 size_t header_size = 0; 266 unsigned char opcode = WS_OPCODE_BINARY_FRAME; 267 union { 268 char buf[WS_HEAD_MAX_LEN]; 269 WsHeader ws; 270 } header; 271 272 if (!payload_size) { 273 return; 274 } 275 276 header.ws.b0 = 0x80 | (opcode & 0x0f); 277 if (payload_size <= 125) { 278 header.ws.b1 = (uint8_t)payload_size; 279 header_size = 2; 280 } else if (payload_size < 65536) { 281 header.ws.b1 = 0x7e; 282 header.ws.u.s16.l16 = cpu_to_be16((uint16_t)payload_size); 283 header_size = 4; 284 } else { 285 header.ws.b1 = 0x7f; 286 header.ws.u.s64.l64 = cpu_to_be64(payload_size); 287 header_size = 10; 288 } 289 290 buffer_reserve(output, header_size + payload_size); 291 buffer_append(output, header.buf, header_size); 292 buffer_append(output, payload, payload_size); 293 } 294 295 int vncws_decode_frame_header(Buffer *input, 296 size_t *header_size, 297 size_t *payload_remain, 298 WsMask *payload_mask) 299 { 300 unsigned char opcode = 0, fin = 0, has_mask = 0; 301 size_t payload_len; 302 WsHeader *header = (WsHeader *)input->buffer; 303 304 if (input->offset < WS_HEAD_MIN_LEN + 4) { 305 /* header not complete */ 306 return 0; 307 } 308 309 fin = (header->b0 & 0x80) >> 7; 310 opcode = header->b0 & 0x0f; 311 has_mask = (header->b1 & 0x80) >> 7; 312 payload_len = header->b1 & 0x7f; 313 314 if (opcode == WS_OPCODE_CLOSE) { 315 /* disconnect */ 316 return -1; 317 } 318 319 /* Websocket frame sanity check: 320 * * Websocket fragmentation is not supported. 321 * * All websockets frames sent by a client have to be masked. 322 * * Only binary encoding is supported. 323 */ 324 if (!fin || !has_mask || opcode != WS_OPCODE_BINARY_FRAME) { 325 VNC_DEBUG("Received faulty/unsupported Websocket frame\n"); 326 return -2; 327 } 328 329 if (payload_len < 126) { 330 *payload_remain = payload_len; 331 *header_size = 6; 332 *payload_mask = header->u.m; 333 } else if (payload_len == 126 && input->offset >= 8) { 334 *payload_remain = be16_to_cpu(header->u.s16.l16); 335 *header_size = 8; 336 *payload_mask = header->u.s16.m16; 337 } else if (payload_len == 127 && input->offset >= 14) { 338 *payload_remain = be64_to_cpu(header->u.s64.l64); 339 *header_size = 14; 340 *payload_mask = header->u.s64.m64; 341 } else { 342 /* header not complete */ 343 return 0; 344 } 345 346 return 1; 347 } 348 349 int vncws_decode_frame_payload(Buffer *input, 350 size_t *payload_remain, WsMask *payload_mask, 351 uint8_t **payload, size_t *payload_size) 352 { 353 size_t i; 354 uint32_t *payload32; 355 356 *payload = input->buffer; 357 /* If we aren't at the end of the payload, then drop 358 * off the last bytes, so we're always multiple of 4 359 * for purpose of unmasking, except at end of payload 360 */ 361 if (input->offset < *payload_remain) { 362 *payload_size = input->offset - (input->offset % 4); 363 } else { 364 *payload_size = *payload_remain; 365 } 366 if (*payload_size == 0) { 367 return 0; 368 } 369 *payload_remain -= *payload_size; 370 371 /* unmask frame */ 372 /* process 1 frame (32 bit op) */ 373 payload32 = (uint32_t *)(*payload); 374 for (i = 0; i < *payload_size / 4; i++) { 375 payload32[i] ^= payload_mask->u; 376 } 377 /* process the remaining bytes (if any) */ 378 for (i *= 4; i < *payload_size; i++) { 379 (*payload)[i] ^= payload_mask->c[i % 4]; 380 } 381 382 return 1; 383 } 384