Statistics
| Branch: | Revision:

root / vnc.c @ f36672ae

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