1 /*
2 * GTK VNC Widget
3 *
4 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.0 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <config.h>
23
24 #include "vncconnection.h"
25 #include "vncconnectionenums.h"
26 #include "vncmarshal.h"
27 #include "vncutil.h"
28
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39
40 #include "coroutine.h"
41 #include "d3des.h"
42
43 #include <gnutls/gnutls.h>
44 #include <gnutls/x509.h>
45 #include <gdk-pixbuf/gdk-pixbuf.h>
46
47 #ifdef HAVE_SASL
48 #include <sasl/sasl.h>
49 #endif
50
51 #ifdef HAVE_PWD_H
52 #include <pwd.h>
53 #endif
54
55 #include <zlib.h>
56
57 #include "dh.h"
58
59 #if GLIB_CHECK_VERSION(2, 31, 0)
60 #define g_mutex_new() g_new0(GMutex, 1)
61 #define g_mutex_free(m) g_free(m)
62 #endif
63
64 /*
65 * When GNUTLS >= 2.12, we must not initialize gcrypt threading
66 * because GNUTLS will do that itself, *provided* it is built
67 * against gcrypt, and not nettle.
68 * When GNUTLS < 2.12 we must always initialize gcrypt threading
69 * When GNUTLS > 3.0 we must always initialize gcrypt threading
70 *
71 * But....
72 *
73 * When gcrypt >= 1.6.0 we must not initialize gcrypt threading
74 * because gcrypt will do that itself.
75 *
76 * So we need to init grypt threading if
77 *
78 * - gcrypt < 1.6.0
79 *
80 * and either
81 *
82 * - gnutls does not use gcrypt
83 *
84 * or
85 *
86 * - gnutls < 2.12
87 */
88 #ifndef GNUTLS_VERSION_NUMBER
89 #ifndef LIBGNUTLS_VERSION_NUMBER
90 #error "GNUTLS >= 2.2.0 required to build GTK-VNC"
91 #else
92 #define GNUTLS_VERSION_NUMBER LIBGNUTLS_VERSION_NUMBER
93 #endif
94 #endif
95
96 #if ((!defined(HAVE_GNUTLS_GCRYPT) || \
97 (GNUTLS_VERSION_NUMBER < 0x020c00)) && \
98 (!defined(GCRYPT_VERSION_NUMBER) || \
99 (GCRYPT_VERSION_NUMBER < 0x010600)))
100 #define VNC_INIT_GCRYPT_THREADING
101 #else
102 #undef VNC_INIT_GCRYPT_THREADING
103 #endif
104
105
106 #define GTK_VNC_ERROR g_quark_from_static_string("gtk-vnc")
107
108 struct wait_queue
109 {
110 gboolean waiting;
111 struct coroutine *context;
112 };
113
114 typedef enum {
115 VNC_CONNECTION_SERVER_MESSAGE_FRAMEBUFFER_UPDATE = 0,
116 VNC_CONNECTION_SERVER_MESSAGE_SET_COLOR_MAP_ENTRIES = 1,
117 VNC_CONNECTION_SERVER_MESSAGE_BELL = 2,
118 VNC_CONNECTION_SERVER_MESSAGE_SERVER_CUT_TEXT = 3,
119 VNC_CONNECTION_SERVER_MESSAGE_QEMU = 255,
120 } VncConnectionServerMessage;
121
122 typedef enum {
123 VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO = 1,
124 } VncConnectionServerMessageQEMU;
125
126 typedef enum {
127 VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_STOP = 0,
128 VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_START = 1,
129 VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_DATA = 2,
130 } VncConnectionServerMessageQEMUAudio;
131
132
133 typedef enum {
134 VNC_CONNECTION_CLIENT_MESSAGE_SET_PIXEL_FORMAT = 0,
135 VNC_CONNECTION_CLIENT_MESSAGE_SET_ENCODINGS = 2,
136 VNC_CONNECTION_CLIENT_MESSAGE_FRAMEBUFFER_UPDATE_REQUEST = 3,
137 VNC_CONNECTION_CLIENT_MESSAGE_KEY = 4,
138 VNC_CONNECTION_CLIENT_MESSAGE_POINTER = 5,
139 VNC_CONNECTION_CLIENT_MESSAGE_CUT_TEXT = 6,
140 VNC_CONNECTION_CLIENT_MESSAGE_QEMU = 255,
141 } VncConnectionClientMessage;
142
143 typedef enum {
144 VNC_CONNECTION_CLIENT_MESSAGE_QEMU_KEY = 0,
145 VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO = 1,
146 } VncConnectionClientMessageQEMU;
147
148 typedef enum {
149 VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_ENABLE = 0,
150 VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_DISABLE = 1,
151 VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_SET_FORMAT = 2,
152 } VncConnectionClientMessageQEMUAudio;
153
154
155 typedef void vnc_connection_rich_cursor_blt_func(VncConnection *conn, guint8 *, guint8 *,
156 guint8 *, int, guint16, guint16);
157
158 typedef void vnc_connection_tight_compute_predicted_func(VncConnection *conn, guint8 *,
159 guint8 *, guint8 *,
160 guint8 *);
161
162 typedef void vnc_connection_tight_sum_pixel_func(VncConnection *conn, guint8 *, guint8 *);
163 static void vnc_connection_close(VncConnection *conn);
164 static void vnc_connection_set_error(VncConnection *conn,
165 const char *format,
166 ...) G_GNUC_PRINTF(2, 3);
167
168 /*
169 * A special GSource impl which allows us to wait on a certain
170 * condition to be satisfied. This is effectively a boolean test
171 * run on each iteration of the main loop. So whenever a file has
172 * new I/O, or a timer occurs, etc we'll do the check. This is
173 * pretty efficient compared to a normal GLib Idle func which has
174 * to busy wait on a timeout, since our condition is only checked
175 * when some other source's state changes
176 */
177 typedef gboolean (*g_condition_wait_func)(gpointer);
178
179 struct g_condition_wait_source
180 {
181 GSource src;
182 struct coroutine *co;
183 g_condition_wait_func func;
184 gpointer data;
185 };
186
187 #define VNC_CONNECTION_GET_PRIVATE(obj) \
188 (G_TYPE_INSTANCE_GET_PRIVATE((obj), VNC_TYPE_CONNECTION, VncConnectionPrivate))
189
190
191 struct _VncConnectionPrivate
192 {
193 struct coroutine coroutine;
194 guint open_id;
195 GSocket *sock;
196 GSocketAddress *addr;
197 int fd;
198 char *host;
199 char *port;
200 VncPixelFormat fmt;
201 char *error;
202 gboolean coroutine_stop;
203 int width;
204 int height;
205 char *name;
206
207 int major;
208 int minor;
209 gnutls_session_t tls_session;
210
211 /* Auth related params */
212 unsigned int auth_type;
213 unsigned int auth_subtype;
214 char *cred_username;
215 char *cred_password;
216 char *cred_x509_cacert;
217 char *cred_x509_cacrl;
218 char *cred_x509_cert;
219 char *cred_x509_key;
220 gboolean set_cred_x509;
221 gboolean want_cred_username;
222 gboolean want_cred_password;
223 gboolean want_cred_x509;
224
225 #ifdef HAVE_SASL
226 sasl_conn_t *saslconn; /* SASL context */
227 const char *saslDecoded;
228 unsigned int saslDecodedLength;
229 unsigned int saslDecodedOffset;
230 #endif
231
232 char read_buffer[4096];
233 size_t read_offset;
234 size_t read_size;
235
236 char write_buffer[4096];
237 size_t write_offset;
238
239 VncFramebuffer *fb;
240 gboolean fbSwapRemote;
241
242 VncCursor *cursor;
243 gboolean absPointer;
244 gboolean sharedFlag;
245
246 vnc_connection_rich_cursor_blt_func *rich_cursor_blt;
247 vnc_connection_tight_compute_predicted_func *tight_compute_predicted;
248 vnc_connection_tight_sum_pixel_func *tight_sum_pixel;
249
250 int wait_interruptable;
251 struct wait_queue wait;
252
253 char *xmit_buffer;
254 int xmit_buffer_capacity;
255 int xmit_buffer_size;
256
257 z_stream *strm;
258 z_stream streams[5];
259
260 size_t uncompressed_offset;
261 size_t uncompressed_size;
262 guint8 uncompressed_buffer[4096];
263
264 size_t compressed_length;
265 guint8 *compressed_buffer;
266
267 guint8 zrle_pi;
268 int zrle_pi_bits;
269
270 int ledstate;
271 gboolean has_ext_key_event;
272
273 struct {
274 gboolean incremental;
275 guint16 x;
276 guint16 y;
277 guint16 width;
278 guint16 height;
279 } lastUpdateRequest;
280
281 gboolean has_audio;
282 gboolean audio_format_pending;
283 gboolean audio_enable_pending;
284 gboolean audio_disable_pending;
285 VncAudioFormat audio_format;
286 VncAudio *audio;
287 VncAudioSample *audio_sample;
288 guint audio_timer;
289 };
290
291 G_DEFINE_TYPE(VncConnection, vnc_connection, G_TYPE_OBJECT);
292
293
294 enum {
295 VNC_CURSOR_CHANGED,
296 VNC_POINTER_MODE_CHANGED,
297 VNC_BELL,
298 VNC_SERVER_CUT_TEXT,
299 VNC_FRAMEBUFFER_UPDATE,
300 VNC_DESKTOP_RESIZE,
301 VNC_PIXEL_FORMAT_CHANGED,
302 VNC_LED_STATE,
303
304 VNC_AUTH_FAILURE,
305 VNC_AUTH_UNSUPPORTED,
306 VNC_AUTH_CREDENTIAL,
307 VNC_AUTH_CHOOSE_TYPE,
308 VNC_AUTH_CHOOSE_SUBTYPE,
309
310 VNC_CONNECTED,
311 VNC_INITIALIZED,
312 VNC_DISCONNECTED,
313 VNC_ERROR,
314
315 VNC_LAST_SIGNAL,
316 };
317
318 static guint signals[VNC_LAST_SIGNAL] = { 0, 0, 0, 0,
319 0, 0, 0, 0,
320 0, 0, 0, 0,
321 0, 0, 0 };
322
323 #define nibhi(a) (((a) >> 4) & 0x0F)
324 #define niblo(a) ((a) & 0x0F)
325
326
327 /* Main loop helper functions */
g_io_wait_helper(GSocket * sock G_GNUC_UNUSED,GIOCondition cond,gpointer data)328 static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
329 GIOCondition cond,
330 gpointer data)
331 {
332 struct coroutine *to = data;
333 coroutine_yieldto(to, &cond);
334 return FALSE;
335 }
336
g_io_wait(GSocket * sock,GIOCondition cond)337 static GIOCondition g_io_wait(GSocket *sock, GIOCondition cond)
338 {
339 GIOCondition *ret;
340 GSource *src = g_socket_create_source(sock,
341 cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
342 NULL);
343 g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, coroutine_self(), NULL);
344 g_source_attach(src, NULL);
345 ret = coroutine_yield(NULL);
346 g_source_unref(src);
347 return *ret;
348 }
349
350
g_io_wakeup(struct wait_queue * wait)351 static void g_io_wakeup(struct wait_queue *wait)
352 {
353 if (wait->waiting)
354 coroutine_yieldto(wait->context, NULL);
355 }
356
357
vnc_connection_timeout(gpointer data)358 static gboolean vnc_connection_timeout(gpointer data)
359 {
360 struct wait_queue *wait = data;
361
362 g_io_wakeup(wait);
363
364 return FALSE;
365 }
366
367
g_io_wait_interruptable(struct wait_queue * wait,GSocket * sock,GIOCondition cond)368 static GIOCondition g_io_wait_interruptable(struct wait_queue *wait,
369 GSocket *sock,
370 GIOCondition cond)
371 {
372 GIOCondition *ret;
373 gint id;
374
375 wait->context = coroutine_self();
376 GSource *src = g_socket_create_source(sock,
377 cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
378 NULL);
379 g_source_set_callback(src, (GSourceFunc)g_io_wait_helper,
380 wait->context, NULL);
381 id = g_source_attach(src, NULL);
382 wait->waiting = TRUE;
383 ret = coroutine_yield(NULL);
384 g_source_unref(src);
385 wait->waiting = FALSE;
386
387 if (ret == NULL) {
388 g_source_remove(id);
389 return 0;
390 } else
391 return *ret;
392 }
393
394 /*
395 * Call immediately before the main loop does an iteration. Returns
396 * true if the condition we're checking is ready for dispatch
397 */
g_condition_wait_prepare(GSource * src,int * timeout)398 static gboolean g_condition_wait_prepare(GSource *src,
399 int *timeout) {
400 struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
401 *timeout = -1;
402 return vsrc->func(vsrc->data);
403 }
404
405 /*
406 * Call immediately after the main loop does an iteration. Returns
407 * true if the condition we're checking is ready for dispatch
408 */
g_condition_wait_check(GSource * src)409 static gboolean g_condition_wait_check(GSource *src)
410 {
411 struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
412 return vsrc->func(vsrc->data);
413 }
414
g_condition_wait_dispatch(GSource * src G_GNUC_UNUSED,GSourceFunc cb,gpointer data)415 static gboolean g_condition_wait_dispatch(GSource *src G_GNUC_UNUSED,
416 GSourceFunc cb,
417 gpointer data) {
418 return cb(data);
419 }
420
421 GSourceFuncs waitFuncs = {
422 .prepare = g_condition_wait_prepare,
423 .check = g_condition_wait_check,
424 .dispatch = g_condition_wait_dispatch,
425 };
426
g_condition_wait_helper(gpointer data)427 static gboolean g_condition_wait_helper(gpointer data)
428 {
429 struct coroutine *co = (struct coroutine *)data;
430 coroutine_yieldto(co, NULL);
431 return FALSE;
432 }
433
g_condition_wait(g_condition_wait_func func,gpointer data)434 static gboolean g_condition_wait(g_condition_wait_func func, gpointer data)
435 {
436 GSource *src;
437 struct g_condition_wait_source *vsrc;
438
439 /* Short-circuit check in case we've got it ahead of time */
440 if (func(data)) {
441 return TRUE;
442 }
443
444 /*
445 * Don't have it, so yield to the main loop, checking the condition
446 * on each iteration of the main loop
447 */
448 src = g_source_new(&waitFuncs, sizeof(struct g_condition_wait_source));
449 vsrc = (struct g_condition_wait_source *)src;
450
451 vsrc->func = func;
452 vsrc->data = data;
453 vsrc->co = coroutine_self();
454
455 g_source_attach(src, NULL);
456 g_source_set_callback(src, g_condition_wait_helper, coroutine_self(), NULL);
457 coroutine_yield(NULL);
458 g_source_unref(src);
459
460 return TRUE;
461 }
462
463
464 enum {
465 PROP_0,
466 PROP_FRAMEBUFFER,
467 };
468
469
vnc_connection_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)470 static void vnc_connection_get_property(GObject *object,
471 guint prop_id,
472 GValue *value,
473 GParamSpec *pspec)
474 {
475 VncConnection *conn = VNC_CONNECTION(object);
476 VncConnectionPrivate *priv = conn->priv;
477
478 switch (prop_id) {
479 case PROP_FRAMEBUFFER:
480 g_value_set_object(value, priv->fb);
481 break;
482
483 default:
484 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
485 }
486 }
487
vnc_connection_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)488 static void vnc_connection_set_property(GObject *object,
489 guint prop_id,
490 const GValue *value,
491 GParamSpec *pspec)
492 {
493 VncConnection *conn = VNC_CONNECTION(object);
494
495 switch (prop_id) {
496 case PROP_FRAMEBUFFER:
497 vnc_connection_set_framebuffer(conn, g_value_get_object(value));
498 break;
499
500 default:
501 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
502 }
503 }
504
505 struct signal_data
506 {
507 VncConnection *conn;
508 struct coroutine *caller;
509
510 int signum;
511
512 union {
513 VncCursor *cursor;
514 gboolean absPointer;
515 const char *text;
516 int ledstate;
517 struct {
518 int x;
519 int y;
520 int width;
521 int height;
522 } area;
523 struct {
524 int width;
525 int height;
526 } size;
527 VncPixelFormat *pixelFormat;
528 const char *authReason;
529 unsigned int authUnsupported;
530 GValueArray *authCred;
531 GValueArray *authTypes;
532 const char *message;
533 } params;
534 };
535
do_vnc_connection_emit_main_context(gpointer opaque)536 static gboolean do_vnc_connection_emit_main_context(gpointer opaque)
537 {
538 struct signal_data *data = opaque;
539
540 VNC_DEBUG("Emit main context %d", data->signum);
541 switch (data->signum) {
542 case VNC_CURSOR_CHANGED:
543 g_signal_emit(G_OBJECT(data->conn),
544 signals[data->signum],
545 0,
546 data->params.cursor);
547 break;
548
549 case VNC_POINTER_MODE_CHANGED:
550 g_signal_emit(G_OBJECT(data->conn),
551 signals[data->signum],
552 0,
553 data->params.absPointer);
554 break;
555
556 case VNC_BELL:
557 g_signal_emit(G_OBJECT(data->conn),
558 signals[data->signum],
559 0);
560 break;
561
562 case VNC_SERVER_CUT_TEXT:
563 g_signal_emit(G_OBJECT(data->conn),
564 signals[data->signum],
565 0,
566 data->params.text);
567 break;
568
569 case VNC_FRAMEBUFFER_UPDATE:
570 g_signal_emit(G_OBJECT(data->conn),
571 signals[data->signum],
572 0,
573 data->params.area.x,
574 data->params.area.y,
575 data->params.area.width,
576 data->params.area.height);
577 break;
578
579 case VNC_DESKTOP_RESIZE:
580 g_signal_emit(G_OBJECT(data->conn),
581 signals[data->signum],
582 0,
583 data->params.size.width,
584 data->params.size.height);
585 break;
586
587 case VNC_PIXEL_FORMAT_CHANGED:
588 g_signal_emit(G_OBJECT(data->conn),
589 signals[data->signum],
590 0,
591 data->params.pixelFormat);
592 break;
593
594 case VNC_LED_STATE:
595 g_signal_emit(G_OBJECT(data->conn),
596 signals[data->signum],
597 0,
598 data->params.ledstate);
599 break;
600
601 case VNC_AUTH_FAILURE:
602 g_signal_emit(G_OBJECT(data->conn),
603 signals[data->signum],
604 0,
605 data->params.authReason);
606 break;
607
608 case VNC_AUTH_UNSUPPORTED:
609 g_signal_emit(G_OBJECT(data->conn),
610 signals[data->signum],
611 0,
612 data->params.authUnsupported);
613 break;
614
615 case VNC_AUTH_CREDENTIAL:
616 g_signal_emit(G_OBJECT(data->conn),
617 signals[data->signum],
618 0,
619 data->params.authCred);
620 break;
621
622 case VNC_AUTH_CHOOSE_TYPE:
623 g_signal_emit(G_OBJECT(data->conn),
624 signals[data->signum],
625 0,
626 data->params.authTypes);
627 break;
628
629 case VNC_AUTH_CHOOSE_SUBTYPE:
630 g_signal_emit(G_OBJECT(data->conn),
631 signals[data->signum],
632 0,
633 data->conn->priv->auth_type,
634 data->params.authTypes);
635 break;
636
637 case VNC_CONNECTED:
638 case VNC_INITIALIZED:
639 case VNC_DISCONNECTED:
640 g_signal_emit(G_OBJECT(data->conn),
641 signals[data->signum],
642 0);
643 break;
644
645 case VNC_ERROR:
646 g_signal_emit(G_OBJECT(data->conn),
647 signals[data->signum],
648 0,
649 data->params.message);
650 break;
651
652 default:
653 g_warn_if_reached();
654 }
655
656 coroutine_yieldto(data->caller, NULL);
657
658 return FALSE;
659 }
660
vnc_connection_emit_main_context(VncConnection * conn,int signum,struct signal_data * data)661 static void vnc_connection_emit_main_context(VncConnection *conn,
662 int signum,
663 struct signal_data *data)
664 {
665 data->conn = conn;
666 data->caller = coroutine_self();
667 data->signum = signum;
668
669 g_idle_add(do_vnc_connection_emit_main_context, data);
670
671 /* This switches to the system coroutine context, lets
672 * the idle function run to dispatch the signal, and
673 * finally returns once complete. ie this is synchronous
674 * from the POV of the VNC coroutine despite there being
675 * an idle function involved
676 */
677 coroutine_yield(NULL);
678 }
679
680
vnc_connection_set_error(VncConnection * conn,const char * format,...)681 static G_GNUC_PRINTF(2, 3) void vnc_connection_set_error(VncConnection *conn,
682 const char *format,
683 ...)
684 {
685 va_list args;
686 struct signal_data s;
687
688 va_start(args, format);
689
690 g_free(conn->priv->error);
691 conn->priv->error = g_strdup_vprintf(format, args);
692 va_end(args);
693 conn->priv->coroutine_stop = TRUE;
694
695 VNC_DEBUG("Error: %s", conn->priv->error);
696
697 s.params.message = conn->priv->error;
698 vnc_connection_emit_main_context(conn, VNC_ERROR, &s);
699 }
700
701
vnc_connection_use_compression(VncConnection * conn)702 static gboolean vnc_connection_use_compression(VncConnection *conn)
703 {
704 VncConnectionPrivate *priv = conn->priv;
705
706 return priv->compressed_buffer != NULL;
707 }
708
vnc_connection_zread(VncConnection * conn,void * buffer,size_t size)709 static int vnc_connection_zread(VncConnection *conn, void *buffer, size_t size)
710 {
711 VncConnectionPrivate *priv = conn->priv;
712 char *ptr = buffer;
713 size_t offset = 0;
714
715 while (offset < size) {
716 /* if data is available in the uncompressed buffer, then
717 * copy */
718 if (priv->uncompressed_size - priv->uncompressed_offset) {
719 size_t len = MIN(priv->uncompressed_size - priv->uncompressed_offset,
720 size - offset);
721
722 memcpy(ptr + offset,
723 priv->uncompressed_buffer + priv->uncompressed_offset,
724 len);
725
726 priv->uncompressed_offset += len;
727 offset += len;
728 } else {
729 int err;
730
731 priv->strm->next_in = priv->compressed_buffer;
732 priv->strm->avail_in = priv->compressed_length;
733 priv->strm->next_out = priv->uncompressed_buffer;
734 priv->strm->avail_out = sizeof(priv->uncompressed_buffer);
735
736 /* inflate as much as possible */
737 err = inflate(priv->strm, Z_SYNC_FLUSH);
738 if (err != Z_OK) {
739 errno = EIO;
740 return -1;
741 }
742
743 priv->uncompressed_offset = 0;
744 priv->uncompressed_size = (guint8 *)priv->strm->next_out - priv->uncompressed_buffer;
745 priv->compressed_length -= (guint8 *)priv->strm->next_in - priv->compressed_buffer;
746 priv->compressed_buffer = priv->strm->next_in;
747 }
748 }
749
750 return offset;
751 }
752
753 /* IO functions */
754
755
756 /*
757 * Read at least 1 more byte of data straight off the wire
758 * into the requested buffer.
759 */
vnc_connection_read_wire(VncConnection * conn,void * data,size_t len)760 static int vnc_connection_read_wire(VncConnection *conn, void *data, size_t len)
761 {
762 VncConnectionPrivate *priv = conn->priv;
763 int ret;
764 gboolean blocking = FALSE;
765
766 reread:
767
768 if (priv->coroutine_stop) return -EINVAL;
769
770 if (priv->tls_session) {
771 ret = gnutls_read(priv->tls_session, data, len);
772 if (ret < 0) {
773 if (ret == GNUTLS_E_AGAIN)
774 blocking = TRUE;
775 ret = -1;
776 }
777 } else {
778 GError *error = NULL;
779 ret = g_socket_receive(priv->sock,
780 data, len,
781 NULL, &error);
782 if (ret < 0) {
783 if (error) {
784 VNC_DEBUG("Read error %s", error->message);
785 if (error->code == G_IO_ERROR_WOULD_BLOCK)
786 blocking = TRUE;
787 g_error_free(error);
788 } else {
789 VNC_DEBUG("Read error unknown");
790 }
791 ret = -1;
792 }
793 }
794
795 if (ret == -1) {
796 if (blocking) {
797 if (priv->wait_interruptable) {
798 if (!g_io_wait_interruptable(&priv->wait,
799 priv->sock, G_IO_IN)) {
800 return -EAGAIN;
801 }
802 } else {
803 g_io_wait(priv->sock, G_IO_IN);
804 }
805 blocking = FALSE;
806 goto reread;
807 } else {
808 vnc_connection_set_error(conn, "%s", "Unable to read from server");
809 return -errno;
810 }
811 }
812 if (ret == 0) {
813 VNC_DEBUG("Closing the connection: vnc_connection_read() - ret=0");
814 vnc_connection_set_error(conn, "%s", "Server closed the connection");
815 return -EPIPE;
816 }
817 //VNC_DEBUG("Read wire %p %d -> %d", data, len, ret);
818
819 return ret;
820 }
821
822
823 #ifdef HAVE_SASL
824 /*
825 * Read at least 1 more byte of data out of the SASL decrypted
826 * data buffer, into the internal read buffer
827 */
vnc_connection_read_sasl(VncConnection * conn)828 static int vnc_connection_read_sasl(VncConnection *conn)
829 {
830 VncConnectionPrivate *priv = conn->priv;
831 size_t want;
832
833 //VNC_DEBUG("Read SASL %p size %d offset %d", priv->saslDecoded,
834 // priv->saslDecodedLength, priv->saslDecodedOffset);
835 if (priv->saslDecoded == NULL) {
836 char *encoded;
837 int encodedLen;
838 int err, ret;
839
840 encodedLen = 8192;
841 encoded = g_new0(char, encodedLen);
842
843 ret = vnc_connection_read_wire(conn, encoded, encodedLen);
844 if (ret < 0) {
845 g_free(encoded);
846 return ret;
847 }
848
849 err = sasl_decode(priv->saslconn, encoded, ret,
850 &priv->saslDecoded, &priv->saslDecodedLength);
851 g_free(encoded);
852 if (err != SASL_OK) {
853 vnc_connection_set_error(conn,
854 "Failed to decode SASL data %s",
855 sasl_errstring(err, NULL, NULL));
856 return -EINVAL;
857 }
858 priv->saslDecodedOffset = 0;
859 }
860
861 want = priv->saslDecodedLength - priv->saslDecodedOffset;
862 if (want > sizeof(priv->read_buffer))
863 want = sizeof(priv->read_buffer);
864
865 memcpy(priv->read_buffer,
866 priv->saslDecoded + priv->saslDecodedOffset,
867 want);
868 priv->saslDecodedOffset += want;
869 if (priv->saslDecodedOffset == priv->saslDecodedLength) {
870 priv->saslDecodedLength = priv->saslDecodedOffset = 0;
871 priv->saslDecoded = NULL;
872 }
873
874 return want;
875 }
876 #endif
877
878
879 /*
880 * Read at least 1 more byte of data straight off the wire
881 * into the internal read buffer
882 */
vnc_connection_read_plain(VncConnection * conn)883 static int vnc_connection_read_plain(VncConnection *conn)
884 {
885 VncConnectionPrivate *priv = conn->priv;
886
887 //VNC_DEBUG("Read plain %d", sizeof(priv->read_buffer));
888 return vnc_connection_read_wire(conn, priv->read_buffer, sizeof(priv->read_buffer));
889 }
890
891 /*
892 * Read at least 1 more byte of data into the internal read_buffer
893 */
vnc_connection_read_buf(VncConnection * conn)894 static int vnc_connection_read_buf(VncConnection *conn)
895 {
896 #ifdef HAVE_SASL
897 VncConnectionPrivate *priv = conn->priv;
898
899 if (priv->saslconn)
900 return vnc_connection_read_sasl(conn);
901 else
902 #endif
903 return vnc_connection_read_plain(conn);
904 }
905
906 /*
907 * Fill the 'data' buffer up with exactly 'len' bytes worth of data
908 *
909 * Must only be called from the VNC coroutine
910 */
vnc_connection_read(VncConnection * conn,void * data,size_t len)911 static int vnc_connection_read(VncConnection *conn, void *data, size_t len)
912 {
913 VncConnectionPrivate *priv = conn->priv;
914 char *ptr = data;
915 size_t offset = 0;
916
917 if (priv->coroutine_stop) return -EINVAL;
918
919 while (offset < len) {
920 size_t tmp;
921
922 /* compressed data is buffered independently of the read buffer
923 * so we must by-pass it */
924 if (vnc_connection_use_compression(conn)) {
925 int ret = vnc_connection_zread(conn, ptr + offset, len);
926 if (ret == -1) {
927 vnc_connection_set_error(conn, "%s", "Failure decompressing data");
928 return -errno;
929 }
930 offset += ret;
931 continue;
932 } else if (priv->read_offset == priv->read_size) {
933 int ret = vnc_connection_read_buf(conn);
934
935 if (ret < 0) {
936 if (ret == -EAGAIN) {
937 return offset == 0 ? -EAGAIN : offset;
938 } else {
939 return ret;
940 }
941 }
942 priv->read_offset = 0;
943 priv->read_size = ret;
944 }
945
946 tmp = MIN(priv->read_size - priv->read_offset, len - offset);
947
948 memcpy(ptr + offset, priv->read_buffer + priv->read_offset, tmp);
949
950 priv->read_offset += tmp;
951 offset += tmp;
952 }
953
954 return len;
955 }
956
957 /*
958 * Write all 'data' of length 'datalen' bytes out to
959 * the wire
960 */
vnc_connection_flush_wire(VncConnection * conn,const void * data,size_t datalen)961 static void vnc_connection_flush_wire(VncConnection *conn,
962 const void *data,
963 size_t datalen)
964 {
965 VncConnectionPrivate *priv = conn->priv;
966 const char *ptr = data;
967 size_t offset = 0;
968 //VNC_DEBUG("Flush write %p %d", data, datalen);
969 while (offset < datalen) {
970 int ret;
971 gboolean blocking = FALSE;
972
973 if (priv->coroutine_stop) return;
974
975 if (priv->tls_session) {
976 ret = gnutls_write(priv->tls_session,
977 ptr+offset,
978 datalen-offset);
979 if (ret < 0) {
980 if (ret == GNUTLS_E_AGAIN)
981 blocking = TRUE;
982 ret = -1;
983 }
984 } else {
985 GError *error = NULL;
986 ret = g_socket_send(priv->sock,
987 ptr+offset,
988 datalen-offset,
989 NULL, &error);
990 if (ret < 0) {
991 if (error) {
992 if (error->code == G_IO_ERROR_WOULD_BLOCK)
993 blocking = TRUE;
994 g_error_free(error);
995 }
996 ret = -1;
997 }
998 }
999 if (ret == -1) {
1000 if (blocking) {
1001 g_io_wait(priv->sock, G_IO_OUT);
1002 } else {
1003 vnc_connection_set_error(conn, "%s", "Failed to flush data");
1004 return;
1005 }
1006 }
1007 if (ret == 0) {
1008 vnc_connection_set_error(conn, "%s", "Failed to any flush data");
1009 return;
1010 }
1011 offset += ret;
1012 }
1013 }
1014
1015
1016 #ifdef HAVE_SASL
1017 /*
1018 * Encode all buffered data, write all encrypted data out
1019 * to the wire
1020 */
vnc_connection_flush_sasl(VncConnection * conn)1021 static void vnc_connection_flush_sasl(VncConnection *conn)
1022 {
1023 VncConnectionPrivate *priv = conn->priv;
1024 const char *output;
1025 unsigned int outputlen;
1026 int err;
1027
1028 err = sasl_encode(priv->saslconn,
1029 priv->write_buffer,
1030 priv->write_offset,
1031 &output, &outputlen);
1032 if (err != SASL_OK) {
1033 vnc_connection_set_error(conn, "Failed to encode SASL data %s",
1034 sasl_errstring(err, NULL, NULL));
1035 return;
1036 }
1037 //VNC_DEBUG("Flush SASL %d: %p %d", priv->write_offset, output, outputlen);
1038 vnc_connection_flush_wire(conn, output, outputlen);
1039 }
1040 #endif
1041
1042 /*
1043 * Write all buffered data straight out to the wire
1044 */
vnc_connection_flush_plain(VncConnection * conn)1045 static void vnc_connection_flush_plain(VncConnection *conn)
1046 {
1047 VncConnectionPrivate *priv = conn->priv;
1048
1049 //VNC_DEBUG("Flush plain %d", priv->write_offset);
1050 vnc_connection_flush_wire(conn,
1051 priv->write_buffer,
1052 priv->write_offset);
1053 }
1054
1055
1056 /*
1057 * Write all buffered data out to the wire
1058 */
vnc_connection_flush(VncConnection * conn)1059 static void vnc_connection_flush(VncConnection *conn)
1060 {
1061 VncConnectionPrivate *priv = conn->priv;
1062
1063 #ifdef HAVE_SASL
1064 if (priv->saslconn)
1065 vnc_connection_flush_sasl(conn);
1066 else
1067 #endif
1068 vnc_connection_flush_plain(conn);
1069 priv->write_offset = 0;
1070 }
1071
1072
1073 /*
1074 * Must only be called from the VNC coroutine
1075 */
vnc_connection_write(VncConnection * conn,const void * data,size_t len)1076 static void vnc_connection_write(VncConnection *conn, const void *data, size_t len)
1077 {
1078 VncConnectionPrivate *priv = conn->priv;
1079 const char *ptr = data;
1080 size_t offset = 0;
1081
1082 while (offset < len) {
1083 ssize_t tmp;
1084
1085 if (priv->write_offset == sizeof(priv->write_buffer)) {
1086 vnc_connection_flush(conn);
1087 }
1088
1089 tmp = MIN(sizeof(priv->write_buffer) - priv->write_offset,
1090 len - offset);
1091
1092 memcpy(priv->write_buffer+priv->write_offset, ptr + offset, tmp);
1093
1094 priv->write_offset += tmp;
1095 offset += tmp;
1096 }
1097 }
1098
1099
vnc_connection_tls_push(gnutls_transport_ptr_t transport,const void * data,size_t len)1100 static ssize_t vnc_connection_tls_push(gnutls_transport_ptr_t transport,
1101 const void *data,
1102 size_t len) {
1103 VncConnection *conn = transport;
1104 VncConnectionPrivate *priv = conn->priv;
1105 int ret;
1106 GError *error = NULL;
1107
1108 if (!priv->sock) {
1109 VNC_DEBUG("Unexpected TLS push on closed socket");
1110 errno = EBADF;
1111 return -1;
1112 }
1113
1114 ret = g_socket_send(priv->sock, data, len, NULL, &error);
1115 if (ret < 0) {
1116 if (error) {
1117 if (error->code == G_IO_ERROR_WOULD_BLOCK)
1118 errno = EAGAIN; /* For gnutls compat */
1119 else
1120 VNC_DEBUG("Read error %s", error->message);
1121 g_error_free(error);
1122 }
1123 return -1;
1124 }
1125 return ret;
1126 }
1127
1128
vnc_connection_tls_pull(gnutls_transport_ptr_t transport,void * data,size_t len)1129 static ssize_t vnc_connection_tls_pull(gnutls_transport_ptr_t transport,
1130 void *data,
1131 size_t len) {
1132 VncConnection *conn = transport;
1133 VncConnectionPrivate *priv = conn->priv;
1134 int ret;
1135 GError *error = NULL;
1136
1137 if (!priv->sock) {
1138 VNC_DEBUG("Unexpected TLS pull on closed socket");
1139 errno = EBADF;
1140 return -1;
1141 }
1142
1143 ret = g_socket_receive(priv->sock, data, len, NULL, &error);
1144 if (ret < 0) {
1145 if (error) {
1146 if (error->code == G_IO_ERROR_WOULD_BLOCK)
1147 errno = EAGAIN; /* For gnutls compat */
1148 else
1149 VNC_DEBUG("Read error %s", error->message);
1150 g_error_free(error);
1151 }
1152 return -1;
1153 }
1154 return ret;
1155 }
1156
vnc_connection_pixel_size(VncConnection * conn)1157 static size_t vnc_connection_pixel_size(VncConnection *conn)
1158 {
1159 VncConnectionPrivate *priv = conn->priv;
1160
1161 return priv->fmt.bits_per_pixel / 8;
1162 }
1163
1164 /*
1165 * Must only be called from the VNC coroutine
1166 */
vnc_connection_read_pixel(VncConnection * conn,guint8 * pixel)1167 static void vnc_connection_read_pixel(VncConnection *conn, guint8 *pixel)
1168 {
1169 vnc_connection_read(conn, pixel, vnc_connection_pixel_size(conn));
1170 }
1171
1172 /*
1173 * Must only be called from the VNC coroutine
1174 */
vnc_connection_read_u8(VncConnection * conn)1175 static guint8 vnc_connection_read_u8(VncConnection *conn)
1176 {
1177 guint8 value = 0;
1178 vnc_connection_read(conn, &value, sizeof(value));
1179 return value;
1180 }
1181
1182 /*
1183 * Must only be called from the VNC coroutine
1184 */
vnc_connection_read_u8_interruptable(VncConnection * conn,guint8 * value)1185 static int vnc_connection_read_u8_interruptable(VncConnection *conn, guint8 *value)
1186 {
1187 VncConnectionPrivate *priv = conn->priv;
1188 int ret;
1189
1190 priv->wait_interruptable = 1;
1191 ret = vnc_connection_read(conn, value, sizeof(*value));
1192 priv->wait_interruptable = 0;
1193
1194 return ret;
1195 }
1196
1197 /*
1198 * Must only be called from the VNC coroutine
1199 */
vnc_connection_read_u16(VncConnection * conn)1200 static guint16 vnc_connection_read_u16(VncConnection *conn)
1201 {
1202 guint16 value = 0;
1203 vnc_connection_read(conn, &value, sizeof(value));
1204 return g_ntohs(value);
1205 }
1206
1207 /*
1208 * Must only be called from the VNC coroutine
1209 */
vnc_connection_read_u32(VncConnection * conn)1210 static guint32 vnc_connection_read_u32(VncConnection *conn)
1211 {
1212 guint32 value = 0;
1213 vnc_connection_read(conn, &value, sizeof(value));
1214 return g_ntohl(value);
1215 }
1216
1217 /*
1218 * Must only be called from the VNC coroutine
1219 */
vnc_connection_read_s32(VncConnection * conn)1220 static gint32 vnc_connection_read_s32(VncConnection *conn)
1221 {
1222 gint32 value = 0;
1223 vnc_connection_read(conn, &value, sizeof(value));
1224 return g_ntohl(value);
1225 }
1226
1227 /*
1228 * Must only be called from the VNC coroutine
1229 */
vnc_connection_write_u8(VncConnection * conn,guint8 value)1230 static void vnc_connection_write_u8(VncConnection *conn, guint8 value)
1231 {
1232 vnc_connection_write(conn, &value, sizeof(value));
1233 }
1234
1235 /*
1236 * Must only be called from the VNC coroutine
1237 */
vnc_connection_write_u16(VncConnection * conn,guint16 value)1238 static void vnc_connection_write_u16(VncConnection *conn, guint16 value)
1239 {
1240 value = g_htons(value);
1241 vnc_connection_write(conn, &value, sizeof(value));
1242 }
1243
1244 /*
1245 * Must only be called from the VNC coroutine
1246 */
vnc_connection_write_u32(VncConnection * conn,guint32 value)1247 static void vnc_connection_write_u32(VncConnection *conn, guint32 value)
1248 {
1249 value = g_htonl(value);
1250 vnc_connection_write(conn, &value, sizeof(value));
1251 }
1252
1253 #define DH_BITS 1024
1254 static gnutls_dh_params_t dh_params;
1255
1256 #if 0
1257 static void vnc_connection_debug_gnutls_log(int level, const char* str) {
1258 VNC_DEBUG("%d %s", level, str);
1259 }
1260 #endif
1261
1262 #ifdef VNC_INIT_GCRYPT_THREADING
gvnc_tls_mutex_init(void ** priv)1263 static int gvnc_tls_mutex_init (void **priv)
1264 { \
1265 GMutex *lock = NULL;
1266 lock = g_mutex_new();
1267 *priv = lock;
1268 return 0;
1269 }
1270
gvnc_tls_mutex_destroy(void ** priv)1271 static int gvnc_tls_mutex_destroy(void **priv)
1272 {
1273 GMutex *lock = *priv;
1274 g_mutex_free(lock);
1275 return 0;
1276 }
1277
gvnc_tls_mutex_lock(void ** priv)1278 static int gvnc_tls_mutex_lock(void **priv)
1279 {
1280 GMutex *lock = *priv;
1281 g_mutex_lock(lock);
1282 return 0;
1283 }
1284
gvnc_tls_mutex_unlock(void ** priv)1285 static int gvnc_tls_mutex_unlock(void **priv)
1286 {
1287 GMutex *lock = *priv;
1288 g_mutex_unlock(lock);
1289 return 0;
1290 }
1291
1292 static struct gcry_thread_cbs gvnc_thread_impl = {
1293 (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)),
1294 NULL,
1295 gvnc_tls_mutex_init,
1296 gvnc_tls_mutex_destroy,
1297 gvnc_tls_mutex_lock,
1298 gvnc_tls_mutex_unlock,
1299 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
1300 };
1301 #endif /* VNC_INIT_GCRYPT_THREADING */
1302
1303
vnc_connection_tls_initialize(void)1304 static gboolean vnc_connection_tls_initialize(void)
1305 {
1306 static int tlsinitialized = 0;
1307
1308 if (tlsinitialized)
1309 return TRUE;
1310
1311 if (g_thread_supported()) {
1312 #ifdef VNC_INIT_GCRYPT_THREADING
1313 gcry_control(GCRYCTL_SET_THREAD_CBS, &gvnc_thread_impl);
1314 #endif /* VNC_INIT_GCRYPT_THREADING */
1315 gcry_check_version(NULL);
1316 }
1317
1318 if (gnutls_global_init () < 0)
1319 return FALSE;
1320
1321 if (gnutls_dh_params_init (&dh_params) < 0)
1322 return FALSE;
1323 if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1324 return FALSE;
1325
1326 #if 0
1327 if (debug_enabled) {
1328 gnutls_global_set_log_level(10);
1329 gnutls_global_set_log_function(vnc_connection_debug_gnutls_log);
1330 }
1331 #endif
1332
1333 tlsinitialized = TRUE;
1334
1335 return TRUE;
1336 }
1337
vnc_connection_tls_initialize_anon_cred(void)1338 static gnutls_anon_client_credentials vnc_connection_tls_initialize_anon_cred(void)
1339 {
1340 gnutls_anon_client_credentials anon_cred;
1341 int ret;
1342
1343 if ((ret = gnutls_anon_allocate_client_credentials(&anon_cred)) < 0) {
1344 VNC_DEBUG("Cannot allocate credentials %s", gnutls_strerror(ret));
1345 return NULL;
1346 }
1347
1348 return anon_cred;
1349 }
1350
vnc_connection_tls_initialize_cert_cred(VncConnection * conn)1351 static gnutls_certificate_credentials_t vnc_connection_tls_initialize_cert_cred(VncConnection *conn)
1352 {
1353 VncConnectionPrivate *priv = conn->priv;
1354 gnutls_certificate_credentials_t x509_cred;
1355 int ret;
1356
1357 if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1358 VNC_DEBUG("Cannot allocate credentials %s", gnutls_strerror(ret));
1359 return NULL;
1360 }
1361 if (priv->cred_x509_cacert) {
1362 if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1363 priv->cred_x509_cacert,
1364 GNUTLS_X509_FMT_PEM)) < 0) {
1365 VNC_DEBUG("Cannot load CA certificate %s", gnutls_strerror(ret));
1366 return NULL;
1367 }
1368 } else {
1369 #if GNUTLS_VERSION_NUMBER >= 0x030000
1370 VNC_DEBUG("No CA certificate provided; trying the system trust store instead");
1371
1372 if ((ret = gnutls_certificate_set_x509_system_trust(x509_cred)) < 0) {
1373 VNC_DEBUG("Cannot load system trust: %s", gnutls_strerror(ret));
1374 return NULL;
1375 }
1376
1377 VNC_DEBUG("Using the system trust store and CRL");
1378 #else
1379 VNC_DEBUG("No CA certificate provided and system trust not supported");
1380 return NULL;
1381 #endif
1382 }
1383
1384 if (priv->cred_x509_cert && priv->cred_x509_key) {
1385 if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1386 priv->cred_x509_cert,
1387 priv->cred_x509_key,
1388 GNUTLS_X509_FMT_PEM)) < 0) {
1389 VNC_DEBUG("Cannot load certificate & key %s", gnutls_strerror(ret));
1390 return NULL;
1391 }
1392 } else {
1393 VNC_DEBUG("No client cert or key provided");
1394 }
1395
1396 if (priv->cred_x509_cacrl) {
1397 if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1398 priv->cred_x509_cacrl,
1399 GNUTLS_X509_FMT_PEM)) < 0) {
1400 VNC_DEBUG("Cannot load CRL %s", gnutls_strerror(ret));
1401 return NULL;
1402 }
1403 } else {
1404 VNC_DEBUG("No CA revocation list provided");
1405 }
1406
1407 gnutls_certificate_set_dh_params (x509_cred, dh_params);
1408
1409 return x509_cred;
1410 }
1411
vnc_connection_validate_certificate(VncConnection * conn)1412 static int vnc_connection_validate_certificate(VncConnection *conn)
1413 {
1414 VncConnectionPrivate *priv = conn->priv;
1415 int ret;
1416 unsigned int status;
1417 const gnutls_datum_t *certs;
1418 unsigned int nCerts, i;
1419 time_t now;
1420
1421 VNC_DEBUG("Validating");
1422 if ((ret = gnutls_certificate_verify_peers2 (priv->tls_session, &status)) < 0) {
1423 vnc_connection_set_error(conn, "Failed to verify peer %s", gnutls_strerror(ret));
1424 return FALSE;
1425 }
1426
1427 if ((now = time(NULL)) == ((time_t)-1)) {
1428 vnc_connection_set_error(conn, "%s", "Failed to get current time");
1429 return FALSE;
1430 }
1431
1432 if (status != 0) {
1433 if (status & GNUTLS_CERT_INVALID) {
1434 vnc_connection_set_error(conn, "%s", "The certificate is not trusted");
1435 } else if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1436 vnc_connection_set_error(conn, "%s", "The certificate hasn't got a known issuer");
1437 } else if (status & GNUTLS_CERT_REVOKED) {
1438 vnc_connection_set_error(conn, "%s", "The certificate has been revoked");
1439 } else if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1440 vnc_connection_set_error(conn, "%s", "The certificate uses an insecure algorithm");
1441 } else {
1442 vnc_connection_set_error(conn, "%s", "The certificate is not valid");
1443 }
1444 return FALSE;
1445 } else {
1446 VNC_DEBUG("Certificate is valid.");
1447 }
1448
1449 if (gnutls_certificate_type_get(priv->tls_session) != GNUTLS_CRT_X509) {
1450 vnc_connection_set_error(conn, "%s", "Only x509 certificates are supported");
1451 return FALSE;
1452 }
1453
1454 if (!(certs = gnutls_certificate_get_peers(priv->tls_session, &nCerts))) {
1455 vnc_connection_set_error(conn, "%s", "Unable to query certificate peers");
1456 return FALSE;
1457 }
1458
1459 for (i = 0 ; i < nCerts ; i++) {
1460 gnutls_x509_crt_t cert;
1461 VNC_DEBUG ("Checking chain %u", i);
1462 if (gnutls_x509_crt_init (&cert) < 0) {
1463 vnc_connection_set_error(conn, "%s", "Unable to initialize cert");
1464 return FALSE;
1465 }
1466
1467 if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1468 gnutls_x509_crt_deinit (cert);
1469 vnc_connection_set_error(conn, "%s", "Unable to import certificate");
1470 return FALSE;
1471 }
1472
1473 if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1474 vnc_connection_set_error(conn, "%s", "The certificate has expired");
1475 gnutls_x509_crt_deinit (cert);
1476 return FALSE;
1477 }
1478
1479 if (gnutls_x509_crt_get_activation_time (cert) > now) {
1480 vnc_connection_set_error(conn, "%s", "The certificate is not yet activated");
1481 gnutls_x509_crt_deinit (cert);
1482 return FALSE;
1483 }
1484
1485 if (i == 0) {
1486 if (!priv->host) {
1487 vnc_connection_set_error(conn, "%s", "No hostname provided for certificate verification");
1488 gnutls_x509_crt_deinit (cert);
1489 return FALSE;
1490 }
1491 if (!gnutls_x509_crt_check_hostname (cert, priv->host)) {
1492 vnc_connection_set_error(conn,
1493 "The certificate's owner does not match hostname '%s'",
1494 priv->host);
1495 gnutls_x509_crt_deinit (cert);
1496 return FALSE;
1497 }
1498 }
1499 }
1500
1501 return TRUE;
1502 }
1503
1504
vnc_connection_read_pixel_format(VncConnection * conn,VncPixelFormat * fmt)1505 static void vnc_connection_read_pixel_format(VncConnection *conn, VncPixelFormat *fmt)
1506 {
1507 guint8 pad[3];
1508
1509 fmt->bits_per_pixel = vnc_connection_read_u8(conn);
1510 fmt->depth = vnc_connection_read_u8(conn);
1511 fmt->byte_order = vnc_connection_read_u8(conn) ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
1512 fmt->true_color_flag = vnc_connection_read_u8(conn);
1513
1514 fmt->red_max = vnc_connection_read_u16(conn);
1515 fmt->green_max = vnc_connection_read_u16(conn);
1516 fmt->blue_max = vnc_connection_read_u16(conn);
1517
1518 fmt->red_shift = vnc_connection_read_u8(conn);
1519 fmt->green_shift = vnc_connection_read_u8(conn);
1520 fmt->blue_shift = vnc_connection_read_u8(conn);
1521
1522 vnc_connection_read(conn, pad, 3);
1523
1524 VNC_DEBUG("Pixel format BPP: %d, Depth: %d, Byte order: %d, True color: %d\n"
1525 " Mask red: %3d, green: %3d, blue: %3d\n"
1526 " Shift red: %3d, green: %3d, blue: %3d",
1527 fmt->bits_per_pixel, fmt->depth, fmt->byte_order, fmt->true_color_flag,
1528 fmt->red_max, fmt->green_max, fmt->blue_max,
1529 fmt->red_shift, fmt->green_shift, fmt->blue_shift);
1530 }
1531
vnc_connection_ledstate_change(VncConnection * conn)1532 static void vnc_connection_ledstate_change(VncConnection *conn)
1533 {
1534 VncConnectionPrivate *priv = conn->priv;
1535 struct signal_data sigdata;
1536
1537 priv->ledstate = vnc_connection_read_u8(conn);
1538
1539 VNC_DEBUG("LED state: %d\n", priv->ledstate);
1540
1541 sigdata.params.ledstate = priv->ledstate;
1542 vnc_connection_emit_main_context(conn, VNC_LED_STATE, &sigdata);
1543 }
1544
1545 /* initialize function */
1546
1547 /**
1548 * vnc_connection_has_error:
1549 * @conn: (transfer none): the connection object
1550 *
1551 * Determine if the current connection is in an error
1552 * state
1553 *
1554 * Returns: TRUE if an error has occurred, FALSE otherwise
1555 */
vnc_connection_has_error(VncConnection * conn)1556 gboolean vnc_connection_has_error(VncConnection *conn)
1557 {
1558 VncConnectionPrivate *priv = conn->priv;
1559
1560 return priv->coroutine_stop;
1561 }
1562
1563 /**
1564 * vnc_connection_get_pixel_format:
1565 * @conn: (transfer none): the connection object
1566 *
1567 * Get a specification of the current pixel format
1568 *
1569 * Returns: (transfer none): the current pixel format
1570 */
vnc_connection_get_pixel_format(VncConnection * conn)1571 const VncPixelFormat *vnc_connection_get_pixel_format(VncConnection *conn)
1572 {
1573 VncConnectionPrivate *priv = conn->priv;
1574
1575 return &priv->fmt;
1576 }
1577
1578
1579 /**
1580 * vnc_connection_set_shared:
1581 * @conn: (transfer none): the connection object
1582 * @sharedFlag: the new sharing state
1583 *
1584 * Set the shared state for the connection. A TRUE value
1585 * allow allow this client to co-exist with other existing
1586 * clients. A FALSE value will cause other clients to be
1587 * dropped
1588 *
1589 * Returns: TRUE if the connection is ok, FALSE if it has an error
1590 */
vnc_connection_set_shared(VncConnection * conn,gboolean sharedFlag)1591 gboolean vnc_connection_set_shared(VncConnection *conn, gboolean sharedFlag)
1592 {
1593 VncConnectionPrivate *priv = conn->priv;
1594
1595 if (vnc_connection_is_open(conn))
1596 return FALSE;
1597
1598 priv->sharedFlag = sharedFlag;
1599
1600 return !vnc_connection_has_error(conn);
1601 }
1602
1603
1604 /**
1605 * vnc_connection_get_shared:
1606 * @conn: (transfer none): the connection object
1607 *
1608 * Get the sharing state for the connection
1609 *
1610 * Returns: TRUE if other clients are permitted, FALSE otherwise
1611 */
vnc_connection_get_shared(VncConnection * conn)1612 gboolean vnc_connection_get_shared(VncConnection *conn)
1613 {
1614 VncConnectionPrivate *priv = conn->priv;
1615
1616 return priv->sharedFlag;
1617 }
1618
1619
1620 /*
1621 * Must only be called from the SYSTEM coroutine
1622 */
vnc_connection_buffered_write(VncConnection * conn,const void * data,size_t size)1623 static void vnc_connection_buffered_write(VncConnection *conn, const void *data, size_t size)
1624 {
1625 VncConnectionPrivate *priv = conn->priv;
1626 size_t left;
1627
1628 left = priv->xmit_buffer_capacity - priv->xmit_buffer_size;
1629 if (left < size) {
1630 priv->xmit_buffer_capacity += size + 4095;
1631 priv->xmit_buffer_capacity &= ~4095;
1632
1633 priv->xmit_buffer = g_realloc(priv->xmit_buffer, priv->xmit_buffer_capacity);
1634 }
1635
1636 memcpy(&priv->xmit_buffer[priv->xmit_buffer_size],
1637 data, size);
1638
1639 priv->xmit_buffer_size += size;
1640 }
1641
1642 /*
1643 * Must only be called from the SYSTEM coroutine
1644 */
vnc_connection_buffered_write_u8(VncConnection * conn,guint8 value)1645 static void vnc_connection_buffered_write_u8(VncConnection *conn, guint8 value)
1646 {
1647 vnc_connection_buffered_write(conn, &value, 1);
1648 }
1649
1650 /*
1651 * Must only be called from the SYSTEM coroutine
1652 */
vnc_connection_buffered_write_u16(VncConnection * conn,guint16 value)1653 static void vnc_connection_buffered_write_u16(VncConnection *conn, guint16 value)
1654 {
1655 value = g_htons(value);
1656 vnc_connection_buffered_write(conn, &value, 2);
1657 }
1658
1659 /*
1660 * Must only be called from the SYSTEM coroutine
1661 */
vnc_connection_buffered_write_u32(VncConnection * conn,guint32 value)1662 static void vnc_connection_buffered_write_u32(VncConnection *conn, guint32 value)
1663 {
1664 value = g_htonl(value);
1665 vnc_connection_buffered_write(conn, &value, 4);
1666 }
1667
1668 /*
1669 * Must only be called from the SYSTEM coroutine
1670 */
vnc_connection_buffered_write_s32(VncConnection * conn,gint32 value)1671 static void vnc_connection_buffered_write_s32(VncConnection *conn, gint32 value)
1672 {
1673 value = g_htonl(value);
1674 vnc_connection_buffered_write(conn, &value, 4);
1675 }
1676
1677 /*
1678 * Must only be called from the SYSTEM coroutine
1679 */
vnc_connection_buffered_flush(VncConnection * conn)1680 static void vnc_connection_buffered_flush(VncConnection *conn)
1681 {
1682 VncConnectionPrivate *priv = conn->priv;
1683
1684 g_io_wakeup(&priv->wait);
1685 }
1686
1687 /**
1688 * vnc_connection_set_pixel_format:
1689 * @conn: (transfer none): the connection object
1690 * @fmt: (transfer none): the new pixel format
1691 *
1692 * Tell the server what pixel format to use for
1693 * framebuffer updates. It is only safe to use this
1694 * when no framebuffer updates are pending, otherwise
1695 * it is impossible to determine when the server has
1696 * switched over to using the new format.
1697 *
1698 * Returns: TRUE if the connection is ok, FALSE if it has an error
1699 */
vnc_connection_set_pixel_format(VncConnection * conn,const VncPixelFormat * fmt)1700 gboolean vnc_connection_set_pixel_format(VncConnection *conn,
1701 const VncPixelFormat *fmt)
1702 {
1703 VncConnectionPrivate *priv = conn->priv;
1704 guint8 pad[3] = {0};
1705
1706 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_SET_PIXEL_FORMAT);
1707 vnc_connection_buffered_write(conn, pad, 3);
1708
1709 vnc_connection_buffered_write_u8(conn, fmt->bits_per_pixel);
1710 vnc_connection_buffered_write_u8(conn, fmt->depth);
1711 vnc_connection_buffered_write_u8(conn, fmt->byte_order == G_BIG_ENDIAN ? 1 : 0);
1712 vnc_connection_buffered_write_u8(conn, fmt->true_color_flag);
1713
1714 vnc_connection_buffered_write_u16(conn, fmt->red_max);
1715 vnc_connection_buffered_write_u16(conn, fmt->green_max);
1716 vnc_connection_buffered_write_u16(conn, fmt->blue_max);
1717
1718 vnc_connection_buffered_write_u8(conn, fmt->red_shift);
1719 vnc_connection_buffered_write_u8(conn, fmt->green_shift);
1720 vnc_connection_buffered_write_u8(conn, fmt->blue_shift);
1721
1722 vnc_connection_buffered_write(conn, pad, 3);
1723 vnc_connection_buffered_flush(conn);
1724
1725 memcpy(&priv->fmt, fmt, sizeof(*fmt));
1726
1727 return !vnc_connection_has_error(conn);
1728 }
1729
1730
1731 /**
1732 * vnc_connection_set_audio:
1733 * @conn: (transfer none): the connection object
1734 * @audio: (transfer none): the audio sink
1735 *
1736 * Set the audio sink to use for playing back audio from
1737 * the remote session.
1738 *
1739 * Returns: TRUE if the connection is ok, FALSE if it has an error
1740 */
vnc_connection_set_audio(VncConnection * conn,VncAudio * audio)1741 gboolean vnc_connection_set_audio(VncConnection *conn,
1742 VncAudio *audio)
1743 {
1744 VncConnectionPrivate *priv = conn->priv;
1745
1746 if (priv->audio)
1747 g_object_unref(priv->audio);
1748 priv->audio = audio;
1749 if (priv->audio)
1750 g_object_ref(priv->audio);
1751
1752 return !vnc_connection_has_error(conn);
1753 }
1754
1755
vnc_connection_send_audio_format(VncConnection * conn)1756 static void vnc_connection_send_audio_format(VncConnection *conn)
1757 {
1758 VncConnectionPrivate *priv = conn->priv;
1759
1760 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU);
1761 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO);
1762 vnc_connection_buffered_write_u16(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_SET_FORMAT);
1763
1764 vnc_connection_buffered_write_u8(conn, priv->audio_format.format);
1765 vnc_connection_buffered_write_u8(conn, priv->audio_format.nchannels);
1766 vnc_connection_buffered_write_u32(conn, priv->audio_format.frequency);
1767 vnc_connection_buffered_flush(conn);
1768 priv->audio_format_pending=FALSE;
1769 }
1770
1771 /**
1772 * vnc_connection_set_audio_format:
1773 * @conn: (transfer none): the connection object
1774 * @fmt: (transfer none): the audio format
1775 *
1776 * Set the audio format specification to use for playback
1777 * from the remote session. The format should only be set
1778 * when the audio stream is not active, otherwise it will
1779 * be impossible to determine when the server has switched
1780 * to sending data in the new format
1781 *
1782 * Returns: TRUE if the connection is ok, FALSE if it has an error
1783 */
vnc_connection_set_audio_format(VncConnection * conn,const VncAudioFormat * fmt)1784 gboolean vnc_connection_set_audio_format(VncConnection *conn,
1785 const VncAudioFormat *fmt)
1786 {
1787 VncConnectionPrivate *priv = conn->priv;
1788
1789 memcpy(&priv->audio_format, fmt, sizeof(*fmt));
1790 priv->audio_format_pending = TRUE;
1791
1792 if (priv->has_audio)
1793 vnc_connection_send_audio_format(conn);
1794
1795 return !vnc_connection_has_error(conn);
1796 }
1797
1798
1799 /**
1800 * vnc_connection_get_audio_format:
1801 * @conn: (transfer none): the connection object
1802 *
1803 * Get the current audio format specification
1804 *
1805 * Returns: (transfer none): the current audio format
1806 */
vnc_connection_get_audio_format(VncConnection * conn)1807 const VncAudioFormat *vnc_connection_get_audio_format(VncConnection *conn)
1808 {
1809 VncConnectionPrivate *priv = conn->priv;
1810 return &priv->audio_format;
1811 }
1812
1813
1814 /**
1815 * vnc_connection_audio_enable:
1816 * @conn: (transfer none): the connection object
1817 *
1818 * Tell the server that it is permitted to send audio
1819 * data.
1820 *
1821 * Returns: TRUE if the connection is ok, FALSE if it has an error
1822 */
vnc_connection_audio_enable(VncConnection * conn)1823 gboolean vnc_connection_audio_enable(VncConnection *conn)
1824 {
1825 VncConnectionPrivate *priv = conn->priv;
1826
1827 if (priv->has_audio)
1828 {
1829 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU);
1830 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO);
1831 vnc_connection_buffered_write_u16(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_ENABLE);
1832 vnc_connection_buffered_flush(conn);
1833 priv->audio_enable_pending=FALSE;
1834 }
1835 else
1836 priv->audio_enable_pending=TRUE;
1837 return !vnc_connection_has_error(conn);
1838 }
1839
1840
1841 /**
1842 * vnc_connection_audio_disable:
1843 * @conn: (transfer none): the connection object
1844 *
1845 * Tell the server that it is no longer permitted to send
1846 * audio. The client may continue to receive audio for a
1847 * time after this, since packets may already be in flight.
1848 *
1849 * Returns: TRUE if the connection is ok, FALSE if it has an error
1850 */
vnc_connection_audio_disable(VncConnection * conn)1851 gboolean vnc_connection_audio_disable(VncConnection *conn)
1852 {
1853 VncConnectionPrivate *priv = conn->priv;
1854 priv->audio_disable_pending=TRUE;
1855
1856 if (priv->has_audio)
1857 {
1858 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU);
1859 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO);
1860 vnc_connection_buffered_write_u16(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_AUDIO_DISABLE);
1861 vnc_connection_buffered_flush(conn);
1862 priv->audio_disable_pending=FALSE;
1863 }
1864 else
1865 priv->audio_disable_pending=TRUE;
1866 return !vnc_connection_has_error(conn);
1867 }
1868
1869
1870 /**
1871 * vnc_connection_set_encodings:
1872 * @conn: (transfer none): the connection object
1873 * @n_encoding: number of entries in @encoding
1874 * @encoding: (transfer none)(array length=n_encoding): the list of permitted encodings
1875 *
1876 * Inform the server of the list of encodings that it is
1877 * allowed to send. This should be done before requesting
1878 * any framebuffer updates
1879 *
1880 * Returns: TRUE if the connection is ok, FALSE if it has an error
1881 */
vnc_connection_set_encodings(VncConnection * conn,int n_encoding,gint32 * encoding)1882 gboolean vnc_connection_set_encodings(VncConnection *conn, int n_encoding, gint32 *encoding)
1883 {
1884 VncConnectionPrivate *priv = conn->priv;
1885 guint8 pad[1] = {0};
1886 int i, skip_zrle=0;
1887
1888 /*
1889 * RealVNC server is broken for ZRLE in some pixel formats.
1890 * Specifically if you have a format with either R, G or B
1891 * components with a max value > 255, it still uses a CPIXEL
1892 * of 3 bytes, even though the colour requirs 4 bytes. It
1893 * thus messes up the colours of the server in a way we can't
1894 * recover from on the client. Most VNC clients don't see this
1895 * problem since they send a 'set pixel format' message instead
1896 * of running with the server's default format.
1897 *
1898 * So we kill off ZRLE encoding for problematic pixel formats
1899 */
1900 for (i = 0; i < n_encoding; i++)
1901 if (priv->fmt.depth == 32 &&
1902 (priv->fmt.red_max > 255 ||
1903 priv->fmt.blue_max > 255 ||
1904 priv->fmt.green_max > 255) &&
1905 encoding[i] == VNC_CONNECTION_ENCODING_ZRLE) {
1906 VNC_DEBUG("Dropping ZRLE encoding for broken pixel format");
1907 skip_zrle++;
1908 }
1909
1910 priv->has_ext_key_event = FALSE;
1911 priv->has_audio = FALSE;
1912 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_SET_ENCODINGS);
1913 vnc_connection_buffered_write(conn, pad, 1);
1914 vnc_connection_buffered_write_u16(conn, n_encoding - skip_zrle);
1915 for (i = 0; i < n_encoding; i++) {
1916 if (skip_zrle && encoding[i] == VNC_CONNECTION_ENCODING_ZRLE)
1917 continue;
1918 vnc_connection_buffered_write_s32(conn, encoding[i]);
1919 }
1920 vnc_connection_buffered_flush(conn);
1921 return !vnc_connection_has_error(conn);
1922 }
1923
1924
1925 /**
1926 * vnc_connection_framebuffer_update_request:
1927 * @conn: (transfer none): the connection object
1928 * @incremental: TRUE to only receive region with changes
1929 * @x: horizontal offset to region of update
1930 * @y: vertical offset to region of update
1931 * @width: horizontal size of region of update
1932 * @height: vertical size of region of update
1933 *
1934 * Request that the server send a framebuffer update when the
1935 * region positioned at (@x, @y) wth size (@width, @height)
1936 * sees damage. The update sent may be a subset of the region
1937 * requested, if @incremental is FALSE.
1938 *
1939 * Returns: TRUE if the connection is ok, FALSE if it has an error
1940 */
vnc_connection_framebuffer_update_request(VncConnection * conn,gboolean incremental,guint16 x,guint16 y,guint16 width,guint16 height)1941 gboolean vnc_connection_framebuffer_update_request(VncConnection *conn,
1942 gboolean incremental,
1943 guint16 x, guint16 y,
1944 guint16 width, guint16 height)
1945 {
1946 VncConnectionPrivate *priv = conn->priv;
1947
1948 VNC_DEBUG("Requesting framebuffer update at %d,%d size %dx%d, incremental %d",
1949 x, y, width, height, (int)incremental);
1950
1951 priv->lastUpdateRequest.incremental = incremental;
1952 priv->lastUpdateRequest.x = x;
1953 priv->lastUpdateRequest.y = y;
1954 priv->lastUpdateRequest.width = width;
1955 priv->lastUpdateRequest.height = height;
1956
1957 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_FRAMEBUFFER_UPDATE_REQUEST);
1958 vnc_connection_buffered_write_u8(conn, incremental ? 1 : 0);
1959 vnc_connection_buffered_write_u16(conn, x);
1960 vnc_connection_buffered_write_u16(conn, y);
1961 vnc_connection_buffered_write_u16(conn, width);
1962 vnc_connection_buffered_write_u16(conn, height);
1963 vnc_connection_buffered_flush(conn);
1964
1965 return !vnc_connection_has_error(conn);
1966 }
1967
1968
1969 /*
1970 * This is called when getting a psuedo-encoding message that
1971 * is not a desktop size, pixel format change.
1972 */
1973 static gboolean
vnc_connection_resend_framebuffer_update_request(VncConnection * conn)1974 vnc_connection_resend_framebuffer_update_request(VncConnection *conn)
1975 {
1976 VncConnectionPrivate *priv = conn->priv;
1977
1978 VNC_DEBUG("Re-requesting framebuffer update at %d,%d size %dx%d, incremental %d",
1979 priv->lastUpdateRequest.x,
1980 priv->lastUpdateRequest.y,
1981 priv->lastUpdateRequest.width,
1982 priv->lastUpdateRequest.height,
1983 (int)priv->lastUpdateRequest.incremental);
1984
1985 vnc_connection_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_FRAMEBUFFER_UPDATE_REQUEST);
1986 vnc_connection_write_u8(conn, priv->lastUpdateRequest.incremental ? 1 : 0);
1987 vnc_connection_write_u16(conn, priv->lastUpdateRequest.x);
1988 vnc_connection_write_u16(conn, priv->lastUpdateRequest.y);
1989 vnc_connection_write_u16(conn, priv->lastUpdateRequest.width);
1990 vnc_connection_write_u16(conn, priv->lastUpdateRequest.height);
1991 vnc_connection_flush(conn);
1992
1993 return !vnc_connection_has_error(conn);
1994 }
1995
1996
1997 /**
1998 * vnc_connection_key_event:
1999 * @conn: (transfer none): the connection object
2000 * @down_flag: TRUE if this is a key press, FALSE for a key release
2001 * @key: the X11 key code
2002 * @scancode: the XT scan code
2003 *
2004 * Send a key press/release event to the server. By default the
2005 * event will be sent with the X11 key code from @key. If the
2006 * extended key event protocol extension is active, the @scancode
2007 * will be sent instead.
2008 *
2009 * Returns: TRUE if the connection is ok, FALSE if it has an error
2010 */
vnc_connection_key_event(VncConnection * conn,gboolean down_flag,guint32 key,guint16 scancode)2011 gboolean vnc_connection_key_event(VncConnection *conn, gboolean down_flag,
2012 guint32 key, guint16 scancode)
2013 {
2014 VncConnectionPrivate *priv = conn->priv;
2015 guint8 pad[2] = {0};
2016
2017 VNC_DEBUG("Key event %u %u %d Extended: %d", key, scancode, down_flag, priv->has_ext_key_event);
2018 if (priv->has_ext_key_event) {
2019 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU);
2020 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_QEMU_KEY);
2021 vnc_connection_buffered_write_u16(conn, down_flag ? 1 : 0);
2022 vnc_connection_buffered_write_u32(conn, key);
2023 vnc_connection_buffered_write_u32(conn, scancode);
2024 } else {
2025 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_KEY);
2026 vnc_connection_buffered_write_u8(conn, down_flag ? 1 : 0);
2027 vnc_connection_buffered_write(conn, pad, 2);
2028 vnc_connection_buffered_write_u32(conn, key);
2029 }
2030
2031 vnc_connection_buffered_flush(conn);
2032 return !vnc_connection_has_error(conn);
2033 }
2034
2035 /**
2036 * vnc_connection_pointer_event:
2037 * @conn: (transfer none): the connection object
2038 * @button_mask: the new state of the buttons
2039 * @x: the new horizontal position of the pointer
2040 * @y: the new veritical position of the pointer
2041 *
2042 * Send a pointer event to the server, reflecting either movement
2043 * of the pointer, or a change in state of its buttons, or both.
2044 *
2045 * Returns: TRUE if the connection is ok, FALSE if it has an error
2046 */
vnc_connection_pointer_event(VncConnection * conn,guint8 button_mask,guint16 x,guint16 y)2047 gboolean vnc_connection_pointer_event(VncConnection *conn, guint8 button_mask,
2048 guint16 x, guint16 y)
2049 {
2050 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_POINTER);
2051 vnc_connection_buffered_write_u8(conn, button_mask);
2052 vnc_connection_buffered_write_u16(conn, x);
2053 vnc_connection_buffered_write_u16(conn, y);
2054 vnc_connection_buffered_flush(conn);
2055 return !vnc_connection_has_error(conn);
2056 }
2057
2058 /**
2059 * vnc_connection_cut_text:
2060 * @conn: (transfer none): the connection object
2061 * @data: (transfer none)(array length=@length): the data to send
2062 * @length: the length of @data
2063 *
2064 * Send updated clipboard text to the server. The encoding of @data
2065 * is undefined by the protocol specification, but recommended practice
2066 * is to use UTF-8
2067 *
2068 * Returns: TRUE if the connection is ok, FALSE if it has an error
2069 */
vnc_connection_client_cut_text(VncConnection * conn,const void * data,size_t length)2070 gboolean vnc_connection_client_cut_text(VncConnection *conn,
2071 const void *data, size_t length)
2072 {
2073 guint8 pad[3] = {0};
2074
2075 vnc_connection_buffered_write_u8(conn, VNC_CONNECTION_CLIENT_MESSAGE_CUT_TEXT);
2076 vnc_connection_buffered_write(conn, pad, 3);
2077 vnc_connection_buffered_write_u32(conn, length);
2078 vnc_connection_buffered_write(conn, data, length);
2079 vnc_connection_buffered_flush(conn);
2080 return !vnc_connection_has_error(conn);
2081 }
2082
2083
vnc_connection_swap_rfb_8(VncConnection * conn G_GNUC_UNUSED,guint8 pixel)2084 static guint8 vnc_connection_swap_rfb_8(VncConnection *conn G_GNUC_UNUSED, guint8 pixel)
2085 {
2086 return pixel;
2087 }
2088
2089 /* VNC server RFB format -> local host native format */
vnc_connection_swap_rfb_16(VncConnection * conn,guint16 pixel)2090 static guint16 vnc_connection_swap_rfb_16(VncConnection *conn, guint16 pixel)
2091 {
2092 VncConnectionPrivate *priv = conn->priv;
2093
2094 if (priv->fbSwapRemote)
2095 return (((pixel >> 8) & 0xFF) << 0) |
2096 (((pixel >> 0) & 0xFF) << 8);
2097 else
2098 return pixel;
2099 }
2100
2101 /* VNC server RFB format -> local host native format */
vnc_connection_swap_rfb_32(VncConnection * conn,guint32 pixel)2102 static guint32 vnc_connection_swap_rfb_32(VncConnection *conn, guint32 pixel)
2103 {
2104 VncConnectionPrivate *priv = conn->priv;
2105
2106 if (priv->fbSwapRemote)
2107 return (((pixel >> 24) & 0xFF) << 0) |
2108 (((pixel >> 16) & 0xFF) << 8) |
2109 (((pixel >> 8) & 0xFF) << 16) |
2110 (((pixel >> 0) & 0xFF) << 24);
2111 else
2112 return pixel;
2113 }
2114
2115 #define SRC 8
2116 #define DST 8
2117 #include "vncconnectionblt.h"
2118 #undef SRC
2119 #undef DST
2120
2121 #define SRC 8
2122 #define DST 16
2123 #include "vncconnectionblt.h"
2124 #undef SRC
2125 #undef DST
2126
2127 #define SRC 8
2128 #define DST 32
2129 #include "vncconnectionblt.h"
2130 #undef SRC
2131 #undef DST
2132
2133
2134 #define SRC 16
2135 #define DST 8
2136 #include "vncconnectionblt.h"
2137 #undef SRC
2138 #undef DST
2139
2140 #define SRC 16
2141 #define DST 16
2142 #include "vncconnectionblt.h"
2143 #undef SRC
2144 #undef DST
2145
2146 #define SRC 16
2147 #define DST 32
2148 #include "vncconnectionblt.h"
2149 #undef SRC
2150 #undef DST
2151
2152
2153 #define SRC 32
2154 #define DST 8
2155 #include "vncconnectionblt.h"
2156 #undef SRC
2157 #undef DST
2158
2159 #define SRC 32
2160 #define DST 16
2161 #include "vncconnectionblt.h"
2162 #undef SRC
2163 #undef DST
2164
2165 #define SRC 32
2166 #define DST 32
2167 #include "vncconnectionblt.h"
2168 #undef SRC
2169 #undef DST
2170
2171 static vnc_connection_rich_cursor_blt_func *vnc_connection_rich_cursor_blt_table[3] = {
2172 vnc_connection_rich_cursor_blt_8x32,
2173 vnc_connection_rich_cursor_blt_16x32,
2174 vnc_connection_rich_cursor_blt_32x32,
2175 };
2176
2177 static vnc_connection_tight_compute_predicted_func *vnc_connection_tight_compute_predicted_table[3] = {
2178 (vnc_connection_tight_compute_predicted_func *)vnc_connection_tight_compute_predicted_8x8,
2179 (vnc_connection_tight_compute_predicted_func *)vnc_connection_tight_compute_predicted_16x16,
2180 (vnc_connection_tight_compute_predicted_func *)vnc_connection_tight_compute_predicted_32x32,
2181 };
2182
2183 static vnc_connection_tight_sum_pixel_func *vnc_connection_tight_sum_pixel_table[3] = {
2184 (vnc_connection_tight_sum_pixel_func *)vnc_connection_tight_sum_pixel_8x8,
2185 (vnc_connection_tight_sum_pixel_func *)vnc_connection_tight_sum_pixel_16x16,
2186 (vnc_connection_tight_sum_pixel_func *)vnc_connection_tight_sum_pixel_32x32,
2187 };
2188
vnc_connection_validate_boundary(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2189 static gboolean vnc_connection_validate_boundary(VncConnection *conn,
2190 guint16 x, guint16 y,
2191 guint16 width, guint16 height)
2192 {
2193 VncConnectionPrivate *priv = conn->priv;
2194
2195 if ((x + width) > priv->width || (y + height) > priv->height) {
2196 vnc_connection_set_error(conn, "Framebuffer update %dx%d at %d,%d "
2197 "outside boundary %dx%d",
2198 width, height, x, y, priv->width, priv->height);
2199 }
2200
2201 return !vnc_connection_has_error(conn);
2202 }
2203
2204
vnc_connection_raw_update(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2205 static void vnc_connection_raw_update(VncConnection *conn,
2206 guint16 x, guint16 y,
2207 guint16 width, guint16 height)
2208 {
2209 VncConnectionPrivate *priv = conn->priv;
2210
2211 /* optimize for perfect match between server/client
2212 FWIW, in the local case, we ought to be doing a write
2213 directly from the source framebuffer and a read directly
2214 into the client framebuffer
2215 */
2216 if (vnc_framebuffer_perfect_format_match(priv->fb)) {
2217 int i;
2218 int rowstride = vnc_framebuffer_get_rowstride(priv->fb);
2219 guint8 *dst = vnc_framebuffer_get_buffer(priv->fb);
2220
2221 dst += (y * rowstride) + (x * (priv->fmt.bits_per_pixel/8));
2222
2223 for (i = 0; i < height; i++) {
2224 vnc_connection_read(conn, dst,
2225 width * (priv->fmt.bits_per_pixel/8));
2226 dst += rowstride;
2227 }
2228 } else {
2229 guint8 *dst;
2230 int i;
2231
2232 dst = g_malloc(width * (priv->fmt.bits_per_pixel / 8));
2233 for (i = 0; i < height; i++) {
2234 vnc_connection_read(conn, dst, width * (priv->fmt.bits_per_pixel / 8));
2235 vnc_framebuffer_blt(priv->fb, dst, 0, x, y + i, width, 1);
2236 }
2237 g_free(dst);
2238 }
2239 }
2240
vnc_connection_copyrect_update(VncConnection * conn,guint16 dst_x,guint16 dst_y,guint16 width,guint16 height)2241 static void vnc_connection_copyrect_update(VncConnection *conn,
2242 guint16 dst_x, guint16 dst_y,
2243 guint16 width, guint16 height)
2244 {
2245 VncConnectionPrivate *priv = conn->priv;
2246 int src_x, src_y;
2247
2248 src_x = vnc_connection_read_u16(conn);
2249 src_y = vnc_connection_read_u16(conn);
2250
2251 if (!vnc_connection_validate_boundary(conn, src_x, src_y, width, height))
2252 return;
2253
2254 vnc_framebuffer_copyrect(priv->fb,
2255 src_x, src_y,
2256 dst_x, dst_y,
2257 width, height);
2258 }
2259
vnc_connection_hextile_rect(VncConnection * conn,guint8 flags,guint16 x,guint16 y,guint16 width,guint16 height,guint8 * fg,guint8 * bg)2260 static void vnc_connection_hextile_rect(VncConnection *conn,
2261 guint8 flags,
2262 guint16 x, guint16 y,
2263 guint16 width, guint16 height,
2264 guint8 *fg, guint8 *bg)
2265 {
2266 VncConnectionPrivate *priv = conn->priv;
2267 int i;
2268
2269 if (flags & 0x01) {
2270 vnc_connection_raw_update(conn, x, y, width, height);
2271 } else {
2272 /* Background Specified */
2273 if (flags & 0x02)
2274 vnc_connection_read_pixel(conn, bg);
2275
2276 /* Foreground Specified */
2277 if (flags & 0x04)
2278 vnc_connection_read_pixel(conn, fg);
2279
2280 vnc_framebuffer_fill(priv->fb, bg, x, y, width, height);
2281
2282 /* AnySubrects */
2283 if (flags & 0x08) {
2284 guint8 n_rects = vnc_connection_read_u8(conn);
2285
2286 for (i = 0; i < n_rects; i++) {
2287 guint8 xy, wh;
2288
2289 /* SubrectsColored */
2290 if (flags & 0x10)
2291 vnc_connection_read_pixel(conn, fg);
2292
2293 xy = vnc_connection_read_u8(conn);
2294 wh = vnc_connection_read_u8(conn);
2295
2296 if (!vnc_connection_validate_boundary(conn, x + nibhi(xy), y + niblo(xy),
2297 nibhi(wh) + 1, niblo(wh) + 1))
2298 return;
2299
2300 vnc_framebuffer_fill(priv->fb, fg,
2301 x + nibhi(xy), y + niblo(xy),
2302 nibhi(wh) + 1, niblo(wh) + 1);
2303 }
2304 }
2305 }
2306 }
2307
2308
vnc_connection_hextile_update(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2309 static void vnc_connection_hextile_update(VncConnection *conn,
2310 guint16 x, guint16 y,
2311 guint16 width, guint16 height)
2312 {
2313 guint8 fg[4];
2314 guint8 bg[4];
2315
2316 int j;
2317 for (j = 0; j < height; j += 16) {
2318 int i;
2319 for (i = 0; i < width; i += 16) {
2320 guint8 flags;
2321 int w = MIN(16, width - i);
2322 int h = MIN(16, height - j);
2323
2324 flags = vnc_connection_read_u8(conn);
2325 vnc_connection_hextile_rect(conn, flags,
2326 x + i, y + j,
2327 w, h,
2328 fg, bg);
2329 }
2330 }
2331 }
2332
vnc_connection_rre_update(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2333 static void vnc_connection_rre_update(VncConnection *conn,
2334 guint16 x, guint16 y,
2335 guint16 width, guint16 height)
2336 {
2337 VncConnectionPrivate *priv = conn->priv;
2338 guint8 bg[4];
2339 guint32 num;
2340 guint32 i;
2341
2342 num = vnc_connection_read_u32(conn);
2343 vnc_connection_read_pixel(conn, bg);
2344 vnc_framebuffer_fill(priv->fb, bg, x, y, width, height);
2345
2346 for (i = 0; i < num; i++) {
2347 guint8 fg[4];
2348 guint16 sub_x, sub_y, sub_w, sub_h;
2349
2350 vnc_connection_read_pixel(conn, fg);
2351 sub_x = vnc_connection_read_u16(conn);
2352 sub_y = vnc_connection_read_u16(conn);
2353 sub_w = vnc_connection_read_u16(conn);
2354 sub_h = vnc_connection_read_u16(conn);
2355
2356 if (!vnc_connection_validate_boundary(conn, x + sub_x, y + sub_y, sub_w, sub_h))
2357 break;
2358
2359 vnc_framebuffer_fill(priv->fb, fg,
2360 x + sub_x, y + sub_y, sub_w, sub_h);
2361 }
2362 }
2363
2364 /* CPIXELs are optimized slightly. 32-bit pixel values are packed into 24-bit
2365 * values. */
vnc_connection_read_cpixel(VncConnection * conn,guint8 * pixel)2366 static void vnc_connection_read_cpixel(VncConnection *conn, guint8 *pixel)
2367 {
2368 VncConnectionPrivate *priv = conn->priv;
2369 int bpp = vnc_connection_pixel_size(conn);
2370
2371 memset(pixel, 0, bpp);
2372
2373 if (bpp == 4 && priv->fmt.true_color_flag) {
2374 int fitsInMSB = ((priv->fmt.red_shift > 7) &&
2375 (priv->fmt.green_shift > 7) &&
2376 (priv->fmt.blue_shift > 7));
2377 int fitsInLSB = (((priv->fmt.red_max << priv->fmt.red_shift) < (1 << 24)) &&
2378 ((priv->fmt.green_max << priv->fmt.green_shift) < (1 << 24)) &&
2379 ((priv->fmt.blue_max << priv->fmt.blue_shift) < (1 << 24)));
2380
2381 /*
2382 * We need to analyse the shifts to see if they fit in 3 bytes,
2383 * rather than looking at the declared 'depth' for the format
2384 * because despite what the RFB spec says, this is what RealVNC
2385 * server actually does in practice.
2386 */
2387 if (fitsInMSB || fitsInLSB) {
2388 bpp = 3;
2389 if (priv->fmt.depth == 24 &&
2390 priv->fmt.byte_order == G_BIG_ENDIAN)
2391 pixel++;
2392 }
2393 }
2394
2395 vnc_connection_read(conn, pixel, bpp);
2396 }
2397
vnc_connection_zrle_update_tile_blit(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2398 static void vnc_connection_zrle_update_tile_blit(VncConnection *conn,
2399 guint16 x, guint16 y,
2400 guint16 width, guint16 height)
2401 {
2402 VncConnectionPrivate *priv = conn->priv;
2403 guint8 *blit_data;
2404 int i, bpp;
2405
2406 blit_data = g_new0(guint8, 4*64*64);
2407
2408 bpp = vnc_connection_pixel_size(conn);
2409
2410 for (i = 0; i < width * height; i++)
2411 vnc_connection_read_cpixel(conn, blit_data + (i * bpp));
2412
2413 vnc_framebuffer_blt(priv->fb, blit_data, width * bpp, x, y, width, height);
2414
2415 g_free(blit_data);
2416 }
2417
vnc_connection_read_zrle_pi(VncConnection * conn,int palette_size)2418 static guint8 vnc_connection_read_zrle_pi(VncConnection *conn, int palette_size)
2419 {
2420 VncConnectionPrivate *priv = conn->priv;
2421 guint8 pi = 0;
2422
2423 if (priv->zrle_pi_bits == 0) {
2424 priv->zrle_pi = vnc_connection_read_u8(conn);
2425 priv->zrle_pi_bits = 8;
2426 }
2427 if ( palette_size == 2) {
2428 pi = (priv->zrle_pi >> (priv->zrle_pi_bits - 1)) & 1;
2429 priv->zrle_pi_bits -= 1;
2430 } else if ((palette_size == 3) || (palette_size == 4)) {
2431 pi = (priv->zrle_pi >> (priv->zrle_pi_bits - 2)) & 3;
2432 priv->zrle_pi_bits -= 2;
2433 } else if ((palette_size >=5) && (palette_size <=16)){
2434 pi = (priv->zrle_pi >> (priv->zrle_pi_bits - 4)) & 15;
2435 priv->zrle_pi_bits -= 4;
2436 }
2437
2438 return pi;
2439 }
2440
vnc_connection_zrle_update_tile_palette(VncConnection * conn,guint8 palette_size,guint16 x,guint16 y,guint16 width,guint16 height)2441 static void vnc_connection_zrle_update_tile_palette(VncConnection *conn,
2442 guint8 palette_size,
2443 guint16 x, guint16 y,
2444 guint16 width, guint16 height)
2445 {
2446 VncConnectionPrivate *priv = conn->priv;
2447 guint8 palette[128][4];
2448 int i, j;
2449
2450 for (i = 0; i < palette_size; i++)
2451 vnc_connection_read_cpixel(conn, palette[i]);
2452
2453 for (j = 0; j < height; j++) {
2454 /* discard any padding bits */
2455 priv->zrle_pi_bits = 0;
2456
2457 for (i = 0; i < width; i++) {
2458 int ind = vnc_connection_read_zrle_pi(conn, palette_size);
2459
2460 vnc_framebuffer_set_pixel_at(priv->fb, palette[ind & 0x7F],
2461 x + i, y + j);
2462 }
2463 }
2464 }
2465
vnc_connection_read_zrle_rl(VncConnection * conn)2466 static int vnc_connection_read_zrle_rl(VncConnection *conn)
2467 {
2468 int rl = 1;
2469 guint8 b;
2470
2471 do {
2472 b = vnc_connection_read_u8(conn);
2473 rl += b;
2474 } while (!vnc_connection_has_error(conn) && b == 255);
2475
2476 return rl;
2477 }
2478
vnc_connection_zrle_update_tile_rle(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2479 static void vnc_connection_zrle_update_tile_rle(VncConnection *conn,
2480 guint16 x, guint16 y,
2481 guint16 width, guint16 height)
2482 {
2483 VncConnectionPrivate *priv = conn->priv;
2484 int i, j, rl = 0;
2485 guint8 pixel[4];
2486
2487 for (j = 0; j < height; j++) {
2488 for (i = 0; i < width; i++) {
2489 if (rl == 0) {
2490 vnc_connection_read_cpixel(conn, pixel);
2491 rl = vnc_connection_read_zrle_rl(conn);
2492 }
2493 vnc_framebuffer_set_pixel_at(priv->fb, pixel, x + i, y + j);
2494 rl -= 1;
2495 }
2496 }
2497 }
2498
vnc_connection_zrle_update_tile_prle(VncConnection * conn,guint8 palette_size,guint16 x,guint16 y,guint16 width,guint16 height)2499 static void vnc_connection_zrle_update_tile_prle(VncConnection *conn,
2500 guint8 palette_size,
2501 guint16 x, guint16 y,
2502 guint16 width, guint16 height)
2503 {
2504 VncConnectionPrivate *priv = conn->priv;
2505 int i, j, rl = 0;
2506 guint8 palette[128][4];
2507 guint8 pi = 0;
2508
2509 for (i = 0; i < palette_size; i++)
2510 vnc_connection_read_cpixel(conn, palette[i]);
2511
2512 for (j = 0; j < height; j++) {
2513 for (i = 0; i < width; i++) {
2514 if (rl == 0) {
2515 pi = vnc_connection_read_u8(conn);
2516 if (pi & 0x80) {
2517 rl = vnc_connection_read_zrle_rl(conn);
2518 pi &= 0x7F;
2519 } else
2520 rl = 1;
2521 }
2522
2523 vnc_framebuffer_set_pixel_at(priv->fb, palette[pi], x + i, y + j);
2524 rl -= 1;
2525 }
2526 }
2527 }
2528
vnc_connection_zrle_update_tile(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2529 static void vnc_connection_zrle_update_tile(VncConnection *conn, guint16 x, guint16 y,
2530 guint16 width, guint16 height)
2531 {
2532 VncConnectionPrivate *priv = conn->priv;
2533 guint8 subencoding = vnc_connection_read_u8(conn);
2534 guint8 pixel[4];
2535
2536 if (subencoding == 0 ) {
2537 /* Raw pixel data */
2538 vnc_connection_zrle_update_tile_blit(conn, x, y, width, height);
2539 } else if (subencoding == 1) {
2540 /* Solid tile of a single color */
2541 vnc_connection_read_cpixel(conn, pixel);
2542 vnc_framebuffer_fill(priv->fb, pixel, x, y, width, height);
2543 } else if ((subencoding >= 2) && (subencoding <= 16)) {
2544 /* Packed palette types */
2545 vnc_connection_zrle_update_tile_palette(conn, subencoding,
2546 x, y, width, height);
2547 } else if ((subencoding >= 17) && (subencoding <= 127)) {
2548 /* FIXME raise error? */
2549 } else if (subencoding == 128) {
2550 /* Plain RLE */
2551 vnc_connection_zrle_update_tile_rle(conn, x, y, width, height);
2552 } else if (subencoding == 129) {
2553
2554 } else if (subencoding >= 130) {
2555 /* Palette RLE */
2556 vnc_connection_zrle_update_tile_prle(conn, subencoding - 128,
2557 x, y, width, height);
2558 }
2559 }
2560
vnc_connection_zrle_update(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2561 static void vnc_connection_zrle_update(VncConnection *conn,
2562 guint16 x, guint16 y,
2563 guint16 width, guint16 height)
2564 {
2565 VncConnectionPrivate *priv = conn->priv;
2566 guint32 length;
2567 guint16 i, j;
2568 guint8 *zlib_data;
2569
2570 length = vnc_connection_read_u32(conn);
2571 zlib_data = g_malloc(length);
2572 vnc_connection_read(conn, zlib_data, length);
2573
2574 /* setup subsequent calls to vnc_connection_read*() to use the compressed data */
2575 priv->uncompressed_offset = 0;
2576 priv->uncompressed_size = 0;
2577 priv->compressed_length = length;
2578 priv->compressed_buffer = zlib_data;
2579 priv->strm = &priv->streams[0];
2580
2581 for (j = 0; j < height; j += 64) {
2582 for (i = 0; i < width; i += 64) {
2583 guint16 w, h;
2584
2585 w = MIN(width - i, 64);
2586 h = MIN(height - j, 64);
2587 vnc_connection_zrle_update_tile(conn, x + i, y + j, w, h);
2588 }
2589 }
2590
2591 priv->strm = NULL;
2592 priv->uncompressed_offset = 0;
2593 priv->uncompressed_size = 0;
2594 priv->compressed_length = 0;
2595 priv->compressed_buffer = NULL;
2596
2597 g_free(zlib_data);
2598 }
2599
vnc_connection_read_cint(VncConnection * conn)2600 static guint32 vnc_connection_read_cint(VncConnection *conn)
2601 {
2602 guint32 value = 0;
2603 guint8 val;
2604
2605 val = vnc_connection_read_u8(conn);
2606 value = (val & 0x7F);
2607 if (!(val & 0x80))
2608 return value;
2609
2610 val = vnc_connection_read_u8(conn);
2611 value |= (val & 0x7F) << 7;
2612
2613 if (!(val & 0x80))
2614 return value;
2615
2616 value |= vnc_connection_read_u8(conn) << 14;
2617
2618 return value;
2619 }
2620
vnc_connection_tpixel_size(VncConnection * conn)2621 static int vnc_connection_tpixel_size(VncConnection *conn)
2622 {
2623 VncConnectionPrivate *priv = conn->priv;
2624
2625 if (priv->fmt.depth == 24)
2626 return 3;
2627 return priv->fmt.bits_per_pixel / 8;
2628 }
2629
vnc_connection_read_tpixel(VncConnection * conn,guint8 * pixel)2630 static void vnc_connection_read_tpixel(VncConnection *conn, guint8 *pixel)
2631 {
2632 VncConnectionPrivate *priv = conn->priv;
2633
2634 if (priv->fmt.depth == 24) {
2635 guint32 val;
2636 vnc_connection_read(conn, pixel, 3);
2637 val = (pixel[0] << priv->fmt.red_shift)
2638 | (pixel[1] << priv->fmt.green_shift)
2639 | (pixel[2] << priv->fmt.blue_shift);
2640
2641 if (priv->fmt.byte_order != G_BYTE_ORDER)
2642 val = (((val >> 0) & 0xFF) << 24) |
2643 (((val >> 8) & 0xFF) << 16) |
2644 (((val >> 16) & 0xFF) << 8) |
2645 (((val >> 24) & 0xFF) << 0);
2646
2647 memcpy(pixel, &val, 4);
2648 } else
2649 vnc_connection_read_pixel(conn, pixel);
2650 }
2651
vnc_connection_tight_update_copy(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2652 static void vnc_connection_tight_update_copy(VncConnection *conn,
2653 guint16 x, guint16 y,
2654 guint16 width, guint16 height)
2655 {
2656 VncConnectionPrivate *priv = conn->priv;
2657 guint8 pixel[4];
2658 int i, j;
2659
2660 for (j = 0; j < height; j++) {
2661 for (i = 0; i < width; i++) {
2662 vnc_connection_read_tpixel(conn, pixel);
2663 vnc_framebuffer_set_pixel_at(priv->fb, pixel, x + i, y + j);
2664 }
2665 }
2666 }
2667
vnc_connection_tight_get_pi(VncConnection * conn,guint8 * ra,int i,guint8 palette_size)2668 static int vnc_connection_tight_get_pi(VncConnection *conn, guint8 *ra,
2669 int i, guint8 palette_size)
2670 {
2671 if (palette_size == 2) {
2672 if ((i % 8) == 0)
2673 *ra = vnc_connection_read_u8(conn);
2674 return (*ra >> (7 - (i % 8))) & 1;
2675 }
2676
2677 return vnc_connection_read_u8(conn);
2678 }
2679
vnc_connection_tight_update_palette(VncConnection * conn,int palette_size,guint8 * palette,guint16 x,guint16 y,guint16 width,guint16 height)2680 static void vnc_connection_tight_update_palette(VncConnection *conn,
2681 int palette_size, guint8 *palette,
2682 guint16 x, guint16 y,
2683 guint16 width, guint16 height)
2684 {
2685 VncConnectionPrivate *priv = conn->priv;
2686 int i, j;
2687
2688 for (j = 0; j < height; j++) {
2689 guint8 ra = 0;
2690
2691 for (i = 0; i < width; i++) {
2692 guint8 ind;
2693
2694 ind = vnc_connection_tight_get_pi(conn, &ra, i, palette_size);
2695 vnc_framebuffer_set_pixel_at(priv->fb, &palette[ind * 4], x + i, y + j);
2696 }
2697 }
2698 }
2699
vnc_connection_tight_compute_predicted(VncConnection * conn,guint8 * ppixel,guint8 * lp,guint8 * cp,guint8 * llp)2700 static void vnc_connection_tight_compute_predicted(VncConnection *conn, guint8 *ppixel,
2701 guint8 *lp, guint8 *cp,
2702 guint8 *llp)
2703 {
2704 VncConnectionPrivate *priv = conn->priv;
2705
2706 priv->tight_compute_predicted(conn, ppixel, lp, cp, llp);
2707 }
2708
vnc_connection_tight_sum_pixel(VncConnection * conn,guint8 * lhs,guint8 * rhs)2709 static void vnc_connection_tight_sum_pixel(VncConnection *conn,
2710 guint8 *lhs, guint8 *rhs)
2711 {
2712 VncConnectionPrivate *priv = conn->priv;
2713
2714 priv->tight_sum_pixel(conn, lhs, rhs);
2715 }
2716
vnc_connection_tight_update_gradient(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2717 static void vnc_connection_tight_update_gradient(VncConnection *conn,
2718 guint16 x, guint16 y,
2719 guint16 width, guint16 height)
2720 {
2721 int i, j;
2722 guint8 zero_pixel[4];
2723 guint8 *last_row, *row;
2724 int bpp;
2725 VncConnectionPrivate *priv = conn->priv;
2726
2727 bpp = vnc_connection_pixel_size(conn);
2728 last_row = g_malloc(width * bpp);
2729 row = g_malloc(width * bpp);
2730
2731 memset(last_row, 0, width * bpp);
2732 memset(zero_pixel, 0, 4);
2733
2734 for (j = 0; j < height; j++) {
2735 guint8 *tmp_row;
2736 guint8 *llp, *lp;
2737
2738 /* use zero pixels for the edge cases */
2739 llp = zero_pixel;
2740 lp = zero_pixel;
2741
2742 for (i = 0; i < width; i++) {
2743 guint8 predicted_pixel[4];
2744
2745 /* compute predicted pixel value */
2746 vnc_connection_tight_compute_predicted(conn, predicted_pixel,
2747 lp, last_row + i * bpp,
2748 llp);
2749
2750 /* read the difference pixel from the wire */
2751 vnc_connection_read_tpixel(conn, row + i * bpp);
2752
2753 /* sum the predicted pixel and the difference to get
2754 * the original pixel value */
2755 vnc_connection_tight_sum_pixel(conn, row + i * bpp,
2756 predicted_pixel);
2757
2758 llp = last_row + i * bpp;
2759 lp = row + i * bpp;
2760 }
2761
2762 /* write out row of pixel data */
2763 vnc_framebuffer_blt(priv->fb, row, width * bpp, x, y + j, width, 1);
2764
2765 /* swap last row and current row */
2766 tmp_row = last_row;
2767 last_row = row;
2768 row = tmp_row;
2769 }
2770
2771 g_free(row);
2772 g_free(last_row);
2773 }
2774
2775
vnc_connection_tight_update_jpeg(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height,guint8 * data,size_t length)2776 static void vnc_connection_tight_update_jpeg(VncConnection *conn, guint16 x, guint16 y,
2777 guint16 width, guint16 height,
2778 guint8 *data, size_t length)
2779 {
2780 VncConnectionPrivate *priv = conn->priv;
2781 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
2782 GdkPixbuf *p;
2783
2784 if (!gdk_pixbuf_loader_write(loader, data, length, NULL)) {
2785 vnc_connection_set_error(conn, "%s", "Unable to decode jpeg data");
2786 return;
2787 }
2788
2789 gdk_pixbuf_loader_close(loader, NULL);
2790
2791 p = g_object_ref(gdk_pixbuf_loader_get_pixbuf(loader));
2792 g_object_unref(loader);
2793
2794 vnc_framebuffer_rgb24_blt(priv->fb,
2795 gdk_pixbuf_get_pixels(p),
2796 gdk_pixbuf_get_rowstride(p),
2797 x, y, width, height);
2798
2799 g_object_unref(p);
2800 }
2801
vnc_connection_tight_update(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)2802 static void vnc_connection_tight_update(VncConnection *conn,
2803 guint16 x, guint16 y,
2804 guint16 width, guint16 height)
2805 {
2806 VncConnectionPrivate *priv = conn->priv;
2807 guint8 ccontrol;
2808 guint8 pixel[4];
2809 int i;
2810
2811 ccontrol = vnc_connection_read_u8(conn);
2812
2813 for (i = 0; i < 4; i++) {
2814 if (ccontrol & (1 << i)) {
2815 inflateEnd(&priv->streams[i + 1]);
2816 inflateInit(&priv->streams[i + 1]);
2817 }
2818 }
2819
2820 ccontrol >>= 4;
2821 ccontrol &= 0x0F;
2822
2823 if (ccontrol <= 7) {
2824 /* basic */
2825 guint8 filter_id = 0;
2826 guint32 data_size, zlib_length;
2827 guint8 *zlib_data = NULL;
2828 guint8 palette[256][4];
2829 int palette_size = 0;
2830
2831 if (ccontrol & 0x04)
2832 filter_id = vnc_connection_read_u8(conn);
2833
2834 priv->strm = &priv->streams[(ccontrol & 0x03) + 1];
2835
2836 if (filter_id == 1) {
2837 palette_size = vnc_connection_read_u8(conn);
2838 palette_size += 1;
2839 for (i = 0; i < palette_size; i++)
2840 vnc_connection_read_tpixel(conn, palette[i]);
2841 }
2842
2843 if (filter_id == 1) {
2844 if (palette_size == 2)
2845 data_size = ((width + 7) / 8) * height;
2846 else
2847 data_size = width * height;
2848 } else
2849 data_size = width * height * vnc_connection_tpixel_size(conn);
2850
2851 if (data_size >= 12) {
2852 zlib_length = vnc_connection_read_cint(conn);
2853 zlib_data = g_malloc(zlib_length);
2854
2855 vnc_connection_read(conn, zlib_data, zlib_length);
2856
2857 priv->uncompressed_offset = 0;
2858 priv->uncompressed_size = 0;
2859 priv->compressed_length = zlib_length;
2860 priv->compressed_buffer = zlib_data;
2861 }
2862
2863 switch (filter_id) {
2864 case 0: /* copy */
2865 vnc_connection_tight_update_copy(conn, x, y, width, height);
2866 break;
2867 case 1: /* palette */
2868 vnc_connection_tight_update_palette(conn, palette_size,
2869 (guint8 *)palette,
2870 x, y, width, height);
2871 break;
2872 case 2: /* gradient */
2873 vnc_connection_tight_update_gradient(conn, x, y, width, height);
2874 break;
2875 default: /* error */
2876 vnc_connection_set_error(conn, "Unexpected tight filter id %d",
2877 filter_id);
2878 break;
2879 }
2880
2881 if (data_size >= 12) {
2882 priv->uncompressed_offset = 0;
2883 priv->uncompressed_size = 0;
2884 priv->compressed_length = 0;
2885 priv->compressed_buffer = NULL;
2886
2887 g_free(zlib_data);
2888 }
2889
2890 priv->strm = NULL;
2891 } else if (ccontrol == 8) {
2892 /* fill */
2893 /* FIXME check each width; endianness */
2894 vnc_connection_read_tpixel(conn, pixel);
2895 vnc_framebuffer_fill(priv->fb, pixel, x, y, width, height);
2896 } else if (ccontrol == 9) {
2897 /* jpeg */
2898 guint32 length;
2899 guint8 *jpeg_data;
2900
2901 length = vnc_connection_read_cint(conn);
2902 jpeg_data = g_malloc(length);
2903 vnc_connection_read(conn, jpeg_data, length);
2904 vnc_connection_tight_update_jpeg(conn, x, y, width, height,
2905 jpeg_data, length);
2906 g_free(jpeg_data);
2907 } else {
2908 vnc_connection_set_error(conn, "Unexpected tight ccontrol %d",
2909 ccontrol);
2910 }
2911 }
2912
vnc_connection_update(VncConnection * conn,int x,int y,int width,int height)2913 static void vnc_connection_update(VncConnection *conn, int x, int y, int width, int height)
2914 {
2915 VncConnectionPrivate *priv = conn->priv;
2916 struct signal_data sigdata;
2917
2918 if (priv->coroutine_stop)
2919 return;
2920
2921 VNC_DEBUG("Notify update area (%dx%d) at location %d,%d", width, height, x, y);
2922
2923 sigdata.params.area.x = x;
2924 sigdata.params.area.y = y;
2925 sigdata.params.area.width = width;
2926 sigdata.params.area.height = height;
2927 vnc_connection_emit_main_context(conn, VNC_FRAMEBUFFER_UPDATE, &sigdata);
2928 }
2929
2930
vnc_connection_bell(VncConnection * conn)2931 static void vnc_connection_bell(VncConnection *conn)
2932 {
2933 VncConnectionPrivate *priv = conn->priv;
2934 struct signal_data sigdata;
2935
2936 if (priv->coroutine_stop)
2937 return;
2938
2939 VNC_DEBUG("Server beep");
2940
2941 vnc_connection_emit_main_context(conn, VNC_BELL, &sigdata);
2942 }
2943
vnc_connection_server_cut_text(VncConnection * conn,const void * data,size_t len)2944 static void vnc_connection_server_cut_text(VncConnection *conn,
2945 const void *data,
2946 size_t len)
2947 {
2948 VncConnectionPrivate *priv = conn->priv;
2949 struct signal_data sigdata;
2950 GString *text;
2951
2952 if (priv->coroutine_stop)
2953 return;
2954
2955 text = g_string_new_len ((const gchar *)data, len);
2956 sigdata.params.text = text->str;
2957
2958 vnc_connection_emit_main_context(conn, VNC_SERVER_CUT_TEXT, &sigdata);
2959
2960 g_string_free(text, TRUE);
2961 }
2962
vnc_connection_resize(VncConnection * conn,int width,int height)2963 static void vnc_connection_resize(VncConnection *conn, int width, int height)
2964 {
2965 VncConnectionPrivate *priv = conn->priv;
2966 struct signal_data sigdata;
2967
2968 VNC_DEBUG("Desktop resize w=%d h=%d", width, height);
2969
2970 if (priv->coroutine_stop)
2971 return;
2972
2973 priv->width = width;
2974 priv->height = height;
2975
2976 sigdata.params.size.width = width;
2977 sigdata.params.size.height = height;
2978 vnc_connection_emit_main_context(conn, VNC_DESKTOP_RESIZE, &sigdata);
2979 }
2980
vnc_connection_pixel_format(VncConnection * conn)2981 static void vnc_connection_pixel_format(VncConnection *conn)
2982 {
2983 VncConnectionPrivate *priv = conn->priv;
2984 struct signal_data sigdata;
2985
2986 if (priv->coroutine_stop)
2987 return;
2988
2989 sigdata.params.pixelFormat = &priv->fmt;
2990 vnc_connection_emit_main_context(conn, VNC_PIXEL_FORMAT_CHANGED, &sigdata);
2991 }
2992
vnc_connection_pointer_type_change(VncConnection * conn,gboolean absPointer)2993 static void vnc_connection_pointer_type_change(VncConnection *conn, gboolean absPointer)
2994 {
2995 VncConnectionPrivate *priv = conn->priv;
2996 struct signal_data sigdata;
2997
2998 VNC_DEBUG("Pointer mode %s", absPointer ? "absolute" : "relative");
2999
3000 if (priv->absPointer == absPointer)
3001 return;
3002 priv->absPointer = absPointer;
3003
3004 if (priv->coroutine_stop)
3005 return;
3006
3007 sigdata.params.absPointer = absPointer;
3008 vnc_connection_emit_main_context(conn, VNC_POINTER_MODE_CHANGED, &sigdata);
3009 }
3010
vnc_connection_rich_cursor_blt(VncConnection * conn,guint8 * pixbuf,guint8 * image,guint8 * mask,int pitch,guint16 width,guint16 height)3011 static void vnc_connection_rich_cursor_blt(VncConnection *conn, guint8 *pixbuf,
3012 guint8 *image, guint8 *mask,
3013 int pitch, guint16 width, guint16 height)
3014 {
3015 VncConnectionPrivate *priv = conn->priv;
3016
3017 priv->rich_cursor_blt(conn, pixbuf, image, mask, pitch, width, height);
3018 }
3019
vnc_connection_rich_cursor(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)3020 static void vnc_connection_rich_cursor(VncConnection *conn, guint16 x, guint16 y, guint16 width, guint16 height)
3021 {
3022 VncConnectionPrivate *priv = conn->priv;
3023 struct signal_data sigdata;
3024
3025 if (priv->cursor) {
3026 g_object_unref(priv->cursor);
3027 priv->cursor = NULL;
3028 }
3029
3030 if (width && height) {
3031 guint8 *pixbuf = NULL;
3032 guint8 *image = NULL, *mask = NULL;
3033 int imagelen, masklen;
3034
3035 imagelen = width * height * (priv->fmt.bits_per_pixel / 8);
3036 masklen = ((width + 7)/8) * height;
3037
3038 image = g_malloc(imagelen);
3039 mask = g_malloc(masklen);
3040 pixbuf = g_malloc(width * height * 4); /* RGB-A 8bit */
3041
3042 vnc_connection_read(conn, image, imagelen);
3043 vnc_connection_read(conn, mask, masklen);
3044
3045 vnc_connection_rich_cursor_blt(conn, pixbuf, image, mask,
3046 width * (priv->fmt.bits_per_pixel/8),
3047 width, height);
3048
3049 g_free(image);
3050 g_free(mask);
3051
3052 /* Some broken VNC servers send hot-pixel outside
3053 * bounds of the cursor. We could disconnect and
3054 * report an error, but it is more user friendly
3055 * to just clamp the hot pixel coords
3056 */
3057 if (x >= width)
3058 x = width - 1;
3059 if (y >= height)
3060 y = height - 1;
3061
3062 priv->cursor = vnc_cursor_new(pixbuf, x, y, width, height);
3063 }
3064
3065 if (priv->coroutine_stop)
3066 return;
3067
3068 sigdata.params.cursor = priv->cursor;
3069
3070 vnc_connection_emit_main_context(conn, VNC_CURSOR_CHANGED, &sigdata);
3071 }
3072
vnc_connection_xcursor(VncConnection * conn,guint16 x,guint16 y,guint16 width,guint16 height)3073 static void vnc_connection_xcursor(VncConnection *conn, guint16 x, guint16 y, guint16 width, guint16 height)
3074 {
3075 VncConnectionPrivate *priv = conn->priv;
3076 struct signal_data sigdata;
3077
3078 if (priv->cursor) {
3079 g_object_unref(priv->cursor);
3080 priv->cursor = NULL;
3081 }
3082
3083 if (width && height) {
3084 guint8 *pixbuf = NULL;
3085 guint8 *data, *mask, *datap, *maskp;
3086 guint32 *pixp;
3087 guint rowlen;
3088 int x1, y1;
3089 guint8 fgrgb[3], bgrgb[3];
3090 guint32 fg, bg;
3091 vnc_connection_read(conn, fgrgb, 3);
3092 vnc_connection_read(conn, bgrgb, 3);
3093 fg = (255 << 24) | (fgrgb[0] << 16) | (fgrgb[1] << 8) | fgrgb[2];
3094 bg = (255 << 24) | (bgrgb[0] << 16) | (bgrgb[1] << 8) | bgrgb[2];
3095
3096 rowlen = ((width + 7)/8);
3097 data = g_malloc(rowlen*height);
3098 mask = g_malloc(rowlen*height);
3099 pixbuf = g_malloc(width * height * 4); /* RGB-A 8bit */
3100
3101 vnc_connection_read(conn, data, rowlen*height);
3102 vnc_connection_read(conn, mask, rowlen*height);
3103 datap = data;
3104 maskp = mask;
3105 pixp = (guint32*)pixbuf;
3106 for (y1 = 0; y1 < height; y1++) {
3107 for (x1 = 0; x1 < width; x1++) {
3108 *pixp++ = ((maskp[x1 / 8] >> (7-(x1 % 8))) & 1) ?
3109 (((datap[x1 / 8] >> (7-(x1 % 8))) & 1) ? fg : bg) : 0;
3110 }
3111 datap += rowlen;
3112 maskp += rowlen;
3113 }
3114 g_free(data);
3115 g_free(mask);
3116
3117 /* Some broken VNC servers send hot-pixel outside
3118 * bounds of the cursor. We could disconnect and
3119 * report an error, but it is more user friendly
3120 * to just clamp the hot pixel coords
3121 */
3122 if (x >= width)
3123 x = width - 1;
3124 if (y >= height)
3125 y = height - 1;
3126
3127 priv->cursor = vnc_cursor_new(pixbuf, x, y, width, height);
3128 }
3129
3130 if (priv->coroutine_stop)
3131 return;
3132
3133 sigdata.params.cursor = priv->cursor;
3134
3135 vnc_connection_emit_main_context(conn, VNC_CURSOR_CHANGED, &sigdata);
3136 }
3137
vnc_connection_ext_key_event(VncConnection * conn)3138 static void vnc_connection_ext_key_event(VncConnection *conn)
3139 {
3140 VncConnectionPrivate *priv = conn->priv;
3141
3142 VNC_DEBUG("Keyboard mode extended");
3143 priv->has_ext_key_event = TRUE;
3144 }
3145
3146
vnc_connection_framebuffer_update(VncConnection * conn,gint32 etype,guint16 x,guint16 y,guint16 width,guint16 height)3147 static gboolean vnc_connection_framebuffer_update(VncConnection *conn, gint32 etype,
3148 guint16 x, guint16 y,
3149 guint16 width, guint16 height)
3150 {
3151 VncConnectionPrivate *priv = conn->priv;
3152
3153 VNC_DEBUG("FramebufferUpdate type=%d area (%dx%d) at location %d,%d",
3154 etype, width, height, x, y);
3155
3156 if (vnc_connection_has_error(conn))
3157 return !vnc_connection_has_error(conn);
3158
3159 switch (etype) {
3160 case VNC_CONNECTION_ENCODING_RAW:
3161 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3162 break;
3163 vnc_connection_raw_update(conn, x, y, width, height);
3164 vnc_connection_update(conn, x, y, width, height);
3165 break;
3166 case VNC_CONNECTION_ENCODING_COPY_RECT:
3167 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3168 break;
3169 vnc_connection_copyrect_update(conn, x, y, width, height);
3170 vnc_connection_update(conn, x, y, width, height);
3171 break;
3172 case VNC_CONNECTION_ENCODING_RRE:
3173 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3174 break;
3175 vnc_connection_rre_update(conn, x, y, width, height);
3176 vnc_connection_update(conn, x, y, width, height);
3177 break;
3178 case VNC_CONNECTION_ENCODING_HEXTILE:
3179 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3180 break;
3181 vnc_connection_hextile_update(conn, x, y, width, height);
3182 vnc_connection_update(conn, x, y, width, height);
3183 break;
3184 case VNC_CONNECTION_ENCODING_ZRLE:
3185 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3186 break;
3187 vnc_connection_zrle_update(conn, x, y, width, height);
3188 vnc_connection_update(conn, x, y, width, height);
3189 break;
3190 case VNC_CONNECTION_ENCODING_TIGHT:
3191 if (!vnc_connection_validate_boundary(conn, x, y, width, height))
3192 break;
3193 vnc_connection_tight_update(conn, x, y, width, height);
3194 vnc_connection_update(conn, x, y, width, height);
3195 break;
3196 case VNC_CONNECTION_ENCODING_DESKTOP_RESIZE:
3197 vnc_connection_resize(conn, width, height);
3198 break;
3199 case VNC_CONNECTION_ENCODING_POINTER_CHANGE:
3200 vnc_connection_pointer_type_change(conn, x);
3201 vnc_connection_resend_framebuffer_update_request(conn);
3202 break;
3203 case VNC_CONNECTION_ENCODING_LED_STATE:
3204 vnc_connection_ledstate_change(conn);
3205 vnc_connection_resend_framebuffer_update_request(conn);
3206 break;
3207 case VNC_CONNECTION_ENCODING_WMVi:
3208 vnc_connection_read_pixel_format(conn, &priv->fmt);
3209 vnc_connection_pixel_format(conn);
3210 break;
3211 case VNC_CONNECTION_ENCODING_RICH_CURSOR:
3212 vnc_connection_rich_cursor(conn, x, y, width, height);
3213 vnc_connection_resend_framebuffer_update_request(conn);
3214 break;
3215 case VNC_CONNECTION_ENCODING_XCURSOR:
3216 vnc_connection_xcursor(conn, x, y, width, height);
3217 vnc_connection_resend_framebuffer_update_request(conn);
3218 break;
3219 case VNC_CONNECTION_ENCODING_EXT_KEY_EVENT:
3220 vnc_connection_ext_key_event(conn);
3221 vnc_connection_resend_framebuffer_update_request(conn);
3222 break;
3223 case VNC_CONNECTION_ENCODING_AUDIO:
3224 VNC_DEBUG("Audio encoding support");
3225 priv->has_audio=TRUE;
3226
3227 if (priv->audio_disable_pending)
3228 vnc_connection_audio_disable(conn);
3229 if (priv->audio_format_pending)
3230 vnc_connection_send_audio_format(conn);
3231 if (priv->audio_enable_pending)
3232 vnc_connection_audio_enable(conn);
3233 break;
3234 default:
3235 vnc_connection_set_error(conn, "Received an unknown encoding type: %d", etype);
3236 break;
3237 }
3238
3239 return !vnc_connection_has_error(conn);
3240 }
3241
3242
vnc_connection_audio_timer(gpointer opaque)3243 static gboolean vnc_connection_audio_timer(gpointer opaque)
3244 {
3245 VncConnection *conn = opaque;
3246 VncConnectionPrivate *priv = conn->priv;
3247
3248 priv->audio_timer = 0;
3249 if (!priv->audio_sample)
3250 return FALSE;
3251
3252 VNC_DEBUG("Audio tick %u\n", priv->audio_sample->length);
3253
3254 if (priv->audio)
3255 vnc_audio_playback_data(priv->audio, priv->audio_sample);
3256
3257 vnc_audio_sample_free(priv->audio_sample);
3258 priv->audio_sample = NULL;
3259 return FALSE;
3260 }
3261
3262
3263 struct audio_action_data
3264 {
3265 VncConnection *conn;
3266 struct coroutine *caller;
3267 enum {
3268 VNC_AUDIO_PLAYBACK_STOP = 0,
3269 VNC_AUDIO_PLAYBACK_START = 1,
3270 VNC_AUDIO_PLAYBACK_DATA = 2,
3271 } action;
3272 };
3273
do_vnc_connection_audio_action(gpointer opaque)3274 static gboolean do_vnc_connection_audio_action(gpointer opaque)
3275 {
3276 struct audio_action_data *data = opaque;
3277 VncConnectionPrivate *priv = data->conn->priv;
3278
3279 VNC_DEBUG("Audio action main context %u", data->action);
3280
3281 switch (data->action) {
3282 case VNC_AUDIO_PLAYBACK_STOP:
3283 vnc_audio_playback_stop(priv->audio);
3284 break;
3285 case VNC_AUDIO_PLAYBACK_START:
3286 vnc_audio_playback_start(priv->audio, &priv->audio_format);
3287 break;
3288 case VNC_AUDIO_PLAYBACK_DATA:
3289 vnc_audio_playback_data(priv->audio, priv->audio_sample);
3290 break;
3291 default:
3292 g_warn_if_reached();
3293 }
3294
3295 coroutine_yieldto(data->caller, NULL);
3296 return FALSE;
3297 }
3298
vnc_connection_audio_action(VncConnection * conn,int action)3299 static void vnc_connection_audio_action(VncConnection *conn,
3300 int action)
3301 {
3302 struct audio_action_data data = {
3303 conn,
3304 coroutine_self(),
3305 action,
3306 };
3307
3308 VNC_DEBUG("Emit audio action %d\n", action);
3309
3310 g_idle_add(do_vnc_connection_audio_action, &data);
3311
3312 /* This switches to the system coroutine context, lets
3313 * the idle function run to dispatch the action, and
3314 * finally returns once complete. ie this is synchronous
3315 * from the POV of the VNC coroutine despite there being
3316 * an idle function involved
3317 */
3318 coroutine_yield(NULL);
3319 }
3320
3321
vnc_connection_server_message(VncConnection * conn)3322 static gboolean vnc_connection_server_message(VncConnection *conn)
3323 {
3324 VncConnectionPrivate *priv = conn->priv;
3325 guint8 msg;
3326 int ret;
3327
3328 if (vnc_connection_has_error(conn))
3329 return !vnc_connection_has_error(conn);
3330
3331 /* NB: make sure that all server message functions
3332 handle has_error appropriately */
3333
3334 do {
3335 if (priv->xmit_buffer_size) {
3336 vnc_connection_write(conn, priv->xmit_buffer, priv->xmit_buffer_size);
3337 vnc_connection_flush(conn);
3338 priv->xmit_buffer_size = 0;
3339 }
3340 } while ((ret = vnc_connection_read_u8_interruptable(conn, &msg)) == -EAGAIN);
3341
3342 if (ret < 0) {
3343 VNC_DEBUG("Aborting message processing on error");
3344 return !vnc_connection_has_error(conn);
3345 }
3346
3347 switch (msg) {
3348 case VNC_CONNECTION_SERVER_MESSAGE_FRAMEBUFFER_UPDATE: {
3349 guint8 pad[1];
3350 guint16 n_rects;
3351 int i;
3352
3353 vnc_connection_read(conn, pad, 1);
3354 n_rects = vnc_connection_read_u16(conn);
3355 for (i = 0; i < n_rects; i++) {
3356 guint16 x, y, w, h;
3357 gint32 etype;
3358
3359 x = vnc_connection_read_u16(conn);
3360 y = vnc_connection_read_u16(conn);
3361 w = vnc_connection_read_u16(conn);
3362 h = vnc_connection_read_u16(conn);
3363 etype = vnc_connection_read_s32(conn);
3364
3365 if (!vnc_connection_framebuffer_update(conn, etype, x, y, w, h))
3366 break;
3367 }
3368 } break;
3369 case VNC_CONNECTION_SERVER_MESSAGE_SET_COLOR_MAP_ENTRIES: {
3370 guint16 first_color;
3371 guint16 n_colors;
3372 guint8 pad[1];
3373 VncColorMap *map;
3374 int i;
3375
3376 if (priv->fmt.true_color_flag) {
3377 vnc_connection_set_error(conn, "Got color map entries in true-color pix format");
3378 break;
3379 }
3380
3381 vnc_connection_read(conn, pad, 1);
3382 first_color = vnc_connection_read_u16(conn);
3383 n_colors = vnc_connection_read_u16(conn);
3384
3385 VNC_DEBUG("Colour map from %d with %d entries",
3386 first_color, n_colors);
3387
3388 if (first_color > (65536 - n_colors)) {
3389 vnc_connection_set_error(conn, "Colormap start %d out of range %d", first_color, 65536 - n_colors);
3390 break;
3391 }
3392
3393 map = vnc_color_map_new(first_color, n_colors);
3394 for (i = 0; i < n_colors; i++) {
3395 guint16 red, green, blue;
3396
3397 red = vnc_connection_read_u16(conn);
3398 green = vnc_connection_read_u16(conn);
3399 blue = vnc_connection_read_u16(conn);
3400
3401 if (!vnc_color_map_set(map,
3402 i + first_color,
3403 red, green, blue)) {
3404 /* Should not be reachable given earlier range check */
3405 vnc_connection_set_error(conn, "Colormap index %d out of range %d,%d",
3406 i + first_color, first_color, 65536 - n_colors);
3407 break;
3408 }
3409 }
3410
3411 vnc_framebuffer_set_color_map(priv->fb, map);
3412 vnc_color_map_free(map);
3413 } break;
3414 case VNC_CONNECTION_SERVER_MESSAGE_BELL:
3415 vnc_connection_bell(conn);
3416 break;
3417 case VNC_CONNECTION_SERVER_MESSAGE_SERVER_CUT_TEXT: {
3418 guint8 pad[3];
3419 guint32 n_text;
3420 char *data;
3421
3422 vnc_connection_read(conn, pad, 3);
3423 n_text = vnc_connection_read_u32(conn);
3424 if (n_text > (32 << 20)) {
3425 vnc_connection_set_error(conn, "Cut text length %u longer than permitted %d",
3426 n_text, (32 << 20));
3427 break;
3428 }
3429
3430 data = g_new(char, n_text + 1);
3431 vnc_connection_read(conn, data, n_text);
3432 data[n_text] = 0;
3433
3434 vnc_connection_server_cut_text(conn, data, n_text);
3435 g_free(data);
3436 } break;
3437 case VNC_CONNECTION_SERVER_MESSAGE_QEMU: {
3438 guint8 n_type;
3439
3440 n_type = vnc_connection_read_u8(conn);
3441
3442 if (priv->coroutine_stop)
3443 break;
3444
3445 switch (n_type) {
3446 case VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO: {
3447 guint16 n_subtype;
3448 guint32 n_length;
3449
3450 n_subtype = vnc_connection_read_u16(conn);
3451 switch (n_subtype) {
3452 case VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_DATA:
3453 n_length = vnc_connection_read_u32(conn);
3454 if (n_length > (1024*1024)) {
3455 vnc_connection_set_error(conn,
3456 "Audio sample length %u longer than permitted %d",
3457 n_length, 1024 * 1024);
3458 break;
3459 }
3460 if (priv->coroutine_stop)
3461 break;
3462
3463 if (!priv->audio) {
3464 vnc_connection_set_error(conn, "%s",
3465 "No audio playback sink configured");
3466 break;
3467 }
3468 if (priv->audio_sample &&
3469 ((priv->audio_sample->capacity - priv->audio_sample->length) < n_length)) {
3470 g_source_remove(priv->audio_timer);
3471 vnc_connection_audio_action(conn, VNC_AUDIO_PLAYBACK_DATA);
3472 vnc_audio_sample_free(priv->audio_sample);
3473 priv->audio_sample = NULL;
3474 }
3475 if (!priv->audio_sample) {
3476 priv->audio_sample = vnc_audio_sample_new(1024*1024);
3477 priv->audio_timer = g_timeout_add(50,
3478 vnc_connection_audio_timer,
3479 conn);
3480 }
3481
3482 vnc_connection_read(conn,
3483 priv->audio_sample->data + priv->audio_sample->length,
3484 n_length);
3485 priv->audio_sample->length += n_length;
3486 break;
3487 case VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_START:
3488 if (priv->audio)
3489 vnc_connection_audio_action(conn, VNC_AUDIO_PLAYBACK_START);
3490 else
3491 vnc_connection_set_error(conn, "%s", "No audio sink configured");
3492 break;
3493 case VNC_CONNECTION_SERVER_MESSAGE_QEMU_AUDIO_STOP:
3494 if (priv->audio) {
3495 if (priv->audio_sample) {
3496 g_source_remove(priv->audio_timer);
3497 vnc_connection_audio_action(conn, VNC_AUDIO_PLAYBACK_DATA);
3498 vnc_audio_sample_free(priv->audio_sample);
3499 priv->audio_sample = NULL;
3500 }
3501 vnc_connection_audio_action(conn, VNC_AUDIO_PLAYBACK_STOP);
3502 } else {
3503 vnc_connection_set_error(conn, "%s", "No audio sink configured");
3504 }
3505 break;
3506 default:
3507 vnc_connection_set_error(conn, "Received unknown QEMU audio message: %u", (int)n_subtype);
3508 break;
3509 }
3510 } break;
3511 default:
3512 vnc_connection_set_error(conn, "Received an unknown QEMU message: %u", n_type);
3513 }
3514 } break;
3515 default:
3516 vnc_connection_set_error(conn, "Received an unknown message: %u", msg);
3517 break;
3518 }
3519
3520 return !vnc_connection_has_error(conn);
3521 }
3522
vnc_connection_has_credentials(gpointer data)3523 static gboolean vnc_connection_has_credentials(gpointer data)
3524 {
3525 VncConnection *conn = data;
3526 VncConnectionPrivate *priv = conn->priv;
3527
3528 if (priv->coroutine_stop)
3529 return TRUE;
3530 if (priv->want_cred_username && !priv->cred_username)
3531 return FALSE;
3532 if (priv->want_cred_password && !priv->cred_password)
3533 return FALSE;
3534 if (priv->want_cred_x509 && !priv->set_cred_x509)
3535 return FALSE;
3536 return TRUE;
3537 }
3538
vnc_connection_gather_credentials(VncConnection * conn)3539 static gboolean vnc_connection_gather_credentials(VncConnection *conn)
3540 {
3541 VncConnectionPrivate *priv = conn->priv;
3542
3543 VNC_DEBUG("Checking if credentials are needed");
3544
3545 if (priv->coroutine_stop)
3546 return FALSE;
3547
3548 if (!vnc_connection_has_credentials(conn)) {
3549 GValueArray *authCred;
3550 GValue username, password, clientname;
3551 struct signal_data sigdata;
3552
3553 memset(&username, 0, sizeof(username));
3554 memset(&password, 0, sizeof(password));
3555 memset(&clientname, 0, sizeof(clientname));
3556
3557 authCred = g_value_array_new(0);
3558 if (priv->want_cred_username) {
3559 g_value_init(&username, VNC_TYPE_CONNECTION_CREDENTIAL);
3560 g_value_set_enum(&username, VNC_CONNECTION_CREDENTIAL_USERNAME);
3561 authCred = g_value_array_append(authCred, &username);
3562 VNC_DEBUG("Want a username");
3563 }
3564 if (priv->want_cred_password) {
3565 g_value_init(&password, VNC_TYPE_CONNECTION_CREDENTIAL);
3566 g_value_set_enum(&password, VNC_CONNECTION_CREDENTIAL_PASSWORD);
3567 authCred = g_value_array_append(authCred, &password);
3568 VNC_DEBUG("Want a password");
3569 }
3570 if (priv->want_cred_x509) {
3571 g_value_init(&clientname, VNC_TYPE_CONNECTION_CREDENTIAL);
3572 g_value_set_enum(&clientname, VNC_CONNECTION_CREDENTIAL_CLIENTNAME);
3573 authCred = g_value_array_append(authCred, &clientname);
3574 VNC_DEBUG("Want a TLS clientname");
3575 }
3576
3577 sigdata.params.authCred = authCred;
3578 VNC_DEBUG("Requesting missing credentials");
3579 vnc_connection_emit_main_context(conn, VNC_AUTH_CREDENTIAL, &sigdata);
3580
3581 g_value_array_free(authCred);
3582
3583 if (priv->coroutine_stop)
3584 return FALSE;
3585 VNC_DEBUG("Waiting for missing credentials");
3586 g_condition_wait(vnc_connection_has_credentials, conn);
3587 VNC_DEBUG("Got all credentials");
3588 } else {
3589 VNC_DEBUG("No credentials required");
3590 }
3591 return !vnc_connection_has_error(conn);
3592 }
3593
3594
vnc_connection_check_auth_result(VncConnection * conn)3595 static gboolean vnc_connection_check_auth_result(VncConnection *conn)
3596 {
3597 VncConnectionPrivate *priv = conn->priv;
3598 guint32 result;
3599
3600 VNC_DEBUG("Checking auth result");
3601 result = vnc_connection_read_u32(conn);
3602 if (!result) {
3603 VNC_DEBUG("Success");
3604 return TRUE;
3605 }
3606
3607 if (priv->minor >= 8) {
3608 guint32 len;
3609 char reason[1024];
3610 len = vnc_connection_read_u32(conn);
3611 if (len > (sizeof(reason)-1))
3612 return FALSE;
3613 vnc_connection_read(conn, reason, len);
3614 reason[len] = '\0';
3615 VNC_DEBUG("Fail %s", reason);
3616 if (!priv->coroutine_stop) {
3617 struct signal_data sigdata;
3618 sigdata.params.authReason = reason;
3619 vnc_connection_set_error(conn, "%s", reason);
3620 vnc_connection_emit_main_context(conn, VNC_AUTH_FAILURE, &sigdata);
3621 }
3622 } else {
3623 VNC_DEBUG("Fail auth no result");
3624 if (!priv->coroutine_stop) {
3625 struct signal_data sigdata;
3626 sigdata.params.authReason = "Unknown authentication failure";
3627 vnc_connection_set_error(conn, "%s", "Unknown authentication failure");
3628 vnc_connection_emit_main_context(conn, VNC_AUTH_FAILURE, &sigdata);
3629 }
3630 }
3631 return FALSE;
3632 }
3633
vnc_connection_perform_auth_vnc(VncConnection * conn)3634 static gboolean vnc_connection_perform_auth_vnc(VncConnection *conn)
3635 {
3636 VncConnectionPrivate *priv = conn->priv;
3637 guint8 challenge[16];
3638 guint8 key[8];
3639 gsize keylen;
3640
3641 VNC_DEBUG("Do Challenge");
3642 priv->want_cred_password = TRUE;
3643 priv->want_cred_username = FALSE;
3644 priv->want_cred_x509 = FALSE;
3645 if (!vnc_connection_gather_credentials(conn))
3646 return FALSE;
3647
3648 if (!priv->cred_password)
3649 return FALSE;
3650
3651 vnc_connection_read(conn, challenge, 16);
3652
3653 memset(key, 0, sizeof(key));
3654 keylen = strlen(priv->cred_password);
3655 if (keylen > sizeof(key))
3656 keylen = sizeof(key);
3657 memcpy(key, priv->cred_password, keylen);
3658
3659 deskey(key, EN0);
3660 des(challenge, challenge);
3661 des(challenge + 8, challenge + 8);
3662
3663 vnc_connection_write(conn, challenge, 16);
3664 vnc_connection_flush(conn);
3665 return vnc_connection_check_auth_result(conn);
3666 }
3667
3668 /*
3669 * marscha@2006 - Martin Scharpf
3670 * Encrypt bytes[length] in memory using key.
3671 * Key has to be 8 bytes, length a multiple of 8 bytes.
3672 */
3673 static void
vncEncryptBytes2(unsigned char * where,const int length,unsigned char * key)3674 vncEncryptBytes2(unsigned char *where, const int length, unsigned char *key)
3675 {
3676 int i, j;
3677 deskey(key, EN0);
3678 for (i = 0; i< 8; i++)
3679 where[i] ^= key[i];
3680 des(where, where);
3681 for (i = 8; i < length; i += 8) {
3682 for (j = 0; j < 8; j++)
3683 where[i + j] ^= where[i + j - 8];
3684 des(where + i, where + i);
3685 }
3686 }
3687
vnc_connection_perform_auth_mslogon(VncConnection * conn)3688 static gboolean vnc_connection_perform_auth_mslogon(VncConnection *conn)
3689 {
3690 VncConnectionPrivate *priv = conn->priv;
3691 struct vnc_dh *dh;
3692 guchar gen[8], mod[8], resp[8], pub[8], key[8];
3693 gcry_mpi_t genmpi, modmpi, respmpi, pubmpi, keympi;
3694 guchar username[256], password[64];
3695 guint passwordLen, usernameLen;
3696
3697 VNC_DEBUG("Do Challenge");
3698 priv->want_cred_password = TRUE;
3699 priv->want_cred_username = TRUE;
3700 priv->want_cred_x509 = FALSE;
3701 if (!vnc_connection_gather_credentials(conn))
3702 return FALSE;
3703
3704 vnc_connection_read(conn, gen, sizeof(gen));
3705 vnc_connection_read(conn, mod, sizeof(mod));
3706 vnc_connection_read(conn, resp, sizeof(resp));
3707
3708 genmpi = vnc_bytes_to_mpi(gen,sizeof(gen));
3709 modmpi = vnc_bytes_to_mpi(mod,sizeof(mod));
3710 respmpi = vnc_bytes_to_mpi(resp,sizeof(resp));
3711
3712 dh = vnc_dh_new(genmpi, modmpi);
3713
3714 pubmpi = vnc_dh_gen_secret(dh);
3715 vnc_mpi_to_bytes(pubmpi, pub, sizeof(pub));
3716
3717 vnc_connection_write(conn, pub, sizeof(pub));
3718
3719 keympi = vnc_dh_gen_key(dh, respmpi);
3720 vnc_mpi_to_bytes(keympi, key, sizeof(key));
3721
3722 passwordLen = strlen(priv->cred_password);
3723 usernameLen = strlen(priv->cred_username);
3724 if (passwordLen > sizeof(password))
3725 passwordLen = sizeof(password);
3726 if (usernameLen > sizeof(username))
3727 usernameLen = sizeof(username);
3728
3729 memset(password, 0, sizeof password);
3730 memset(username, 0, sizeof username);
3731 memcpy(password, priv->cred_password, passwordLen);
3732 memcpy(username, priv->cred_username, usernameLen);
3733
3734 vncEncryptBytes2(username, sizeof(username), key);
3735 vncEncryptBytes2(password, sizeof(password), key);
3736
3737 vnc_connection_write(conn, username, sizeof(username));
3738 vnc_connection_write(conn, password, sizeof(password));
3739 vnc_connection_flush(conn);
3740
3741 gcry_mpi_release(genmpi);
3742 gcry_mpi_release(modmpi);
3743 gcry_mpi_release(respmpi);
3744 vnc_dh_free (dh);
3745
3746 return vnc_connection_check_auth_result(conn);
3747 }
3748
vnc_connection_perform_auth_ard(VncConnection * conn)3749 static gboolean vnc_connection_perform_auth_ard(VncConnection *conn)
3750 {
3751 VncConnectionPrivate *priv = conn->priv;
3752 struct vnc_dh *dh;
3753 guchar gen[2], len[2];
3754 size_t keylen;
3755 guchar *mod, *resp, *pub, *key, *shared;
3756 gcry_mpi_t genmpi, modmpi, respmpi, pubmpi, keympi;
3757 guchar userpass[128], ciphertext[128];
3758 guint passwordLen, usernameLen;
3759 gcry_md_hd_t md5;
3760 gcry_cipher_hd_t aes;
3761 gcry_error_t error;
3762
3763 VNC_DEBUG("Do Challenge");
3764 priv->want_cred_password = TRUE;
3765 priv->want_cred_username = TRUE;
3766 priv->want_cred_x509 = FALSE;
3767 if (!vnc_connection_gather_credentials(conn))
3768 return FALSE;
3769
3770 vnc_connection_read(conn, gen, sizeof(gen));
3771 vnc_connection_read(conn, len, sizeof(len));
3772
3773 keylen = 256*len[0] + len[1];
3774 mod = malloc(keylen);
3775 if (mod == NULL) {
3776 VNC_DEBUG("malloc failed\n");
3777 return FALSE;
3778 }
3779 resp = malloc(keylen);
3780 if (resp == NULL) {
3781 free(mod);
3782 VNC_DEBUG("malloc failed\n");
3783 return FALSE;
3784 }
3785 pub = malloc(keylen);
3786 if (pub == NULL) {
3787 free(resp);
3788 free(mod);
3789 VNC_DEBUG("malloc failed\n");
3790 return FALSE;
3791 }
3792 key = malloc(keylen);
3793 if (key == NULL) {
3794 free(pub);
3795 free(resp);
3796 free(mod);
3797 VNC_DEBUG("malloc failed\n");
3798 return FALSE;
3799 }
3800
3801 vnc_connection_read(conn, mod, keylen);
3802 vnc_connection_read(conn, resp, keylen);
3803
3804 genmpi = vnc_bytes_to_mpi(gen,sizeof(gen));
3805 modmpi = vnc_bytes_to_mpi(mod,keylen);
3806 respmpi = vnc_bytes_to_mpi(resp,keylen);
3807
3808 dh = vnc_dh_new(genmpi, modmpi);
3809
3810 pubmpi = vnc_dh_gen_secret(dh);
3811 vnc_mpi_to_bytes(pubmpi, pub, keylen);
3812
3813 keympi = vnc_dh_gen_key(dh, respmpi);
3814 vnc_mpi_to_bytes(keympi, key, keylen);
3815
3816 error=gcry_md_open(&md5, GCRY_MD_MD5, 0);
3817 if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
3818 VNC_DEBUG("gcry_md_open error: %s\n", gcry_strerror(error));
3819 free(pub);
3820 free(resp);
3821 free(mod);
3822 return FALSE;
3823 }
3824 gcry_md_write(md5, key, keylen);
3825 error=gcry_md_final(md5);
3826 if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
3827 VNC_DEBUG("gcry_md_final error: %s\n", gcry_strerror(error));
3828 free(pub);
3829 free(resp);
3830 free(mod);
3831 return FALSE;
3832 }
3833 shared = gcry_md_read(md5, GCRY_MD_MD5);
3834
3835 passwordLen = strlen(priv->cred_password)+1;
3836 usernameLen = strlen(priv->cred_username)+1;
3837 if (passwordLen > sizeof(userpass)/2)
3838 passwordLen = sizeof(userpass)/2;
3839 if (usernameLen > sizeof(userpass)/2)
3840 usernameLen = sizeof(userpass)/2;
3841
3842 gcry_randomize(userpass, sizeof(userpass), GCRY_STRONG_RANDOM);
3843 memcpy(userpass, priv->cred_username, usernameLen);
3844 memcpy(userpass+sizeof(userpass)/2, priv->cred_password, passwordLen);
3845
3846 error=gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0);
3847 if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
3848 VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error));
3849 free(pub);
3850 free(resp);
3851 free(mod);
3852 return FALSE;
3853 }
3854 error=gcry_cipher_setkey(aes, shared, 16);
3855 if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
3856 VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error));
3857 free(pub);
3858 free(resp);
3859 free(mod);
3860 return FALSE;
3861 }
3862 error=gcry_cipher_encrypt(aes, ciphertext, sizeof(ciphertext), userpass, sizeof(userpass));
3863 if (gcry_err_code (error) != GPG_ERR_NO_ERROR) {
3864 VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error));
3865 free(pub);
3866 free(resp);
3867 free(mod);
3868 return FALSE;
3869 }
3870
3871 vnc_connection_write(conn, ciphertext, sizeof(ciphertext));
3872 vnc_connection_write(conn, pub, keylen);
3873 vnc_connection_flush(conn);
3874
3875 free(mod);
3876 free(resp);
3877 free(pub);
3878 free(key);
3879 gcry_md_close(md5);
3880 gcry_mpi_release(genmpi);
3881 gcry_mpi_release(modmpi);
3882 gcry_mpi_release(respmpi);
3883 vnc_dh_free (dh);
3884
3885 return vnc_connection_check_auth_result(conn);
3886 }
3887
3888
3889 #ifdef HAVE_SASL
3890 /*
3891 * NB, keep in sync with similar method in qemud/remote.c
3892 */
vnc_connection_addr_to_string(GSocketAddress * addr)3893 static char *vnc_connection_addr_to_string(GSocketAddress *addr)
3894 {
3895 GInetSocketAddress *iaddr = G_INET_SOCKET_ADDRESS(addr);
3896 guint16 port;
3897 GInetAddress *host;
3898 gchar *hoststr;
3899 gchar *ret;
3900
3901 host = g_inet_socket_address_get_address(iaddr);
3902 port = g_inet_socket_address_get_port(iaddr);
3903 hoststr = g_inet_address_to_string(host);
3904
3905 ret = g_strdup_printf("%s;%hu", hoststr, port);
3906 g_free(hoststr);
3907
3908 return ret;
3909 }
3910
3911
3912
3913 static gboolean
vnc_connection_gather_sasl_credentials(VncConnection * conn,sasl_interact_t * interact)3914 vnc_connection_gather_sasl_credentials(VncConnection *conn,
3915 sasl_interact_t *interact)
3916 {
3917 VncConnectionPrivate *priv = conn->priv;
3918 int ninteract;
3919
3920 priv->want_cred_password = FALSE;
3921 priv->want_cred_username = FALSE;
3922 priv->want_cred_x509 = FALSE;
3923
3924 for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
3925 switch (interact[ninteract].id) {
3926 case SASL_CB_AUTHNAME:
3927 case SASL_CB_USER:
3928 priv->want_cred_username = TRUE;
3929 break;
3930
3931 case SASL_CB_PASS:
3932 priv->want_cred_password = TRUE;
3933 break;
3934
3935 default:
3936 VNC_DEBUG("Unsupported credential %lu",
3937 interact[ninteract].id);
3938 /* Unsupported */
3939 return FALSE;
3940 }
3941 }
3942
3943 if ((priv->want_cred_password ||
3944 priv->want_cred_username) &&
3945 !vnc_connection_gather_credentials(conn)) {
3946 VNC_DEBUG("%s", "cannot gather sasl credentials");
3947 return FALSE;
3948 }
3949
3950 for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
3951 switch (interact[ninteract].id) {
3952 case SASL_CB_AUTHNAME:
3953 case SASL_CB_USER:
3954 interact[ninteract].result = priv->cred_username;
3955 interact[ninteract].len = strlen(priv->cred_username);
3956 VNC_DEBUG("Gather Username %s", priv->cred_username);
3957 break;
3958
3959 case SASL_CB_PASS:
3960 interact[ninteract].result = priv->cred_password;
3961 interact[ninteract].len = strlen(priv->cred_password);
3962 //VNC_DEBUG("Gather Password %s", priv->cred_password);
3963 break;
3964
3965 default:
3966 g_warn_if_reached();
3967 }
3968 }
3969
3970 VNC_DEBUG("%s", "Filled SASL interact");
3971
3972 return TRUE;
3973 }
3974
3975
3976
3977 /*
3978 *
3979 * Init msg from server
3980 *
3981 * u32 mechlist-length
3982 * u8-array mechlist-string
3983 *
3984 * Start msg to server
3985 *
3986 * u32 mechname-length
3987 * u8-array mechname-string
3988 * u32 clientout-length
3989 * u8-array clientout-string
3990 *
3991 * Start msg from server
3992 *
3993 * u32 serverin-length
3994 * u8-array serverin-string
3995 * u8 continue
3996 *
3997 * Step msg to server
3998 *
3999 * u32 clientout-length
4000 * u8-array clientout-string
4001 *
4002 * Step msg from server
4003 *
4004 * u32 serverin-length
4005 * u8-array serverin-string
4006 * u8 continue
4007 */
4008
4009 #define SASL_MAX_MECHLIST_LEN 300
4010 #define SASL_MAX_DATA_LEN (1024 * 1024)
4011
4012 /* Perform the SASL authentication process
4013 */
vnc_connection_perform_auth_sasl(VncConnection * conn)4014 static gboolean vnc_connection_perform_auth_sasl(VncConnection *conn)
4015 {
4016 VncConnectionPrivate *priv = conn->priv;
4017 sasl_conn_t *saslconn = NULL;
4018 sasl_security_properties_t secprops;
4019 const char *clientout;
4020 char *serverin = NULL;
4021 unsigned int clientoutlen, serverinlen;
4022 int err, complete;
4023 char *localAddr = NULL, *remoteAddr = NULL;
4024 const void *val;
4025 sasl_ssf_t ssf;
4026 sasl_callback_t saslcb[] = {
4027 { .id = SASL_CB_AUTHNAME },
4028 // { .id = SASL_CB_USER },
4029 { .id = SASL_CB_PASS },
4030 { .id = 0 },
4031 };
4032 sasl_interact_t *interact = NULL;
4033 guint32 mechlistlen;
4034 char *mechlist;
4035 const char *mechname;
4036 gboolean ret;
4037 GSocketAddress *addr;
4038
4039 /* Sets up the SASL library as a whole */
4040 err = sasl_client_init(NULL);
4041 VNC_DEBUG("Client initialize SASL authentication %d", err);
4042 if (err != SASL_OK) {
4043 vnc_connection_set_error(conn,
4044 "failed to initialize SASL library: %d (%s)",
4045 err, sasl_errstring(err, NULL, NULL));
4046 goto error;
4047 }
4048
4049 /* Get local address in form IPADDR:PORT */
4050 addr = g_socket_get_local_address(priv->sock, NULL);
4051 if (!addr) {
4052 vnc_connection_set_error(conn, "%s", "failed to get local address");
4053 goto error;
4054 }
4055 if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 ||
4056 g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) &&
4057 (localAddr = vnc_connection_addr_to_string(addr)) == NULL) {
4058 vnc_connection_set_error(conn, "%s", "Unable to format address as string");
4059 goto error;
4060 }
4061
4062 /* Get remote address in form IPADDR:PORT */
4063 addr = g_socket_get_remote_address(priv->sock, NULL);
4064 if (!addr) {
4065 vnc_connection_set_error(conn, "%s", "failed to get peer address");
4066 goto error;
4067 }
4068 if ((g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV4 ||
4069 g_socket_address_get_family(addr) == G_SOCKET_FAMILY_IPV6) &&
4070 (remoteAddr = vnc_connection_addr_to_string(addr)) == NULL) {
4071 vnc_connection_set_error(conn, "%s", "Unable to format address as string");
4072 goto error;
4073 }
4074
4075 VNC_DEBUG("Client SASL new host:'%s' local:'%s' remote:'%s'", priv->host, localAddr, remoteAddr);
4076
4077 /* Setup a handle for being a client */
4078 err = sasl_client_new("vnc",
4079 priv->host,
4080 localAddr,
4081 remoteAddr,
4082 saslcb,
4083 SASL_SUCCESS_DATA,
4084 &saslconn);
4085 g_free(localAddr);
4086 g_free(remoteAddr);
4087
4088 if (err != SASL_OK) {
4089 vnc_connection_set_error(conn,
4090 "Failed to create SASL client context: %d (%s)",
4091 err, sasl_errstring(err, NULL, NULL));
4092 goto error;
4093 }
4094
4095 /* Initialize some connection props we care about */
4096 if (priv->tls_session) {
4097 gnutls_cipher_algorithm_t cipher;
4098
4099 cipher = gnutls_cipher_get(priv->tls_session);
4100 if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) {
4101 vnc_connection_set_error(conn, "%s",
4102 "invalid cipher size for TLS session");
4103 goto error;
4104 }
4105 ssf *= 8; /* key size is bytes, sasl wants bits */
4106
4107 VNC_DEBUG("Setting external SSF %d", (int)ssf);
4108 err = sasl_setprop(saslconn, SASL_SSF_EXTERNAL, &ssf);
4109 if (err != SASL_OK) {
4110 vnc_connection_set_error(conn,
4111 "cannot set external SSF %d (%s)",
4112 err, sasl_errstring(err, NULL, NULL));
4113 goto error;
4114 }
4115 }
4116
4117 memset (&secprops, 0, sizeof secprops);
4118 /* If we've got TLS, we don't care about SSF */
4119 secprops.min_ssf = priv->tls_session ? 0 : 56; /* Equiv to DES supported by all Kerberos */
4120 secprops.max_ssf = priv->tls_session ? 0 : 100000; /* Very strong ! AES == 256 */
4121 secprops.maxbufsize = 100000;
4122 /* If we're not TLS, then forbid any anonymous or trivially crackable auth */
4123 secprops.security_flags = priv->tls_session ? 0 :
4124 SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT;
4125
4126 err = sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops);
4127 if (err != SASL_OK) {
4128 vnc_connection_set_error(conn,
4129 "cannot set security props %d (%s)",
4130 err, sasl_errstring(err, NULL, NULL));
4131 goto error;
4132 }
4133
4134 /* Get the supported mechanisms from the server */
4135 mechlistlen = vnc_connection_read_u32(conn);
4136 if (priv->coroutine_stop)
4137 goto error;
4138 if (mechlistlen > SASL_MAX_MECHLIST_LEN) {
4139 vnc_connection_set_error(conn,
4140 "mechlistlen %u too long",
4141 mechlistlen);
4142 goto error;
4143 }
4144
4145 mechlist = g_malloc(mechlistlen+1);
4146 vnc_connection_read(conn, mechlist, mechlistlen);
4147 mechlist[mechlistlen] = '\0';
4148 if (priv->coroutine_stop) {
4149 g_free(mechlist);
4150 mechlist = NULL;
4151 goto error;
4152 }
4153
4154 restart:
4155 /* Start the auth negotiation on the client end first */
4156 VNC_DEBUG("Client start negotiation mechlist '%s'", mechlist);
4157 err = sasl_client_start(saslconn,
4158 mechlist,
4159 &interact,
4160 &clientout,
4161 &clientoutlen,
4162 &mechname);
4163 if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) {
4164 vnc_connection_set_error(conn,
4165 "Failed to start SASL negotiation: %d (%s)",
4166 err, sasl_errdetail(saslconn));
4167 g_free(mechlist);
4168 mechlist = NULL;
4169 goto error;
4170 }
4171
4172 /* Need to gather some credentials from the client */
4173 if (err == SASL_INTERACT) {
4174 if (!vnc_connection_gather_sasl_credentials(conn,
4175 interact)) {
4176 vnc_connection_set_error(conn, "%s",
4177 "Failed to collect auth credentials");
4178 goto error;
4179 }
4180 goto restart;
4181 }
4182
4183 VNC_DEBUG("Server start negotiation with mech %s. Data %u bytes %p '%s'",
4184 mechname, clientoutlen, clientout, clientout);
4185
4186 if (clientoutlen > SASL_MAX_DATA_LEN) {
4187 vnc_connection_set_error(conn,
4188 "SASL negotiation data too long: %u bytes",
4189 clientoutlen);
4190 goto error;
4191 }
4192
4193 /* Send back the chosen mechname */
4194 vnc_connection_write_u32(conn, strlen(mechname));
4195 vnc_connection_write(conn, mechname, strlen(mechname));
4196
4197 /* NB, distinction of NULL vs "" is *critical* in SASL */
4198 if (clientout) {
4199 vnc_connection_write_u32(conn, clientoutlen + 1);
4200 vnc_connection_write(conn, clientout, clientoutlen + 1);
4201 } else {
4202 vnc_connection_write_u32(conn, 0);
4203 }
4204 vnc_connection_flush(conn);
4205 if (priv->coroutine_stop)
4206 goto error;
4207
4208
4209 VNC_DEBUG("%s", "Getting sever start negotiation reply");
4210 /* Read the 'START' message reply from server */
4211 serverinlen = vnc_connection_read_u32(conn);
4212 if (priv->coroutine_stop)
4213 goto error;
4214 if (serverinlen > SASL_MAX_DATA_LEN) {
4215 vnc_connection_set_error(conn,
4216 "SASL negotiation data too long: %u bytes",
4217 clientoutlen);
4218 goto error;
4219 }
4220
4221 /* NB, distinction of NULL vs "" is *critical* in SASL */
4222 if (serverinlen) {
4223 serverin = g_malloc(serverinlen);
4224 vnc_connection_read(conn, serverin, serverinlen);
4225 serverin[serverinlen-1] = '\0';
4226 serverinlen--;
4227 } else {
4228 serverin = NULL;
4229 }
4230 complete = vnc_connection_read_u8(conn);
4231 if (priv->coroutine_stop)
4232 goto error;
4233
4234 VNC_DEBUG("Client start result complete: %d. Data %u bytes %p '%s'",
4235 complete, serverinlen, serverin, serverin);
4236
4237 /* Previous server call showed completion & sasl_client_start() told us
4238 * we are locally complete too */
4239 if (complete && err == SASL_OK)
4240 goto done;
4241
4242 /* Loop-the-loop...
4243 * Even if the server has completed, the client must *always* do at least one step
4244 * in this loop to verify the server isn't lying about something. Mutual auth */
4245 for (;;) {
4246 restep:
4247 err = sasl_client_step(saslconn,
4248 serverin,
4249 serverinlen,
4250 &interact,
4251 &clientout,
4252 &clientoutlen);
4253 if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) {
4254 vnc_connection_set_error(conn,
4255 "Failed SASL step: %d (%s)",
4256 err, sasl_errdetail(saslconn));
4257 goto error;
4258 }
4259
4260 /* Need to gather some credentials from the client */
4261 if (err == SASL_INTERACT) {
4262 if (!vnc_connection_gather_sasl_credentials(conn,
4263 interact)) {
4264 vnc_connection_set_error(conn, "%s",
4265 "Failed to collect auth credentials");
4266 goto error;
4267 }
4268 goto restep;
4269 }
4270
4271 if (serverin) {
4272 g_free(serverin);
4273 serverin = NULL;
4274 }
4275
4276 VNC_DEBUG("Client step result %d. Data %u bytes %p '%s'",
4277 err, clientoutlen, clientout, clientout);
4278
4279 /* Previous server call showed completion & we're now locally complete too */
4280 if (complete && err == SASL_OK)
4281 break;
4282
4283 /* Not done, prepare to talk with the server for another iteration */
4284
4285 /* NB, distinction of NULL vs "" is *critical* in SASL */
4286 if (clientout) {
4287 vnc_connection_write_u32(conn, clientoutlen + 1);
4288 vnc_connection_write(conn, clientout, clientoutlen + 1);
4289 } else {
4290 vnc_connection_write_u32(conn, 0);
4291 }
4292 vnc_connection_flush(conn);
4293 if (priv->coroutine_stop)
4294 goto error;
4295
4296 VNC_DEBUG("Server step with %u bytes %p", clientoutlen, clientout);
4297
4298 serverinlen = vnc_connection_read_u32(conn);
4299 if (priv->coroutine_stop)
4300 goto error;
4301 if (serverinlen > SASL_MAX_DATA_LEN) {
4302 vnc_connection_set_error(conn,
4303 "SASL negotiation data too long: %u bytes",
4304 clientoutlen);
4305 goto error;
4306 }
4307
4308 /* NB, distinction of NULL vs "" is *critical* in SASL */
4309 if (serverinlen) {
4310 serverin = g_malloc(serverinlen);
4311 vnc_connection_read(conn, serverin, serverinlen);
4312 serverin[serverinlen-1] = '\0';
4313 serverinlen--;
4314 } else {
4315 serverin = NULL;
4316 }
4317 complete = vnc_connection_read_u8(conn);
4318 if (priv->coroutine_stop)
4319 goto error;
4320
4321 VNC_DEBUG("Client step result complete: %d. Data %u bytes %p '%s'",
4322 complete, serverinlen, serverin, serverin);
4323
4324 /* This server call shows complete, and earlier client step was OK */
4325 if (complete && err == SASL_OK) {
4326 g_free(serverin);
4327 serverin = NULL;
4328 break;
4329 }
4330 }
4331
4332 done:
4333 /* Check for suitable SSF if non-TLS */
4334 if (!priv->tls_session) {
4335 err = sasl_getprop(saslconn, SASL_SSF, &val);
4336 if (err != SASL_OK) {
4337 vnc_connection_set_error(conn,
4338 "cannot query SASL ssf on connection %d (%s)",
4339 err, sasl_errstring(err, NULL, NULL));
4340 goto error;
4341 }
4342 ssf = *(const int *)val;
4343 VNC_DEBUG("SASL SSF value %d", (int)ssf);
4344 if (ssf < 56) { /* 56 == DES level, good for Kerberos */
4345 vnc_connection_set_error(conn,
4346 "negotiated SSF %d was not strong enough",
4347 (int)ssf);
4348 goto error;
4349 }
4350 }
4351
4352 VNC_DEBUG("%s", "SASL authentication complete");
4353 ret = vnc_connection_check_auth_result(conn);
4354 /* This must come *after* check-auth-result, because the former
4355 * is defined to be sent unencrypted, and setting saslconn turns
4356 * on the SSF layer encryption processing */
4357 priv->saslconn = saslconn;
4358 return ret;
4359
4360 error:
4361 if (saslconn)
4362 sasl_dispose(&saslconn);
4363 return FALSE;
4364 }
4365 #endif /* HAVE_SASL */
4366
4367
vnc_connection_start_tls(VncConnection * conn,int anonTLS)4368 static gboolean vnc_connection_start_tls(VncConnection *conn, int anonTLS)
4369 {
4370 VncConnectionPrivate *priv = conn->priv;
4371 const char *priority = anonTLS ? TLS_PRIORITY ":+ANON-DH" : TLS_PRIORITY;
4372 int ret;
4373
4374 VNC_DEBUG("Do TLS handshake");
4375 if (vnc_connection_tls_initialize() < 0) {
4376 vnc_connection_set_error(conn, "%s", "Failed to init TLS");
4377 return FALSE;
4378 }
4379 if (priv->tls_session == NULL) {
4380 if (gnutls_init(&priv->tls_session, GNUTLS_CLIENT) < 0) {
4381 vnc_connection_set_error(conn, "%s", "Failed to allocate client session");
4382 return FALSE;
4383 }
4384
4385 if (gnutls_priority_set_direct(priv->tls_session, priority, NULL) < 0) {
4386 gnutls_deinit(priv->tls_session);
4387 vnc_connection_set_error(conn, "%s", "Failed to set priority");
4388 return FALSE;
4389 }
4390
4391 if (anonTLS) {
4392 gnutls_anon_client_credentials anon_cred = vnc_connection_tls_initialize_anon_cred();
4393 if (!anon_cred) {
4394 gnutls_deinit(priv->tls_session);
4395 vnc_connection_set_error(conn, "%s", "Failed to allocate credentials");
4396 return FALSE;
4397 }
4398 if (gnutls_credentials_set(priv->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
4399 gnutls_deinit(priv->tls_session);
4400 vnc_connection_set_error(conn, "%s", "Failed to initialize credentials");
4401 return FALSE;
4402 }
4403 } else {
4404 priv->want_cred_password = FALSE;
4405 priv->want_cred_username = FALSE;
4406 priv->want_cred_x509 = TRUE;
4407 if (!vnc_connection_gather_credentials(conn))
4408 return FALSE;
4409
4410 gnutls_certificate_credentials_t x509_cred = vnc_connection_tls_initialize_cert_cred(conn);
4411 if (!x509_cred) {
4412 gnutls_deinit(priv->tls_session);
4413 vnc_connection_set_error(conn, "%s", "Failed to allocate credentials");
4414 return FALSE;
4415 }
4416 if (gnutls_credentials_set(priv->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
4417 gnutls_deinit(priv->tls_session);
4418 vnc_connection_set_error(conn, "%s", "Failed to initialize credentials");
4419 return FALSE;
4420 }
4421 }
4422
4423 gnutls_transport_set_ptr(priv->tls_session, (gnutls_transport_ptr_t)conn);
4424 gnutls_transport_set_push_function(priv->tls_session, vnc_connection_tls_push);
4425 gnutls_transport_set_pull_function(priv->tls_session, vnc_connection_tls_pull);
4426 }
4427
4428 retry:
4429 if ((ret = gnutls_handshake(priv->tls_session)) < 0) {
4430 if (!gnutls_error_is_fatal(ret)) {
4431 VNC_DEBUG("Handshake was blocking");
4432 if (!gnutls_record_get_direction(priv->tls_session))
4433 g_io_wait(priv->sock, G_IO_IN);
4434 else
4435 g_io_wait(priv->sock, G_IO_OUT);
4436 goto retry;
4437 }
4438 gnutls_deinit(priv->tls_session);
4439 priv->tls_session = NULL;
4440 vnc_connection_set_error(conn, "Failed to complete handshake %s",
4441 gnutls_strerror(ret));
4442 return FALSE;
4443 }
4444
4445 VNC_DEBUG("Handshake done");
4446
4447 if (anonTLS) {
4448 return TRUE;
4449 } else {
4450 if (!vnc_connection_validate_certificate(conn)) {
4451 return FALSE;
4452 }
4453 return TRUE;
4454 }
4455 }
4456
vnc_connection_has_auth_subtype(gpointer data)4457 static gboolean vnc_connection_has_auth_subtype(gpointer data)
4458 {
4459 VncConnection *conn = data;
4460 VncConnectionPrivate *priv = conn->priv;
4461
4462 if (priv->coroutine_stop)
4463 return TRUE;
4464 if (priv->auth_subtype == VNC_CONNECTION_AUTH_INVALID)
4465 return FALSE;
4466 return TRUE;
4467 }
4468
vnc_connection_choose_auth(VncConnection * conn,int signum,unsigned int ntypes,unsigned int * types)4469 static void vnc_connection_choose_auth(VncConnection *conn,
4470 int signum,
4471 unsigned int ntypes,
4472 unsigned int *types)
4473 {
4474 VncConnectionPrivate *priv = conn->priv;
4475 struct signal_data sigdata;
4476 GValueArray *authTypes;
4477 GValue authType;
4478
4479 authTypes = g_value_array_new(0);
4480
4481 for (int i = 0 ; i < ntypes ; i++) {
4482 memset(&authType, 0, sizeof(authType));
4483
4484 if (signum == VNC_AUTH_CHOOSE_TYPE) {
4485 g_value_init(&authType, VNC_TYPE_CONNECTION_AUTH);
4486 } else {
4487 if (priv->auth_type == VNC_CONNECTION_AUTH_VENCRYPT)
4488 g_value_init(&authType, VNC_TYPE_CONNECTION_AUTH_VENCRYPT);
4489 else
4490 g_value_init(&authType, VNC_TYPE_CONNECTION_AUTH);
4491 }
4492 g_value_set_enum(&authType, types[i]);
4493 authTypes = g_value_array_append(authTypes, &authType);
4494 }
4495
4496 sigdata.params.authCred = authTypes;
4497 vnc_connection_emit_main_context(conn, signum, &sigdata);
4498 g_value_array_free(authTypes);
4499 }
4500
vnc_connection_perform_auth_tls(VncConnection * conn)4501 static gboolean vnc_connection_perform_auth_tls(VncConnection *conn)
4502 {
4503 VncConnectionPrivate *priv = conn->priv;
4504 unsigned int nauth, i;
4505 unsigned int auth[20];
4506
4507 if (!vnc_connection_start_tls(conn, 1)) {
4508 VNC_DEBUG("Could not start TLS");
4509 return FALSE;
4510 }
4511 VNC_DEBUG("Completed TLS setup");
4512
4513 nauth = vnc_connection_read_u8(conn);
4514 if (vnc_connection_has_error(conn))
4515 return FALSE;
4516
4517 VNC_DEBUG("Got %u subauths", nauth);
4518 if (nauth == 0) {
4519 VNC_DEBUG("No sub-auth types requested");
4520 return vnc_connection_check_auth_result(conn);
4521 }
4522
4523 if (nauth > sizeof(auth)) {
4524 vnc_connection_set_error(conn, "Too many (%u) auth types", nauth);
4525 return FALSE;
4526 }
4527 for (i = 0 ; i < nauth ; i++) {
4528 auth[i] = vnc_connection_read_u8(conn);
4529 }
4530
4531 for (i = 0 ; i < nauth ; i++) {
4532 VNC_DEBUG("Possible TLS sub-auth %u", auth[i]);
4533 }
4534
4535 if (priv->coroutine_stop)
4536 return FALSE;
4537 vnc_connection_choose_auth(conn, VNC_AUTH_CHOOSE_SUBTYPE, nauth, auth);
4538 if (priv->coroutine_stop)
4539 return FALSE;
4540
4541 VNC_DEBUG("Waiting for TLS auth subtype");
4542 g_condition_wait(vnc_connection_has_auth_subtype, conn);
4543 if (priv->coroutine_stop)
4544 return FALSE;
4545
4546 VNC_DEBUG("Choose auth %u", priv->auth_subtype);
4547
4548 vnc_connection_write_u8(conn, priv->auth_subtype);
4549 vnc_connection_flush(conn);
4550
4551 switch (priv->auth_subtype) {
4552 case VNC_CONNECTION_AUTH_NONE:
4553 if (priv->minor == 8)
4554 return vnc_connection_check_auth_result(conn);
4555 return TRUE;
4556 case VNC_CONNECTION_AUTH_VNC:
4557 return vnc_connection_perform_auth_vnc(conn);
4558 #ifdef HAVE_SASL
4559 case VNC_CONNECTION_AUTH_SASL:
4560 return vnc_connection_perform_auth_sasl(conn);
4561 #endif
4562 default:
4563 vnc_connection_set_error(conn, "Auth subtype %u is not supported",
4564 priv->auth_subtype);
4565 return FALSE;
4566 }
4567
4568 return TRUE;
4569 }
4570
vnc_connection_perform_auth_vencrypt(VncConnection * conn)4571 static gboolean vnc_connection_perform_auth_vencrypt(VncConnection *conn)
4572 {
4573 VncConnectionPrivate *priv = conn->priv;
4574 int major, minor, status, anonTLS;
4575 unsigned int nauth, i;
4576 unsigned int auth[20];
4577
4578 major = vnc_connection_read_u8(conn);
4579 minor = vnc_connection_read_u8(conn);
4580
4581 if (major != 0 &&
4582 minor != 2) {
4583 vnc_connection_set_error(conn, "Unsupported VeNCrypt version %d %d", major, minor);
4584 return FALSE;
4585 }
4586
4587 vnc_connection_write_u8(conn, major);
4588 vnc_connection_write_u8(conn, minor);
4589 vnc_connection_flush(conn);
4590 status = vnc_connection_read_u8(conn);
4591 if (status != 0) {
4592 vnc_connection_set_error(conn, "Server refused VeNCrypt version %d %d", major, minor);
4593 return FALSE;
4594 }
4595
4596 nauth = vnc_connection_read_u8(conn);
4597 if (nauth > (sizeof(auth)/sizeof(auth[0]))) {
4598 vnc_connection_set_error(conn, "Too many (%u) auth types", nauth);
4599 return FALSE;
4600 }
4601
4602 for (i = 0 ; i < nauth ; i++) {
4603 auth[i] = vnc_connection_read_u32(conn);
4604 }
4605
4606 for (i = 0 ; i < nauth ; i++) {
4607 VNC_DEBUG("Possible VeNCrypt sub-auth %u", auth[i]);
4608 }
4609
4610 if (priv->coroutine_stop)
4611 return FALSE;
4612 vnc_connection_choose_auth(conn, VNC_AUTH_CHOOSE_SUBTYPE, nauth, auth);
4613 if (priv->coroutine_stop)
4614 return FALSE;
4615
4616 VNC_DEBUG("Waiting for VeNCrypt auth subtype");
4617 g_condition_wait(vnc_connection_has_auth_subtype, conn);
4618 if (priv->coroutine_stop)
4619 return FALSE;
4620
4621 VNC_DEBUG("Choose auth %u", priv->auth_subtype);
4622
4623 if (!vnc_connection_gather_credentials(conn))
4624 return FALSE;
4625
4626 #ifndef DEBUG
4627 if (priv->auth_subtype == VNC_CONNECTION_AUTH_VENCRYPT_PLAIN) {
4628 vnc_connection_set_error(conn, "%s",
4629 "Cowardly refusing to transmit plain text password");
4630 return FALSE;
4631 }
4632 #endif
4633
4634 vnc_connection_write_u32(conn, priv->auth_subtype);
4635 vnc_connection_flush(conn);
4636 status = vnc_connection_read_u8(conn);
4637 if (status != 1) {
4638 vnc_connection_set_error(conn,
4639 "Server refused VeNCrypt auth %u %d", priv->auth_subtype, status);
4640 return FALSE;
4641 }
4642
4643 switch (priv->auth_subtype) {
4644 case VNC_CONNECTION_AUTH_VENCRYPT_TLSNONE:
4645 case VNC_CONNECTION_AUTH_VENCRYPT_TLSPLAIN:
4646 case VNC_CONNECTION_AUTH_VENCRYPT_TLSVNC:
4647 case VNC_CONNECTION_AUTH_VENCRYPT_TLSSASL:
4648 anonTLS = 1;
4649 break;
4650 default:
4651 anonTLS = 0;
4652 }
4653
4654 if (!vnc_connection_start_tls(conn, anonTLS)) {
4655 return FALSE;
4656 }
4657 VNC_DEBUG("Completed TLS setup, do subauth %u", priv->auth_subtype);
4658
4659 switch (priv->auth_subtype) {
4660 /* Plain certificate based auth */
4661 case VNC_CONNECTION_AUTH_VENCRYPT_TLSNONE:
4662 case VNC_CONNECTION_AUTH_VENCRYPT_X509NONE:
4663 VNC_DEBUG("Completing auth");
4664 return vnc_connection_check_auth_result(conn);
4665
4666 /* Regular VNC layered over TLS */
4667 case VNC_CONNECTION_AUTH_VENCRYPT_TLSVNC:
4668 case VNC_CONNECTION_AUTH_VENCRYPT_X509VNC:
4669 VNC_DEBUG("Handing off to VNC auth");
4670 return vnc_connection_perform_auth_vnc(conn);
4671
4672 #ifdef HAVE_SASL
4673 /* SASL layered over TLS */
4674 case VNC_CONNECTION_AUTH_VENCRYPT_TLSSASL:
4675 case VNC_CONNECTION_AUTH_VENCRYPT_X509SASL:
4676 VNC_DEBUG("Handing off to SASL auth");
4677 return vnc_connection_perform_auth_sasl(conn);
4678 #endif
4679
4680 default:
4681 vnc_connection_set_error(conn, "Unknown auth subtype %u", priv->auth_subtype);
4682 return FALSE;
4683 }
4684 }
4685
vnc_connection_has_auth_type(gpointer data)4686 static gboolean vnc_connection_has_auth_type(gpointer data)
4687 {
4688 VncConnection *conn = data;
4689 VncConnectionPrivate *priv = conn->priv;
4690
4691 if (priv->coroutine_stop)
4692 return TRUE;
4693 if (priv->auth_type == VNC_CONNECTION_AUTH_INVALID)
4694 return FALSE;
4695 return TRUE;
4696 }
4697
vnc_connection_perform_auth(VncConnection * conn)4698 static gboolean vnc_connection_perform_auth(VncConnection *conn)
4699 {
4700 VncConnectionPrivate *priv = conn->priv;
4701 unsigned int nauth, i;
4702 unsigned int auth[10];
4703
4704 if (priv->minor <= 6) {
4705 nauth = 1;
4706 auth[0] = vnc_connection_read_u32(conn);
4707 } else {
4708 nauth = vnc_connection_read_u8(conn);
4709 if (vnc_connection_has_error(conn))
4710 return FALSE;
4711
4712 if (nauth == 0)
4713 return vnc_connection_check_auth_result(conn);
4714
4715 if (nauth > sizeof(auth)) {
4716 vnc_connection_set_error(conn, "Too many auth types %u",
4717 nauth);
4718 return FALSE;
4719 }
4720 for (i = 0 ; i < nauth ; i++)
4721 auth[i] = vnc_connection_read_u8(conn);
4722 }
4723
4724 for (i = 0 ; i < nauth ; i++) {
4725 VNC_DEBUG("Possible auth %u", auth[i]);
4726 }
4727
4728 if (priv->coroutine_stop)
4729 return FALSE;
4730 vnc_connection_choose_auth(conn, VNC_AUTH_CHOOSE_TYPE, nauth, auth);
4731 if (priv->coroutine_stop)
4732 return FALSE;
4733
4734 VNC_DEBUG("Waiting for auth type");
4735 g_condition_wait(vnc_connection_has_auth_type, conn);
4736 if (priv->coroutine_stop)
4737 return FALSE;
4738
4739 VNC_DEBUG("Choose auth %u", priv->auth_type);
4740 if (!vnc_connection_gather_credentials(conn))
4741 return FALSE;
4742
4743 if (priv->minor > 6) {
4744 vnc_connection_write_u8(conn, priv->auth_type);
4745 vnc_connection_flush(conn);
4746 }
4747
4748 switch (priv->auth_type) {
4749 case VNC_CONNECTION_AUTH_NONE:
4750 if (priv->minor == 8)
4751 return vnc_connection_check_auth_result(conn);
4752 return TRUE;
4753 case VNC_CONNECTION_AUTH_VNC:
4754 return vnc_connection_perform_auth_vnc(conn);
4755
4756 case VNC_CONNECTION_AUTH_TLS:
4757 if (priv->minor < 7) {
4758 vnc_connection_set_error(conn, "%s", "TLS auth requires protocol 3.8");
4759 return FALSE;
4760 }
4761 return vnc_connection_perform_auth_tls(conn);
4762
4763 case VNC_CONNECTION_AUTH_VENCRYPT:
4764 return vnc_connection_perform_auth_vencrypt(conn);
4765
4766 #ifdef HAVE_SASL
4767 case VNC_CONNECTION_AUTH_SASL:
4768 return vnc_connection_perform_auth_sasl(conn);
4769 #endif
4770
4771 case VNC_CONNECTION_AUTH_MSLOGON:
4772 return vnc_connection_perform_auth_mslogon(conn);
4773
4774 case VNC_CONNECTION_AUTH_ARD:
4775 return vnc_connection_perform_auth_ard(conn);
4776
4777 default:
4778 {
4779 struct signal_data sigdata;
4780 sigdata.params.authUnsupported = priv->auth_type;
4781 vnc_connection_emit_main_context(conn, VNC_AUTH_UNSUPPORTED, &sigdata);
4782 }
4783 vnc_connection_set_error(conn, "Unsupported auth type %u", priv->auth_type);
4784 return FALSE;
4785 }
4786
4787 return TRUE;
4788 }
4789
vnc_connection_finalize(GObject * object)4790 static void vnc_connection_finalize (GObject *object)
4791 {
4792 VncConnection *conn = VNC_CONNECTION(object);
4793 VncConnectionPrivate *priv = conn->priv;
4794
4795 VNC_DEBUG("Finalize VncConnection=%p", conn);
4796
4797 if (vnc_connection_is_open(conn))
4798 vnc_connection_close(conn);
4799
4800 if (priv->cursor)
4801 g_object_unref(G_OBJECT(priv->cursor));
4802
4803 if (priv->fb)
4804 g_object_unref(G_OBJECT(priv->fb));
4805
4806 if (priv->audio)
4807 g_object_unref(G_OBJECT(priv->audio));
4808 if (priv->audio_sample)
4809 g_object_unref(G_OBJECT(priv->audio_sample));
4810 if (priv->audio_timer)
4811 g_source_remove(priv->audio_timer);
4812
4813 G_OBJECT_CLASS(vnc_connection_parent_class)->finalize (object);
4814 }
4815
vnc_connection_class_init(VncConnectionClass * klass)4816 static void vnc_connection_class_init(VncConnectionClass *klass)
4817 {
4818 GObjectClass *object_class = G_OBJECT_CLASS (klass);
4819
4820 object_class->finalize = vnc_connection_finalize;
4821 object_class->get_property = vnc_connection_get_property;
4822 object_class->set_property = vnc_connection_set_property;
4823
4824 g_object_class_install_property(object_class,
4825 PROP_FRAMEBUFFER,
4826 g_param_spec_object("framebuffer",
4827 "The desktop framebuffer",
4828 "The desktop framebuffer instance",
4829 VNC_TYPE_FRAMEBUFFER,
4830 G_PARAM_READABLE |
4831 G_PARAM_WRITABLE |
4832 G_PARAM_STATIC_NAME |
4833 G_PARAM_STATIC_NICK |
4834 G_PARAM_STATIC_BLURB));
4835
4836 signals[VNC_CURSOR_CHANGED] =
4837 g_signal_new ("vnc-cursor-changed",
4838 G_OBJECT_CLASS_TYPE (object_class),
4839 G_SIGNAL_RUN_FIRST,
4840 G_STRUCT_OFFSET (VncConnectionClass, vnc_cursor_changed),
4841 NULL, NULL,
4842 g_cclosure_marshal_VOID__OBJECT,
4843 G_TYPE_NONE,
4844 1,
4845 VNC_TYPE_CURSOR);
4846
4847 signals[VNC_POINTER_MODE_CHANGED] =
4848 g_signal_new ("vnc-pointer-mode-changed",
4849 G_OBJECT_CLASS_TYPE (object_class),
4850 G_SIGNAL_RUN_FIRST,
4851 G_STRUCT_OFFSET (VncConnectionClass, vnc_pointer_mode_changed),
4852 NULL, NULL,
4853 g_cclosure_marshal_VOID__BOOLEAN,
4854 G_TYPE_NONE,
4855 1,
4856 G_TYPE_BOOLEAN);
4857
4858 signals[VNC_BELL] =
4859 g_signal_new ("vnc-bell",
4860 G_OBJECT_CLASS_TYPE (object_class),
4861 G_SIGNAL_RUN_FIRST,
4862 G_STRUCT_OFFSET (VncConnectionClass, vnc_bell),
4863 NULL, NULL,
4864 g_cclosure_marshal_VOID__VOID,
4865 G_TYPE_NONE,
4866 0);
4867
4868 signals[VNC_SERVER_CUT_TEXT] =
4869 g_signal_new ("vnc-server-cut-text",
4870 G_OBJECT_CLASS_TYPE (object_class),
4871 G_SIGNAL_RUN_FIRST,
4872 G_STRUCT_OFFSET (VncConnectionClass, vnc_server_cut_text),
4873 NULL, NULL,
4874 g_cclosure_marshal_VOID__STRING,
4875 G_TYPE_NONE,
4876 1,
4877 G_TYPE_STRING);
4878
4879 signals[VNC_FRAMEBUFFER_UPDATE] =
4880 g_signal_new ("vnc-framebuffer-update",
4881 G_OBJECT_CLASS_TYPE (object_class),
4882 G_SIGNAL_RUN_FIRST,
4883 G_STRUCT_OFFSET (VncConnectionClass, vnc_framebuffer_update),
4884 NULL, NULL,
4885 g_cclosure_user_marshal_VOID__INT_INT_INT_INT,
4886 G_TYPE_NONE,
4887 4,
4888 G_TYPE_INT,
4889 G_TYPE_INT,
4890 G_TYPE_INT,
4891 G_TYPE_INT);
4892
4893 signals[VNC_DESKTOP_RESIZE] =
4894 g_signal_new ("vnc-desktop-resize",
4895 G_OBJECT_CLASS_TYPE (object_class),
4896 G_SIGNAL_RUN_FIRST,
4897 G_STRUCT_OFFSET (VncConnectionClass, vnc_desktop_resize),
4898 NULL, NULL,
4899 g_cclosure_user_marshal_VOID__INT_INT,
4900 G_TYPE_NONE,
4901 2,
4902 G_TYPE_INT,
4903 G_TYPE_INT);
4904
4905 signals[VNC_PIXEL_FORMAT_CHANGED] =
4906 g_signal_new ("vnc-pixel-format-changed",
4907 G_OBJECT_CLASS_TYPE (object_class),
4908 G_SIGNAL_RUN_FIRST,
4909 G_STRUCT_OFFSET (VncConnectionClass, vnc_pixel_format_changed),
4910 NULL, NULL,
4911 g_cclosure_marshal_VOID__POINTER,
4912 G_TYPE_NONE,
4913 1,
4914 G_TYPE_POINTER);
4915
4916 signals[VNC_LED_STATE] =
4917 g_signal_new ("vnc-led-state",
4918 G_OBJECT_CLASS_TYPE (object_class),
4919 G_SIGNAL_RUN_FIRST,
4920 G_STRUCT_OFFSET (VncConnectionClass, vnc_led_state),
4921 NULL, NULL,
4922 g_cclosure_marshal_VOID__INT,
4923 G_TYPE_NONE,
4924 0);
4925
4926 signals[VNC_AUTH_FAILURE] =
4927 g_signal_new ("vnc-auth-failure",
4928 G_OBJECT_CLASS_TYPE (object_class),
4929 G_SIGNAL_RUN_FIRST,
4930 G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_failure),
4931 NULL, NULL,
4932 g_cclosure_marshal_VOID__STRING,
4933 G_TYPE_NONE,
4934 1,
4935 G_TYPE_STRING);
4936
4937
4938 signals[VNC_AUTH_UNSUPPORTED] =
4939 g_signal_new ("vnc-auth-unsupported",
4940 G_OBJECT_CLASS_TYPE (object_class),
4941 G_SIGNAL_RUN_FIRST,
4942 G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_unsupported),
4943 NULL, NULL,
4944 g_cclosure_marshal_VOID__UINT,
4945 G_TYPE_NONE,
4946 1,
4947 G_TYPE_UINT);
4948
4949 signals[VNC_AUTH_CREDENTIAL] =
4950 g_signal_new ("vnc-auth-credential",
4951 G_OBJECT_CLASS_TYPE (object_class),
4952 G_SIGNAL_RUN_FIRST,
4953 G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_credential),
4954 NULL, NULL,
4955 g_cclosure_marshal_VOID__BOXED,
4956 G_TYPE_NONE,
4957 1,
4958 G_TYPE_VALUE_ARRAY);
4959
4960 signals[VNC_AUTH_CHOOSE_TYPE] =
4961 g_signal_new ("vnc-auth-choose-type",
4962 G_OBJECT_CLASS_TYPE (object_class),
4963 G_SIGNAL_RUN_FIRST,
4964 G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_choose_type),
4965 NULL, NULL,
4966 g_cclosure_marshal_VOID__BOXED,
4967 G_TYPE_NONE,
4968 1,
4969 G_TYPE_VALUE_ARRAY);
4970
4971 signals[VNC_AUTH_CHOOSE_SUBTYPE] =
4972 g_signal_new ("vnc-auth-choose-subtype",
4973 G_OBJECT_CLASS_TYPE (object_class),
4974 G_SIGNAL_RUN_FIRST,
4975 G_STRUCT_OFFSET (VncConnectionClass, vnc_auth_choose_subtype),
4976 NULL, NULL,
4977 g_cclosure_user_marshal_VOID__UINT_BOXED,
4978 G_TYPE_NONE,
4979 2,
4980 G_TYPE_UINT,
4981 G_TYPE_VALUE_ARRAY);
4982
4983
4984 signals[VNC_CONNECTED] =
4985 g_signal_new ("vnc-connected",
4986 G_OBJECT_CLASS_TYPE (object_class),
4987 G_SIGNAL_RUN_FIRST,
4988 G_STRUCT_OFFSET (VncConnectionClass, vnc_connected),
4989 NULL, NULL,
4990 g_cclosure_marshal_VOID__VOID,
4991 G_TYPE_NONE,
4992 0);
4993 signals[VNC_INITIALIZED] =
4994 g_signal_new ("vnc-initialized",
4995 G_OBJECT_CLASS_TYPE (object_class),
4996 G_SIGNAL_RUN_FIRST,
4997 G_STRUCT_OFFSET (VncConnectionClass, vnc_initialized),
4998 NULL, NULL,
4999 g_cclosure_marshal_VOID__VOID,
5000 G_TYPE_NONE,
5001 0);
5002 signals[VNC_DISCONNECTED] =
5003 g_signal_new ("vnc-disconnected",
5004 G_OBJECT_CLASS_TYPE (object_class),
5005 G_SIGNAL_RUN_FIRST,
5006 G_STRUCT_OFFSET (VncConnectionClass, vnc_disconnected),
5007 NULL, NULL,
5008 g_cclosure_marshal_VOID__VOID,
5009 G_TYPE_NONE,
5010 0);
5011 signals[VNC_ERROR] =
5012 g_signal_new ("vnc-error",
5013 G_OBJECT_CLASS_TYPE (object_class),
5014 G_SIGNAL_RUN_FIRST,
5015 G_STRUCT_OFFSET (VncConnectionClass, vnc_error),
5016 NULL, NULL,
5017 g_cclosure_marshal_VOID__STRING,
5018 G_TYPE_NONE,
5019 1,
5020 G_TYPE_STRING);
5021
5022
5023 g_type_class_add_private(klass, sizeof(VncConnectionPrivate));
5024 }
5025
5026
vnc_connection_init(VncConnection * conn)5027 static void vnc_connection_init(VncConnection *conn)
5028 {
5029 VncConnectionPrivate *priv;
5030
5031 VNC_DEBUG("Init VncConnection=%p", conn);
5032
5033 priv = conn->priv = VNC_CONNECTION_GET_PRIVATE(conn);
5034
5035 memset(priv, 0, sizeof(*priv));
5036
5037 priv->fd = -1;
5038 priv->auth_type = VNC_CONNECTION_AUTH_INVALID;
5039 priv->auth_subtype = VNC_CONNECTION_AUTH_INVALID;
5040 }
5041
5042
5043 /**
5044 * vnc_connection_new:
5045 *
5046 * Create a new connection object, which is initially
5047 * in the disconnected state.
5048 *
5049 * Returns: (transfer full): the new connection
5050 */
vnc_connection_new(void)5051 VncConnection *vnc_connection_new(void)
5052 {
5053 return VNC_CONNECTION(g_object_new(VNC_TYPE_CONNECTION,
5054 NULL));
5055 }
5056
vnc_connection_close(VncConnection * conn)5057 static void vnc_connection_close(VncConnection *conn)
5058 {
5059 VncConnectionPrivate *priv = conn->priv;
5060 int i;
5061
5062 VNC_DEBUG("Close VncConnection=%p", conn);
5063
5064 if (priv->tls_session) {
5065 gnutls_bye(priv->tls_session, GNUTLS_SHUT_RDWR);
5066 gnutls_deinit(priv->tls_session);
5067 priv->tls_session = NULL;
5068 }
5069 #ifdef HAVE_SASL
5070 if (priv->saslconn) {
5071 sasl_dispose (&priv->saslconn);
5072 priv->saslconn = NULL;
5073 priv->saslDecodedOffset = priv->saslDecodedLength = 0;
5074 }
5075 #endif
5076
5077 if (priv->sock) {
5078 g_object_unref(priv->sock);
5079 priv->sock = NULL;
5080 }
5081 if (priv->addr) {
5082 g_object_unref(priv->addr);
5083 priv->addr = NULL;
5084 }
5085 if (priv->fd != -1)
5086 priv->fd = -1;
5087
5088 if (priv->host) {
5089 g_free(priv->host);
5090 priv->host = NULL;
5091 }
5092
5093 if (priv->port) {
5094 g_free(priv->port);
5095 priv->port = NULL;
5096 }
5097
5098 if (priv->name) {
5099 g_free(priv->name);
5100 priv->name = NULL;
5101 }
5102
5103 if (priv->xmit_buffer) {
5104 g_free(priv->xmit_buffer);
5105 priv->xmit_buffer = NULL;
5106 priv->xmit_buffer_size = 0;
5107 priv->xmit_buffer_capacity = 0;
5108 }
5109
5110 priv->read_offset = priv->read_size = 0;
5111 priv->write_offset = 0;
5112 priv->uncompressed_offset = 0;
5113 priv->uncompressed_size = 0;
5114 priv->compressed_length = 0;
5115
5116 priv->width = priv->height = 0;
5117 priv->major = priv->minor = 0;
5118
5119 if (priv->cred_username) {
5120 g_free(priv->cred_username);
5121 priv->cred_username = NULL;
5122 }
5123 if (priv->cred_password) {
5124 g_free(priv->cred_password);
5125 priv->cred_password = NULL;
5126 }
5127
5128 priv->set_cred_x509 = FALSE;
5129 if (priv->cred_x509_cacert) {
5130 g_free(priv->cred_x509_cacert);
5131 priv->cred_x509_cacert = NULL;
5132 }
5133 if (priv->cred_x509_cacrl) {
5134 g_free(priv->cred_x509_cacrl);
5135 priv->cred_x509_cacrl = NULL;
5136 }
5137 if (priv->cred_x509_cert) {
5138 g_free(priv->cred_x509_cert);
5139 priv->cred_x509_cert = NULL;
5140 }
5141 if (priv->cred_x509_key) {
5142 g_free(priv->cred_x509_key);
5143 priv->cred_x509_key = NULL;
5144 }
5145
5146 priv->want_cred_x509 = priv->want_cred_username =
5147 priv->want_cred_password = FALSE;
5148
5149 for (i = 0; i < 5; i++)
5150 inflateEnd(&priv->streams[i]);
5151
5152 priv->auth_type = VNC_CONNECTION_AUTH_INVALID;
5153 priv->auth_subtype = VNC_CONNECTION_AUTH_INVALID;
5154 priv->sharedFlag = FALSE;
5155
5156 memset(&priv->fmt, 0, sizeof(priv->fmt));
5157
5158 g_free(priv->error);
5159 priv->error = NULL;
5160 priv->coroutine_stop = FALSE;
5161 }
5162
5163
5164 /**
5165 * vnc_connection_shutdown:
5166 * @conn: (transfer none): the connection object
5167 *
5168 * Initiate a shutdown of the current connection
5169 * by closing its socket
5170 *
5171 */
vnc_connection_shutdown(VncConnection * conn)5172 void vnc_connection_shutdown(VncConnection *conn)
5173 {
5174 VncConnectionPrivate *priv = conn->priv;
5175
5176 VNC_DEBUG("Shutdown VncConnection=%p", conn);
5177
5178 if (priv->open_id) {
5179 g_source_remove(priv->open_id);
5180 priv->open_id = 0;
5181 }
5182
5183 priv->fd = -1;
5184 priv->coroutine_stop = TRUE;
5185 VNC_DEBUG("Waking up coroutine to shutdown gracefully");
5186 g_io_wakeup(&priv->wait);
5187
5188 /* Closing the socket triggers an I/O error in the
5189 * event loop resulting...eventually.. in a call
5190 * to vnc_connection_close for full cleanup
5191 */
5192 if (priv->sock)
5193 g_socket_close(priv->sock, NULL);
5194 }
5195
5196
5197 /**
5198 * vnc_connection_is_open:
5199 * @conn: (transfer none): the connection object
5200 *
5201 * Check if the connection is currently open
5202 *
5203 * Returns: TRUE if open, FALSE if closing/closed
5204 */
vnc_connection_is_open(VncConnection * conn)5205 gboolean vnc_connection_is_open(VncConnection *conn)
5206 {
5207 VncConnectionPrivate *priv = conn->priv;
5208
5209 if (priv->fd != -1)
5210 return TRUE;
5211 if (priv->sock != NULL)
5212 return TRUE;
5213 if (priv->host)
5214 return TRUE;
5215 if (priv->addr)
5216 return TRUE;
5217 return FALSE;
5218 }
5219
5220
5221 /**
5222 * vnc_connection_is_initialized:
5223 * @conn: (transfer none): the connection object
5224 *
5225 * Determine if the connection to the remote desktop is
5226 * fully initialized and thus receiving framebuffer
5227 * updates.
5228 *
5229 * Returns: TRUE if initialized, FALSE if closed or still negotiating
5230 */
vnc_connection_is_initialized(VncConnection * conn)5231 gboolean vnc_connection_is_initialized(VncConnection *conn)
5232 {
5233 VncConnectionPrivate *priv = conn->priv;
5234
5235 if (!vnc_connection_is_open(conn))
5236 return FALSE;
5237 if (priv->name)
5238 return TRUE;
5239 return FALSE;
5240 }
5241
5242
vnc_connection_before_version(VncConnection * conn,int major,int minor)5243 static gboolean vnc_connection_before_version (VncConnection *conn, int major, int minor)
5244 {
5245 VncConnectionPrivate *priv = conn->priv;
5246
5247 return (priv->major < major) || (priv->major == major && priv->minor < minor);
5248 }
5249
5250
vnc_connection_after_version(VncConnection * conn,int major,int minor)5251 static gboolean vnc_connection_after_version (VncConnection *conn, int major, int minor)
5252 {
5253 return !vnc_connection_before_version (conn, major, minor+1);
5254 }
5255
5256
vnc_connection_initialize(VncConnection * conn)5257 static gboolean vnc_connection_initialize(VncConnection *conn)
5258 {
5259 VncConnectionPrivate *priv = conn->priv;
5260 int ret, i, want;
5261 char version[13];
5262 guint32 n_name;
5263 gboolean partialGreeting = FALSE;
5264 guint timeout;
5265
5266 priv->absPointer = TRUE;
5267
5268 timeout = g_timeout_add_seconds(2, vnc_connection_timeout, &priv->wait);
5269 want = 12;
5270 while (want > 0) {
5271 priv->wait_interruptable = 1;
5272 ret = vnc_connection_read(conn, version + (12 - want), want);
5273 priv->wait_interruptable = 0;
5274 if (vnc_connection_has_error(conn)) {
5275 VNC_DEBUG("Error while reading server version");
5276 goto fail;
5277 }
5278 if (ret >= 0) {
5279 want -= ret;
5280 if (ret != 12) {
5281 timeout = 0;
5282 }
5283 } else {
5284 if (ret == -EAGAIN) {
5285 /*
5286 * We didn't see any RFB greeting before our
5287 * timeout. We might have mistakenly connected
5288 * to a SPICE server, in which case we might
5289 * wait forever, since SPICE expects the client
5290 * to send first.
5291 *
5292 * We'll proactively send the 'RFB ' bytes to the
5293 * sever. If we've just got a slow VNC server, it'll
5294 * be harmless, but if we've got a SPICE server, this
5295 * should trigger it to close the connection, avoiding
5296 * us waiting foever.
5297 *
5298 * NB, while we could just send the "RFB " bytes
5299 * immediately, the libvncserver code does something
5300 * really crazy. When it sees a client connection, it
5301 * waits 100ms for an HTTP GET request to indicate
5302 * use of websockets proxy. If it sees the RFB bytes
5303 * it doesn't run a normal VNC connection, it just kills
5304 * the connection :-(
5305 */
5306 VNC_DEBUG("No server greeting, sending partial client greeting");
5307 vnc_connection_write(conn, "RFB ", 4);
5308 vnc_connection_flush(conn);
5309 partialGreeting = TRUE;
5310 timeout = 0;
5311 } else {
5312 VNC_DEBUG("Unexpected read error during greeting");
5313 goto fail;
5314 }
5315 }
5316 }
5317
5318 if (timeout != 0) {
5319 g_source_remove(timeout);
5320 }
5321
5322 version[12] = 0;
5323
5324 ret = sscanf(version, "RFB %03d.%03d\n", &priv->major, &priv->minor);
5325 if (ret != 2) {
5326 vnc_connection_set_error(conn, "%s",
5327 "Error while parsing server version");
5328 goto fail;
5329 }
5330
5331 VNC_DEBUG("Server version: %d.%d", priv->major, priv->minor);
5332
5333 if (vnc_connection_before_version(conn, 3, 3)) {
5334 vnc_connection_set_error(conn,
5335 "Server version is not supported (%d.%d)", priv->major, priv->minor);
5336 goto fail;
5337 } else if (vnc_connection_before_version(conn, 3, 7)) {
5338 priv->minor = 3;
5339 } else if (vnc_connection_after_version(conn, 3, 8)) {
5340 priv->major = 3;
5341 priv->minor = 8;
5342 }
5343
5344 if (partialGreeting) {
5345 VNC_DEBUG("Sending rest of greeting");
5346 snprintf(version, 13, "%03d.%03d\n", priv->major, priv->minor);
5347 want = 8;
5348 } else {
5349 VNC_DEBUG("Sending full greeting");
5350 snprintf(version, 13, "RFB %03d.%03d\n", priv->major, priv->minor);
5351 want = 12;
5352 }
5353 vnc_connection_write(conn, version, want);
5354 vnc_connection_flush(conn);
5355 VNC_DEBUG("Using version: %d.%d", priv->major, priv->minor);
5356
5357 if (!vnc_connection_perform_auth(conn)) {
5358 VNC_DEBUG("Auth failed");
5359 goto fail;
5360 }
5361
5362 vnc_connection_write_u8(conn, priv->sharedFlag);
5363 vnc_connection_flush(conn);
5364 priv->width = vnc_connection_read_u16(conn);
5365 priv->height = vnc_connection_read_u16(conn);
5366
5367 if (vnc_connection_has_error(conn))
5368 return FALSE;
5369
5370 VNC_DEBUG("Initial desktop size %dx%d", priv->width, priv->height);
5371
5372 vnc_connection_read_pixel_format(conn, &priv->fmt);
5373
5374 n_name = vnc_connection_read_u32(conn);
5375 if (n_name > 4096) {
5376 vnc_connection_set_error(conn, "Name length %u too long",
5377 n_name);
5378 goto fail;
5379 }
5380
5381 priv->name = g_new(char, n_name + 1);
5382
5383 vnc_connection_read(conn, priv->name, n_name);
5384 priv->name[n_name] = 0;
5385 VNC_DEBUG("Display name '%s'", priv->name);
5386
5387 if (vnc_connection_has_error(conn))
5388 return FALSE;
5389
5390 memset(&priv->strm, 0, sizeof(priv->strm));
5391 /* FIXME what level? */
5392 for (i = 0; i < 5; i++)
5393 inflateInit(&priv->streams[i]);
5394 priv->strm = NULL;
5395
5396 return !vnc_connection_has_error(conn);
5397
5398 fail:
5399 return !vnc_connection_has_error(conn);
5400 }
5401
5402
vnc_connection_open_fd_internal(VncConnection * conn)5403 static gboolean vnc_connection_open_fd_internal(VncConnection *conn)
5404 {
5405 VncConnectionPrivate *priv = conn->priv;
5406
5407 VNC_DEBUG("Connecting to FD %d", priv->fd);
5408
5409 if (!(priv->sock = g_socket_new_from_fd(priv->fd, NULL))) {
5410 VNC_DEBUG("Failed to open socket from fd %d", priv->fd);
5411 return FALSE;
5412 }
5413
5414 g_socket_set_blocking(priv->sock, FALSE);
5415
5416 return !vnc_connection_has_error(conn);
5417 }
5418
vnc_connection_connect_socket(struct wait_queue * wait,GSocketAddress * sockaddr,GError ** error)5419 static GSocket *vnc_connection_connect_socket(struct wait_queue *wait,
5420 GSocketAddress *sockaddr,
5421 GError **error)
5422 {
5423 GSocket *sock = g_socket_new(g_socket_address_get_family(sockaddr),
5424 G_SOCKET_TYPE_STREAM,
5425 G_SOCKET_PROTOCOL_DEFAULT,
5426 error);
5427
5428 if (!sock)
5429 return NULL;
5430
5431 guint timeout = g_timeout_add_seconds(10, vnc_connection_timeout, wait);
5432
5433 g_socket_set_blocking(sock, FALSE);
5434 if (!g_socket_connect(sock, sockaddr, NULL, error)) {
5435 if (*error && (*error)->code == G_IO_ERROR_PENDING) {
5436 g_error_free(*error);
5437 *error = NULL;
5438 VNC_DEBUG("Socket pending");
5439 if (!g_io_wait_interruptable(wait, sock, G_IO_OUT|G_IO_ERR|G_IO_HUP)) {
5440 g_set_error(error, GTK_VNC_ERROR, 0, "%s", "Connection timed out");
5441 VNC_DEBUG("connect interrupted");
5442 timeout = 0;
5443 goto timeout;
5444 }
5445
5446 if (!g_socket_check_connect_result(sock, error))
5447 goto error;
5448 } else
5449 goto error;
5450 }
5451
5452 VNC_DEBUG("Finally connected");
5453 goto end;
5454
5455 error:
5456 VNC_DEBUG("Socket error: %s", *error ? (*error)->message : "unknown");
5457
5458 timeout:
5459 g_object_unref(sock);
5460 sock = NULL;
5461
5462 end:
5463 if (timeout != 0)
5464 g_source_remove(timeout);
5465
5466 return sock;
5467 }
5468
vnc_connection_open_addr_internal(VncConnection * conn)5469 static gboolean vnc_connection_open_addr_internal(VncConnection *conn)
5470 {
5471 VncConnectionPrivate *priv = conn->priv;
5472 GError *conn_error = NULL;
5473 GSocket *sock = NULL;
5474
5475 VNC_DEBUG("Connecting with addr %p", priv->addr);
5476
5477 sock = vnc_connection_connect_socket(&priv->wait, priv->addr, &conn_error);
5478 if (sock) {
5479 priv->sock = sock;
5480 return TRUE;
5481 }
5482 vnc_connection_set_error(conn, "Unable to connect: %s",
5483 conn_error ? conn_error->message : "Unknown problem");
5484 g_clear_error(&conn_error);
5485 return FALSE;
5486 }
5487
5488
vnc_connection_open_host_internal(VncConnection * conn)5489 static gboolean vnc_connection_open_host_internal(VncConnection *conn)
5490 {
5491 VncConnectionPrivate *priv = conn->priv;
5492 GSocketConnectable *addr;
5493 GSocketAddressEnumerator *enumerator;
5494 GSocketAddress *sockaddr;
5495 GError *conn_error = NULL;
5496 GSocket *sock = NULL;
5497 int port = atoi(priv->port);
5498
5499 VNC_DEBUG("Resolving host %s %s", priv->host, priv->port);
5500
5501 g_return_val_if_fail((priv->host != NULL) && (port != 0), FALSE);
5502
5503 addr = g_network_address_new(priv->host, port);
5504
5505 enumerator = g_socket_connectable_enumerate (addr);
5506 g_object_unref (addr);
5507
5508 /* Try each sockaddr until we succeed. Record the first
5509 * connection error, but not any further ones (since they'll probably
5510 * be basically the same as the first).
5511 */
5512 while (!sock &&
5513 (sockaddr = g_socket_address_enumerator_next(enumerator, NULL, &conn_error))) {
5514 VNC_DEBUG("Trying one socket");
5515 g_clear_error(&conn_error);
5516 sock = vnc_connection_connect_socket(&priv->wait, sockaddr, &conn_error);
5517 g_object_unref(sockaddr);
5518 }
5519 g_object_unref(enumerator);
5520 if (!sock) {
5521 vnc_connection_set_error(conn, "Unable to connect to %s:%s: %s",
5522 priv->host, priv->port,
5523 conn_error ? conn_error->message : "Unknown problem");
5524 }
5525 g_clear_error(&conn_error);
5526 if (sock) {
5527 priv->sock = sock;
5528 return TRUE;
5529 }
5530 return FALSE;
5531 }
5532
5533
5534 /* we use an idle function to allow the coroutine to exit before we actually
5535 * unref the object since the coroutine's state is part of the object */
vnc_connection_delayed_unref(gpointer data)5536 static gboolean vnc_connection_delayed_unref(gpointer data)
5537 {
5538 VncConnection *conn = VNC_CONNECTION(data);
5539 VncConnectionPrivate *priv = conn->priv;
5540
5541 VNC_DEBUG("Delayed unref VncConnection=%p", conn);
5542
5543 g_assert(priv->coroutine.exited == TRUE);
5544
5545 g_object_unref(G_OBJECT(data));
5546
5547 return FALSE;
5548 }
5549
vnc_connection_coroutine(void * opaque)5550 static void *vnc_connection_coroutine(void *opaque)
5551 {
5552 VncConnection *conn = VNC_CONNECTION(opaque);
5553 VncConnectionPrivate *priv = conn->priv;
5554 int ret;
5555 struct signal_data s;
5556
5557 VNC_DEBUG("Started background coroutine");
5558
5559 if (priv->fd != -1) {
5560 if (!vnc_connection_open_fd_internal(conn))
5561 goto cleanup;
5562 } else if (priv->addr != NULL) {
5563 if (!vnc_connection_open_addr_internal(conn))
5564 goto cleanup;
5565 } else {
5566 if (!vnc_connection_open_host_internal(conn))
5567 goto cleanup;
5568 }
5569
5570 vnc_connection_emit_main_context(conn, VNC_CONNECTED, &s);
5571
5572 VNC_DEBUG("Protocol initialization");
5573 if (!vnc_connection_initialize(conn))
5574 goto cleanup;
5575
5576 vnc_connection_emit_main_context(conn, VNC_INITIALIZED, &s);
5577
5578 VNC_DEBUG("Running main loop");
5579 while ((ret = vnc_connection_server_message(conn)))
5580 ;
5581
5582 cleanup:
5583 VNC_DEBUG("Doing final VNC cleanup");
5584 vnc_connection_close(conn);
5585 vnc_connection_emit_main_context(conn, VNC_DISCONNECTED, &s);
5586 g_idle_add(vnc_connection_delayed_unref, conn);
5587 /* Co-routine exits now - the VncDisplay object may no longer exist,
5588 so don't do anything else now unless you like SEGVs */
5589 return NULL;
5590 }
5591
do_vnc_connection_open(gpointer data)5592 static gboolean do_vnc_connection_open(gpointer data)
5593 {
5594 VncConnection *conn = VNC_CONNECTION(data);
5595 VncConnectionPrivate *priv = conn->priv;
5596 struct coroutine *co;
5597
5598 VNC_DEBUG("Open coroutine starting");
5599 priv->open_id = 0;
5600
5601 co = &priv->coroutine;
5602
5603 co->stack_size = 16 << 20;
5604 co->entry = vnc_connection_coroutine;
5605 co->release = NULL;
5606
5607 coroutine_init(co);
5608 coroutine_yieldto(co, conn);
5609
5610 return FALSE;
5611 }
5612
5613
5614 /**
5615 * vnc_connection_open_fd:
5616 * @conn: (transfer none): the connection object
5617 * @fd: file descriptor to use for the connection
5618 *
5619 * Open a connection using @fd as the transport. If @fd
5620 * refers to a TCP connection, it is recommended to use
5621 * vnc_connection_open_fd_with_hostname instead, to
5622 * provide the remote hostname. This allows use of
5623 * x509 based authentication which requires a hostname
5624 * to be available.
5625 *
5626 * Returns: TRUE if a connection was opened, FALSE if already open
5627 */
vnc_connection_open_fd(VncConnection * conn,int fd)5628 gboolean vnc_connection_open_fd(VncConnection *conn, int fd)
5629 {
5630 return vnc_connection_open_fd_with_hostname(conn, fd, NULL);
5631 }
5632
5633
5634 /**
5635 * vnc_connection_open_fd_with_hostname:
5636 * @conn: (transfer none): the connection object
5637 * @fd: file descriptor to use for the connection
5638 * @hostname: (transfer none)(nullable): the host associated with the connection
5639 *
5640 * Open a connection using @fd as the transport. The
5641 * @hostname provided should reflect the name of the
5642 * host that the @fd provides a connection to. This
5643 * will be used by some authentication schemes, for
5644 * example x509 certificate validation against @hostname.
5645 *
5646 * Returns: TRUE if a connection was opened, FALSE if already open
5647 */
vnc_connection_open_fd_with_hostname(VncConnection * conn,int fd,const char * hostname)5648 gboolean vnc_connection_open_fd_with_hostname(VncConnection *conn, int fd, const char *hostname)
5649 {
5650 VncConnectionPrivate *priv = conn->priv;
5651
5652 VNC_DEBUG("Open fd=%d", fd);
5653
5654 if (vnc_connection_is_open(conn))
5655 return FALSE;
5656
5657 priv->fd = fd;
5658 priv->addr = NULL;
5659 priv->host = g_strdup(hostname ? hostname : "localhost");
5660 priv->port = g_strdup("");
5661
5662 g_object_ref(G_OBJECT(conn)); /* Unref'd when co-routine exits */
5663 priv->open_id = g_idle_add(do_vnc_connection_open, conn);
5664
5665 return TRUE;
5666 }
5667
5668
5669 /**
5670 * vnc_connection_open_host:
5671 * @conn: (transfer none): the connection object
5672 * @host: (transfer none): the host name or IP address
5673 * @port: (transfer none): the service name or port number
5674 *
5675 * Open a TCP connection to the remote desktop at @host
5676 * listening on @port.
5677 *
5678 * Returns: TRUE if a connection was opened, FALSE if already open
5679 */
vnc_connection_open_host(VncConnection * conn,const char * host,const char * port)5680 gboolean vnc_connection_open_host(VncConnection *conn, const char *host, const char *port)
5681 {
5682 VncConnectionPrivate *priv = conn->priv;
5683
5684 VNC_DEBUG("Open host=%s port=%s", host, port);
5685
5686 if (vnc_connection_is_open(conn))
5687 return FALSE;
5688
5689 priv->fd = -1;
5690 priv->addr = NULL;
5691 priv->host = g_strdup(host);
5692 priv->port = g_strdup(port);
5693
5694 g_object_ref(G_OBJECT(conn)); /* Unref'd when co-routine exits */
5695 priv->open_id = g_idle_add(do_vnc_connection_open, conn);
5696
5697 return TRUE;
5698 }
5699
5700
5701 /**
5702 * vnc_connection_open_addr:
5703 * @conn: (transfer none): the connection object
5704 * @addr: (transfer none): the socket address
5705 * @hostname: (transfer none)(nullable): the hostname
5706 *
5707 * Open a socket connection to server identified by @addr.
5708 * @addr may refer to either a TCP address (IPv4/6) or
5709 * a UNIX socket address. The @hostname provided should
5710 * reflect the name of the host that the @addr provides a
5711 * connection to, if it is not already available in @addr.
5712 * For example, if @addr points to a proxy server, then
5713 * @hostname can be used to provide the name of the final
5714 * endpoint. This will be used by some authentication
5715 * schemes, for example x509 certificate validation
5716 * against @hostname.
5717 *
5718 * Returns: TRUE if a connection was opened, FALSE if already open
5719 */
vnc_connection_open_addr(VncConnection * conn,GSocketAddress * addr,const char * hostname)5720 gboolean vnc_connection_open_addr(VncConnection *conn, GSocketAddress *addr, const char *hostname)
5721 {
5722 VncConnectionPrivate *priv = conn->priv;
5723
5724 VNC_DEBUG("Open addr=%p", addr);
5725
5726 if (vnc_connection_is_open(conn))
5727 return FALSE;
5728
5729 priv->fd = -1;
5730 priv->addr = g_object_ref(addr);
5731
5732 priv->host = g_strdup(hostname ? hostname : "localhost");
5733 if (G_IS_INET_SOCKET_ADDRESS(addr)) {
5734 guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(addr));
5735 priv->port = g_strdup_printf("%d", (int)port);
5736 } else {
5737 priv->port = g_strdup("");
5738 }
5739
5740 g_object_ref(G_OBJECT(conn)); /* Unref'd when co-routine exits */
5741 priv->open_id = g_idle_add(do_vnc_connection_open, conn);
5742
5743 return TRUE;
5744 }
5745
5746
5747 /**
5748 * vnc_connection_set_auth_type:
5749 * @conn: (transfer none): the connection object
5750 * @type: the requested auth type
5751 *
5752 * Set the authentication type to use to complete the
5753 * connection.
5754 *
5755 * Returns: TRUE if the connection is ok, FALSE if it has an error
5756 */
vnc_connection_set_auth_type(VncConnection * conn,unsigned int type)5757 gboolean vnc_connection_set_auth_type(VncConnection *conn, unsigned int type)
5758 {
5759 VncConnectionPrivate *priv = conn->priv;
5760
5761 VNC_DEBUG("Thinking about auth type %u", type);
5762 if (priv->auth_type != VNC_CONNECTION_AUTH_INVALID) {
5763 vnc_connection_set_error(conn, "%s", "Auth type has already been set");
5764 return !vnc_connection_has_error(conn);
5765 }
5766 if (type != VNC_CONNECTION_AUTH_NONE &&
5767 type != VNC_CONNECTION_AUTH_VNC &&
5768 type != VNC_CONNECTION_AUTH_MSLOGON &&
5769 type != VNC_CONNECTION_AUTH_ARD &&
5770 type != VNC_CONNECTION_AUTH_TLS &&
5771 type != VNC_CONNECTION_AUTH_VENCRYPT &&
5772 type != VNC_CONNECTION_AUTH_SASL) {
5773 vnc_connection_set_error(conn, "Auth type %u is not supported",
5774 type);
5775 g_signal_emit(conn, VNC_AUTH_UNSUPPORTED, 0, type);
5776 return !vnc_connection_has_error(conn);
5777 }
5778 VNC_DEBUG("Decided on auth type %u", type);
5779 priv->auth_type = type;
5780 priv->auth_subtype = VNC_CONNECTION_AUTH_INVALID;
5781
5782 return !vnc_connection_has_error(conn);
5783 }
5784
5785
5786 /**
5787 * vnc_connection_set_auth_subtype:
5788 * @conn: (transfer none): the connection object
5789 * @type: the auth sub-type
5790 *
5791 * If a multi-level authentication scheme was requested, this
5792 * identifies which auth type to use for the second phase.
5793 *
5794 * Returns: TRUE if the connection is ok, FALSE if it has an error
5795 */
vnc_connection_set_auth_subtype(VncConnection * conn,unsigned int type)5796 gboolean vnc_connection_set_auth_subtype(VncConnection *conn, unsigned int type)
5797 {
5798 VncConnectionPrivate *priv = conn->priv;
5799
5800 VNC_DEBUG("Requested auth subtype %u", type);
5801 if (priv->auth_type != VNC_CONNECTION_AUTH_VENCRYPT &&
5802 priv->auth_type != VNC_CONNECTION_AUTH_TLS) {
5803 vnc_connection_set_error(conn, "Auth type %u does not support subauth",
5804 priv->auth_type);
5805 return !vnc_connection_has_error(conn);
5806 }
5807 if (priv->auth_subtype != VNC_CONNECTION_AUTH_INVALID) {
5808 vnc_connection_set_error(conn, "%s", "Auth subtype has already been set");
5809 return !vnc_connection_has_error(conn);
5810 }
5811 priv->auth_subtype = type;
5812
5813 return !vnc_connection_has_error(conn);
5814 }
5815
5816
vnc_connection_best_path(char ** buf,const char * basedir,const char * basefile,char ** dirs,unsigned int ndirs)5817 static int vnc_connection_best_path(char **buf,
5818 const char *basedir,
5819 const char *basefile,
5820 char **dirs,
5821 unsigned int ndirs)
5822 {
5823 unsigned int i;
5824 gchar *tmp;
5825 for (i = 0 ; i < ndirs ; i++) {
5826 struct stat sb;
5827 tmp = g_strdup_printf("%s/%s/%s", dirs[i], basedir, basefile);
5828 if (stat(tmp, &sb) == 0) {
5829 *buf = tmp;
5830 return 0;
5831 }
5832 g_free(tmp);
5833 }
5834 VNC_DEBUG("Failed to find certificate %s/%s", basedir, basefile);
5835 return -1;
5836 }
5837
5838
5839
vnc_connection_set_credential_x509(VncConnection * conn,const gchar * name)5840 static gboolean vnc_connection_set_credential_x509(VncConnection *conn,
5841 const gchar *name)
5842 {
5843 VncConnectionPrivate *priv = conn->priv;
5844 char *sysdir = g_strdup_printf("%s/pki", SYSCONFDIR);
5845 int ret;
5846 #ifndef WIN32
5847 struct passwd *pw;
5848
5849 if (!(pw = getpwuid(getuid())))
5850 return TRUE;
5851
5852 char *userdir = g_strdup_printf("%s/.pki", pw->pw_dir);
5853 char *dirs[] = { sysdir, userdir };
5854 #else
5855 char *dirs[] = { sysdir };
5856 #endif
5857 for (int i = 0 ; i < sizeof(dirs)/sizeof(dirs[0]) ; i++)
5858 VNC_DEBUG("Searching for certs in %s", dirs[i]);
5859
5860 ret = vnc_connection_best_path(&priv->cred_x509_cacert, "CA", "cacert.pem",
5861 dirs, sizeof(dirs)/sizeof(dirs[0]));
5862 /* With modern GNUTLS we can just allow the global GNUTLS trust database
5863 * to be used to validate CA certificates if no specific cert is set
5864 */
5865 if (ret < 0) {
5866 #if GNUTLS_VERSION_NUMBER < 0x030000
5867 VNC_DEBUG("No CA certificate provided and no global fallback");
5868 return FALSE;
5869 #else
5870 VNC_DEBUG("No CA certificate provided, using GNUTLS global trust");
5871 #endif
5872 }
5873
5874 /* Don't mind failures of CRL */
5875 vnc_connection_best_path(&priv->cred_x509_cacrl, "CA", "cacrl.pem",
5876 dirs, sizeof(dirs)/sizeof(dirs[0]));
5877
5878 /* Set client key & cert if we have them. Server will reject auth
5879 * if it decides it requires them*/
5880 vnc_connection_best_path(&priv->cred_x509_key, name, "private/clientkey.pem",
5881 dirs, sizeof(dirs)/sizeof(dirs[0]));
5882 vnc_connection_best_path(&priv->cred_x509_cert, name, "clientcert.pem",
5883 dirs, sizeof(dirs)/sizeof(dirs[0]));
5884
5885 priv->set_cred_x509 = TRUE;
5886
5887 return TRUE;
5888 }
5889
5890
5891 /**
5892 * vnc_connection_set_credential:
5893 * @conn: (transfer none): the connection object
5894 * @type: the authentication credential type
5895 * @data: (transfer none): the value associated with the credential
5896 *
5897 * Sets the value of the authentication credential
5898 * @type to the string @data.
5899 *
5900 * @type is one of the VncConnectionCredential enum vlaues
5901 *
5902 * Returns: TRUE if the connection is ok, FALSE if it has an error
5903 */
vnc_connection_set_credential(VncConnection * conn,int type,const gchar * data)5904 gboolean vnc_connection_set_credential(VncConnection *conn, int type, const gchar *data)
5905 {
5906 VncConnectionPrivate *priv = conn->priv;
5907
5908 VNC_DEBUG("Set credential %d %s", type, data);
5909 switch (type) {
5910 case VNC_CONNECTION_CREDENTIAL_PASSWORD:
5911 g_free(priv->cred_password);
5912 priv->cred_password = g_strdup(data);
5913 break;
5914
5915 case VNC_CONNECTION_CREDENTIAL_USERNAME:
5916 g_free(priv->cred_username);
5917 priv->cred_username = g_strdup(data);
5918 break;
5919
5920 case VNC_CONNECTION_CREDENTIAL_CLIENTNAME:
5921 g_free(priv->cred_x509_cacert);
5922 g_free(priv->cred_x509_cacrl);
5923 g_free(priv->cred_x509_key);
5924 g_free(priv->cred_x509_cert);
5925 return vnc_connection_set_credential_x509(conn, data);
5926
5927 default:
5928 vnc_connection_set_error(conn, "Unknown credential type %d", type);
5929 }
5930
5931 return !vnc_connection_has_error(conn);
5932 }
5933
5934
5935 /**
5936 * vnc_connection_set_framebuffer:
5937 * @conn: (transfer none): the connection object
5938 * @fb: (transfer none): the framebuffer object
5939 *
5940 * Set the framebuffer object to which frame buffer updates
5941 * will be written.
5942 *
5943 * Returns: TRUE if the connection is ok, FALSE if it has an error
5944 */
vnc_connection_set_framebuffer(VncConnection * conn,VncFramebuffer * fb)5945 gboolean vnc_connection_set_framebuffer(VncConnection *conn, VncFramebuffer *fb)
5946 {
5947 VncConnectionPrivate *priv = conn->priv;
5948 const VncPixelFormat *remote;
5949 int i;
5950
5951 VNC_DEBUG("Set framebuffer %p", fb);
5952
5953 if (priv->fb)
5954 g_object_unref(G_OBJECT(priv->fb));
5955 priv->fb = fb;
5956 g_object_ref(G_OBJECT(priv->fb));
5957
5958 remote = vnc_framebuffer_get_remote_format(priv->fb);
5959
5960 priv->fbSwapRemote = remote->byte_order != G_BYTE_ORDER;
5961
5962 i = priv->fmt.bits_per_pixel / 8;
5963
5964 if (i == 4) i = 3;
5965
5966 priv->rich_cursor_blt = vnc_connection_rich_cursor_blt_table[i - 1];
5967 priv->tight_compute_predicted = vnc_connection_tight_compute_predicted_table[i - 1];
5968 priv->tight_sum_pixel = vnc_connection_tight_sum_pixel_table[i - 1];
5969
5970 return !vnc_connection_has_error(conn);
5971 }
5972
5973
5974 /**
5975 * vnc_connection_get_name:
5976 * @conn: (transfer none): the connection object
5977 *
5978 * Get the name of the remote display. A name will only
5979 * be available once the "vnc-initialized" signal has
5980 * been emitted
5981 *
5982 * Returns: (transfer none): the remote display name
5983 */
vnc_connection_get_name(VncConnection * conn)5984 const char *vnc_connection_get_name(VncConnection *conn)
5985 {
5986 VncConnectionPrivate *priv = conn->priv;
5987
5988 return priv->name;
5989 }
5990
5991 /**
5992 * vnc_connection_get_width:
5993 * @conn: (transfer none): the connection object
5994 *
5995 * Get the width of the remote display. The width will
5996 * only be set once the "vnc-initialized" signal has
5997 * been emitted
5998 *
5999 * Returns: the desktop width
6000 */
vnc_connection_get_width(VncConnection * conn)6001 int vnc_connection_get_width(VncConnection *conn)
6002 {
6003 VncConnectionPrivate *priv = conn->priv;
6004
6005 return priv->width;
6006 }
6007
6008 /**
6009 * vnc_connection_get_height:
6010 * @conn: (transfer none): the connection object
6011 *
6012 * Get the height of the remote display. The height will
6013 * only be set once the "vnc-initialized" signal has
6014 * been emitted
6015 *
6016 * Returns: the desktop height
6017 */
vnc_connection_get_height(VncConnection * conn)6018 int vnc_connection_get_height(VncConnection *conn)
6019 {
6020 VncConnectionPrivate *priv = conn->priv;
6021
6022 return priv->height;
6023 }
6024
6025 /**
6026 * vnc_connection_get_ext_key_event:
6027 * @conn: (transfer none): the connection object
6028 *
6029 * Determine if the remote server supports the extended
6030 * keyboard event which transmits raw XT scancodes.
6031 * This will only be valid once the "vnc-initialized"
6032 * signal has been emitted
6033 *
6034 * Returns: TRUE if supported, FALSE otherwise
6035 */
vnc_connection_get_ext_key_event(VncConnection * conn)6036 gboolean vnc_connection_get_ext_key_event(VncConnection *conn)
6037 {
6038 VncConnectionPrivate *priv = conn->priv;
6039
6040 return priv->has_ext_key_event;
6041 }
6042
6043
6044 /**
6045 * vnc_connection_get_cursor:
6046 * @conn: the VNC connection
6047 *
6048 * Get the cursor currently associated with the desktop,
6049 * if any.
6050 *
6051 * Returns: (transfer none): the cursor or NULL
6052 */
vnc_connection_get_cursor(VncConnection * conn)6053 VncCursor *vnc_connection_get_cursor(VncConnection *conn)
6054 {
6055 VncConnectionPrivate *priv = conn->priv;
6056
6057 return priv->cursor;
6058 }
6059
6060
6061 /**
6062 * vnc_connection_get_abs_pointer:
6063 * @conn: (transfer none): the connection object
6064 *
6065 * Determine if the remote server supports absolute pointer
6066 * motion events. This will only be valid once the
6067 * "vnc-initialized" signal has been emitted.
6068 *
6069 * Returns: TRUE if the server supports absolute pointer mode
6070 */
vnc_connection_get_abs_pointer(VncConnection * conn)6071 gboolean vnc_connection_get_abs_pointer(VncConnection *conn)
6072 {
6073 VncConnectionPrivate *priv = conn->priv;
6074
6075 return priv->absPointer;
6076 }
6077
6078 /**
6079 * vnc_connection_get_ledstate:
6080 * @conn: (transfer none): the connection object
6081 *
6082 * Get the current LED state bitmap. This is only
6083 * valid once the "vnc-initialized" signal has been
6084 * emitted.
6085 *
6086 * Returns: the LED state
6087 */
vnc_connection_get_ledstate(VncConnection * conn)6088 int vnc_connection_get_ledstate(VncConnection *conn)
6089 {
6090 VncConnectionPrivate *priv = conn->priv;
6091
6092 return priv->ledstate;
6093 }
6094
6095 /*
6096 * Local variables:
6097 * c-indent-level: 4
6098 * c-basic-offset: 4
6099 * indent-tabs-mode: nil
6100 * End:
6101 */
6102