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