Statistics
| Branch: | Revision:

root / vnc.c @ 5bfd5521

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