Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package gtk-vnc for openSUSE:Factory checked in at 2021-11-24 23:54:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gtk-vnc (Old) and /work/SRC/openSUSE:Factory/.gtk-vnc.new.1895 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gtk-vnc" Wed Nov 24 23:54:14 2021 rev:55 rq:933065 version:1.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/gtk-vnc/gtk-vnc.changes 2021-04-24 23:07:02.315215396 +0200 +++ /work/SRC/openSUSE:Factory/.gtk-vnc.new.1895/gtk-vnc.changes 2021-11-24 23:54:23.536495181 +0100 @@ -1,0 +2,15 @@ +Wed Nov 17 11:39:16 UTC 2021 - Bj??rn Lie <bjorn....@gmail.com> + +- Update to version 1.3.0: + + Add API to request screen rotation. + + Automatically pick gthread coroutine if ucontext is not + available. + + Fix meson logic bug when disabling vala. + + Honour choice of python when generating keymaps. + + Fix error reporting and memory leaks encrypting auth data. + + Fix missing includes for GDK quartz and broadway backends. + + Switch to GNUTLS for VNC auth challenge to fix empty password + handling. + + Fix handling of auth subtypes in gvnccapture program. + +------------------------------------------------------------------- Old: ---- gtk-vnc-1.2.0.tar.xz New: ---- gtk-vnc-1.3.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gtk-vnc.spec ++++++ --- /var/tmp/diff_new_pack.KKmN6H/_old 2021-11-24 23:54:23.972493718 +0100 +++ /var/tmp/diff_new_pack.KKmN6H/_new 2021-11-24 23:54:23.976493704 +0100 @@ -21,13 +21,13 @@ %define _sonamepkg 2_0 Name: gtk-vnc -Version: 1.2.0 +Version: 1.3.0 Release: 0 Summary: A GTK widget for VNC clients License: LGPL-2.1-only AND LGPL-2.1-or-later Group: Development/Libraries/X11 URL: https://wiki.gnome.org/Projects/gtk-vnc -Source0: https://download.gnome.org/sources/gtk-vnc/1.2/%{name}-%{version}.tar.xz +Source0: https://download.gnome.org/sources/gtk-vnc/1.3/%{name}-%{version}.tar.xz BuildRequires: cyrus-sasl-devel BuildRequires: gobject-introspection-devel >= 0.9.4 ++++++ gtk-vnc-1.2.0.tar.xz -> gtk-vnc-1.3.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/AUTHORS new/gtk-vnc-1.3.0/AUTHORS --- old/gtk-vnc-1.2.0/AUTHORS 2021-04-14 11:47:12.927097600 +0200 +++ new/gtk-vnc-1.3.0/AUTHORS 2021-11-17 11:24:01.254825400 +0100 @@ -84,6 +84,7 @@ Marton Balint <c...@fazekas.hu> Mart Raudsepp <l...@gentoo.org> Matej Urban??i?? <mat...@svn.gnome.org> +Matt Turner <matts...@gmail.com> Michael Ram??rez <radical_mich...@hotmail.com> Michal Novotny <minov...@redhat.com> Michal Suchanek <hramr...@centrum.cz> @@ -115,6 +116,7 @@ Stefano Stabellini <stefano.stabell...@eu.citrix.com> Steven Carr <steven.c...@scaa-usa.com> Takeshi AIHANA <takeshi.aih...@gmail.com> +Thomas Loimer <thomas.loi...@tuwien.ac.at> Tom Schoonjans <tom.schoonj...@diamond.ac.uk> Victor Ibragimov <victor.ibragi...@gmail.com> Victor Toso <m...@victortoso.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/ChangeLog new/gtk-vnc-1.3.0/ChangeLog --- old/gtk-vnc-1.2.0/ChangeLog 2021-04-14 11:47:12.916097600 +0200 +++ new/gtk-vnc-1.3.0/ChangeLog 2021-11-17 11:24:01.237825400 +0100 @@ -1,3 +1,112 @@ +2021-11-17 Daniel P. Berrang?? <berra...@redhat.com> + + Bump version to 1.3.0 and add release notes + + The vala-tools package was dropped long ago + It has only existed as a virtual Provides line since Fedora 25 + +2021-11-15 Daniel P. Berrang?? <berra...@redhat.com> + + Remove bogus newlines from VNC_DEBUG calls + This macro is a wrappar around g_debug and as such doesn't need to add + its own newline, unless trying to break a single message across lines. + +2021-11-12 Daniel P. Berrang?? <berra...@redhat.com> + + tools: fix gvnccapture handling of subauth types + + src: rewrite challenge code to use gnutls + gcrypt refuses to encrypt DES data using an all-zeros key. While this + might seem reasonable, this is the key that you get when someone sets + a zero length password in a VNC server. + + IOW, the gcrypt behaviour prevents gtk-vnc connecting to a server with + zero length password. + + GNUTLS doesn't have this problem but also doesn't support DES-ECB, + so we have to fake it by calling DES-CBC for each block individually. + Conceptually this is horribly inefficient, but since the VNC challenge + is only 16 bytes long it isn't a problem in the real world. + + src: pull challenge encryption out into separate helper method + +2021-05-27 Daniel P. Berrang?? <berra...@redhat.com> + + fix missing includes for quartz and broadway GDK backends + This is another case of the bug fixed in + + commit d2c93a2bc0a9caa73bbebb41333fa7930d4165ab + Author: Daniel P. Berrang?? <d...@berrange.com> + Date: Tue Mar 30 15:00:00 2021 +0100 + + Add missing include of gdkwin32.h + + Closes: https://gitlab.gnome.org/GNOME/gtk-vnc/-/issues/16 + + Remove unused variables + +2021-05-27 Thomas Loimer <thomas.loi...@tuwien.ac.at> + + Add a button to rotate the screen + On each click on the new menu item, the screen is rotated by additional + 90 degrees clockwise. + +2021-05-27 Jakub Jank?? <jja...@redhat.com> + + ard: set connection error + As with vncEncryptBytes2 in the earlier patch, + the connection error must be set, otherwise the connection + stays in the mainloop, but nothing is happening. + + ard: cleanup properly + With the current code, if one of the gcry functions in + vnc_connection_perform_auth_ard() fails: + * key isn't released + * md5 isn't closed + * mpis and dh aren't released + + vncEncryptBytes2: set connection error and cleanup + If vncEncryptBytes2 fails, the false return value propagates + upwards, but no error is set. The connection ends up stuck in + the mainloop with nothing happening. + + Additionally, the mpis and dh aren't freed. + + To fix that, return the gcry error from vncEncryptBytes2 + and set the connection error accordingly. + + vnc-auth: emit "vnc-auth-failure" for weak key + In vnc_connection_perform_auth_vnc(), if the user enters an empty + password, gcry_cipher_setkey() fails with GPG_ERR_WEAK_KEY. + + In such case, we want to give the useranother chance to reenter + the password, as is the case when the password is incorrect. + + To enable that, the auth-failure signal needs to be emitted. + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1941398 + +2021-05-07 Mart Raudsepp <l...@gentoo.org> + + meson: Find python explicitly to honor downstream python choice + +2021-04-28 Matt Turner <matts...@gmail.com> + + meson: Fix configuration failure with -Dwith-vala=disabled + Otherwise with_vala is not defined, and meson setup results in + + src/meson.build:169:5: ERROR: Unknown variable "with_vala". + +2021-04-26 Jakub Jank?? <jja...@redhat.com> + + build: improve --with-coroutine=auto choice + When the required ucontext functions aren't found, switch to gthread + coroutines instead of failing during the build. + + These functions are absent from the POSIX.1-2008. + + Fixes: https://gitlab.gnome.org/GNOME/gtk-vnc/-/issues/11 + 2021-04-14 Daniel P. Berrang?? <berra...@redhat.com> meson: bump release to 1.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/NEWS new/gtk-vnc-1.3.0/NEWS --- old/gtk-vnc-1.2.0/NEWS 2021-04-14 11:47:11.076112000 +0200 +++ new/gtk-vnc-1.3.0/NEWS 2021-11-17 11:23:59.967830400 +0100 @@ -1,6 +1,18 @@ GTK VNC News ============ +Nov 16, 2021: Release 1.3.0 +=========================== + + o Add API to request screen rotation + o Automatically pick gthread coroutine if ucontext is not available + o Fix meson logic bug when disabling vala + o Honour choice of python when generating keymaps + o Fix error reporting and memory leaks encrypting auth data + o Fix missing includes for GDK quartz and broadway backends + o Switch to GNUTLS for VNC auth challenge to fix empty password handling + o Fix handling of auth subtypes in gvnccapture program + Apr 14, 2021: Release 1.2.0 =========================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/examples/gvncviewer.c new/gtk-vnc-1.3.0/examples/gvncviewer.c --- old/gtk-vnc-1.2.0/examples/gvncviewer.c 2021-04-14 11:47:11.077112000 +0200 +++ new/gtk-vnc-1.3.0/examples/gvncviewer.c 2021-11-17 11:23:59.968830300 +0100 @@ -423,6 +423,13 @@ vnc_display_set_keep_aspect_ratio(VNC_DISPLAY(vncdisplay), FALSE); } +static void do_rotate(GtkWidget *menu G_GNUC_UNUSED, GtkWidget *vncdisplay) +{ + guint rotation = vnc_display_get_rotation(VNC_DISPLAY(vncdisplay)); + vnc_display_set_rotation(VNC_DISPLAY(vncdisplay), rotation + 90u); +} + + static void do_power_control(VncDisplay *vncdisplay, VncConnectionPowerAction action) { VncConnection *conn = vnc_display_get_connection(vncdisplay); @@ -721,6 +728,7 @@ GtkWidget *smoothing; GtkWidget *keep_aspect_ratio; GtkWidget *resize; + GtkWidget *rotate; GtkWidget *showgrabkeydlg; GtkWidget *shutdown; GtkWidget *reboot; @@ -800,6 +808,7 @@ smoothing = gtk_check_menu_item_new_with_mnemonic("Smooth scaling"); keep_aspect_ratio = gtk_check_menu_item_new_with_mnemonic("Keep aspect ratio"); resize = gtk_check_menu_item_new_with_mnemonic("Allow resizing"); + rotate = gtk_menu_item_new_with_mnemonic("Rotate ???"); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(scaling), TRUE); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(smoothing), TRUE); @@ -809,6 +818,7 @@ gtk_menu_shell_append(GTK_MENU_SHELL(submenu), scaling); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), smoothing); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), keep_aspect_ratio); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), rotate); gtk_menu_shell_append(GTK_MENU_SHELL(submenu), resize); gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), submenu); @@ -892,6 +902,7 @@ vnc_display_set_scaling(VNC_DISPLAY(vnc), TRUE); vnc_display_set_allow_resize(VNC_DISPLAY(vnc), TRUE); + vnc_display_set_rotation(VNC_DISPLAY(vnc), 0u); vnc_display_set_lossy_encoding(VNC_DISPLAY(vnc), TRUE); vnc_display_set_zoom_level(VNC_DISPLAY(vnc), opt_zoom); @@ -963,6 +974,8 @@ G_CALLBACK(do_smoothing), vnc); g_signal_connect(keep_aspect_ratio, "toggled", G_CALLBACK(do_keep_aspect_ratio), vnc); + g_signal_connect(rotate, "activate", + G_CALLBACK(do_rotate), vnc); g_signal_connect(shutdown, "activate", G_CALLBACK(do_shutdown), vnc); g_signal_connect(reboot, "activate", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/gtk-vnc.spec new/gtk-vnc-1.3.0/gtk-vnc.spec --- old/gtk-vnc-1.2.0/gtk-vnc.spec 2021-04-14 11:47:12.917097600 +0200 +++ new/gtk-vnc-1.3.0/gtk-vnc.spec 2021-11-17 11:24:01.238825600 +0100 @@ -8,7 +8,7 @@ Summary: A GTK widget for VNC clients Name: gtk-vnc -Version: 1.2.0 +Version: 1.3.0 Release: 1%{?dist} License: LGPLv2+ Source: https://download.gnome.org/sources/%{name}/%{verdir}/%{name}-%{version}.tar.xz @@ -18,7 +18,7 @@ BuildRequires: gnutls-devel libgcrypt-devel cyrus-sasl-devel zlib-devel BuildRequires: gobject-introspection-devel BuildRequires: gtk3-devel -BuildRequires: vala-tools +BuildRequires: vala BuildRequires: pulseaudio-libs-devel BuildRequires: /usr/bin/pod2man BuildRequires: meson diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/gtk-vnc.spec.in new/gtk-vnc-1.3.0/gtk-vnc.spec.in --- old/gtk-vnc-1.2.0/gtk-vnc.spec.in 2021-04-14 11:47:11.077112000 +0200 +++ new/gtk-vnc-1.3.0/gtk-vnc.spec.in 2021-11-17 11:23:59.969830300 +0100 @@ -18,7 +18,7 @@ BuildRequires: gnutls-devel libgcrypt-devel cyrus-sasl-devel zlib-devel BuildRequires: gobject-introspection-devel BuildRequires: gtk3-devel -BuildRequires: vala-tools +BuildRequires: vala BuildRequires: pulseaudio-libs-devel BuildRequires: /usr/bin/pod2man BuildRequires: meson diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/meson.build new/gtk-vnc-1.3.0/meson.build --- old/gtk-vnc-1.2.0/meson.build 2021-04-14 11:47:11.077112000 +0200 +++ new/gtk-vnc-1.3.0/meson.build 2021-11-17 11:23:59.969830300 +0100 @@ -1,6 +1,6 @@ project( 'gtk-vnc','c', - version: '1.2.0', + version: '1.3.0', license: 'LGPLv2.1+', default_options: [ 'buildtype=debugoptimized', @@ -43,8 +43,20 @@ coroutine = get_option('with-coroutine') +uctx_args = [] +if host_machine.system() == 'darwin' + uctx_args += ['-D_XOPEN_SOURCE=600'] +endif +has_ucontext = true +foreach uctx_func : ['makecontext', 'swapcontext', 'getcontext'] + if not cc.has_function(uctx_func, prefix: '#include <ucontext.h>', args: uctx_args) + has_ucontext = false + break + endif +endforeach + if coroutine == 'auto' - if host_machine.system() == 'windows' + if host_machine.system() == 'windows' or not has_ucontext coroutine = 'gthread' else coroutine = 'ucontext' @@ -52,6 +64,9 @@ endif if coroutine == 'ucontext' + if not has_ucontext + error('ucontext requested, but not available') + endif conf_data.set('WITH_UCONTEXT', true) elif coroutine != 'gthread' error('Unknown coroutine backend') @@ -303,12 +318,11 @@ with_gir = gir.found() vala_opt = get_option('with-vala') +with_vala = false if not vala_opt.disabled() if not with_gir if vala_opt.enabled() error('Vala API requires GObject introspection (-Dintrospection=true)') - else - with_vala = false endif else with_vala = add_languages('vala', required: vala_opt) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/libgtk-vnc_sym.version new/gtk-vnc-1.3.0/src/libgtk-vnc_sym.version --- old/gtk-vnc-1.2.0/src/libgtk-vnc_sym.version 2021-04-14 11:47:11.080112000 +0200 +++ new/gtk-vnc-1.3.0/src/libgtk-vnc_sym.version 2021-11-17 11:23:59.972830300 +0100 @@ -100,6 +100,9 @@ vnc_display_get_zoom_level; vnc_display_set_zoom_level; + vnc_display_get_rotation; + vnc_display_set_rotation; + local: *; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/meson.build new/gtk-vnc-1.3.0/src/meson.build --- old/gtk-vnc-1.2.0/src/meson.build 2021-04-14 11:47:11.080112000 +0200 +++ new/gtk-vnc-1.3.0/src/meson.build 2021-11-17 11:23:59.972830300 +0100 @@ -319,7 +319,7 @@ 'vncdisplaykeymap.c', ] -python = import('python').find_installation() +python = import('python').find_installation('python3') keymaps = [ 'xorgevdev', 'xorgkbd', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncconnection.c new/gtk-vnc-1.3.0/src/vncconnection.c --- old/gtk-vnc-1.2.0/src/vncconnection.c 2021-04-14 11:47:11.081112000 +0200 +++ new/gtk-vnc-1.3.0/src/vncconnection.c 2021-11-17 11:23:59.974830400 +0100 @@ -1487,7 +1487,7 @@ priv->ledstate = vnc_connection_read_u8(conn); - VNC_DEBUG("LED state: %d\n", priv->ledstate); + VNC_DEBUG("LED state: %d", priv->ledstate); sigdata.params.ledstate = priv->ledstate; vnc_connection_emit_main_context(conn, VNC_LED_STATE, &sigdata); @@ -3472,7 +3472,7 @@ if (!priv->audio_sample) return FALSE; - VNC_DEBUG("Audio tick %u\n", priv->audio_sample->length); + VNC_DEBUG("Audio tick %u", priv->audio_sample->length); if (priv->audio) vnc_audio_playback_data(priv->audio, priv->audio_sample); @@ -3528,7 +3528,7 @@ action, }; - VNC_DEBUG("Emit audio action %d\n", action); + VNC_DEBUG("Emit audio action %d", action); g_idle_add(do_vnc_connection_audio_action, &data); @@ -3898,14 +3898,52 @@ } } + +static gboolean vnc_connection_encrypt_challenge(VncConnection *conn, + guint8 *challenge, + guint8 *key) +{ + int error; + size_t i; + unsigned char iv[8] = {}; + + vnc_munge_des_key(key, key); + + for (i = 0; i < 16; i += 8) { + gnutls_cipher_hd_t handle; + gnutls_datum_t gkey = { (unsigned char *)key, 8 }; + error = gnutls_cipher_init(&handle, + GNUTLS_CIPHER_DES_CBC, + &gkey, NULL); + if (error != 0) + goto error; + + gnutls_cipher_set_iv(handle, iv, sizeof(iv)); + + error = gnutls_cipher_encrypt2(handle, + challenge + i, 8, + challenge + i, 8); + if (error != 0) { + gnutls_cipher_deinit(handle); + goto error; + } + gnutls_cipher_deinit(handle); + } + + return TRUE; + + error: + vnc_connection_set_error(conn, "Unknown authentication failure: %s", + gnutls_strerror(error)); + return FALSE; +} + static gboolean vnc_connection_perform_auth_vnc(VncConnection *conn) { VncConnectionPrivate *priv = conn->priv; guint8 challenge[16]; guint8 key[8]; gsize keylen; - gcry_cipher_hd_t c; - gcry_error_t error; VNC_DEBUG("Do Challenge"); priv->want_cred_password = TRUE; @@ -3925,43 +3963,12 @@ keylen = sizeof(key); memcpy(key, priv->cred_password, keylen); - vnc_munge_des_key(key, key); - - error = gcry_cipher_open(&c, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); - if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error)); - goto error; - } - - error = gcry_cipher_setkey(c, key, 8); - if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error)); - gcry_cipher_close(c); - goto error; - } - - error = gcry_cipher_encrypt(c, challenge, 8, challenge, 8); - if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error)); - gcry_cipher_close(c); - goto error; - } - error = gcry_cipher_encrypt(c, challenge + 8, 8, challenge + 8, 8); - if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error)); - gcry_cipher_close(c); - goto error; - } - gcry_cipher_close(c); + if (!vnc_connection_encrypt_challenge(conn, challenge, key)) + return FALSE; vnc_connection_write(conn, challenge, 16); vnc_connection_flush(conn); return vnc_connection_check_auth_result(conn); - -error: - vnc_connection_set_error(conn, "Unknown authentication failure: %s", - gcry_strerror(error)); - return FALSE; } static gboolean vnc_connection_perform_auth_plain(VncConnection *conn) @@ -3992,12 +3999,11 @@ * Encrypt bytes[length] in memory using key. * Key has to be 8 bytes, length a multiple of 8 bytes. */ -static gboolean +static gcry_error_t vncEncryptBytes2(unsigned char *where, const int length, unsigned char *key) { gcry_cipher_hd_t c; int i, j; - gboolean ret = FALSE; gcry_error_t error; unsigned char newkey[8]; @@ -4005,13 +4011,13 @@ error = gcry_cipher_open(&c, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error)); - return FALSE; + VNC_DEBUG("gcry_cipher_open error: %s", gcry_strerror(error)); + return error; } error = gcry_cipher_setkey(c, newkey, 8); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error)); + VNC_DEBUG("gcry_cipher_setkey error: %s", gcry_strerror(error)); goto cleanup; } @@ -4020,7 +4026,7 @@ error = gcry_cipher_encrypt(c, where, 8, where, 8); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error)); + VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error)); goto cleanup; } @@ -4030,16 +4036,14 @@ error = gcry_cipher_encrypt(c, where + i, 8, where + i, 8); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error)); + VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error)); goto cleanup; } } - ret = TRUE; - cleanup: gcry_cipher_close(c); - return ret; + return error; } static gboolean vnc_connection_perform_auth_mslogon(VncConnection *conn) @@ -4048,6 +4052,7 @@ struct vnc_dh *dh; guchar gen[8], mod[8], resp[8], pub[8], key[8]; gcry_mpi_t genmpi, modmpi, respmpi, pubmpi, keympi; + gcry_error_t error; guchar username[256], password[64]; guint passwordLen, usernameLen; gboolean allzeroes = TRUE; @@ -4105,20 +4110,28 @@ memcpy(password, priv->cred_password, passwordLen); memcpy(username, priv->cred_username, usernameLen); - if (!vncEncryptBytes2(username, sizeof(username), key)) - return FALSE; - if (!vncEncryptBytes2(password, sizeof(password), key)) - return FALSE; + error = vncEncryptBytes2(username, sizeof(username), key); + if (gcry_err_code(error) != GPG_ERR_NO_ERROR) + goto cleanup; + error = vncEncryptBytes2(password, sizeof(password), key); + if (gcry_err_code(error) != GPG_ERR_NO_ERROR) + goto cleanup; vnc_connection_write(conn, username, sizeof(username)); vnc_connection_write(conn, password, sizeof(password)); vnc_connection_flush(conn); +cleanup: gcry_mpi_release(genmpi); gcry_mpi_release(modmpi); gcry_mpi_release(respmpi); vnc_dh_free (dh); + if (gcry_err_code(error) != GPG_ERR_NO_ERROR) { + vnc_connection_set_error(conn, "Unknown authentication failure: %s", + gcry_strerror(error)); + return FALSE; + } return vnc_connection_check_auth_result(conn); } @@ -4148,30 +4161,14 @@ keylen = 256*len[0] + len[1]; mod = malloc(keylen); - if (mod == NULL) { - VNC_DEBUG("malloc failed\n"); - return FALSE; - } resp = malloc(keylen); - if (resp == NULL) { - free(mod); - VNC_DEBUG("malloc failed\n"); - return FALSE; - } pub = malloc(keylen); - if (pub == NULL) { - free(resp); - free(mod); - VNC_DEBUG("malloc failed\n"); - return FALSE; - } key = malloc(keylen); - if (key == NULL) { - free(pub); - free(resp); - free(mod); - VNC_DEBUG("malloc failed\n"); - return FALSE; + if (mod == NULL || resp == NULL + || pub == NULL || key == NULL) { + VNC_DEBUG("malloc failed"); + error = GPG_ERR_ENOMEM; + goto cleanup_mem; } vnc_connection_read(conn, mod, keylen); @@ -4191,20 +4188,14 @@ error=gcry_md_open(&md5, GCRY_MD_MD5, 0); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_md_open error: %s\n", gcry_strerror(error)); - free(pub); - free(resp); - free(mod); - return FALSE; + VNC_DEBUG("gcry_md_open error: %s", gcry_strerror(error)); + goto cleanup_mpi; } gcry_md_write(md5, key, keylen); error=gcry_md_final(md5); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_md_final error: %s\n", gcry_strerror(error)); - free(pub); - free(resp); - free(mod); - return FALSE; + VNC_DEBUG("gcry_md_final error: %s", gcry_strerror(error)); + goto cleanup_md5; } shared = gcry_md_read(md5, GCRY_MD_MD5); @@ -4221,45 +4212,44 @@ error=gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_open error: %s\n", gcry_strerror(error)); - free(pub); - free(resp); - free(mod); - return FALSE; + VNC_DEBUG("gcry_cipher_open error: %s", gcry_strerror(error)); + goto cleanup_md5; } error=gcry_cipher_setkey(aes, shared, 16); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_setkey error: %s\n", gcry_strerror(error)); - free(pub); - free(resp); - free(mod); - gcry_cipher_close(aes); - return FALSE; + VNC_DEBUG("gcry_cipher_setkey error: %s", gcry_strerror(error)); + goto cleanup; } error=gcry_cipher_encrypt(aes, ciphertext, sizeof(ciphertext), userpass, sizeof(userpass)); if (gcry_err_code (error) != GPG_ERR_NO_ERROR) { - VNC_DEBUG("gcry_cipher_encrypt error: %s\n", gcry_strerror(error)); - free(pub); - free(resp); - free(mod); - gcry_cipher_close(aes); - return FALSE; + VNC_DEBUG("gcry_cipher_encrypt error: %s", gcry_strerror(error)); + goto cleanup; } vnc_connection_write(conn, ciphertext, sizeof(ciphertext)); vnc_connection_write(conn, pub, keylen); vnc_connection_flush(conn); - free(mod); - free(resp); - free(pub); - free(key); +cleanup: gcry_cipher_close(aes); +cleanup_md5: gcry_md_close(md5); +cleanup_mpi: gcry_mpi_release(genmpi); gcry_mpi_release(modmpi); gcry_mpi_release(respmpi); vnc_dh_free (dh); +cleanup_mem: + free(mod); + free(resp); + free(pub); + free(key); + + if (gcry_err_code(error) != GPG_ERR_NO_ERROR) { + vnc_connection_set_error(conn, "Unknown authentication failure: %s", + gcry_strerror(error)); + return FALSE; + } return vnc_connection_check_auth_result(conn); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplay.c new/gtk-vnc-1.3.0/src/vncdisplay.c --- old/gtk-vnc-1.2.0/src/vncdisplay.c 2021-04-14 11:47:11.082111800 +0200 +++ new/gtk-vnc-1.3.0/src/vncdisplay.c 2021-11-17 11:23:59.975830300 +0100 @@ -87,6 +87,7 @@ gboolean allow_resize; gboolean smoothing; gboolean keep_aspect_ratio; + guint rotation; guint zoom_level; GSList *preferable_auths; @@ -123,6 +124,7 @@ PROP_ALLOW_RESIZE, PROP_SMOOTHING, PROP_KEEP_ASPECT_RATIO, + PROP_ROTATE, PROP_DEPTH, PROP_ZOOM_LEVEL, PROP_GRAB_KEYS, @@ -232,6 +234,9 @@ case PROP_KEEP_ASPECT_RATIO: g_value_set_boolean (value, vnc->priv->keep_aspect_ratio); break; + case PROP_ROTATE: + g_value_set_uint (value, vnc->priv->rotation); + break; case PROP_DEPTH: g_value_set_enum (value, vnc->priv->depth); break; @@ -293,6 +298,9 @@ case PROP_KEEP_ASPECT_RATIO: vnc_display_set_keep_aspect_ratio (vnc, g_value_get_boolean (value)); break; + case PROP_ROTATE: + vnc_display_set_rotation (vnc, g_value_get_uint (value)); + break; case PROP_DEPTH: vnc_display_set_depth (vnc, g_value_get_enum (value)); break; @@ -405,6 +413,9 @@ { VncDisplay *obj = VNC_DISPLAY(widget); VncDisplayPrivate *priv = obj->priv; + /* + * Width and height of the unscaled, but possibly rotated remote desktop. */ + int rotwidth, rotheight; *winwidth = gdk_window_get_width(gtk_widget_get_window(widget)); *winheight = gdk_window_get_height(gtk_widget_get_window(widget)); @@ -424,36 +435,44 @@ *fbwidth = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)); *fbheight = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)); + if (priv->rotation == 0u || priv->rotation == 180u) { + rotwidth = *fbwidth; + rotheight = *fbheight; + } else { + rotwidth = *fbheight; + rotheight = *fbwidth; + } + if (priv->allow_scaling) { *offsetx = 0; *offsety = 0; *width = *winwidth; *height = *winheight; - *scalex = (double)*winwidth / (double)*fbwidth; - *scaley = (double)*winheight / (double)*fbheight; + *scalex = (double)*winwidth / (double)rotwidth; + *scaley = (double)*winheight / (double)rotheight; if (priv->keep_aspect_ratio) { if (*scalex > *scaley) { *scalex = *scaley; - *width = *fbwidth * *scalex; + *width = rotwidth * *scalex; *offsetx = (*winwidth - *width) / 2; } else if (*scalex < *scaley) { *scaley = *scalex; - *height = *fbheight * *scaley; + *height = rotheight * *scaley; *offsety = (*winheight - *height) / 2; } } } else { - if (*winwidth > *fbwidth) { - *offsetx = (*winwidth - *fbwidth) / 2; - *width = *fbwidth; + if (*winwidth > rotwidth) { + *offsetx = (*winwidth - rotwidth) / 2; + *width = rotwidth; } else { *offsetx = 0; *width = *winwidth; } - if (*winheight > *fbheight) { - *offsety = (*winheight - *fbheight) / 2; - *height = *fbheight; + if (*winheight > rotheight) { + *offsety = (*winheight - rotheight) / 2; + *height = rotheight; } else { *offsety = 0; *height = *winheight; @@ -506,11 +525,46 @@ /* Now render the remote desktop, scaling/offsetting * as needed */ if (priv->fb) { - cairo_scale(cr, scalex, scaley); + cairo_matrix_t mtx = {0., 0., 0., 0., 0., 0.}; + double source_surface_offsetx, source_surface_offsety; + + switch (priv->rotation) { + case 0u: + default: + mtx.xx = scalex; + mtx.yy = scaley; + source_surface_offsetx = offsetx / scalex; + source_surface_offsety = offsety / scaley; + break; + case 90u: + mtx.yx = scaley; + mtx.xy = -scalex; + mtx.x0 = (double)winwidth; + source_surface_offsetx = offsety / scaley; + source_surface_offsety = offsetx / scalex; + break; + case 180u: + mtx.xx = -scalex; + mtx.yy = -scaley; + mtx.x0 = (double)winwidth; + mtx.y0 = (double)winheight; + source_surface_offsetx = offsetx / scalex; + source_surface_offsety = offsety / scaley; + break; + case 270u: + mtx.yx = -scaley; + mtx.xy = scalex; + mtx.y0 = (double)winheight; + source_surface_offsetx = offsety / scaley; + source_surface_offsety = offsetx / scalex; + break; + } + cairo_transform(cr, &mtx); cairo_set_source_surface(cr, - priv->fbCache, - offsetx / scalex, - offsety / scaley); + priv->fbCache, + source_surface_offsetx, + source_surface_offsety); + if (!priv->smoothing) { cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); @@ -840,8 +894,28 @@ motion->x -= offsetx; motion->y -= offsety; - motion->x /= scalex; - motion->y /= scaley; + /* The inverse transform of that applied in draw_event(). */ + switch (priv->rotation) { + int tmp; + case 0u: + default: + motion->x /= scalex; + motion->y /= scaley; + break; + case 90u: + tmp = motion->x; + motion->x = motion->y / scaley; + motion->y = (width - tmp) / scalex; + break; + case 180u: + motion->x = (width - motion->x) / scalex; + motion->y = (height - motion->y) / scaley; + break; + case 270u: + tmp = motion->x; + motion->x = (height - motion->y) / scaley; + motion->y = tmp / scalex; + } /* Next adjust the real client pointer */ if (!priv->absolute) { @@ -881,7 +955,7 @@ * them to the boundaries. We don't want to actually * drop the events though, because even if the X coord * is out of bounds we want the server to see Y coord - * changes, and vica-verca. */ + * changes, and vice-versa. */ if (dx < 0) dx = 0; if (dy < 0) @@ -1269,7 +1343,9 @@ vnc_connection_is_initialized(priv->conn) && priv->fb && priv->force_size) - *defwidth = vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)); + *defwidth = (priv->rotation == 0u || priv->rotation == 180u) ? + vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)) : + vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)); else *defwidth = 0; @@ -1290,7 +1366,9 @@ vnc_connection_is_initialized(priv->conn) && priv->fb && priv->force_size) - *defheight = vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)); + *defheight = (priv->rotation == 0u || priv->rotation == 180u) ? + vnc_framebuffer_get_height(VNC_FRAMEBUFFER(priv->fb)) : + vnc_framebuffer_get_width(VNC_FRAMEBUFFER(priv->fb)); else *defheight = 0; @@ -1336,10 +1414,39 @@ cairo_destroy(cr); } - x *= scalex; - y *= scaley; - w *= scalex; - h *= scaley; + switch (priv->rotation) { + /* This repeates the same transformation as in draw_event() above. */ + /* To put cairo_matrix_t mtx into struct priv, and use here? */ + int tmp; + case 0u: + default: + x *= scalex; + y *= scaley; + w *= scalex; + h *= scaley; + break; + case 90u: + tmp = x; + x = (fbheight - y - h) * scalex; + y = tmp * scaley; + tmp = w; + w = h * scalex; + h = tmp * scaley; + break; + case 180u: + x = (fbwidth - x - w) * scalex; + y = (fbheight - y - h) * scaley; + w *= scalex; + h *= scaley; + break; + case 270u: + tmp = x; + x = y * scalex; + y = (fbwidth - tmp - w) * scaley; + tmp = w; + w = h * scalex; + h = tmp * scaley; + } x += offsetx; y += offsety; @@ -2472,6 +2579,20 @@ G_PARAM_STATIC_BLURB)); g_object_class_install_property (object_class, + PROP_ROTATE, + g_param_spec_uint ( "rotation", + "Rotate +90?? clockwise", + "Rotate the image of the remote desktop 90?? clockwise", + 0, + 270, + 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property (object_class, PROP_DEPTH, g_param_spec_enum ( "depth", "Depth", @@ -2753,6 +2874,7 @@ priv->allow_resize = FALSE; priv->smoothing = TRUE; priv->keep_aspect_ratio = FALSE; + priv->rotation = 0u; priv->zoom_level = 100; priv->vncgrabseq = vnc_grab_sequence_new_from_string("Control_L+Alt_L"); priv->vncactiveseq = g_new0(gboolean, priv->vncgrabseq->nkeysyms); @@ -3218,7 +3340,7 @@ * Set whether changes in the widget size will be translated * into requests to resize the remote desktop. Resizing of * the remote desktop is not guaranteed to be honoured by - * servers, but when it is, it will avoid the need todo + * servers, but when it is, it will avoid the need to do * scaling. */ void vnc_display_set_allow_resize(VncDisplay *obj, gboolean enable) @@ -3287,6 +3409,25 @@ /** + * vnc_display_set_rotation: + * @obj: (transfer none): the VNC display widget + * @rotation: The angle of rotation, degrees clockwise. + * + * Set the rotation angle to view the display of the remote desktop, in + * clockwise direction. + */ +void vnc_display_set_rotation(VncDisplay *obj, guint rotation) +{ + g_return_if_fail (VNC_IS_DISPLAY (obj)); + obj->priv->rotation = rotation % 360u; + + if (obj->priv->fb != NULL) { + gtk_widget_queue_resize(GTK_WIDGET(obj)); + } +} + + +/** * vnc_display_set_depth: * @obj: (transfer none): the VNC display widget * @depth: the desired colour depth @@ -3395,6 +3536,22 @@ } +/** + * vnc_display_get_rotation: + * @obj: (transfer none): the VNC display widget + * + * Determine the current rotation angle of the remote desktop. + * + * Returns: the rotation angle in clockwise direction + */ +guint vnc_display_get_rotation(VncDisplay *obj) +{ + g_return_val_if_fail (VNC_IS_DISPLAY (obj), 0u); + + return obj->priv->rotation; +} + + /** * vnc_display_get_scaling: * @obj: (transfer none): the VNC display widget diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplay.h new/gtk-vnc-1.3.0/src/vncdisplay.h --- old/gtk-vnc-1.2.0/src/vncdisplay.h 2021-04-14 11:47:11.082111800 +0200 +++ new/gtk-vnc-1.3.0/src/vncdisplay.h 2021-11-17 11:23:59.975830300 +0100 @@ -143,6 +143,9 @@ void vnc_display_set_keep_aspect_ratio(VncDisplay *obj, gboolean enable); gboolean vnc_display_get_keep_aspect_ratio(VncDisplay *obj); +void vnc_display_set_rotation(VncDisplay *obj, guint rotation); +guint vnc_display_get_rotation(VncDisplay *obj); + void vnc_display_set_shared_flag(VncDisplay *obj, gboolean shared); gboolean vnc_display_get_shared_flag(VncDisplay *obj); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/src/vncdisplaykeymap.c new/gtk-vnc-1.3.0/src/vncdisplaykeymap.c --- old/gtk-vnc-1.2.0/src/vncdisplaykeymap.c 2021-04-14 11:47:11.082111800 +0200 +++ new/gtk-vnc-1.3.0/src/vncdisplaykeymap.c 2021-11-17 11:23:59.975830300 +0100 @@ -64,12 +64,14 @@ #ifdef GDK_WINDOWING_BROADWAY /* X11 keysyms */ +#include <gdk/gdkbroadway.h> #include "vncdisplaykeymap_x112qnum.h" #endif #ifdef GDK_WINDOWING_QUARTZ /* OS-X native keycodes */ +#include <gdk/gdkquartz.h> #include "vncdisplaykeymap_osx2qnum.h" #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gtk-vnc-1.2.0/tools/gvnccapture.c new/gtk-vnc-1.3.0/tools/gvnccapture.c --- old/gtk-vnc-1.2.0/tools/gvnccapture.c 2021-04-14 11:47:11.083112000 +0200 +++ new/gtk-vnc-1.3.0/tools/gvnccapture.c 2021-11-17 11:23:59.976830200 +0100 @@ -136,6 +136,16 @@ VNC_CONNECTION_AUTH_NONE }; +static const guint preferable_vencrypt_auths[] = { + VNC_CONNECTION_AUTH_VENCRYPT_X509SASL, + VNC_CONNECTION_AUTH_VENCRYPT_X509PLAIN, + VNC_CONNECTION_AUTH_VENCRYPT_X509VNC, + VNC_CONNECTION_AUTH_VENCRYPT_X509NONE, + VNC_CONNECTION_AUTH_VENCRYPT_TLSSASL, + VNC_CONNECTION_AUTH_VENCRYPT_TLSPLAIN, + VNC_CONNECTION_AUTH_VENCRYPT_TLSVNC, + VNC_CONNECTION_AUTH_VENCRYPT_TLSNONE, +}; #ifndef G_OS_WIN32 static gchar * @@ -400,34 +410,76 @@ g_free(data); } -static void do_vnc_auth_choose_type(VncConnection *conn, - GValueArray *types, - gpointer opaque G_GNUC_UNUSED) + +static int do_vnc_auth_choose(const guint *prefer, + gsize nprefer, + GValueArray *avail) { guint i, j; - if (!types->n_values) { - VNC_DEBUG("No auth types to choose from"); - return; - } - - for (i = 0 ; i < G_N_ELEMENTS(preferable_auths) ; i++) { - int pref = preferable_auths[i]; + for (i = 0 ; i < nprefer ; i++) { + int pref = prefer[i]; - for (j = 0 ; j < types->n_values ; j++) { - GValue *type = g_value_array_get_nth(types, j); + for (j = 0 ; j < avail->n_values ; j++) { + GValue *type = g_value_array_get_nth(avail, j); VNC_DEBUG("Compare %d vs %d", pref, g_value_get_enum(type)); if (pref == g_value_get_enum(type)) { VNC_DEBUG("Chosen auth %d", pref); - vnc_connection_set_auth_type(conn, pref); - return; + return pref; } } } - GValue *type = g_value_array_get_nth(types, 0); + GValue *type = g_value_array_get_nth(avail, 0); VNC_DEBUG("Chosen default auth %d", g_value_get_enum(type)); - vnc_connection_set_auth_type(conn, g_value_get_enum(type)); + return g_value_get_enum(type); +} + +static void do_vnc_auth_choose_subtype(VncConnection *conn, + int type, + GValueArray *subtypes, + gpointer opaque G_GNUC_UNUSED) +{ + guint auth; + + if (!subtypes->n_values) { + VNC_DEBUG("No auth subtypes to choose from"); + return; + } + + if (type == VNC_CONNECTION_AUTH_TLS) { + auth = do_vnc_auth_choose(preferable_auths, + G_N_ELEMENTS(preferable_auths), + subtypes); + } else if (type == VNC_CONNECTION_AUTH_VENCRYPT) { + auth = do_vnc_auth_choose(preferable_vencrypt_auths, + G_N_ELEMENTS(preferable_vencrypt_auths), + subtypes); + } else { + VNC_DEBUG("Unexpected stackable auth type %u", type); + vnc_connection_shutdown(conn); + return; + } + + vnc_connection_set_auth_subtype(conn, auth); +} + + +static void do_vnc_auth_choose_type(VncConnection *conn, + GValueArray *types, + gpointer opaque G_GNUC_UNUSED) +{ + guint auth; + if (!types->n_values) { + VNC_DEBUG("No auth types to choose from"); + return; + } + + auth = do_vnc_auth_choose(preferable_auths, + G_N_ELEMENTS(preferable_auths), + types); + + vnc_connection_set_auth_type(conn, auth); } @@ -528,7 +580,7 @@ g_signal_connect(capture->conn, "vnc-auth-choose-type", G_CALLBACK(do_vnc_auth_choose_type), capture); g_signal_connect(capture->conn, "vnc-auth-choose-subtype", - G_CALLBACK(do_vnc_auth_choose_type), capture); + G_CALLBACK(do_vnc_auth_choose_subtype), capture); g_signal_connect(capture->conn, "vnc-auth-credential", G_CALLBACK(do_vnc_auth_credential), capture); g_signal_connect(capture->conn, "vnc-desktop-resize",