Statistics
| Branch: | Revision:

root / vnc.c @ cf7a2fe2

History | View | Annotate | Download (58 kB)

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