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