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