]> git.proxmox.com Git - mirror_qemu.git/blame - vnc.c
Add basic audio functionality to vnc.c
[mirror_qemu.git] / vnc.c
CommitLineData
7d510b8c
FB
1/*
2 * QEMU VNC display driver
5fafdf24 3 *
7d510b8c
FB
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2006 Fabrice Bellard
5fafdf24 6 *
7d510b8c
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
87ecb68b
PB
26#include "qemu-common.h"
27#include "console.h"
28#include "sysemu.h"
6ca957f0 29#include "qemu_socket.h"
87ecb68b 30#include "qemu-timer.h"
429a8ed3 31#include "audio/audio.h"
24236869
FB
32
33#define VNC_REFRESH_INTERVAL (1000 / 30)
34
35#include "vnc_keysym.h"
36#include "keymaps.c"
70848515
TS
37#include "d3des.h"
38
eb38c52c 39#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
40#include <gnutls/gnutls.h>
41#include <gnutls/x509.h>
42#endif /* CONFIG_VNC_TLS */
70848515 43
8d5d2d4c
TS
44// #define _VNC_DEBUG 1
45
eb38c52c 46#ifdef _VNC_DEBUG
70848515 47#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
8d5d2d4c
TS
48
49#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
50/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
51static void vnc_debug_gnutls_log(int level, const char* str) {
52 VNC_DEBUG("%d %s", level, str);
53}
54#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
70848515
TS
55#else
56#define VNC_DEBUG(fmt, ...) do { } while (0)
57#endif
24236869 58
8d5d2d4c 59
24236869
FB
60typedef struct Buffer
61{
62 size_t capacity;
63 size_t offset;
60fe76f3 64 uint8_t *buffer;
24236869
FB
65} Buffer;
66
67typedef struct VncState VncState;
68
60fe76f3 69typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
24236869 70
3512779a
FB
71typedef void VncWritePixels(VncState *vs, void *data, int size);
72
73typedef void VncSendHextileTile(VncState *vs,
74 int x, int y, int w, int h,
7eac3a87
AL
75 void *last_bg,
76 void *last_fg,
3512779a
FB
77 int *has_bg, int *has_fg);
78
99589bdc
FB
79#define VNC_MAX_WIDTH 2048
80#define VNC_MAX_HEIGHT 2048
81#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
82
70848515
TS
83#define VNC_AUTH_CHALLENGE_SIZE 16
84
85enum {
86 VNC_AUTH_INVALID = 0,
87 VNC_AUTH_NONE = 1,
88 VNC_AUTH_VNC = 2,
89 VNC_AUTH_RA2 = 5,
90 VNC_AUTH_RA2NE = 6,
91 VNC_AUTH_TIGHT = 16,
92 VNC_AUTH_ULTRA = 17,
93 VNC_AUTH_TLS = 18,
94 VNC_AUTH_VENCRYPT = 19
95};
96
eb38c52c 97#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
98enum {
99 VNC_WIREMODE_CLEAR,
100 VNC_WIREMODE_TLS,
101};
102
103enum {
104 VNC_AUTH_VENCRYPT_PLAIN = 256,
105 VNC_AUTH_VENCRYPT_TLSNONE = 257,
106 VNC_AUTH_VENCRYPT_TLSVNC = 258,
107 VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
108 VNC_AUTH_VENCRYPT_X509NONE = 260,
109 VNC_AUTH_VENCRYPT_X509VNC = 261,
110 VNC_AUTH_VENCRYPT_X509PLAIN = 262,
111};
3a702699 112
3a702699
TS
113#define X509_CA_CERT_FILE "ca-cert.pem"
114#define X509_CA_CRL_FILE "ca-crl.pem"
115#define X509_SERVER_KEY_FILE "server-key.pem"
116#define X509_SERVER_CERT_FILE "server-cert.pem"
3a702699 117
8d5d2d4c
TS
118#endif /* CONFIG_VNC_TLS */
119
24236869
FB
120struct VncState
121{
122 QEMUTimer *timer;
123 int lsock;
124 int csock;
125 DisplayState *ds;
126 int need_update;
127 int width;
128 int height;
99589bdc 129 uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
24236869 130 char *old_data;
3512779a 131 int depth; /* internal VNC frame buffer byte per pixel */
24236869
FB
132 int has_resize;
133 int has_hextile;
564c337e 134 int has_pointer_type_change;
ca4cca4d 135 int has_WMVi;
564c337e
FB
136 int absolute;
137 int last_x;
138 int last_y;
139
70848515
TS
140 int major;
141 int minor;
142
71cab5ca 143 char *display;
70848515
TS
144 char *password;
145 int auth;
eb38c52c 146#ifdef CONFIG_VNC_TLS
8d5d2d4c 147 int subauth;
469b15c6 148 int x509verify;
6f43024c
TS
149
150 char *x509cacert;
151 char *x509cacrl;
152 char *x509cert;
153 char *x509key;
8d5d2d4c 154#endif
70848515 155 char challenge[VNC_AUTH_CHALLENGE_SIZE];
a9ce8590 156
eb38c52c 157#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
158 int wiremode;
159 gnutls_session_t tls_session;
160#endif
161
24236869
FB
162 Buffer output;
163 Buffer input;
164 kbd_layout_t *kbd_layout;
3512779a
FB
165 /* current output mode information */
166 VncWritePixels *write_pixels;
167 VncSendHextileTile *send_hextile_tile;
168 int pix_bpp, pix_big_endian;
7eac3a87
AL
169 int client_red_shift, client_red_max, server_red_shift, server_red_max;
170 int client_green_shift, client_green_max, server_green_shift, server_green_max;
171 int client_blue_shift, client_blue_max, server_blue_shift, server_blue_max;
24236869 172
429a8ed3 173 CaptureVoiceOut *audio_cap;
174 audsettings_t as;
175
24236869
FB
176 VncReadEvent *read_handler;
177 size_t read_handler_expect;
64f5a135
FB
178 /* input */
179 uint8_t modifiers_state[256];
24236869
FB
180};
181
a9ce8590
FB
182static VncState *vnc_state; /* needed for info vnc */
183
184void do_info_vnc(void)
185{
186 if (vnc_state == NULL)
187 term_printf("VNC server disabled\n");
188 else {
189 term_printf("VNC server active on: ");
190 term_print_filename(vnc_state->display);
191 term_printf("\n");
192
193 if (vnc_state->csock == -1)
194 term_printf("No client connected\n");
195 else
196 term_printf("Client connected\n");
197 }
198}
199
24236869
FB
200/* TODO
201 1) Get the queue working for IO.
202 2) there is some weirdness when using the -S option (the screen is grey
203 and not totally invalidated
204 3) resolutions > 1024
205*/
206
207static void vnc_write(VncState *vs, const void *data, size_t len);
208static void vnc_write_u32(VncState *vs, uint32_t value);
209static void vnc_write_s32(VncState *vs, int32_t value);
210static void vnc_write_u16(VncState *vs, uint16_t value);
211static void vnc_write_u8(VncState *vs, uint8_t value);
212static void vnc_flush(VncState *vs);
213static void vnc_update_client(void *opaque);
214static void vnc_client_read(void *opaque);
215
7eac3a87
AL
216static void vnc_colordepth(DisplayState *ds, int depth);
217
99589bdc
FB
218static inline void vnc_set_bit(uint32_t *d, int k)
219{
220 d[k >> 5] |= 1 << (k & 0x1f);
221}
222
223static inline void vnc_clear_bit(uint32_t *d, int k)
224{
225 d[k >> 5] &= ~(1 << (k & 0x1f));
226}
227
228static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
229{
230 int j;
231
232 j = 0;
233 while (n >= 32) {
234 d[j++] = -1;
235 n -= 32;
236 }
5fafdf24 237 if (n > 0)
99589bdc
FB
238 d[j++] = (1 << n) - 1;
239 while (j < nb_words)
240 d[j++] = 0;
241}
242
243static inline int vnc_get_bit(const uint32_t *d, int k)
244{
245 return (d[k >> 5] >> (k & 0x1f)) & 1;
246}
247
5fafdf24 248static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
99589bdc
FB
249 int nb_words)
250{
251 int i;
252 for(i = 0; i < nb_words; i++) {
253 if ((d1[i] & d2[i]) != 0)
254 return 1;
255 }
256 return 0;
257}
258
24236869
FB
259static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
260{
261 VncState *vs = ds->opaque;
262 int i;
263
264 h += y;
265
0486e8a7
AZ
266 /* round x down to ensure the loop only spans one 16-pixel block per,
267 iteration. otherwise, if (x % 16) != 0, the last iteration may span
268 two 16-pixel blocks but we only mark the first as dirty
269 */
270 w += (x % 16);
271 x -= (x % 16);
272
788abf8e
AZ
273 x = MIN(x, vs->width);
274 y = MIN(y, vs->height);
275 w = MIN(x + w, vs->width) - x;
731dd637 276 h = MIN(h, vs->height);
788abf8e 277
24236869
FB
278 for (; y < h; y++)
279 for (i = 0; i < w; i += 16)
99589bdc 280 vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
24236869
FB
281}
282
283static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
284 int32_t encoding)
285{
286 vnc_write_u16(vs, x);
287 vnc_write_u16(vs, y);
288 vnc_write_u16(vs, w);
289 vnc_write_u16(vs, h);
290
291 vnc_write_s32(vs, encoding);
292}
293
294static void vnc_dpy_resize(DisplayState *ds, int w, int h)
295{
73e14b62 296 int size_changed;
24236869
FB
297 VncState *vs = ds->opaque;
298
2137b4cc
TS
299 ds->data = qemu_realloc(ds->data, w * h * vs->depth);
300 vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
24236869
FB
301
302 if (ds->data == NULL || vs->old_data == NULL) {
303 fprintf(stderr, "vnc: memory allocation failed\n");
304 exit(1);
305 }
306
a528b80c
AZ
307 if (ds->depth != vs->depth * 8) {
308 ds->depth = vs->depth * 8;
309 console_color_init(ds);
310 }
73e14b62 311 size_changed = ds->width != w || ds->height != h;
24236869
FB
312 ds->width = w;
313 ds->height = h;
314 ds->linesize = w * vs->depth;
b94eb43f
AZ
315 if (size_changed) {
316 vs->width = ds->width;
317 vs->height = ds->height;
318 if (vs->csock != -1 && vs->has_resize) {
319 vnc_write_u8(vs, 0); /* msg id */
320 vnc_write_u8(vs, 0);
321 vnc_write_u16(vs, 1); /* number of rects */
322 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
323 vnc_flush(vs);
324 }
24236869 325 }
8bba5c81
AZ
326
327 memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
0e1f5a0c 328 memset(vs->old_data, 42, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
24236869
FB
329}
330
3512779a
FB
331/* fastest code */
332static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
333{
334 vnc_write(vs, pixels, size);
335}
336
337/* slowest but generic code. */
338static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
339{
7eac3a87
AL
340 uint8_t r, g, b;
341
342 r = ((v >> vs->server_red_shift) & vs->server_red_max) * (vs->client_red_max + 1) /
343 (vs->server_red_max + 1);
344 g = ((v >> vs->server_green_shift) & vs->server_green_max) * (vs->client_green_max + 1) /
345 (vs->server_green_max + 1);
346 b = ((v >> vs->server_blue_shift) & vs->server_blue_max) * (vs->client_blue_max + 1) /
347 (vs->server_blue_max + 1);
348 v = (r << vs->client_red_shift) |
349 (g << vs->client_green_shift) |
350 (b << vs->client_blue_shift);
3512779a
FB
351 switch(vs->pix_bpp) {
352 case 1:
353 buf[0] = v;
354 break;
355 case 2:
356 if (vs->pix_big_endian) {
357 buf[0] = v >> 8;
358 buf[1] = v;
359 } else {
360 buf[1] = v >> 8;
361 buf[0] = v;
362 }
363 break;
364 default:
365 case 4:
366 if (vs->pix_big_endian) {
367 buf[0] = v >> 24;
368 buf[1] = v >> 16;
369 buf[2] = v >> 8;
370 buf[3] = v;
371 } else {
372 buf[3] = v >> 24;
373 buf[2] = v >> 16;
374 buf[1] = v >> 8;
375 buf[0] = v;
376 }
377 break;
378 }
379}
380
381static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
382{
3512779a 383 uint8_t buf[4];
3512779a 384
7eac3a87
AL
385 if (vs->depth == 4) {
386 uint32_t *pixels = pixels1;
387 int n, i;
388 n = size >> 2;
389 for(i = 0; i < n; i++) {
390 vnc_convert_pixel(vs, buf, pixels[i]);
391 vnc_write(vs, buf, vs->pix_bpp);
392 }
393 } else if (vs->depth == 2) {
394 uint16_t *pixels = pixels1;
395 int n, i;
396 n = size >> 1;
397 for(i = 0; i < n; i++) {
398 vnc_convert_pixel(vs, buf, pixels[i]);
399 vnc_write(vs, buf, vs->pix_bpp);
400 }
401 } else if (vs->depth == 1) {
402 uint8_t *pixels = pixels1;
403 int n, i;
404 n = size;
405 for(i = 0; i < n; i++) {
406 vnc_convert_pixel(vs, buf, pixels[i]);
407 vnc_write(vs, buf, vs->pix_bpp);
408 }
409 } else {
410 fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
3512779a
FB
411 }
412}
413
24236869
FB
414static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
415{
416 int i;
60fe76f3 417 uint8_t *row;
24236869
FB
418
419 vnc_framebuffer_update(vs, x, y, w, h, 0);
420
0e1f5a0c 421 row = ds_get_data(vs->ds) + y * ds_get_linesize(vs->ds) + x * vs->depth;
24236869 422 for (i = 0; i < h; i++) {
3512779a 423 vs->write_pixels(vs, row, w * vs->depth);
0e1f5a0c 424 row += ds_get_linesize(vs->ds);
24236869
FB
425 }
426}
427
428static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
429{
430 ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
431 ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
432}
433
434#define BPP 8
435#include "vnchextile.h"
436#undef BPP
437
438#define BPP 16
439#include "vnchextile.h"
440#undef BPP
441
442#define BPP 32
443#include "vnchextile.h"
444#undef BPP
445
7eac3a87
AL
446#define GENERIC
447#define BPP 8
448#include "vnchextile.h"
449#undef BPP
450#undef GENERIC
451
452#define GENERIC
453#define BPP 16
454#include "vnchextile.h"
455#undef BPP
456#undef GENERIC
457
3512779a
FB
458#define GENERIC
459#define BPP 32
460#include "vnchextile.h"
461#undef BPP
462#undef GENERIC
463
24236869
FB
464static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
465{
466 int i, j;
467 int has_fg, has_bg;
7eac3a87 468 uint8_t *last_fg, *last_bg;
24236869
FB
469
470 vnc_framebuffer_update(vs, x, y, w, h, 5);
471
7eac3a87
AL
472 last_fg = (uint8_t *) malloc(vs->depth);
473 last_bg = (uint8_t *) malloc(vs->depth);
24236869
FB
474 has_fg = has_bg = 0;
475 for (j = y; j < (y + h); j += 16) {
476 for (i = x; i < (x + w); i += 16) {
5fafdf24 477 vs->send_hextile_tile(vs, i, j,
3512779a 478 MIN(16, x + w - i), MIN(16, y + h - j),
7eac3a87 479 last_bg, last_fg, &has_bg, &has_fg);
24236869
FB
480 }
481 }
7eac3a87
AL
482 free(last_fg);
483 free(last_bg);
484
24236869
FB
485}
486
487static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
488{
489 if (vs->has_hextile)
490 send_framebuffer_update_hextile(vs, x, y, w, h);
491 else
492 send_framebuffer_update_raw(vs, x, y, w, h);
493}
494
495static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
496{
497 int src, dst;
60fe76f3
TS
498 uint8_t *src_row;
499 uint8_t *dst_row;
24236869
FB
500 char *old_row;
501 int y = 0;
0e1f5a0c 502 int pitch = ds_get_linesize(ds);
24236869
FB
503 VncState *vs = ds->opaque;
504
505 vnc_update_client(vs);
506
507 if (dst_y > src_y) {
508 y = h - 1;
509 pitch = -pitch;
510 }
511
0e1f5a0c
AL
512 src = (ds_get_linesize(ds) * (src_y + y) + vs->depth * src_x);
513 dst = (ds_get_linesize(ds) * (dst_y + y) + vs->depth * dst_x);
24236869 514
0e1f5a0c
AL
515 src_row = ds_get_data(ds) + src;
516 dst_row = ds_get_data(ds) + dst;
24236869
FB
517 old_row = vs->old_data + dst;
518
519 for (y = 0; y < h; y++) {
520 memmove(old_row, src_row, w * vs->depth);
521 memmove(dst_row, src_row, w * vs->depth);
522 src_row += pitch;
523 dst_row += pitch;
524 old_row += pitch;
525 }
526
527 vnc_write_u8(vs, 0); /* msg id */
528 vnc_write_u8(vs, 0);
529 vnc_write_u16(vs, 1); /* number of rects */
530 vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
531 vnc_write_u16(vs, src_x);
532 vnc_write_u16(vs, src_y);
533 vnc_flush(vs);
534}
535
536static int find_dirty_height(VncState *vs, int y, int last_x, int x)
537{
538 int h;
539
540 for (h = 1; h < (vs->height - y); h++) {
541 int tmp_x;
99589bdc 542 if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
24236869
FB
543 break;
544 for (tmp_x = last_x; tmp_x < x; tmp_x++)
99589bdc 545 vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
24236869
FB
546 }
547
548 return h;
549}
550
551static void vnc_update_client(void *opaque)
552{
553 VncState *vs = opaque;
554
555 if (vs->need_update && vs->csock != -1) {
556 int y;
60fe76f3 557 uint8_t *row;
24236869 558 char *old_row;
99589bdc 559 uint32_t width_mask[VNC_DIRTY_WORDS];
24236869
FB
560 int n_rectangles;
561 int saved_offset;
562 int has_dirty = 0;
563
a0ecfb73
AZ
564 vga_hw_update();
565
99589bdc 566 vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
24236869
FB
567
568 /* Walk through the dirty map and eliminate tiles that
569 really aren't dirty */
0e1f5a0c 570 row = ds_get_data(vs->ds);
24236869
FB
571 old_row = vs->old_data;
572
573 for (y = 0; y < vs->height; y++) {
99589bdc 574 if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
24236869 575 int x;
60fe76f3
TS
576 uint8_t *ptr;
577 char *old_ptr;
24236869
FB
578
579 ptr = row;
60fe76f3 580 old_ptr = (char*)old_row;
24236869 581
0e1f5a0c 582 for (x = 0; x < ds_get_width(vs->ds); x += 16) {
24236869 583 if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
99589bdc 584 vnc_clear_bit(vs->dirty_row[y], (x / 16));
24236869
FB
585 } else {
586 has_dirty = 1;
587 memcpy(old_ptr, ptr, 16 * vs->depth);
588 }
589
590 ptr += 16 * vs->depth;
591 old_ptr += 16 * vs->depth;
592 }
593 }
594
0e1f5a0c
AL
595 row += ds_get_linesize(vs->ds);
596 old_row += ds_get_linesize(vs->ds);
24236869
FB
597 }
598
429a8ed3 599 if (!has_dirty && !vs->audio_cap) {
24236869
FB
600 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
601 return;
602 }
603
604 /* Count rectangles */
605 n_rectangles = 0;
606 vnc_write_u8(vs, 0); /* msg id */
607 vnc_write_u8(vs, 0);
608 saved_offset = vs->output.offset;
609 vnc_write_u16(vs, 0);
610
611 for (y = 0; y < vs->height; y++) {
612 int x;
613 int last_x = -1;
614 for (x = 0; x < vs->width / 16; x++) {
99589bdc 615 if (vnc_get_bit(vs->dirty_row[y], x)) {
24236869
FB
616 if (last_x == -1) {
617 last_x = x;
618 }
99589bdc 619 vnc_clear_bit(vs->dirty_row[y], x);
24236869
FB
620 } else {
621 if (last_x != -1) {
622 int h = find_dirty_height(vs, y, last_x, x);
623 send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
624 n_rectangles++;
625 }
626 last_x = -1;
627 }
628 }
629 if (last_x != -1) {
630 int h = find_dirty_height(vs, y, last_x, x);
631 send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
632 n_rectangles++;
633 }
634 }
635 vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
636 vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
637 vnc_flush(vs);
638
639 }
24236869 640
a0ecfb73
AZ
641 if (vs->csock != -1) {
642 qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
24236869 643 }
24236869 644
24236869
FB
645}
646
647static int vnc_listen_poll(void *opaque)
648{
649 VncState *vs = opaque;
650 if (vs->csock == -1)
651 return 1;
652 return 0;
653}
654
655static void buffer_reserve(Buffer *buffer, size_t len)
656{
657 if ((buffer->capacity - buffer->offset) < len) {
658 buffer->capacity += (len + 1024);
2137b4cc 659 buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
24236869
FB
660 if (buffer->buffer == NULL) {
661 fprintf(stderr, "vnc: out of memory\n");
662 exit(1);
663 }
664 }
665}
666
667static int buffer_empty(Buffer *buffer)
668{
669 return buffer->offset == 0;
670}
671
60fe76f3 672static uint8_t *buffer_end(Buffer *buffer)
24236869
FB
673{
674 return buffer->buffer + buffer->offset;
675}
676
677static void buffer_reset(Buffer *buffer)
678{
679 buffer->offset = 0;
680}
681
682static void buffer_append(Buffer *buffer, const void *data, size_t len)
683{
684 memcpy(buffer->buffer + buffer->offset, data, len);
685 buffer->offset += len;
686}
687
429a8ed3 688/* audio */
689static void audio_capture_notify(void *opaque, audcnotification_e cmd)
690{
691 VncState *vs = opaque;
692
693 switch (cmd) {
694 case AUD_CNOTIFY_DISABLE:
695 vnc_write_u8(vs, 255);
696 vnc_write_u8(vs, 1);
697 vnc_write_u16(vs, 0);
698 vnc_flush(vs);
699 break;
700
701 case AUD_CNOTIFY_ENABLE:
702 vnc_write_u8(vs, 255);
703 vnc_write_u8(vs, 1);
704 vnc_write_u16(vs, 1);
705 vnc_flush(vs);
706 break;
707 }
708}
709
710static void audio_capture_destroy(void *opaque)
711{
712}
713
714static void audio_capture(void *opaque, void *buf, int size)
715{
716 VncState *vs = opaque;
717
718 vnc_write_u8(vs, 255);
719 vnc_write_u8(vs, 1);
720 vnc_write_u16(vs, 2);
721 vnc_write_u32(vs, size);
722 vnc_write(vs, buf, size);
723 vnc_flush(vs);
724}
725
726static void audio_add(VncState *vs)
727{
728 struct audio_capture_ops ops;
729
730 if (vs->audio_cap) {
731 term_printf ("audio already running\n");
732 return;
733 }
734
735 ops.notify = audio_capture_notify;
736 ops.destroy = audio_capture_destroy;
737 ops.capture = audio_capture;
738
739 vs->audio_cap = AUD_add_capture(NULL, &vs->as, &ops, vs);
740 if (!vs->audio_cap) {
741 term_printf ("Failed to add audio capture\n");
742 }
743}
744
745static void audio_del(VncState *vs)
746{
747 if (vs->audio_cap) {
748 AUD_del_capture(vs->audio_cap, vs);
749 vs->audio_cap = NULL;
750 }
751}
752
6ca957f0 753static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
24236869
FB
754{
755 if (ret == 0 || ret == -1) {
ea01e5fd
AZ
756 if (ret == -1) {
757 switch (last_errno) {
758 case EINTR:
759 case EAGAIN:
760#ifdef _WIN32
761 case WSAEWOULDBLOCK:
762#endif
763 return 0;
764 default:
765 break;
766 }
767 }
24236869 768
8d5d2d4c 769 VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
24236869 770 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
6ca957f0 771 closesocket(vs->csock);
24236869 772 vs->csock = -1;
bcfad70f 773 vs->ds->idle = 1;
24236869
FB
774 buffer_reset(&vs->input);
775 buffer_reset(&vs->output);
776 vs->need_update = 0;
eb38c52c 777#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
778 if (vs->tls_session) {
779 gnutls_deinit(vs->tls_session);
780 vs->tls_session = NULL;
781 }
782 vs->wiremode = VNC_WIREMODE_CLEAR;
783#endif /* CONFIG_VNC_TLS */
429a8ed3 784 audio_del(vs);
24236869
FB
785 return 0;
786 }
787 return ret;
788}
789
790static void vnc_client_error(VncState *vs)
791{
6ca957f0 792 vnc_client_io_error(vs, -1, EINVAL);
24236869
FB
793}
794
795static void vnc_client_write(void *opaque)
796{
ceb5caaf 797 long ret;
24236869
FB
798 VncState *vs = opaque;
799
eb38c52c 800#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
801 if (vs->tls_session) {
802 ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
803 if (ret < 0) {
804 if (ret == GNUTLS_E_AGAIN)
805 errno = EAGAIN;
806 else
807 errno = EIO;
808 ret = -1;
809 }
810 } else
811#endif /* CONFIG_VNC_TLS */
812 ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
6ca957f0 813 ret = vnc_client_io_error(vs, ret, socket_error());
24236869
FB
814 if (!ret)
815 return;
816
817 memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
818 vs->output.offset -= ret;
819
820 if (vs->output.offset == 0) {
821 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
822 }
823}
824
825static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
826{
827 vs->read_handler = func;
828 vs->read_handler_expect = expecting;
829}
830
831static void vnc_client_read(void *opaque)
832{
833 VncState *vs = opaque;
ceb5caaf 834 long ret;
24236869
FB
835
836 buffer_reserve(&vs->input, 4096);
837
eb38c52c 838#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
839 if (vs->tls_session) {
840 ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
841 if (ret < 0) {
842 if (ret == GNUTLS_E_AGAIN)
843 errno = EAGAIN;
844 else
845 errno = EIO;
846 ret = -1;
847 }
848 } else
849#endif /* CONFIG_VNC_TLS */
850 ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
6ca957f0 851 ret = vnc_client_io_error(vs, ret, socket_error());
24236869
FB
852 if (!ret)
853 return;
854
855 vs->input.offset += ret;
856
857 while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
858 size_t len = vs->read_handler_expect;
859 int ret;
860
861 ret = vs->read_handler(vs, vs->input.buffer, len);
862 if (vs->csock == -1)
863 return;
864
865 if (!ret) {
866 memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
867 vs->input.offset -= len;
868 } else {
869 vs->read_handler_expect = ret;
870 }
871 }
872}
873
874static void vnc_write(VncState *vs, const void *data, size_t len)
875{
876 buffer_reserve(&vs->output, len);
877
878 if (buffer_empty(&vs->output)) {
879 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
880 }
881
882 buffer_append(&vs->output, data, len);
883}
884
885static void vnc_write_s32(VncState *vs, int32_t value)
886{
887 vnc_write_u32(vs, *(uint32_t *)&value);
888}
889
890static void vnc_write_u32(VncState *vs, uint32_t value)
891{
892 uint8_t buf[4];
893
894 buf[0] = (value >> 24) & 0xFF;
895 buf[1] = (value >> 16) & 0xFF;
896 buf[2] = (value >> 8) & 0xFF;
897 buf[3] = value & 0xFF;
898
899 vnc_write(vs, buf, 4);
900}
901
902static void vnc_write_u16(VncState *vs, uint16_t value)
903{
64f5a135 904 uint8_t buf[2];
24236869
FB
905
906 buf[0] = (value >> 8) & 0xFF;
907 buf[1] = value & 0xFF;
908
909 vnc_write(vs, buf, 2);
910}
911
912static void vnc_write_u8(VncState *vs, uint8_t value)
913{
914 vnc_write(vs, (char *)&value, 1);
915}
916
917static void vnc_flush(VncState *vs)
918{
919 if (vs->output.offset)
920 vnc_client_write(vs);
921}
922
64f5a135 923static uint8_t read_u8(uint8_t *data, size_t offset)
24236869
FB
924{
925 return data[offset];
926}
927
64f5a135 928static uint16_t read_u16(uint8_t *data, size_t offset)
24236869
FB
929{
930 return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
931}
932
64f5a135 933static int32_t read_s32(uint8_t *data, size_t offset)
24236869
FB
934{
935 return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
936 (data[offset + 2] << 8) | data[offset + 3]);
937}
938
64f5a135 939static uint32_t read_u32(uint8_t *data, size_t offset)
24236869
FB
940{
941 return ((data[offset] << 24) | (data[offset + 1] << 16) |
942 (data[offset + 2] << 8) | data[offset + 3]);
943}
944
eb38c52c 945#ifdef CONFIG_VNC_TLS
9596ebb7
PB
946static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
947 const void *data,
948 size_t len) {
8d5d2d4c
TS
949 struct VncState *vs = (struct VncState *)transport;
950 int ret;
951
952 retry:
953 ret = send(vs->csock, data, len, 0);
954 if (ret < 0) {
955 if (errno == EINTR)
956 goto retry;
957 return -1;
958 }
959 return ret;
960}
961
962
9596ebb7
PB
963static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
964 void *data,
965 size_t len) {
8d5d2d4c
TS
966 struct VncState *vs = (struct VncState *)transport;
967 int ret;
968
969 retry:
970 ret = recv(vs->csock, data, len, 0);
971 if (ret < 0) {
972 if (errno == EINTR)
973 goto retry;
974 return -1;
975 }
976 return ret;
977}
978#endif /* CONFIG_VNC_TLS */
979
60fe76f3 980static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
24236869
FB
981{
982}
983
564c337e
FB
984static void check_pointer_type_change(VncState *vs, int absolute)
985{
986 if (vs->has_pointer_type_change && vs->absolute != absolute) {
987 vnc_write_u8(vs, 0);
988 vnc_write_u8(vs, 0);
989 vnc_write_u16(vs, 1);
990 vnc_framebuffer_update(vs, absolute, 0,
0e1f5a0c 991 ds_get_width(vs->ds), ds_get_height(vs->ds), -257);
564c337e
FB
992 vnc_flush(vs);
993 }
994 vs->absolute = absolute;
995}
996
24236869
FB
997static void pointer_event(VncState *vs, int button_mask, int x, int y)
998{
999 int buttons = 0;
1000 int dz = 0;
1001
1002 if (button_mask & 0x01)
1003 buttons |= MOUSE_EVENT_LBUTTON;
1004 if (button_mask & 0x02)
1005 buttons |= MOUSE_EVENT_MBUTTON;
1006 if (button_mask & 0x04)
1007 buttons |= MOUSE_EVENT_RBUTTON;
1008 if (button_mask & 0x08)
1009 dz = -1;
1010 if (button_mask & 0x10)
1011 dz = 1;
564c337e
FB
1012
1013 if (vs->absolute) {
0e1f5a0c
AL
1014 kbd_mouse_event(x * 0x7FFF / (ds_get_width(vs->ds) - 1),
1015 y * 0x7FFF / (ds_get_height(vs->ds) - 1),
24236869 1016 dz, buttons);
564c337e
FB
1017 } else if (vs->has_pointer_type_change) {
1018 x -= 0x7FFF;
1019 y -= 0x7FFF;
24236869 1020
564c337e
FB
1021 kbd_mouse_event(x, y, dz, buttons);
1022 } else {
1023 if (vs->last_x != -1)
1024 kbd_mouse_event(x - vs->last_x,
1025 y - vs->last_y,
1026 dz, buttons);
1027 vs->last_x = x;
1028 vs->last_y = y;
24236869 1029 }
564c337e
FB
1030
1031 check_pointer_type_change(vs, kbd_mouse_is_absolute());
24236869
FB
1032}
1033
64f5a135
FB
1034static void reset_keys(VncState *vs)
1035{
1036 int i;
1037 for(i = 0; i < 256; i++) {
1038 if (vs->modifiers_state[i]) {
1039 if (i & 0x80)
1040 kbd_put_keycode(0xe0);
1041 kbd_put_keycode(i | 0x80);
1042 vs->modifiers_state[i] = 0;
1043 }
1044 }
1045}
1046
a528b80c
AZ
1047static void press_key(VncState *vs, int keysym)
1048{
1049 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
1050 kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
1051}
1052
9ca313aa 1053static void do_key_event(VncState *vs, int down, int keycode, int sym)
24236869 1054{
64f5a135
FB
1055 /* QEMU console switch */
1056 switch(keycode) {
1057 case 0x2a: /* Left Shift */
1058 case 0x36: /* Right Shift */
1059 case 0x1d: /* Left CTRL */
1060 case 0x9d: /* Right CTRL */
1061 case 0x38: /* Left ALT */
1062 case 0xb8: /* Right ALT */
1063 if (down)
1064 vs->modifiers_state[keycode] = 1;
1065 else
1066 vs->modifiers_state[keycode] = 0;
1067 break;
5fafdf24 1068 case 0x02 ... 0x0a: /* '1' to '9' keys */
64f5a135
FB
1069 if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1070 /* Reset the modifiers sent to the current console */
1071 reset_keys(vs);
1072 console_select(keycode - 0x02);
1073 return;
1074 }
1075 break;
4d3b6f6e 1076 case 0x3a: /* CapsLock */
a528b80c
AZ
1077 case 0x45: /* NumLock */
1078 if (!down)
1079 vs->modifiers_state[keycode] ^= 1;
1080 break;
1081 }
1082
1083 if (keycode_is_keypad(vs->kbd_layout, keycode)) {
1084 /* If the numlock state needs to change then simulate an additional
1085 keypress before sending this one. This will happen if the user
1086 toggles numlock away from the VNC window.
1087 */
1088 if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) {
1089 if (!vs->modifiers_state[0x45]) {
1090 vs->modifiers_state[0x45] = 1;
1091 press_key(vs, 0xff7f);
1092 }
1093 } else {
1094 if (vs->modifiers_state[0x45]) {
1095 vs->modifiers_state[0x45] = 0;
1096 press_key(vs, 0xff7f);
1097 }
1098 }
64f5a135 1099 }
24236869 1100
64f5a135
FB
1101 if (is_graphic_console()) {
1102 if (keycode & 0x80)
1103 kbd_put_keycode(0xe0);
1104 if (down)
1105 kbd_put_keycode(keycode & 0x7f);
1106 else
1107 kbd_put_keycode(keycode | 0x80);
1108 } else {
1109 /* QEMU console emulation */
1110 if (down) {
1111 switch (keycode) {
1112 case 0x2a: /* Left Shift */
1113 case 0x36: /* Right Shift */
1114 case 0x1d: /* Left CTRL */
1115 case 0x9d: /* Right CTRL */
1116 case 0x38: /* Left ALT */
1117 case 0xb8: /* Right ALT */
1118 break;
1119 case 0xc8:
1120 kbd_put_keysym(QEMU_KEY_UP);
1121 break;
1122 case 0xd0:
1123 kbd_put_keysym(QEMU_KEY_DOWN);
1124 break;
1125 case 0xcb:
1126 kbd_put_keysym(QEMU_KEY_LEFT);
1127 break;
1128 case 0xcd:
1129 kbd_put_keysym(QEMU_KEY_RIGHT);
1130 break;
1131 case 0xd3:
1132 kbd_put_keysym(QEMU_KEY_DELETE);
1133 break;
1134 case 0xc7:
1135 kbd_put_keysym(QEMU_KEY_HOME);
1136 break;
1137 case 0xcf:
1138 kbd_put_keysym(QEMU_KEY_END);
1139 break;
1140 case 0xc9:
1141 kbd_put_keysym(QEMU_KEY_PAGEUP);
1142 break;
1143 case 0xd1:
1144 kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1145 break;
1146 default:
1147 kbd_put_keysym(sym);
1148 break;
1149 }
1150 }
1151 }
24236869
FB
1152}
1153
bdbd7676
FB
1154static void key_event(VncState *vs, int down, uint32_t sym)
1155{
9ca313aa
AL
1156 int keycode;
1157
a528b80c 1158 if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
bdbd7676 1159 sym = sym - 'A' + 'a';
9ca313aa
AL
1160
1161 keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
1162 do_key_event(vs, down, keycode, sym);
1163}
1164
1165static void ext_key_event(VncState *vs, int down,
1166 uint32_t sym, uint16_t keycode)
1167{
1168 /* if the user specifies a keyboard layout, always use it */
1169 if (keyboard_layout)
1170 key_event(vs, down, sym);
1171 else
1172 do_key_event(vs, down, keycode, sym);
bdbd7676
FB
1173}
1174
24236869
FB
1175static void framebuffer_update_request(VncState *vs, int incremental,
1176 int x_position, int y_position,
1177 int w, int h)
1178{
0e1f5a0c
AL
1179 if (x_position > ds_get_width(vs->ds))
1180 x_position = ds_get_width(vs->ds);
1181 if (y_position > ds_get_height(vs->ds))
1182 y_position = ds_get_height(vs->ds);
1183 if (x_position + w >= ds_get_width(vs->ds))
1184 w = ds_get_width(vs->ds) - x_position;
1185 if (y_position + h >= ds_get_height(vs->ds))
1186 h = ds_get_height(vs->ds) - y_position;
cf2d385c 1187
24236869
FB
1188 int i;
1189 vs->need_update = 1;
1190 if (!incremental) {
0e1f5a0c 1191 char *old_row = vs->old_data + y_position * ds_get_linesize(vs->ds);
24236869
FB
1192
1193 for (i = 0; i < h; i++) {
5fafdf24 1194 vnc_set_bits(vs->dirty_row[y_position + i],
0e1f5a0c
AL
1195 (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1196 memset(old_row, 42, ds_get_width(vs->ds) * vs->depth);
1197 old_row += ds_get_linesize(vs->ds);
24236869
FB
1198 }
1199 }
1200}
1201
9ca313aa
AL
1202static void send_ext_key_event_ack(VncState *vs)
1203{
1204 vnc_write_u8(vs, 0);
1205 vnc_write_u8(vs, 0);
1206 vnc_write_u16(vs, 1);
0e1f5a0c 1207 vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -258);
9ca313aa
AL
1208 vnc_flush(vs);
1209}
1210
429a8ed3 1211static void send_ext_audio_ack(VncState *vs)
1212{
1213 vnc_write_u8(vs, 0);
1214 vnc_write_u8(vs, 0);
1215 vnc_write_u16(vs, 1);
1216 vnc_framebuffer_update(vs, 0, 0, ds_get_width(vs->ds), ds_get_height(vs->ds), -259);
1217 vnc_flush(vs);
1218}
1219
24236869
FB
1220static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1221{
1222 int i;
1223
1224 vs->has_hextile = 0;
1225 vs->has_resize = 0;
564c337e 1226 vs->has_pointer_type_change = 0;
ca4cca4d 1227 vs->has_WMVi = 0;
564c337e 1228 vs->absolute = -1;
24236869
FB
1229 vs->ds->dpy_copy = NULL;
1230
1231 for (i = n_encodings - 1; i >= 0; i--) {
1232 switch (encodings[i]) {
1233 case 0: /* Raw */
1234 vs->has_hextile = 0;
1235 break;
1236 case 1: /* CopyRect */
1237 vs->ds->dpy_copy = vnc_copy;
1238 break;
1239 case 5: /* Hextile */
1240 vs->has_hextile = 1;
1241 break;
1242 case -223: /* DesktopResize */
1243 vs->has_resize = 1;
1244 break;
564c337e
FB
1245 case -257:
1246 vs->has_pointer_type_change = 1;
1247 break;
9ca313aa
AL
1248 case -258:
1249 send_ext_key_event_ack(vs);
1250 break;
429a8ed3 1251 case -259:
1252 send_ext_audio_ack(vs);
1253 break;
ca4cca4d
AL
1254 case 0x574D5669:
1255 vs->has_WMVi = 1;
1256 break;
24236869
FB
1257 default:
1258 break;
1259 }
1260 }
564c337e
FB
1261
1262 check_pointer_type_change(vs, kbd_mouse_is_absolute());
24236869
FB
1263}
1264
1265static void set_pixel_format(VncState *vs,
1266 int bits_per_pixel, int depth,
1267 int big_endian_flag, int true_color_flag,
1268 int red_max, int green_max, int blue_max,
1269 int red_shift, int green_shift, int blue_shift)
1270{
3512779a 1271 int host_big_endian_flag;
24236869 1272
3512779a
FB
1273#ifdef WORDS_BIGENDIAN
1274 host_big_endian_flag = 1;
1275#else
1276 host_big_endian_flag = 0;
1277#endif
1278 if (!true_color_flag) {
1279 fail:
24236869 1280 vnc_client_error(vs);
3512779a
FB
1281 return;
1282 }
5fafdf24 1283 if (bits_per_pixel == 32 &&
7eac3a87 1284 bits_per_pixel == vs->depth * 8 &&
3512779a
FB
1285 host_big_endian_flag == big_endian_flag &&
1286 red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1287 red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1288 vs->depth = 4;
1289 vs->write_pixels = vnc_write_pixels_copy;
1290 vs->send_hextile_tile = send_hextile_tile_32;
5fafdf24
TS
1291 } else
1292 if (bits_per_pixel == 16 &&
7eac3a87 1293 bits_per_pixel == vs->depth * 8 &&
3512779a
FB
1294 host_big_endian_flag == big_endian_flag &&
1295 red_max == 31 && green_max == 63 && blue_max == 31 &&
1296 red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1297 vs->depth = 2;
1298 vs->write_pixels = vnc_write_pixels_copy;
1299 vs->send_hextile_tile = send_hextile_tile_16;
5fafdf24
TS
1300 } else
1301 if (bits_per_pixel == 8 &&
7eac3a87 1302 bits_per_pixel == vs->depth * 8 &&
3512779a
FB
1303 red_max == 7 && green_max == 7 && blue_max == 3 &&
1304 red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1305 vs->depth = 1;
1306 vs->write_pixels = vnc_write_pixels_copy;
1307 vs->send_hextile_tile = send_hextile_tile_8;
5fafdf24 1308 } else
3512779a
FB
1309 {
1310 /* generic and slower case */
1311 if (bits_per_pixel != 8 &&
1312 bits_per_pixel != 16 &&
1313 bits_per_pixel != 32)
1314 goto fail;
7eac3a87
AL
1315 if (vs->depth == 4) {
1316 vs->send_hextile_tile = send_hextile_tile_generic_32;
1317 } else if (vs->depth == 2) {
1318 vs->send_hextile_tile = send_hextile_tile_generic_16;
1319 } else {
1320 vs->send_hextile_tile = send_hextile_tile_generic_8;
1321 }
1322
3512779a
FB
1323 vs->pix_big_endian = big_endian_flag;
1324 vs->write_pixels = vnc_write_pixels_generic;
3512779a 1325 }
24236869 1326
7eac3a87
AL
1327 vs->client_red_shift = red_shift;
1328 vs->client_red_max = red_max;
1329 vs->client_green_shift = green_shift;
1330 vs->client_green_max = green_max;
1331 vs->client_blue_shift = blue_shift;
1332 vs->client_blue_max = blue_max;
1333 vs->pix_bpp = bits_per_pixel / 8;
24236869
FB
1334
1335 vga_hw_invalidate();
1336 vga_hw_update();
1337}
1338
ca4cca4d
AL
1339static void pixel_format_message (VncState *vs) {
1340 char pad[3] = { 0, 0, 0 };
1341
1342 vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1343 if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
1344 else vnc_write_u8(vs, vs->depth * 8); /* depth */
1345
1346#ifdef WORDS_BIGENDIAN
1347 vnc_write_u8(vs, 1); /* big-endian-flag */
1348#else
1349 vnc_write_u8(vs, 0); /* big-endian-flag */
1350#endif
1351 vnc_write_u8(vs, 1); /* true-color-flag */
1352 if (vs->depth == 4) {
1353 vnc_write_u16(vs, 0xFF); /* red-max */
1354 vnc_write_u16(vs, 0xFF); /* green-max */
1355 vnc_write_u16(vs, 0xFF); /* blue-max */
1356 vnc_write_u8(vs, 16); /* red-shift */
1357 vnc_write_u8(vs, 8); /* green-shift */
1358 vnc_write_u8(vs, 0); /* blue-shift */
1359 vs->send_hextile_tile = send_hextile_tile_32;
1360 } else if (vs->depth == 2) {
1361 vnc_write_u16(vs, 31); /* red-max */
1362 vnc_write_u16(vs, 63); /* green-max */
1363 vnc_write_u16(vs, 31); /* blue-max */
1364 vnc_write_u8(vs, 11); /* red-shift */
1365 vnc_write_u8(vs, 5); /* green-shift */
1366 vnc_write_u8(vs, 0); /* blue-shift */
1367 vs->send_hextile_tile = send_hextile_tile_16;
1368 } else if (vs->depth == 1) {
1369 /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1370 vnc_write_u16(vs, 7); /* red-max */
1371 vnc_write_u16(vs, 7); /* green-max */
1372 vnc_write_u16(vs, 3); /* blue-max */
1373 vnc_write_u8(vs, 5); /* red-shift */
1374 vnc_write_u8(vs, 2); /* green-shift */
1375 vnc_write_u8(vs, 0); /* blue-shift */
1376 vs->send_hextile_tile = send_hextile_tile_8;
1377 }
1378 vs->client_red_max = vs->server_red_max;
1379 vs->client_green_max = vs->server_green_max;
1380 vs->client_blue_max = vs->server_blue_max;
1381 vs->client_red_shift = vs->server_red_shift;
1382 vs->client_green_shift = vs->server_green_shift;
1383 vs->client_blue_shift = vs->server_blue_shift;
1384 vs->pix_bpp = vs->depth * 8;
1385 vs->write_pixels = vnc_write_pixels_copy;
1386
1387 vnc_write(vs, pad, 3); /* padding */
1388}
1389
7eac3a87
AL
1390static void vnc_colordepth(DisplayState *ds, int depth)
1391{
1392 int host_big_endian_flag;
1393 struct VncState *vs = ds->opaque;
1394
1395 switch (depth) {
1396 case 24:
1397 if (ds->depth == 32) return;
1398 depth = 32;
1399 break;
1400 case 15:
1401 case 8:
1402 case 0:
1403 return;
1404 default:
1405 break;
1406 }
1407
1408#ifdef WORDS_BIGENDIAN
1409 host_big_endian_flag = 1;
1410#else
1411 host_big_endian_flag = 0;
1412#endif
1413
1414 switch (depth) {
1415 case 8:
1416 vs->depth = depth / 8;
1417 vs->server_red_max = 7;
1418 vs->server_green_max = 7;
1419 vs->server_blue_max = 3;
1420 vs->server_red_shift = 5;
1421 vs->server_green_shift = 2;
1422 vs->server_blue_shift = 0;
1423 break;
1424 case 16:
1425 vs->depth = depth / 8;
1426 vs->server_red_max = 31;
1427 vs->server_green_max = 63;
1428 vs->server_blue_max = 31;
1429 vs->server_red_shift = 11;
1430 vs->server_green_shift = 5;
1431 vs->server_blue_shift = 0;
1432 break;
1433 case 32:
1434 vs->depth = 4;
1435 vs->server_red_max = 255;
1436 vs->server_green_max = 255;
1437 vs->server_blue_max = 255;
1438 vs->server_red_shift = 16;
1439 vs->server_green_shift = 8;
1440 vs->server_blue_shift = 0;
1441 break;
1442 default:
1443 return;
1444 }
1445
ca4cca4d
AL
1446 if (vs->csock != -1 && vs->has_WMVi) {
1447 /* Sending a WMVi message to notify the client*/
1448 vnc_write_u8(vs, 0); /* msg id */
1449 vnc_write_u8(vs, 0);
1450 vnc_write_u16(vs, 1); /* number of rects */
1451 vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
1452 pixel_format_message(vs);
1453 vnc_flush(vs);
7eac3a87 1454 } else {
ca4cca4d
AL
1455 if (vs->pix_bpp == 4 && vs->depth == 4 &&
1456 host_big_endian_flag == vs->pix_big_endian &&
1457 vs->client_red_max == 0xff && vs->client_green_max == 0xff && vs->client_blue_max == 0xff &&
1458 vs->client_red_shift == 16 && vs->client_green_shift == 8 && vs->client_blue_shift == 0) {
1459 vs->write_pixels = vnc_write_pixels_copy;
1460 vs->send_hextile_tile = send_hextile_tile_32;
1461 } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
1462 host_big_endian_flag == vs->pix_big_endian &&
1463 vs->client_red_max == 31 && vs->client_green_max == 63 && vs->client_blue_max == 31 &&
1464 vs->client_red_shift == 11 && vs->client_green_shift == 5 && vs->client_blue_shift == 0) {
1465 vs->write_pixels = vnc_write_pixels_copy;
1466 vs->send_hextile_tile = send_hextile_tile_16;
1467 } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
1468 host_big_endian_flag == vs->pix_big_endian &&
1469 vs->client_red_max == 7 && vs->client_green_max == 7 && vs->client_blue_max == 3 &&
1470 vs->client_red_shift == 5 && vs->client_green_shift == 2 && vs->client_blue_shift == 0) {
1471 vs->write_pixels = vnc_write_pixels_copy;
1472 vs->send_hextile_tile = send_hextile_tile_8;
7eac3a87 1473 } else {
ca4cca4d
AL
1474 if (vs->depth == 4) {
1475 vs->send_hextile_tile = send_hextile_tile_generic_32;
1476 } else if (vs->depth == 2) {
1477 vs->send_hextile_tile = send_hextile_tile_generic_16;
1478 } else {
1479 vs->send_hextile_tile = send_hextile_tile_generic_8;
1480 }
1481 vs->write_pixels = vnc_write_pixels_generic;
7eac3a87 1482 }
7eac3a87
AL
1483 }
1484}
1485
60fe76f3 1486static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
24236869
FB
1487{
1488 int i;
1489 uint16_t limit;
1490
1491 switch (data[0]) {
1492 case 0:
1493 if (len == 1)
1494 return 20;
1495
1496 set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1497 read_u8(data, 6), read_u8(data, 7),
1498 read_u16(data, 8), read_u16(data, 10),
1499 read_u16(data, 12), read_u8(data, 14),
1500 read_u8(data, 15), read_u8(data, 16));
1501 break;
1502 case 2:
1503 if (len == 1)
1504 return 4;
1505
1506 if (len == 4)
1507 return 4 + (read_u16(data, 2) * 4);
1508
1509 limit = read_u16(data, 2);
1510 for (i = 0; i < limit; i++) {
1511 int32_t val = read_s32(data, 4 + (i * 4));
1512 memcpy(data + 4 + (i * 4), &val, sizeof(val));
1513 }
1514
1515 set_encodings(vs, (int32_t *)(data + 4), limit);
1516 break;
1517 case 3:
1518 if (len == 1)
1519 return 10;
1520
1521 framebuffer_update_request(vs,
1522 read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1523 read_u16(data, 6), read_u16(data, 8));
1524 break;
1525 case 4:
1526 if (len == 1)
1527 return 8;
1528
1529 key_event(vs, read_u8(data, 1), read_u32(data, 4));
1530 break;
1531 case 5:
1532 if (len == 1)
1533 return 6;
1534
1535 pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1536 break;
1537 case 6:
1538 if (len == 1)
1539 return 8;
1540
baa7666c
TS
1541 if (len == 8) {
1542 uint32_t dlen = read_u32(data, 4);
1543 if (dlen > 0)
1544 return 8 + dlen;
1545 }
24236869
FB
1546
1547 client_cut_text(vs, read_u32(data, 4), data + 8);
1548 break;
9ca313aa
AL
1549 case 255:
1550 if (len == 1)
1551 return 2;
1552
1553 switch (read_u8(data, 1)) {
1554 case 0:
1555 if (len == 2)
1556 return 12;
1557
1558 ext_key_event(vs, read_u16(data, 2),
1559 read_u32(data, 4), read_u32(data, 8));
1560 break;
429a8ed3 1561 case 1:
1562 if (len == 2)
1563 return 4;
1564
1565 switch (read_u16 (data, 2)) {
1566 case 0:
1567 audio_add(vs);
1568 break;
1569 case 1:
1570 audio_del(vs);
1571 break;
1572 case 2:
1573 if (len == 4)
1574 return 10;
1575 switch (read_u8(data, 4)) {
1576 case 0: vs->as.fmt = AUD_FMT_U8; break;
1577 case 1: vs->as.fmt = AUD_FMT_S8; break;
1578 case 2: vs->as.fmt = AUD_FMT_U16; break;
1579 case 3: vs->as.fmt = AUD_FMT_S16; break;
1580 case 4: vs->as.fmt = AUD_FMT_U32; break;
1581 case 5: vs->as.fmt = AUD_FMT_S32; break;
1582 default:
1583 printf("Invalid audio format %d\n", read_u8(data, 4));
1584 vnc_client_error(vs);
1585 break;
1586 }
1587 vs->as.nchannels = read_u8(data, 5);
1588 if (vs->as.nchannels != 1 && vs->as.nchannels != 2) {
1589 printf("Invalid audio channel coount %d\n",
1590 read_u8(data, 5));
1591 vnc_client_error(vs);
1592 break;
1593 }
1594 vs->as.freq = read_u32(data, 6);
1595 break;
1596 default:
1597 printf ("Invalid audio message %d\n", read_u8(data, 4));
1598 vnc_client_error(vs);
1599 break;
1600 }
1601 break;
1602
9ca313aa
AL
1603 default:
1604 printf("Msg: %d\n", read_u16(data, 0));
1605 vnc_client_error(vs);
1606 break;
1607 }
1608 break;
24236869
FB
1609 default:
1610 printf("Msg: %d\n", data[0]);
1611 vnc_client_error(vs);
1612 break;
1613 }
5fafdf24 1614
24236869
FB
1615 vnc_read_when(vs, protocol_client_msg, 1);
1616 return 0;
1617}
1618
60fe76f3 1619static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
24236869 1620{
c35734b2
TS
1621 char buf[1024];
1622 int size;
24236869 1623
0e1f5a0c
AL
1624 vs->width = ds_get_width(vs->ds);
1625 vs->height = ds_get_height(vs->ds);
1626 vnc_write_u16(vs, ds_get_width(vs->ds));
1627 vnc_write_u16(vs, ds_get_height(vs->ds));
24236869 1628
ca4cca4d 1629 pixel_format_message(vs);
24236869 1630
c35734b2
TS
1631 if (qemu_name)
1632 size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1633 else
1634 size = snprintf(buf, sizeof(buf), "QEMU");
1635
1636 vnc_write_u32(vs, size);
1637 vnc_write(vs, buf, size);
24236869
FB
1638 vnc_flush(vs);
1639
1640 vnc_read_when(vs, protocol_client_msg, 1);
1641
1642 return 0;
1643}
1644
70848515
TS
1645static void make_challenge(VncState *vs)
1646{
1647 int i;
1648
1649 srand(time(NULL)+getpid()+getpid()*987654+rand());
1650
1651 for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1652 vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1653}
1654
60fe76f3 1655static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
70848515 1656{
60fe76f3 1657 unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
70848515 1658 int i, j, pwlen;
60fe76f3 1659 unsigned char key[8];
70848515
TS
1660
1661 if (!vs->password || !vs->password[0]) {
1662 VNC_DEBUG("No password configured on server");
1663 vnc_write_u32(vs, 1); /* Reject auth */
1664 if (vs->minor >= 8) {
1665 static const char err[] = "Authentication failed";
1666 vnc_write_u32(vs, sizeof(err));
1667 vnc_write(vs, err, sizeof(err));
1668 }
1669 vnc_flush(vs);
1670 vnc_client_error(vs);
1671 return 0;
1672 }
1673
1674 memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1675
1676 /* Calculate the expected challenge response */
1677 pwlen = strlen(vs->password);
1678 for (i=0; i<sizeof(key); i++)
1679 key[i] = i<pwlen ? vs->password[i] : 0;
1680 deskey(key, EN0);
1681 for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1682 des(response+j, response+j);
1683
1684 /* Compare expected vs actual challenge response */
1685 if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1686 VNC_DEBUG("Client challenge reponse did not match\n");
1687 vnc_write_u32(vs, 1); /* Reject auth */
1688 if (vs->minor >= 8) {
1689 static const char err[] = "Authentication failed";
1690 vnc_write_u32(vs, sizeof(err));
1691 vnc_write(vs, err, sizeof(err));
1692 }
1693 vnc_flush(vs);
1694 vnc_client_error(vs);
1695 } else {
1696 VNC_DEBUG("Accepting VNC challenge response\n");
1697 vnc_write_u32(vs, 0); /* Accept auth */
1698 vnc_flush(vs);
1699
1700 vnc_read_when(vs, protocol_client_init, 1);
1701 }
1702 return 0;
1703}
1704
1705static int start_auth_vnc(VncState *vs)
1706{
1707 make_challenge(vs);
1708 /* Send client a 'random' challenge */
1709 vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1710 vnc_flush(vs);
1711
1712 vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1713 return 0;
1714}
1715
8d5d2d4c 1716
eb38c52c 1717#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
1718#define DH_BITS 1024
1719static gnutls_dh_params_t dh_params;
1720
1721static int vnc_tls_initialize(void)
1722{
1723 static int tlsinitialized = 0;
1724
1725 if (tlsinitialized)
1726 return 1;
1727
1728 if (gnutls_global_init () < 0)
1729 return 0;
1730
1731 /* XXX ought to re-generate diffie-hellmen params periodically */
1732 if (gnutls_dh_params_init (&dh_params) < 0)
1733 return 0;
1734 if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1735 return 0;
1736
234c9bcd 1737#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
8d5d2d4c
TS
1738 gnutls_global_set_log_level(10);
1739 gnutls_global_set_log_function(vnc_debug_gnutls_log);
1740#endif
1741
1742 tlsinitialized = 1;
1743
1744 return 1;
1745}
1746
1747static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1748{
1749 gnutls_anon_server_credentials anon_cred;
1750 int ret;
1751
1752 if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
1753 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1754 return NULL;
1755 }
1756
1757 gnutls_anon_set_server_dh_params(anon_cred, dh_params);
1758
1759 return anon_cred;
1760}
1761
1762
6f43024c 1763static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
3a702699
TS
1764{
1765 gnutls_certificate_credentials_t x509_cred;
1766 int ret;
6f43024c
TS
1767
1768 if (!vs->x509cacert) {
1769 VNC_DEBUG("No CA x509 certificate specified\n");
1770 return NULL;
1771 }
1772 if (!vs->x509cert) {
1773 VNC_DEBUG("No server x509 certificate specified\n");
1774 return NULL;
1775 }
1776 if (!vs->x509key) {
1777 VNC_DEBUG("No server private key specified\n");
1778 return NULL;
1779 }
3a702699
TS
1780
1781 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1782 VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1783 return NULL;
1784 }
6f43024c
TS
1785 if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1786 vs->x509cacert,
1787 GNUTLS_X509_FMT_PEM)) < 0) {
3a702699
TS
1788 VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1789 gnutls_certificate_free_credentials(x509_cred);
1790 return NULL;
1791 }
1792
6f43024c
TS
1793 if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1794 vs->x509cert,
1795 vs->x509key,
3a702699
TS
1796 GNUTLS_X509_FMT_PEM)) < 0) {
1797 VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1798 gnutls_certificate_free_credentials(x509_cred);
1799 return NULL;
1800 }
1801
6f43024c
TS
1802 if (vs->x509cacrl) {
1803 if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1804 vs->x509cacrl,
1805 GNUTLS_X509_FMT_PEM)) < 0) {
3a702699
TS
1806 VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1807 gnutls_certificate_free_credentials(x509_cred);
1808 return NULL;
1809 }
1810 }
1811
1812 gnutls_certificate_set_dh_params (x509_cred, dh_params);
1813
1814 return x509_cred;
1815}
1816
469b15c6
TS
1817static int vnc_validate_certificate(struct VncState *vs)
1818{
1819 int ret;
1820 unsigned int status;
1821 const gnutls_datum_t *certs;
1822 unsigned int nCerts, i;
1823 time_t now;
1824
1825 VNC_DEBUG("Validating client certificate\n");
1826 if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
1827 VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
1828 return -1;
1829 }
1830
1831 if ((now = time(NULL)) == ((time_t)-1)) {
1832 return -1;
1833 }
1834
1835 if (status != 0) {
1836 if (status & GNUTLS_CERT_INVALID)
1837 VNC_DEBUG("The certificate is not trusted.\n");
1838
1839 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1840 VNC_DEBUG("The certificate hasn't got a known issuer.\n");
1841
1842 if (status & GNUTLS_CERT_REVOKED)
1843 VNC_DEBUG("The certificate has been revoked.\n");
1844
1845 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1846 VNC_DEBUG("The certificate uses an insecure algorithm\n");
1847
1848 return -1;
1849 } else {
1850 VNC_DEBUG("Certificate is valid!\n");
1851 }
1852
1853 /* Only support x509 for now */
1854 if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
1855 return -1;
1856
1857 if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
1858 return -1;
1859
1860 for (i = 0 ; i < nCerts ; i++) {
1861 gnutls_x509_crt_t cert;
1862 VNC_DEBUG ("Checking certificate chain %d\n", i);
1863 if (gnutls_x509_crt_init (&cert) < 0)
1864 return -1;
1865
1866 if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1867 gnutls_x509_crt_deinit (cert);
1868 return -1;
1869 }
1870
1871 if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1872 VNC_DEBUG("The certificate has expired\n");
1873 gnutls_x509_crt_deinit (cert);
1874 return -1;
1875 }
1876
1877 if (gnutls_x509_crt_get_activation_time (cert) > now) {
1878 VNC_DEBUG("The certificate is not yet activated\n");
1879 gnutls_x509_crt_deinit (cert);
1880 return -1;
1881 }
1882
1883 if (gnutls_x509_crt_get_activation_time (cert) > now) {
1884 VNC_DEBUG("The certificate is not yet activated\n");
1885 gnutls_x509_crt_deinit (cert);
1886 return -1;
1887 }
1888
1889 gnutls_x509_crt_deinit (cert);
1890 }
1891
1892 return 0;
1893}
1894
1895
8d5d2d4c
TS
1896static int start_auth_vencrypt_subauth(VncState *vs)
1897{
1898 switch (vs->subauth) {
1899 case VNC_AUTH_VENCRYPT_TLSNONE:
3a702699 1900 case VNC_AUTH_VENCRYPT_X509NONE:
8d5d2d4c
TS
1901 VNC_DEBUG("Accept TLS auth none\n");
1902 vnc_write_u32(vs, 0); /* Accept auth completion */
1903 vnc_read_when(vs, protocol_client_init, 1);
1904 break;
1905
1906 case VNC_AUTH_VENCRYPT_TLSVNC:
3a702699 1907 case VNC_AUTH_VENCRYPT_X509VNC:
8d5d2d4c
TS
1908 VNC_DEBUG("Start TLS auth VNC\n");
1909 return start_auth_vnc(vs);
1910
1911 default: /* Should not be possible, but just in case */
1912 VNC_DEBUG("Reject auth %d\n", vs->auth);
1913 vnc_write_u8(vs, 1);
1914 if (vs->minor >= 8) {
1915 static const char err[] = "Unsupported authentication type";
1916 vnc_write_u32(vs, sizeof(err));
1917 vnc_write(vs, err, sizeof(err));
1918 }
1919 vnc_client_error(vs);
1920 }
1921
1922 return 0;
1923}
1924
1925static void vnc_handshake_io(void *opaque);
1926
1927static int vnc_continue_handshake(struct VncState *vs) {
1928 int ret;
1929
1930 if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
1931 if (!gnutls_error_is_fatal(ret)) {
1932 VNC_DEBUG("Handshake interrupted (blocking)\n");
1933 if (!gnutls_record_get_direction(vs->tls_session))
1934 qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
1935 else
1936 qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
1937 return 0;
1938 }
1939 VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
1940 vnc_client_error(vs);
1941 return -1;
1942 }
1943
469b15c6
TS
1944 if (vs->x509verify) {
1945 if (vnc_validate_certificate(vs) < 0) {
1946 VNC_DEBUG("Client verification failed\n");
1947 vnc_client_error(vs);
1948 return -1;
1949 } else {
1950 VNC_DEBUG("Client verification passed\n");
1951 }
1952 }
1953
8d5d2d4c
TS
1954 VNC_DEBUG("Handshake done, switching to TLS data mode\n");
1955 vs->wiremode = VNC_WIREMODE_TLS;
1956 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1957
1958 return start_auth_vencrypt_subauth(vs);
1959}
1960
1961static void vnc_handshake_io(void *opaque) {
1962 struct VncState *vs = (struct VncState *)opaque;
1963
1964 VNC_DEBUG("Handshake IO continue\n");
1965 vnc_continue_handshake(vs);
1966}
1967
3a702699
TS
1968#define NEED_X509_AUTH(vs) \
1969 ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
1970 (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
1971 (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
1972
1973
8d5d2d4c
TS
1974static int vnc_start_tls(struct VncState *vs) {
1975 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
1976 static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
1977 static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
3a702699 1978 static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
8d5d2d4c
TS
1979
1980 VNC_DEBUG("Do TLS setup\n");
1981 if (vnc_tls_initialize() < 0) {
1982 VNC_DEBUG("Failed to init TLS\n");
1983 vnc_client_error(vs);
1984 return -1;
1985 }
1986 if (vs->tls_session == NULL) {
1987 if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
1988 vnc_client_error(vs);
1989 return -1;
1990 }
1991
1992 if (gnutls_set_default_priority(vs->tls_session) < 0) {
1993 gnutls_deinit(vs->tls_session);
1994 vs->tls_session = NULL;
1995 vnc_client_error(vs);
1996 return -1;
1997 }
1998
3a702699 1999 if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
8d5d2d4c
TS
2000 gnutls_deinit(vs->tls_session);
2001 vs->tls_session = NULL;
2002 vnc_client_error(vs);
2003 return -1;
2004 }
2005
2006 if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
2007 gnutls_deinit(vs->tls_session);
2008 vs->tls_session = NULL;
2009 vnc_client_error(vs);
2010 return -1;
2011 }
2012
2013 if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
2014 gnutls_deinit(vs->tls_session);
2015 vs->tls_session = NULL;
2016 vnc_client_error(vs);
2017 return -1;
2018 }
2019
3a702699 2020 if (NEED_X509_AUTH(vs)) {
6f43024c 2021 gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
3a702699
TS
2022 if (!x509_cred) {
2023 gnutls_deinit(vs->tls_session);
2024 vs->tls_session = NULL;
2025 vnc_client_error(vs);
2026 return -1;
2027 }
2028 if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
2029 gnutls_deinit(vs->tls_session);
2030 vs->tls_session = NULL;
2031 gnutls_certificate_free_credentials(x509_cred);
2032 vnc_client_error(vs);
2033 return -1;
2034 }
469b15c6
TS
2035 if (vs->x509verify) {
2036 VNC_DEBUG("Requesting a client certificate\n");
2037 gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
2038 }
2039
3a702699
TS
2040 } else {
2041 gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
2042 if (!anon_cred) {
2043 gnutls_deinit(vs->tls_session);
2044 vs->tls_session = NULL;
2045 vnc_client_error(vs);
2046 return -1;
2047 }
2048 if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
2049 gnutls_deinit(vs->tls_session);
2050 vs->tls_session = NULL;
2051 gnutls_anon_free_server_credentials(anon_cred);
2052 vnc_client_error(vs);
2053 return -1;
2054 }
8d5d2d4c
TS
2055 }
2056
2057 gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
2058 gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
2059 gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
2060 }
2061
2062 VNC_DEBUG("Start TLS handshake process\n");
2063 return vnc_continue_handshake(vs);
2064}
2065
60fe76f3 2066static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
8d5d2d4c
TS
2067{
2068 int auth = read_u32(data, 0);
2069
2070 if (auth != vs->subauth) {
2071 VNC_DEBUG("Rejecting auth %d\n", auth);
2072 vnc_write_u8(vs, 0); /* Reject auth */
2073 vnc_flush(vs);
2074 vnc_client_error(vs);
2075 } else {
2076 VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
2077 vnc_write_u8(vs, 1); /* Accept auth */
2078 vnc_flush(vs);
2079
2080 if (vnc_start_tls(vs) < 0) {
2081 VNC_DEBUG("Failed to complete TLS\n");
2082 return 0;
2083 }
2084
2085 if (vs->wiremode == VNC_WIREMODE_TLS) {
2086 VNC_DEBUG("Starting VeNCrypt subauth\n");
2087 return start_auth_vencrypt_subauth(vs);
2088 } else {
2089 VNC_DEBUG("TLS handshake blocked\n");
2090 return 0;
2091 }
2092 }
2093 return 0;
2094}
2095
60fe76f3 2096static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
8d5d2d4c
TS
2097{
2098 if (data[0] != 0 ||
2099 data[1] != 2) {
2100 VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
2101 vnc_write_u8(vs, 1); /* Reject version */
2102 vnc_flush(vs);
2103 vnc_client_error(vs);
2104 } else {
2105 VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
2106 vnc_write_u8(vs, 0); /* Accept version */
2107 vnc_write_u8(vs, 1); /* Number of sub-auths */
2108 vnc_write_u32(vs, vs->subauth); /* The supported auth */
2109 vnc_flush(vs);
2110 vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
2111 }
2112 return 0;
2113}
2114
2115static int start_auth_vencrypt(VncState *vs)
2116{
2117 /* Send VeNCrypt version 0.2 */
2118 vnc_write_u8(vs, 0);
2119 vnc_write_u8(vs, 2);
2120
2121 vnc_read_when(vs, protocol_client_vencrypt_init, 2);
2122 return 0;
2123}
2124#endif /* CONFIG_VNC_TLS */
2125
60fe76f3 2126static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
70848515
TS
2127{
2128 /* We only advertise 1 auth scheme at a time, so client
2129 * must pick the one we sent. Verify this */
2130 if (data[0] != vs->auth) { /* Reject auth */
2131 VNC_DEBUG("Reject auth %d\n", (int)data[0]);
2132 vnc_write_u32(vs, 1);
2133 if (vs->minor >= 8) {
2134 static const char err[] = "Authentication failed";
2135 vnc_write_u32(vs, sizeof(err));
2136 vnc_write(vs, err, sizeof(err));
2137 }
2138 vnc_client_error(vs);
2139 } else { /* Accept requested auth */
2140 VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2141 switch (vs->auth) {
2142 case VNC_AUTH_NONE:
2143 VNC_DEBUG("Accept auth none\n");
a26c97ad
AZ
2144 if (vs->minor >= 8) {
2145 vnc_write_u32(vs, 0); /* Accept auth completion */
2146 vnc_flush(vs);
2147 }
70848515
TS
2148 vnc_read_when(vs, protocol_client_init, 1);
2149 break;
2150
2151 case VNC_AUTH_VNC:
2152 VNC_DEBUG("Start VNC auth\n");
2153 return start_auth_vnc(vs);
2154
eb38c52c 2155#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
2156 case VNC_AUTH_VENCRYPT:
2157 VNC_DEBUG("Accept VeNCrypt auth\n");;
2158 return start_auth_vencrypt(vs);
2159#endif /* CONFIG_VNC_TLS */
2160
70848515
TS
2161 default: /* Should not be possible, but just in case */
2162 VNC_DEBUG("Reject auth %d\n", vs->auth);
2163 vnc_write_u8(vs, 1);
2164 if (vs->minor >= 8) {
2165 static const char err[] = "Authentication failed";
2166 vnc_write_u32(vs, sizeof(err));
2167 vnc_write(vs, err, sizeof(err));
2168 }
2169 vnc_client_error(vs);
2170 }
2171 }
2172 return 0;
2173}
2174
60fe76f3 2175static int protocol_version(VncState *vs, uint8_t *version, size_t len)
24236869
FB
2176{
2177 char local[13];
24236869
FB
2178
2179 memcpy(local, version, 12);
2180 local[12] = 0;
2181
70848515
TS
2182 if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2183 VNC_DEBUG("Malformed protocol version %s\n", local);
24236869
FB
2184 vnc_client_error(vs);
2185 return 0;
2186 }
70848515
TS
2187 VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2188 if (vs->major != 3 ||
2189 (vs->minor != 3 &&
b0566f4f 2190 vs->minor != 4 &&
70848515
TS
2191 vs->minor != 5 &&
2192 vs->minor != 7 &&
2193 vs->minor != 8)) {
2194 VNC_DEBUG("Unsupported client version\n");
2195 vnc_write_u32(vs, VNC_AUTH_INVALID);
2196 vnc_flush(vs);
2197 vnc_client_error(vs);
2198 return 0;
2199 }
b0566f4f 2200 /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
70848515
TS
2201 * as equivalent to v3.3 by servers
2202 */
b0566f4f 2203 if (vs->minor == 4 || vs->minor == 5)
70848515
TS
2204 vs->minor = 3;
2205
2206 if (vs->minor == 3) {
2207 if (vs->auth == VNC_AUTH_NONE) {
2208 VNC_DEBUG("Tell client auth none\n");
2209 vnc_write_u32(vs, vs->auth);
2210 vnc_flush(vs);
2211 vnc_read_when(vs, protocol_client_init, 1);
2212 } else if (vs->auth == VNC_AUTH_VNC) {
2213 VNC_DEBUG("Tell client VNC auth\n");
2214 vnc_write_u32(vs, vs->auth);
2215 vnc_flush(vs);
2216 start_auth_vnc(vs);
2217 } else {
2218 VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
2219 vnc_write_u32(vs, VNC_AUTH_INVALID);
2220 vnc_flush(vs);
2221 vnc_client_error(vs);
2222 }
2223 } else {
2224 VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
2225 vnc_write_u8(vs, 1); /* num auth */
2226 vnc_write_u8(vs, vs->auth);
2227 vnc_read_when(vs, protocol_client_auth, 1);
2228 vnc_flush(vs);
2229 }
24236869
FB
2230
2231 return 0;
2232}
2233
3aa3eea3
AZ
2234static void vnc_connect(VncState *vs)
2235{
2236 VNC_DEBUG("New client on socket %d\n", vs->csock);
bcfad70f 2237 vs->ds->idle = 0;
3aa3eea3
AZ
2238 socket_set_nonblock(vs->csock);
2239 qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2240 vnc_write(vs, "RFB 003.008\n", 12);
2241 vnc_flush(vs);
2242 vnc_read_when(vs, protocol_version, 12);
0e1f5a0c 2243 memset(vs->old_data, 0, ds_get_linesize(vs->ds) * ds_get_height(vs->ds));
3aa3eea3
AZ
2244 memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
2245 vs->has_resize = 0;
2246 vs->has_hextile = 0;
2247 vs->ds->dpy_copy = NULL;
2248 vnc_update_client(vs);
2249}
2250
24236869
FB
2251static void vnc_listen_read(void *opaque)
2252{
2253 VncState *vs = opaque;
2254 struct sockaddr_in addr;
2255 socklen_t addrlen = sizeof(addr);
2256
9f60ad50
AZ
2257 /* Catch-up */
2258 vga_hw_update();
2259
24236869
FB
2260 vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2261 if (vs->csock != -1) {
3aa3eea3 2262 vnc_connect(vs);
24236869
FB
2263 }
2264}
2265
71cab5ca 2266void vnc_display_init(DisplayState *ds)
24236869 2267{
24236869
FB
2268 VncState *vs;
2269
2270 vs = qemu_mallocz(sizeof(VncState));
2271 if (!vs)
2272 exit(1);
2273
2274 ds->opaque = vs;
bcfad70f 2275 ds->idle = 1;
a9ce8590 2276 vnc_state = vs;
71cab5ca 2277 vs->display = NULL;
70848515 2278 vs->password = NULL;
24236869
FB
2279
2280 vs->lsock = -1;
2281 vs->csock = -1;
564c337e
FB
2282 vs->last_x = -1;
2283 vs->last_y = -1;
24236869
FB
2284
2285 vs->ds = ds;
2286
9ca313aa
AL
2287 if (keyboard_layout)
2288 vs->kbd_layout = init_keyboard_layout(keyboard_layout);
2289 else
2290 vs->kbd_layout = init_keyboard_layout("en-us");
24236869 2291
24236869
FB
2292 if (!vs->kbd_layout)
2293 exit(1);
2294
a0ecfb73
AZ
2295 vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
2296
73fc9742
TS
2297 vs->ds->data = NULL;
2298 vs->ds->dpy_update = vnc_dpy_update;
2299 vs->ds->dpy_resize = vnc_dpy_resize;
a0ecfb73 2300 vs->ds->dpy_refresh = NULL;
73fc9742 2301
7eac3a87 2302 vnc_colordepth(vs->ds, 32);
73fc9742 2303 vnc_dpy_resize(vs->ds, 640, 400);
429a8ed3 2304
2305 vs->as.freq = 44100;
2306 vs->as.nchannels = 2;
2307 vs->as.fmt = AUD_FMT_S16;
2308 vs->as.endianness = 0;
71cab5ca
TS
2309}
2310
eb38c52c 2311#ifdef CONFIG_VNC_TLS
6f43024c
TS
2312static int vnc_set_x509_credential(VncState *vs,
2313 const char *certdir,
2314 const char *filename,
2315 char **cred,
2316 int ignoreMissing)
2317{
2318 struct stat sb;
2319
2320 if (*cred) {
2321 qemu_free(*cred);
2322 *cred = NULL;
2323 }
2324
2325 if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
2326 return -1;
2327
2328 strcpy(*cred, certdir);
2329 strcat(*cred, "/");
2330 strcat(*cred, filename);
2331
2332 VNC_DEBUG("Check %s\n", *cred);
2333 if (stat(*cred, &sb) < 0) {
2334 qemu_free(*cred);
2335 *cred = NULL;
2336 if (ignoreMissing && errno == ENOENT)
2337 return 0;
2338 return -1;
2339 }
2340
2341 return 0;
2342}
2343
2344static int vnc_set_x509_credential_dir(VncState *vs,
2345 const char *certdir)
2346{
2347 if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
2348 goto cleanup;
2349 if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
2350 goto cleanup;
2351 if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
2352 goto cleanup;
2353 if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
2354 goto cleanup;
2355
2356 return 0;
2357
2358 cleanup:
2359 qemu_free(vs->x509cacert);
2360 qemu_free(vs->x509cacrl);
2361 qemu_free(vs->x509cert);
2362 qemu_free(vs->x509key);
2363 vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
2364 return -1;
2365}
2366#endif /* CONFIG_VNC_TLS */
2367
71cab5ca
TS
2368void vnc_display_close(DisplayState *ds)
2369{
e25a5822 2370 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
71cab5ca
TS
2371
2372 if (vs->display) {
2373 qemu_free(vs->display);
2374 vs->display = NULL;
2375 }
2376 if (vs->lsock != -1) {
2377 qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2378 close(vs->lsock);
2379 vs->lsock = -1;
2380 }
2381 if (vs->csock != -1) {
2382 qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
2383 closesocket(vs->csock);
2384 vs->csock = -1;
2385 buffer_reset(&vs->input);
2386 buffer_reset(&vs->output);
2387 vs->need_update = 0;
eb38c52c 2388#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
2389 if (vs->tls_session) {
2390 gnutls_deinit(vs->tls_session);
2391 vs->tls_session = NULL;
2392 }
2393 vs->wiremode = VNC_WIREMODE_CLEAR;
2394#endif /* CONFIG_VNC_TLS */
71cab5ca 2395 }
70848515 2396 vs->auth = VNC_AUTH_INVALID;
eb38c52c 2397#ifdef CONFIG_VNC_TLS
8d5d2d4c 2398 vs->subauth = VNC_AUTH_INVALID;
469b15c6 2399 vs->x509verify = 0;
8d5d2d4c 2400#endif
429a8ed3 2401 audio_del(vs);
70848515
TS
2402}
2403
2404int vnc_display_password(DisplayState *ds, const char *password)
2405{
2406 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2407
2408 if (vs->password) {
2409 qemu_free(vs->password);
2410 vs->password = NULL;
2411 }
2412 if (password && password[0]) {
2413 if (!(vs->password = qemu_strdup(password)))
2414 return -1;
2415 }
2416
2417 return 0;
71cab5ca
TS
2418}
2419
70848515 2420int vnc_display_open(DisplayState *ds, const char *display)
71cab5ca 2421{
e25a5822 2422 VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
70848515
TS
2423 const char *options;
2424 int password = 0;
3aa3eea3 2425 int reverse = 0;
9712ecaf 2426 int to_port = 0;
eb38c52c 2427#ifdef CONFIG_VNC_TLS
3a702699 2428 int tls = 0, x509 = 0;
8d5d2d4c 2429#endif
71cab5ca
TS
2430
2431 vnc_display_close(ds);
70848515 2432 if (strcmp(display, "none") == 0)
71cab5ca 2433 return 0;
24236869 2434
70848515 2435 if (!(vs->display = strdup(display)))
71cab5ca 2436 return -1;
70848515
TS
2437
2438 options = display;
2439 while ((options = strchr(options, ','))) {
2440 options++;
469b15c6 2441 if (strncmp(options, "password", 8) == 0) {
70848515 2442 password = 1; /* Require password auth */
3aa3eea3
AZ
2443 } else if (strncmp(options, "reverse", 7) == 0) {
2444 reverse = 1;
9712ecaf
AL
2445 } else if (strncmp(options, "to=", 3) == 0) {
2446 to_port = atoi(options+3) + 5900;
eb38c52c 2447#ifdef CONFIG_VNC_TLS
469b15c6 2448 } else if (strncmp(options, "tls", 3) == 0) {
8d5d2d4c 2449 tls = 1; /* Require TLS */
469b15c6 2450 } else if (strncmp(options, "x509", 4) == 0) {
6f43024c 2451 char *start, *end;
3a702699 2452 x509 = 1; /* Require x509 certificates */
6f43024c
TS
2453 if (strncmp(options, "x509verify", 10) == 0)
2454 vs->x509verify = 1; /* ...and verify client certs */
2455
2456 /* Now check for 'x509=/some/path' postfix
2457 * and use that to setup x509 certificate/key paths */
2458 start = strchr(options, '=');
2459 end = strchr(options, ',');
2460 if (start && (!end || (start < end))) {
2461 int len = end ? end-(start+1) : strlen(start+1);
be351261 2462 char *path = qemu_strndup(start + 1, len);
be15b141 2463
6f43024c
TS
2464 VNC_DEBUG("Trying certificate path '%s'\n", path);
2465 if (vnc_set_x509_credential_dir(vs, path) < 0) {
2466 fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2467 qemu_free(path);
2468 qemu_free(vs->display);
2469 vs->display = NULL;
2470 return -1;
2471 }
2472 qemu_free(path);
2473 } else {
2474 fprintf(stderr, "No certificate path provided\n");
2475 qemu_free(vs->display);
2476 vs->display = NULL;
2477 return -1;
2478 }
8d5d2d4c 2479#endif
469b15c6 2480 }
70848515
TS
2481 }
2482
2483 if (password) {
eb38c52c 2484#ifdef CONFIG_VNC_TLS
8d5d2d4c 2485 if (tls) {
8d5d2d4c 2486 vs->auth = VNC_AUTH_VENCRYPT;
3a702699
TS
2487 if (x509) {
2488 VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2489 vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2490 } else {
2491 VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2492 vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2493 }
8d5d2d4c
TS
2494 } else {
2495#endif
2496 VNC_DEBUG("Initializing VNC server with password auth\n");
2497 vs->auth = VNC_AUTH_VNC;
eb38c52c 2498#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
2499 vs->subauth = VNC_AUTH_INVALID;
2500 }
2501#endif
70848515 2502 } else {
eb38c52c 2503#ifdef CONFIG_VNC_TLS
8d5d2d4c 2504 if (tls) {
8d5d2d4c 2505 vs->auth = VNC_AUTH_VENCRYPT;
3a702699
TS
2506 if (x509) {
2507 VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2508 vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2509 } else {
2510 VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2511 vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2512 }
8d5d2d4c
TS
2513 } else {
2514#endif
2515 VNC_DEBUG("Initializing VNC server with no auth\n");
2516 vs->auth = VNC_AUTH_NONE;
eb38c52c 2517#ifdef CONFIG_VNC_TLS
8d5d2d4c
TS
2518 vs->subauth = VNC_AUTH_INVALID;
2519 }
2520#endif
70848515 2521 }
24236869 2522
3aa3eea3 2523 if (reverse) {
9712ecaf
AL
2524 /* connect to viewer */
2525 if (strncmp(display, "unix:", 5) == 0)
2526 vs->lsock = unix_connect(display+5);
2527 else
2528 vs->lsock = inet_connect(display, SOCK_STREAM);
2529 if (-1 == vs->lsock) {
3aa3eea3
AZ
2530 free(vs->display);
2531 vs->display = NULL;
2532 return -1;
2533 } else {
2534 vs->csock = vs->lsock;
2535 vs->lsock = -1;
2536 vnc_connect(vs);
3aa3eea3 2537 }
9712ecaf 2538 return 0;
24236869 2539
9712ecaf
AL
2540 } else {
2541 /* listen for connects */
2542 char *dpy;
2543 dpy = qemu_malloc(256);
2544 if (strncmp(display, "unix:", 5) == 0) {
2545 strcpy(dpy, "unix:");
2546 vs->lsock = unix_listen(display, dpy+5, 256-5);
2547 } else {
2548 vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900);
2549 }
2550 if (-1 == vs->lsock) {
2551 free(dpy);
d0513623 2552 return -1;
9712ecaf
AL
2553 } else {
2554 free(vs->display);
2555 vs->display = dpy;
2556 }
24236869
FB
2557 }
2558
71cab5ca 2559 return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
24236869 2560}