Statistics
| Branch: | Revision:

root / vnc.c @ cec7d0b6

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