Hello community,
here is the log from the commit of package tigervnc.14864 for
openSUSE:Leap:15.1:Update checked in at 2020-11-05 20:25:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.1:Update/tigervnc.14864 (Old)
and /work/SRC/openSUSE:Leap:15.1:Update/.tigervnc.14864.new.11331 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "tigervnc.14864"
Thu Nov 5 20:25:46 2020 rev:1 rq:845504 version:1.9.0
Changes:
--------
New Changes file:
--- /dev/null 2020-10-22 01:51:33.322291705 +0200
+++
/work/SRC/openSUSE:Leap:15.1:Update/.tigervnc.14864.new.11331/tigervnc.changes
2020-11-05 20:25:48.171280402 +0100
@@ -0,0 +1,716 @@
+-------------------------------------------------------------------
+Fri Sep 25 14:29:00 UTC 2020 - Stefan Dirsch <[email protected]>
+
+- CVE-2020-26117: Server certificates were stored as certiticate
+ authoritied, allowing malicious owners of these certificates
+ to impersonate any server after a client had added an exception
+ (boo#1176733)
+ * U_0001-Properly-store-certificate-exceptions.patch,
+ U_0002-Properly-store-certificate-exceptions-in-Java-viewer.patch
+ * Properly store certificate exceptions (boo#1176733)
+- adjusted u_tigervnc-add-autoaccept-parameter.patch
+
+-------------------------------------------------------------------
+Wed May 13 13:02:11 UTC 2020 - Stefan Dirsch <[email protected]>
+
+- U_Avoid-potential-crash-when-replacing-buffer-in-Plain.patch
+ * fixes crash in free() when using "-f" option of vncpasswd
+ command (bsc#1171519)
+
+-------------------------------------------------------------------
+Wed Jan 8 11:32:07 UTC 2020 - Stefan Dirsch <[email protected]>
+
+- TigerVNC security fix:
+ 0001-Make-ZlibInStream-more-robust-against-failures.patch
+ 0002-Encapsulate-PixelBuffer-internal-details.patch
+ 0003-Restrict-PixelBuffer-dimensions-to-safe-values.patch
+ 0004-Add-write-protection-to-OffsetPixelBuffer.patch
+ 0005-Handle-empty-Tight-gradient-rects.patch
+ 0006-Add-unit-test-for-PixelFormat-sanity-checks.patch
+ 0007-Fix-depth-sanity-test-in-PixelFormat.patch
+ 0008-Add-sanity-checks-for-PixelFormat-shift-values.patch
+ 0009-Remove-unused-FixedMemOutStream.patch
+ 0010-Use-size_t-for-lengths-in-stream-objects.patch
+ 0011-Be-defensive-about-overflows-in-stream-objects.patch
+ 0012-Add-unit-tests-for-PixelFormat.is888-detection.patch
+ 0013-Handle-pixel-formats-with-odd-shift-values.patch
+ * stack use-after-return due to incorrect usage of stack memory
+ in ZRLEDecoder (CVE-2019-15691, bsc#1159856)
+ * improper value checks in CopyRectDecode may lead to heap
+ buffer overflow (CVE-2019-15692, bsc#1160250)
+ * heap buffer overflow in TightDecoder::FilterGradient
+ (CVE-2019-15693, bsc#1159858)
+ * improper error handling in processing MemOutStream may lead
+ to heap buffer overflow (CVE-2019-15694, bsc#1160251
+ * stack buffer overflow, which could be triggered from
+ CMsgReader::readSetCurso (CVE-2019-15695, bsc#1159860)
+
+-------------------------------------------------------------------
+Thu Jan 17 12:07:27 UTC 2019 - [email protected]
+
+- Switch websocket dependency to python3. (bsc#1119737)
+
+-------------------------------------------------------------------
+Thu Jan 17 10:21:29 UTC 2019 - [email protected]
+
+- Do not build xorg-x11-Xvnc-module on s390. It fails to build
+ because macros.xorg-server is incomplete on s390 and the module
+ would be useless without real X server anyway.
+
+-------------------------------------------------------------------
+Tue Jan 8 12:38:42 UTC 2019 - [email protected]
+
+- Add U_viewer-reset-ctrl-alt-to-menu-state-on-focus.patch
+ * Fix the ALT and CTRL buttons in viewer's F8 menu. (bsc#1119354)
+
+-------------------------------------------------------------------
+Wed Sep 19 21:19:21 UTC 2018 - Jason Sikes <[email protected]>
+
+- Changed "openssl" requirement to "openssl(cli)"
+ * (bsc#1101470)
+
+-------------------------------------------------------------------
+Mon Aug 6 12:04:52 UTC 2018 - [email protected]
+
+- Add xvnc.target to fix xvnc-novnc.service's dependency.
+ (bnc#1103552)
+- Split the X server's VNC module into subpackage and give it
+ dependency on the current extension ABI.
+
+-------------------------------------------------------------------
+Thu Aug 2 08:31:09 UTC 2018 - [email protected]
+
+- Update to tigervnc 1.9.0
+ * Alternative, "raw" keyboard mode in the native client and all servers
+ * CapsLock/NumLock/ScrollLock synchronisation in the native client and all
servers
+ * Automatic "repair" of JPEG artefacts on screen in all servers
+ * Support for UNIX sockets in the native client and in the UNIX servers
+ * Both clients now warn when sending the password over a possibly insecure
channel
+ * Performance improvements in the Java client
+ * The Java client now requires Java 7
+ * Improved high latency handling in all servers
+ * Slightly better keyboard handling in x0vncserver
+ * x0vncserver now supports cursors and screen resize
+ * Xorg 1.20 can now be used as a base for Xvnc/libvnc.so
+ - Fixes bnc#1103537
+
+- Removed patches (included in 1.9.0):
+ * u_tigervnc-show-unencrypted-warning.patch
+ * U_allow_multiple_certs_with_same_dn_in_saved_certs_file.patch
+ * U_handle_certificate_verification_for_saved_certs_correctly.patch
+ * u_Unset-pixel-buffer-when-x0vncserver-client-disconnect.patch
+ * u_add-support-for-X-server-1.20.0.patch
+ * U_vncviewer-Fix-fullscreen-scrolling.patch
+ * U_vncviewer-Fix-scrollbar-visibility.patch
+
+- Removed patches (no longer needed):
+ * tigervnc-1.8.0-nowindows.patch
+
+- Refreshed patches:
+ * n_tigervnc-date-time.patch
+ * tigervnc-clean-pressed-key-on-exit.patch
+ * u_tigervnc-add-autoaccept-parameter.patch
+ * u_tigervnc-ignore-epipe-on-write.patch
+
+- Added patches:
+ * n_correct_path_in_desktop_file.patch
+
+- Fixed typo in 10-libvnc.conf
+
+-------------------------------------------------------------------
+Fri Jun 8 09:09:38 UTC 2018 - [email protected]
+
+- Updated u_add-support-for-X-server-1.20.0.patch to version sent
+ upstream. Fixes GLX initialization.
+
+-------------------------------------------------------------------
+Wed Jun 6 09:07:23 UTC 2018 - [email protected]
+
+- U_vncviewer-Fix-fullscreen-scrolling.patch,
+ U_vncviewer-Fix-scrollbar-visibility.patch
+ * Fix scrolling in vncviewer. (boo#1095664)
+
+- u_add-support-for-X-server-1.20.0.patch
+ * Fix build against X server 1.20.0.
+
+-------------------------------------------------------------------
+Tue Apr 24 09:16:59 UTC 2018 - [email protected]
+
+- Reload firewalld files after installation.
+
+-------------------------------------------------------------------
+Wed Apr 11 09:48:51 UTC 2018 - [email protected]
+
+- Limit feature description to openSUSE. Ensure neutrality of
+ description.
+
+-------------------------------------------------------------------
+Wed Apr 11 08:12:52 UTC 2018 - [email protected]
+
+- Add u_change-button-layout-in-ServerDialog.patch
+ * To fit strings in languages with longer words... (bnc#1084865)
+- Refresh n_tigervnc-date-time.patch
+ * Completely hide the build time (bnc#1082968)
+
+-------------------------------------------------------------------
+Thu Mar 22 14:27:28 UTC 2018 - [email protected]
+
+- Enable xvnc.socket if upgraded from previous installation that
+ had VNC enabled in xinetd configuration. (bnc#1085974)
+- Subpackage xorg-x11-Xvnc must also obsolete tightvnc.
+
+-------------------------------------------------------------------
+Wed Feb 28 12:19:52 UTC 2018 - [email protected]
+
+- Replace SuSEFirewall2 by firewalld. (bnc#1081952)
+
+-------------------------------------------------------------------
+Mon Dec 18 16:44:20 UTC 2017 - [email protected]
+
+- Do not mess with /usr/lib*64)?/debug: this is RPM's playground
+ for debuginfo packages.
+
+-------------------------------------------------------------------
+Mon Dec 18 14:56:17 UTC 2017 - [email protected]
+
+- Added patch:
+ * tigervnc-1.8.0-nowindows.patch
+ + Remove Windows code that is removed from jdk10
+
+-------------------------------------------------------------------
+Tue Dec 12 13:15:25 UTC 2017 - [email protected]
+
+- Depend on pkgconfig's gl, egl and gbm instead of Mesa-devel.
+ * Those dependencies are what the underlying X server really
+ needs. Mesa-devel is too general and is a bottleneck in
+ distribution build. (bnc#1071297)
+
+-------------------------------------------------------------------
+Tue Sep 26 11:53:23 UTC 2017 - [email protected]
+
+- u_Unset-pixel-buffer-when-x0vncserver-client-disconnect.patch
+ * Fixes crash in x0vncserver after client disconnects.
+ (bnc#1058587)
+
+-------------------------------------------------------------------
+Mon Sep 25 08:36:07 UTC 2017 - [email protected]
+
++++ 519 more lines (skipped)
++++ between /dev/null
++++ and
/work/SRC/openSUSE:Leap:15.1:Update/.tigervnc.14864.new.11331/tigervnc.changes
New:
----
0001-Make-ZlibInStream-more-robust-against-failures.patch
0002-Encapsulate-PixelBuffer-internal-details.patch
0003-Restrict-PixelBuffer-dimensions-to-safe-values.patch
0004-Add-write-protection-to-OffsetPixelBuffer.patch
0005-Handle-empty-Tight-gradient-rects.patch
0006-Add-unit-test-for-PixelFormat-sanity-checks.patch
0007-Fix-depth-sanity-test-in-PixelFormat.patch
0008-Add-sanity-checks-for-PixelFormat-shift-values.patch
0009-Remove-unused-FixedMemOutStream.patch
0010-Use-size_t-for-lengths-in-stream-objects.patch
0011-Be-defensive-about-overflows-in-stream-objects.patch
0012-Add-unit-tests-for-PixelFormat.is888-detection.patch
0013-Handle-pixel-formats-with-odd-shift-values.patch
10-libvnc.conf
U_0001-Properly-store-certificate-exceptions.patch
U_0002-Properly-store-certificate-exceptions-in-Java-viewer.patch
U_Avoid-potential-crash-when-replacing-buffer-in-Plain.patch
U_viewer-reset-ctrl-alt-to-menu-state-on-focus.patch
index.vnc
n_correct_path_in_desktop_file.patch
n_tigervnc-date-time.patch
tigervnc-clean-pressed-key-on-exit.patch
tigervnc-https.firewalld
tigervnc-newfbsize.patch
tigervnc.changes
tigervnc.firewalld
tigervnc.spec
u_build_libXvnc_as_separate_library.patch
u_change-button-layout-in-ServerDialog.patch
u_tigervnc-add-autoaccept-parameter.patch
u_tigervnc-cve-2014-8240.patch
u_tigervnc-ignore-epipe-on-write.patch
u_tigervnc_update_default_vncxstartup.patch
v1.9.0.tar.gz
vnc-httpd.susefirewall
vnc-server.susefirewall
vnc.pam
vnc.reg
vncpasswd.arg
with-vnc-key.sh
x11vnc
xvnc-novnc.service
xvnc-novnc.socket
xvnc.socket
xvnc.target
[email protected]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ tigervnc.spec ++++++
#
# spec file for package tigervnc
#
# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%define vncgroup vnc
%define vncuser vnc
%define tlskey %{_sysconfdir}/vnc/tls.key
%define tlscert %{_sysconfdir}/vnc/tls.cert
%define _unitdir %{_prefix}/lib/systemd/system
%if 0%{?suse_version} >= 1500
%define use_firewalld 1
%else
%define use_firewalld 0
%endif
Name: tigervnc
Version: 1.9.0
Release: 0
Provides: tightvnc = 1.3.9
Obsoletes: tightvnc < 1.3.9
Provides: vnc
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: cmake
BuildRequires: fltk-devel >= 1.3.3
BuildRequires: gcc-c++
BuildRequires: gcc-c++
BuildRequires: java-devel >= 1.6.0
BuildRequires: jpackage-utils
BuildRequires: libjpeg-devel
BuildRequires: libopenssl-devel
BuildRequires: libtool
BuildRequires: nasm
BuildRequires: xorg-x11-server-sdk
BuildRequires: xorg-x11-server-source
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(xext)
BuildRequires: pkgconfig(xproto)
BuildRequires: pkgconfig(xtst)
# Because of keytool to build java client
BuildRequires: libgcrypt-devel
BuildRequires: libgpg-error-devel
BuildRequires: mozilla-nss
BuildRequires: pam-devel
BuildRequires: pkg-config
BuildRequires: systemd-rpm-macros
BuildRequires: xmlto
BuildRequires: xorg-x11-libICE-devel
BuildRequires: xorg-x11-libSM-devel
BuildRequires: pkgconfig(bigreqsproto) >= 1.1.0
BuildRequires: pkgconfig(compositeproto) >= 0.4
BuildRequires: pkgconfig(damageproto) >= 1.1
BuildRequires: pkgconfig(dri)
BuildRequires: pkgconfig(egl)
BuildRequires: pkgconfig(fixesproto) >= 4.1
BuildRequires: pkgconfig(fontsproto)
BuildRequires: pkgconfig(fontutil)
BuildRequires: pkgconfig(gbm)
BuildRequires: pkgconfig(gl)
BuildRequires: pkgconfig(glproto)
BuildRequires: pkgconfig(gnutls)
BuildRequires: pkgconfig(inputproto) >= 1.9.99.902
BuildRequires: pkgconfig(kbproto) >= 1.0.3
BuildRequires: pkgconfig(libtasn1)
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(pciaccess) >= 0.8.0
BuildRequires: pkgconfig(pixman-1) >= 0.15.20
BuildRequires: pkgconfig(presentproto) >= 1.0
BuildRequires: pkgconfig(randrproto) >= 1.2.99.3
BuildRequires: pkgconfig(recordproto) >= 1.13.99.1
BuildRequires: pkgconfig(renderproto) >= 0.11
BuildRequires: pkgconfig(resourceproto)
BuildRequires: pkgconfig(scrnsaverproto) >= 1.1
BuildRequires: pkgconfig(videoproto)
BuildRequires: pkgconfig(xau)
BuildRequires: pkgconfig(xcmiscproto) >= 1.2.0
BuildRequires: pkgconfig(xdmcp)
BuildRequires: pkgconfig(xextproto) >= 7.0.99.3
BuildRequires: pkgconfig(xf86driproto) >= 2.1.1
BuildRequires: pkgconfig(xfont) >= 1.4.2
BuildRequires: pkgconfig(xfont2)
BuildRequires: pkgconfig(xineramaproto)
BuildRequires: pkgconfig(xkbfile)
BuildRequires: pkgconfig(xorg-macros) >= 1.14
BuildRequires: pkgconfig(xproto) >= 7.0.17
BuildRequires: pkgconfig(xtrans) >= 1.2.2
%if 0%{?suse_version} >= 1315
Requires(post): update-alternatives
Requires(postun): update-alternatives
%endif
Url: http://tigervnc.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Summary: An implementation of VNC
License: GPL-2.0-only AND MIT
Group: System/X11/Servers/XF86_4
Source1: https://github.com/TigerVNC/tigervnc/archive/v%{version}.tar.gz
Source4: 10-libvnc.conf
Source5: vnc-server.susefirewall
Source6: vnc-httpd.susefirewall
Source7: vnc.reg
Source8: vncpasswd.arg
Source9: vnc.pam
Source10: with-vnc-key.sh
Source11: index.vnc
Source12: x11vnc
Source13: [email protected]
Source14: xvnc.socket
Source15: xvnc-novnc.service
Source16: xvnc-novnc.socket
Source17: tigervnc.firewalld
Source18: tigervnc-https.firewalld
Source19: xvnc.target
Patch1: tigervnc-newfbsize.patch
Patch2: tigervnc-clean-pressed-key-on-exit.patch
Patch3: u_tigervnc-ignore-epipe-on-write.patch
Patch4: n_tigervnc-date-time.patch
Patch5: u_tigervnc-cve-2014-8240.patch
Patch6: u_tigervnc_update_default_vncxstartup.patch
Patch7: u_build_libXvnc_as_separate_library.patch
Patch8: u_tigervnc-add-autoaccept-parameter.patch
Patch9: u_change-button-layout-in-ServerDialog.patch
Patch10: n_correct_path_in_desktop_file.patch
Patch11: U_viewer-reset-ctrl-alt-to-menu-state-on-focus.patch
Patch21: 0001-Make-ZlibInStream-more-robust-against-failures.patch
Patch22: 0002-Encapsulate-PixelBuffer-internal-details.patch
Patch23: 0003-Restrict-PixelBuffer-dimensions-to-safe-values.patch
Patch24: 0004-Add-write-protection-to-OffsetPixelBuffer.patch
Patch25: 0005-Handle-empty-Tight-gradient-rects.patch
Patch26: 0006-Add-unit-test-for-PixelFormat-sanity-checks.patch
Patch27: 0007-Fix-depth-sanity-test-in-PixelFormat.patch
Patch28: 0008-Add-sanity-checks-for-PixelFormat-shift-values.patch
Patch29: 0009-Remove-unused-FixedMemOutStream.patch
Patch30: 0010-Use-size_t-for-lengths-in-stream-objects.patch
Patch31: 0011-Be-defensive-about-overflows-in-stream-objects.patch
Patch32: 0012-Add-unit-tests-for-PixelFormat.is888-detection.patch
Patch33: 0013-Handle-pixel-formats-with-odd-shift-values.patch
Patch40: U_Avoid-potential-crash-when-replacing-buffer-in-Plain.patch
Patch51: U_0001-Properly-store-certificate-exceptions.patch
Patch52:
U_0002-Properly-store-certificate-exceptions-in-Java-viewer.patch
%description
TigerVNC is an implementation of VNC (Virtual Network Computing), a
client/server application that allows users to launch and interact
with graphical applications on remote machines. TigerVNC is capable
of running 3D and video applications. TigerVNC also provides
extensions for advanced authentication methods and TLS encryption.
%package -n xorg-x11-Xvnc
Requires(post): /usr/sbin/useradd
Requires(post): /usr/sbin/groupadd
Requires(post): /bin/awk
Requires(post): systemd
%if %{use_firewalld}
Requires(post): firewall-macros
%endif
# Needed to generate certificates
Requires: windowmanager
Requires: xauth
Requires: xinit
Requires: xkbcomp
Requires: xkeyboard-config
Requires: xorg-x11-fonts-core
Requires: openssl(cli)
# For the with-vnc-key.sh script
Requires: /bin/hostname
%{?systemd_requires}
%ifnarch s390 s390x
Recommends: xorg-x11-Xvnc-module
%endif
Provides: tightvnc = 1.3.9
Provides: xorg-x11-Xvnc:/usr/lib/vnc/with-vnc-key.sh
Obsoletes: tightvnc < 1.3.9
Summary: TigerVNC implementation of Xvnc
Group: System/X11/Servers/XF86_4
%description -n xorg-x11-Xvnc
This is the TigerVNC implementation of Xvnc.
%ifnarch s390 s390x
%package -n xorg-x11-Xvnc-module
Requires: xorg-x11-Xvnc
Summary: VNC module for X server
Group: System/X11/Servers/XF86_4
%{x11_abi_extension_req}
%description -n xorg-x11-Xvnc-module
This module allows to share content of X server's screen over VNC.
It is loaded into X server as a module if enable in X server's
configuration.
%endif
%package -n xorg-x11-Xvnc-novnc
Requires: novnc
Requires: python3-websockify
Requires: xorg-x11-Xvnc
%{?systemd_requires}
Summary: NoVNC service for Xvnc
Group: System/X11/Servers/XF86_4
BuildArch: noarch
%description -n xorg-x11-Xvnc-novnc
A service that starts noVNC linked to Xvnc server.
%package -n xorg-x11-Xvnc-java
BuildArch: noarch
%{?systemd_requires}
Summary: VNC viewer in java
Group: System/X11/Servers/XF86_4
%description -n xorg-x11-Xvnc-java
A VNC client written in java that can be used as standalone application or as
an applet inside web page.
%package -n libXvnc1
Summary: X extension to control VNC module
Group: System/Libraries
%description -n libXvnc1
Xvnc extension allows X clients to read and change VNC configuration.
%package -n libXvnc-devel
Summary: X extension to control VNC module
Group: Development/Libraries/C and C++
Requires: libXvnc1 = %version
%description -n libXvnc-devel
Xvnc extension allows X clients to read and change VNC configuration.
%package x11vnc
Summary: Wrapper that starts x0vncserver
Group: System/X11/Servers/XF86_4
Requires: python
Requires: xorg-x11-Xvnc
Provides: x11vnc
Conflicts: x11vnc
BuildArch: noarch
%description x11vnc
This is a wrapper that looks like x11vnc, but starts x0vncserver instead.
It maps common x11vnc arguments to x0vncserver arguments.
%prep
%setup -T -b1 -q
cp -r /usr/src/xserver/* unix/xserver/
%patch1 -p1
%patch2 -p1
%patch3 -p0
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch40 -p1
%patch51 -p1
%patch52 -p1
%patch8 -p1
pushd unix/xserver
patch -p1 < ../xserver120.patch
popd
%build
export CXXFLAGS="%optflags"
export CFLAGS="%optflags"
# Build all tigervnc
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix}
-DCMAKE_BUILD_TYPE=RelWithDebInfo
make %{?_smp_mflags}
# Build Xvnc server
pushd unix/xserver
autoreconf -fi
%configure \
--disable-xorg --disable-xnest --disable-xvfb --disable-dmx \
--disable-xwin --disable-xephyr --disable-kdrive --with-pic \
--disable-static --disable-xinerama \
--with-xkb-path="/usr/share/X11/xkb" \
--with-xkb-output="/var/lib/xkb/compiled" \
--enable-glx --enable-dri \
%ifnarch s390 s390x
--enable-dri2 \
%endif
--disable-config-dbus \
--disable-config-hal \
--disable-config-udev \
--without-dtrace \
--disable-unit-tests \
--disable-devel-docs \
--with-fontrootdir=/usr/share/fonts \
--disable-selective-werror
make %{?_smp_mflags} V=1
popd
# Build java client
pushd java
cmake -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} -DJAVACFLAGS="-encoding utf8
-source 1.6 -target 1.6"
make %{?_smp_mflags}
popd
%install
%make_install
mv $RPM_BUILD_ROOT/usr/bin/vncviewer $RPM_BUILD_ROOT/usr/bin/vncviewer-tigervnc
mv $RPM_BUILD_ROOT/usr/share/man/man1/vncviewer.1
$RPM_BUILD_ROOT/usr/share/man/man1/vncviewer-tigervnc.1
pushd unix/xserver
%make_install
popd
pushd java
mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes
install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes
popd
%ifnarch s390x
install -D -m 644 %{SOURCE4} $RPM_BUILD_ROOT/etc/X11/xorg.conf.d/10-libvnc.conf
%endif
%if %{use_firewalld}
install -D -m 644 %{SOURCE17}
$RPM_BUILD_ROOT%{_libexecdir}/firewalld/services/tigervnc.xml
install -D -m 644 %{SOURCE18}
$RPM_BUILD_ROOT%{_libexecdir}/firewalld/services/tigervnc-https.xml
%else
install -D -m 644 %{SOURCE5}
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/vnc-server
install -D -m 644 %{SOURCE6}
$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/vnc-httpd
%endif
install -D -m 644 %{SOURCE7} $RPM_BUILD_ROOT/etc/slp.reg.d/vnc.reg
install -D -m 755 %{SOURCE8} $RPM_BUILD_ROOT%{_bindir}/vncpasswd.arg
install -D -m 644 %{SOURCE9} $RPM_BUILD_ROOT/etc/pam.d/vnc
install -D -m 644 %{SOURCE11} $RPM_BUILD_ROOT%{_datadir}/vnc/classes
%if 0%{?suse_version} >= 1315
ln -s -f %{_sysconfdir}/alternatives/vncviewer
$RPM_BUILD_ROOT%{_bindir}/vncviewer
ln -s -f %{_sysconfdir}/alternatives/vncviewer.1.gz
$RPM_BUILD_ROOT%{_mandir}/man1/vncviewer.1.gz
%endif
mkdir -p %{buildroot}%{_sbindir}
ln -sf %{_sbindir}/service %{buildroot}%{_sbindir}/rcxvnc
ln -sf %{_sbindir}/service %{buildroot}%{_sbindir}/rcxvnc-novnc
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/vnc
mkdir -p $RPM_BUILD_ROOT%{_libexecdir}/vnc
install -D -m 755 %{SOURCE10} $RPM_BUILD_ROOT%{_libexecdir}/vnc
install -D -m 755 %{SOURCE12} $RPM_BUILD_ROOT%{_bindir}/x11vnc
install -D %{SOURCE13} -m 0444 %{buildroot}%{_unitdir}/[email protected]
install -D %{SOURCE14} -m 0444 %{buildroot}%{_unitdir}/xvnc.socket
install -D %{SOURCE15} -m 0444 %{buildroot}%{_unitdir}/xvnc-novnc.service
install -D %{SOURCE16} -m 0444 %{buildroot}%{_unitdir}/xvnc-novnc.socket
install -D %{SOURCE19} -m 0444 %{buildroot}%{_unitdir}/xvnc.target
rm -rf $RPM_BUILD_ROOT/usr/share/doc/tigervnc-*
%find_lang '%{name}'
%post
%if 0%{?suse_version} >= 1315
%_sbindir/update-alternatives \
--install %{_bindir}/vncviewer vncviewer %{_bindir}/vncviewer-tigervnc 20 \
--slave %{_mandir}/man1/vncviewer.1.gz vncviewer.1.gz
%{_mandir}/man1/vncviewer-tigervnc.1.gz
%endif
%postun
%if 0%{?suse_version} >= 1315
if [ "$1" = 0 ] ; then
"%_sbindir/update-alternatives" --remove vncviewer
/usr/bin/vncviewer-tigervnc
fi
%endif
%pre -n xorg-x11-Xvnc
%service_add_pre xvnc.socket
getent group %{vncgroup} > /dev/null || groupadd -r %{vncgroup} || :
getent passwd %{vncuser} > /dev/null || useradd -r -g %{vncgroup} -d
/var/lib/empty -s /sbin/nologin -c "user for VNC" %{vncuser} || :
usermod -G shadow -a %{vncuser} || :
%post -n xorg-x11-Xvnc
%service_add_post xvnc.socket
%if %{use_firewalld}
%{firewalld_reload}
%endif
# If there is old xinetd configuration file and VNC service was enabled, enable
the systemd service too.
# Once we are done, RPM will rename the file to /etc/xinetd.d/vnc.rpmsave, so
this won't happen
# during future updates.
if [ -e /etc/xinetd.d/vnc ] && awk '
BEGIN { in_vnc1_section = 0 }
/service.*vnc1/ { in_vnc1_section = 1 }
in_vnc1_section && /disable\s*=\s*yes/ { exit 1 }
in_vnc1_section && /}/ { exit 0 }
' /etc/xinetd.d/vnc;
then
echo "Found old xinetd configuration with enabled VNC service. Enabling
xvnc.socket."
systemctl enable xvnc.socket
fi
%preun -n xorg-x11-Xvnc
%service_del_preun xvnc.socket
%postun -n xorg-x11-Xvnc
%service_del_postun xvnc.socket
%pre -n xorg-x11-Xvnc-novnc
%service_add_pre xvnc-novnc.service
%service_add_pre xvnc-novnc.socket
%post -n xorg-x11-Xvnc-novnc
%service_add_post xvnc-novnc.service
%service_add_post xvnc-novnc.socket
%preun -n xorg-x11-Xvnc-novnc
%service_del_preun xvnc-novnc.service
%service_del_preun xvnc-novnc.socket
%postun -n xorg-x11-Xvnc-novnc
%service_del_postun xvnc-novnc.service
%service_del_postun xvnc-novnc.socket
%post -n libXvnc1 -p /sbin/ldconfig
%postun -n libXvnc1 -p /sbin/ldconfig
%files -f %{name}.lang
%defattr(-,root,root,-)
%ghost %{_bindir}/vncviewer
%{_bindir}/vncviewer-tigervnc
%doc LICENCE.TXT README.rst
%ghost %_mandir/man1/vncviewer.1.gz
%doc %_mandir/man1/vncviewer-tigervnc.1.gz
%if 0%{?suse_version} >= 1315
%ghost %_sysconfdir/alternatives/vncviewer
%ghost %_sysconfdir/alternatives/vncviewer.1.gz
%endif
%dir %_datadir/icons/hicolor/16x16
%dir %_datadir/icons/hicolor/16x16/apps
%dir %_datadir/icons/hicolor/22x22
%dir %_datadir/icons/hicolor/22x22/apps
%dir %_datadir/icons/hicolor/24x24
%dir %_datadir/icons/hicolor/24x24/apps
%dir %_datadir/icons/hicolor/32x32
%dir %_datadir/icons/hicolor/32x32/apps
%dir %_datadir/icons/hicolor/48x48
%dir %_datadir/icons/hicolor/48x48/apps
%dir %_datadir/icons/hicolor/scalable
%dir %_datadir/icons/hicolor/scalable/apps
%_datadir/icons/hicolor/*/apps/tigervnc.png
%_datadir/icons/hicolor/scalable/apps/tigervnc.svg
%_datadir/applications/vncviewer.desktop
%files -n xorg-x11-Xvnc
%doc LICENCE.TXT README.rst
%defattr(-,root,root)
%{_bindir}/Xvnc
%{_bindir}/vncconfig
%{_bindir}/vncpasswd
%{_bindir}/vncpasswd.arg
%{_bindir}/vncserver
%{_bindir}/x0vncserver
%exclude %{_mandir}/man1/Xserver.1*
%{_mandir}/man1/Xvnc.1*
%{_mandir}/man1/vncconfig.1*
%{_mandir}/man1/vncpasswd.1*
%{_mandir}/man1/vncserver.1*
%{_mandir}/man1/x0vncserver.1*
%{_unitdir}/[email protected]
%{_unitdir}/xvnc.socket
%{_unitdir}/xvnc.target
%{_sbindir}/rcxvnc
%exclude /var/lib/xkb/compiled/README.compiled
%if %{use_firewalld}
%dir %{_libexecdir}/firewalld
%dir %{_libexecdir}/firewalld/services
%{_libexecdir}/firewalld/services/tigervnc.xml
%{_libexecdir}/firewalld/services/tigervnc-https.xml
%else
%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/vnc-server
%config %{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/vnc-httpd
%endif
%dir /etc/slp.reg.d
%config(noreplace) /etc/slp.reg.d/vnc.reg
%config %{_sysconfdir}/pam.d/vnc
%dir %attr(0755,%{vncuser},%{vncuser}) %{_sysconfdir}/vnc
%ghost %attr(0600,%{vncuser},%{vncuser}) %config(noreplace) %{tlskey}
%ghost %attr(0644,%{vncuser},%{vncuser}) %config(noreplace) %{tlscert}
%{_libexecdir}/vnc
%ifarch s390 s390x
# These would be in xorg-x11-Xvnc-module, but we don't build that on s390
%exclude /usr/%{_lib}/xorg/protocol.txt
%exclude /usr/%{_lib}/xorg/modules/extensions/libvnc.la
%exclude /usr/%{_lib}/xorg/modules/extensions/libvnc.so
%endif
%ifnarch s390 s390x
%files -n xorg-x11-Xvnc-module
%exclude /usr/%{_lib}/xorg/protocol.txt
%exclude /usr/%{_lib}/xorg/modules/extensions/libvnc.la
%{_libdir}/xorg/modules/extensions/libvnc.so
%config(noreplace) /etc/X11/xorg.conf.d/10-libvnc.conf
%endif
%files -n xorg-x11-Xvnc-novnc
%{_unitdir}/xvnc-novnc.service
%{_unitdir}/xvnc-novnc.socket
%{_sbindir}/rcxvnc-novnc
%files -n xorg-x11-Xvnc-java
%doc java/com/tigervnc/vncviewer/README
%{_datadir}/vnc
%files -n libXvnc1
%defattr(-,root,root)
%{_libdir}/libXvnc.so.1*
%files -n libXvnc-devel
%defattr(-,root,root)
%{_libdir}/libXvnc.so
%{_includedir}/X11/extensions/Xvnc.h
%files x11vnc
%defattr(-,root,root)
%{_bindir}/x11vnc
%changelog
++++++ 0001-Make-ZlibInStream-more-robust-against-failures.patch ++++++
>From d61a767d6842b530ffb532ddd5a3d233119aad40 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 11:05:48 +0200
Subject: [PATCH] Make ZlibInStream more robust against failures
Move the checks around to avoid missing cases where we might access
memory that is no longer valid. Also avoid touching the underlying
stream implicitly (e.g. via the destructor) as it might also no
longer be valid.
A malicious server could theoretically use this for remote code
execution in the client.
Issue found by Pavel Cheremushkin from Kaspersky Lab
---
common/rdr/ZlibInStream.cxx | 13 +++++++------
common/rdr/ZlibInStream.h | 2 +-
common/rfb/CMsgReader.cxx | 3 ++-
common/rfb/SMsgReader.cxx | 3 ++-
common/rfb/TightDecoder.cxx | 3 ++-
common/rfb/zrleDecode.h | 3 ++-
6 files changed, 16 insertions(+), 11 deletions(-)
Index: tigervnc-1.9.0/common/rdr/ZlibInStream.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rdr/ZlibInStream.cxx
+++ tigervnc-1.9.0/common/rdr/ZlibInStream.cxx
@@ -52,16 +52,16 @@ int ZlibInStream::pos()
return offset + ptr - start;
}
-void ZlibInStream::removeUnderlying()
+void ZlibInStream::flushUnderlying()
{
ptr = end = start;
- if (!underlying) return;
while (bytesIn > 0) {
decompress(true);
end = start; // throw away any data
}
- underlying = 0;
+
+ setUnderlying(NULL, 0);
}
void ZlibInStream::reset()
@@ -90,7 +90,7 @@ void ZlibInStream::init()
void ZlibInStream::deinit()
{
assert(zs != NULL);
- removeUnderlying();
+ setUnderlying(NULL, 0);
inflateEnd(zs);
delete zs;
zs = NULL;
@@ -100,8 +100,6 @@ int ZlibInStream::overrun(int itemSize,
{
if (itemSize > bufSize)
throw Exception("ZlibInStream overrun: max itemSize exceeded");
- if (!underlying)
- throw Exception("ZlibInStream overrun: no underlying stream");
if (end - ptr != 0)
memmove(start, ptr, end - ptr);
@@ -127,6 +125,9 @@ int ZlibInStream::overrun(int itemSize,
bool ZlibInStream::decompress(bool wait)
{
+ if (!underlying)
+ throw Exception("ZlibInStream overrun: no underlying stream");
+
zs->next_out = (U8*)end;
zs->avail_out = start + bufSize - end;
Index: tigervnc-1.9.0/common/rdr/ZlibInStream.h
===================================================================
--- tigervnc-1.9.0.orig/common/rdr/ZlibInStream.h
+++ tigervnc-1.9.0/common/rdr/ZlibInStream.h
@@ -38,7 +38,7 @@ namespace rdr {
virtual ~ZlibInStream();
void setUnderlying(InStream* is, int bytesIn);
- void removeUnderlying();
+ void flushUnderlying();
int pos();
void reset();
Index: tigervnc-1.9.0/common/rfb/TightDecoder.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/TightDecoder.cxx
+++ tigervnc-1.9.0/common/rfb/TightDecoder.cxx
@@ -340,7 +340,8 @@ void TightDecoder::decodeRect(const Rect
zis[streamId].readBytes(netbuf, dataSize);
- zis[streamId].removeUnderlying();
+ zis[streamId].flushUnderlying();
+ zis[streamId].setUnderlying(NULL, 0);
delete ms;
bufptr = netbuf;
Index: tigervnc-1.9.0/common/rfb/zrleDecode.h
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/zrleDecode.h
+++ tigervnc-1.9.0/common/rfb/zrleDecode.h
@@ -178,7 +178,8 @@ void ZRLE_DECODE (const Rect& r, rdr::In
}
}
- zis->removeUnderlying();
+ zis->flushUnderlying();
+ zis->setUnderlying(NULL, 0);
}
#undef ZRLE_DECODE
++++++ 0002-Encapsulate-PixelBuffer-internal-details.patch ++++++
>From 53f913a76196c7357d4858bfbf2c33caa9181bae Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 15:18:30 +0200
Subject: [PATCH] Encapsulate PixelBuffer internal details
Don't allow subclasses to just override dimensions or buffer details
directly and instead force them to go via methods. This allows us
to do sanity checks on the new values and catch bugs and attacks.
---
common/rfb/Cursor.cxx | 3 +-
common/rfb/EncodeManager.cxx | 5 +-
common/rfb/PixelBuffer.cxx | 103 +++++++++++++++++++++-------------
common/rfb/PixelBuffer.h | 17 ++++--
unix/x0vncserver/XPixelBuffer.cxx | 9 +--
unix/xserver/hw/vnc/XserverDesktop.cc | 24 ++++----
unix/xserver/hw/vnc/XserverDesktop.h | 2 +-
vncviewer/PlatformPixelBuffer.cxx | 9 ++-
win/rfb_win32/DIBSectionBuffer.cxx | 41 ++++++--------
9 files changed, 111 insertions(+), 102 deletions(-)
Index: tigervnc-1.9.0/common/rfb/Cursor.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/Cursor.cxx
+++ tigervnc-1.9.0/common/rfb/Cursor.cxx
@@ -271,8 +271,7 @@ void RenderedCursor::update(PixelBuffer*
assert(cursor);
format = framebuffer->getPF();
- width_ = framebuffer->width();
- height_ = framebuffer->height();
+ setSize(framebuffer->width(), framebuffer->height());
rawOffset = pos.subtract(cursor->hotspot());
clippedRect = Rect(0, 0, cursor->width(), cursor->height())
Index: tigervnc-1.9.0/common/rfb/EncodeManager.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/EncodeManager.cxx
+++ tigervnc-1.9.0/common/rfb/EncodeManager.cxx
@@ -979,11 +979,8 @@ void EncodeManager::OffsetPixelBuffer::u
int stride_)
{
format = pf;
- width_ = width;
- height_ = height;
// Forced cast. We never write anything though, so it should be safe.
- data = (rdr::U8*)data_;
- stride = stride_;
+ setBuffer(width, height, (rdr::U8*)data_, stride_);
}
// Preprocessor generated, optimised methods
Index: tigervnc-1.9.0/common/rfb/PixelBuffer.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/PixelBuffer.cxx
+++ tigervnc-1.9.0/common/rfb/PixelBuffer.cxx
@@ -35,8 +35,14 @@ static LogWriter vlog("PixelBuffer");
// -=- Generic pixel buffer class
PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h)
- : format(pf), width_(w), height_(h) {}
-PixelBuffer::PixelBuffer() : width_(0), height_(0) {}
+ : format(pf), width_(0), height_(0)
+{
+ setSize(w, h);
+}
+
+PixelBuffer::PixelBuffer() : width_(0), height_(0)
+{
+}
PixelBuffer::~PixelBuffer() {}
@@ -53,7 +59,7 @@ PixelBuffer::getImage(void* imageBuf, co
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
r.width(), r.height(),
- r.tl.x, r.tl.y, width_, height_);
+ r.tl.x, r.tl.y, width(), height());
data = getBuffer(r, &inStride);
@@ -89,7 +95,7 @@ void PixelBuffer::getImage(const PixelFo
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
r.width(), r.height(),
- r.tl.x, r.tl.y, width_, height_);
+ r.tl.x, r.tl.y, width(), height());
if (stride == 0)
stride = r.width();
@@ -100,6 +106,12 @@ void PixelBuffer::getImage(const PixelFo
stride, srcStride);
}
+void PixelBuffer::setSize(int width, int height)
+{
+ width_ = width;
+ height_ = height;
+}
+
// -=- Modifiable generic pixel buffer class
ModifiablePixelBuffer::ModifiablePixelBuffer(const PixelFormat& pf,
@@ -124,7 +136,7 @@ void ModifiablePixelBuffer::fillRect(con
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
- r.width(), r.height(), r.tl.x, r.tl.y, width_,
height_);
+ r.width(), r.height(), r.tl.x, r.tl.y, width(),
height());
w = r.width();
h = r.height();
@@ -175,7 +187,7 @@ void ModifiablePixelBuffer::imageRect(co
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
r.width(), r.height(),
- r.tl.x, r.tl.y, width_, height_);
+ r.tl.x, r.tl.y, width(), height());
bytesPerPixel = getPF().bpp/8;
@@ -213,13 +225,13 @@ void ModifiablePixelBuffer::copyRect(con
if (!drect.enclosed_by(getRect()))
throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
drect.width(), drect.height(),
- drect.tl.x, drect.tl.y, width_, height_);
+ drect.tl.x, drect.tl.y, width(), height());
srect = drect.translate(move_by_delta.negate());
if (!srect.enclosed_by(getRect()))
throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
srect.width(), srect.height(),
- srect.tl.x, srect.tl.y, width_, height_);
+ srect.tl.x, srect.tl.y, width(), height());
srcData = getBuffer(srect, &srcStride);
dstData = getBufferRW(drect, &dstStride);
@@ -272,7 +284,7 @@ void ModifiablePixelBuffer::imageRect(co
if (!dest.enclosed_by(getRect()))
throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer
%dx%d",
dest.width(), dest.height(),
- dest.tl.x, dest.tl.y, width_, height_);
+ dest.tl.x, dest.tl.y, width(), height());
if (stride == 0)
stride = dest.width();
@@ -301,7 +313,7 @@ rdr::U8* FullFramePixelBuffer::getBuffer
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds
framebuffer %dx%d",
r.width(), r.height(),
- r.tl.x, r.tl.y, width_, height_);
+ r.tl.x, r.tl.y, width(), height());
*stride_ = stride;
return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8];
@@ -316,55 +328,67 @@ const rdr::U8* FullFramePixelBuffer::get
if (!r.enclosed_by(getRect()))
throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds
framebuffer %dx%d",
r.width(), r.height(),
- r.tl.x, r.tl.y, width_, height_);
+ r.tl.x, r.tl.y, width(), height());
*stride_ = stride;
return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8];
}
+void FullFramePixelBuffer::setBuffer(int width, int height,
+ rdr::U8* data_, int stride_)
+{
+ ModifiablePixelBuffer::setSize(width, height);
+ stride = stride_;
+ data = data_;
+}
+
+void FullFramePixelBuffer::setSize(int w, int h)
+{
+ // setBuffer() should be used
+ throw rfb::Exception("Invalid call to FullFramePixelBuffer::setSize()");
+}
+
// -=- Managed pixel buffer class
// Automatically allocates enough space for the specified format & area
ManagedPixelBuffer::ManagedPixelBuffer()
- : datasize(0)
+ : data_(NULL), datasize(0)
{
- checkDataSize();
-};
+}
ManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h)
- : FullFramePixelBuffer(pf, w, h, NULL, w), datasize(0)
+ : FullFramePixelBuffer(pf, 0, 0, NULL, 0), data_(NULL), datasize(0)
{
- checkDataSize();
-};
-
-ManagedPixelBuffer::~ManagedPixelBuffer() {
- if (data) delete [] data;
-};
-
+ setSize(w, h);
+}
-void
-ManagedPixelBuffer::setPF(const PixelFormat &pf) {
- format = pf; checkDataSize();
-};
-void
-ManagedPixelBuffer::setSize(int w, int h) {
- width_ = w; height_ = h; stride = w; checkDataSize();
-};
+ManagedPixelBuffer::~ManagedPixelBuffer()
+{
+ if (data_)
+ delete [] data_;
+}
+void ManagedPixelBuffer::setPF(const PixelFormat &pf)
+{
+ format = pf;
+ setSize(width(), height());
+}
+
+void ManagedPixelBuffer::setSize(int w, int h)
+{
+ unsigned long new_datasize = w * h * (format.bpp/8);
-inline void
-ManagedPixelBuffer::checkDataSize() {
- unsigned long new_datasize = width_ * height_ * (format.bpp/8);
+ new_datasize = w * h * (format.bpp/8);
if (datasize < new_datasize) {
- if (data) {
- delete [] data;
- datasize = 0; data = 0;
+ if (data_) {
+ delete [] data_;
+ data_ = NULL;
+ datasize = 0;
}
if (new_datasize) {
- data = new U8[new_datasize];
- if (!data)
- throw Exception("rfb::ManagedPixelBuffer unable to allocate buffer");
+ data_ = new U8[new_datasize];
datasize = new_datasize;
}
}
+ setBuffer(w, h, data_, w);
};
Index: tigervnc-1.9.0/common/rfb/PixelBuffer.h
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/PixelBuffer.h
+++ tigervnc-1.9.0/common/rfb/PixelBuffer.h
@@ -90,7 +90,12 @@ namespace rfb {
protected:
PixelBuffer();
+ virtual void setSize(int width, int height);
+
+ protected:
PixelFormat format;
+
+ private:
int width_, height_;
};
@@ -154,7 +159,12 @@ namespace rfb {
protected:
FullFramePixelBuffer();
+ virtual void setBuffer(int width, int height, rdr::U8* data, int stride);
+ private:
+ virtual void setSize(int w, int h);
+
+ private:
rdr::U8* data;
int stride;
};
@@ -172,12 +182,9 @@ namespace rfb {
virtual void setPF(const PixelFormat &pf);
virtual void setSize(int w, int h);
- // Return the total number of bytes of pixel data in the buffer
- int dataLen() const { return width_ * height_ * (format.bpp/8); }
-
- protected:
+ private:
+ rdr::U8* data_; // Mirrors FullFramePixelBuffer::data
unsigned long datasize;
- void checkDataSize();
};
};
Index: tigervnc-1.9.0/unix/x0vncserver/XPixelBuffer.cxx
===================================================================
--- tigervnc-1.9.0.orig/unix/x0vncserver/XPixelBuffer.cxx
+++ tigervnc-1.9.0/unix/x0vncserver/XPixelBuffer.cxx
@@ -50,13 +50,8 @@ XPixelBuffer::XPixelBuffer(Display *dpy,
ffs(m_image->xim->blue_mask) - 1);
// Set up the remaining data of the parent class.
- width_ = rect.width();
- height_ = rect.height();
- data = (rdr::U8 *)m_image->xim->data;
-
- // Calculate the distance in pixels between two subsequent scan
- // lines of the framebuffer. This may differ from image width.
- stride = m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel;
+ setBuffer(rect.width(), rect.height(), (rdr::U8 *)m_image->xim->data,
+ m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel);
// Get initial screen image from the X display.
m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop);
Index: tigervnc-1.9.0/unix/xserver/hw/vnc/XserverDesktop.cc
===================================================================
--- tigervnc-1.9.0.orig/unix/xserver/hw/vnc/XserverDesktop.cc
+++ tigervnc-1.9.0/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -115,7 +115,7 @@ XserverDesktop::XserverDesktop(int scree
: screenIndex(screenIndex_),
server(0), httpServer(0),
listeners(listeners_), httpListeners(httpListeners_),
- directFbptr(true),
+ shadowFramebuffer(NULL),
queryConnectId(0), queryConnectTimer(this)
{
format = pf;
@@ -152,8 +152,8 @@ XserverDesktop::~XserverDesktop()
delete httpListeners.back();
httpListeners.pop_back();
}
- if (!directFbptr)
- delete [] data;
+ if (shadowFramebuffer)
+ delete [] shadowFramebuffer;
delete httpServer;
delete server;
}
@@ -172,22 +172,18 @@ void XserverDesktop::setFramebuffer(int
{
ScreenSet layout;
- width_ = w;
- height_ = h;
-
- if (!directFbptr) {
- delete [] data;
- directFbptr = true;
+ if (shadowFramebuffer) {
+ delete [] shadowFramebuffer;
+ shadowFramebuffer = NULL;
}
if (!fbptr) {
- fbptr = new rdr::U8[w * h * (format.bpp/8)];
+ shadowFramebuffer = new rdr::U8[w * h * (format.bpp/8)];
+ fbptr = shadowFramebuffer;
stride_ = w;
- directFbptr = false;
}
- data = (rdr::U8*)fbptr;
- stride = stride_;
+ setBuffer(w, h, (rdr::U8*)fbptr, stride_);
vncSetGlueContext(screenIndex);
layout = ::computeScreenLayout(&outputIdMap);
@@ -569,7 +565,7 @@ unsigned int XserverDesktop::setScreenLa
void XserverDesktop::grabRegion(const rfb::Region& region)
{
- if (directFbptr)
+ if (shadowFramebuffer == NULL)
return;
std::vector<rfb::Rect> rects;
Index: tigervnc-1.9.0/unix/xserver/hw/vnc/XserverDesktop.h
===================================================================
--- tigervnc-1.9.0.orig/unix/xserver/hw/vnc/XserverDesktop.h
+++ tigervnc-1.9.0/unix/xserver/hw/vnc/XserverDesktop.h
@@ -124,7 +124,7 @@ private:
rfb::HTTPServer* httpServer;
std::list<network::SocketListener*> listeners;
std::list<network::SocketListener*> httpListeners;
- bool directFbptr;
+ rdr::U8* shadowFramebuffer;
uint32_t queryConnectId;
network::Socket* queryConnectSocket;
Index: tigervnc-1.9.0/vncviewer/PlatformPixelBuffer.cxx
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/PlatformPixelBuffer.cxx
+++ tigervnc-1.9.0/vncviewer/PlatformPixelBuffer.cxx
@@ -36,7 +36,7 @@ static rfb::LogWriter vlog("PlatformPixe
PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) :
FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true,
255, 255, 255, 16, 8, 0),
- width, height, 0, stride),
+ 0, 0, NULL, 0),
Surface(width, height)
#if !defined(WIN32) && !defined(__APPLE__)
, shminfo(NULL), xim(NULL)
@@ -56,11 +56,10 @@ PlatformPixelBuffer::PlatformPixelBuffer
vlog.debug("Using standard XImage");
}
- data = (rdr::U8*)xim->data;
- stride = xim->bytes_per_line / (getPF().bpp/8);
+ setBuffer(width, height, (rdr::U8*)xim->data,
+ xim->bytes_per_line / (getPF().bpp/8));
#else
- FullFramePixelBuffer::data = (rdr::U8*)Surface::data;
- stride = width;
+ setBuffer(width, height, (rdr::U8*)Surface::data, width);
#endif
}
Index: tigervnc-1.9.0/win/rfb_win32/DIBSectionBuffer.cxx
===================================================================
--- tigervnc-1.9.0.orig/win/rfb_win32/DIBSectionBuffer.cxx
+++ tigervnc-1.9.0/win/rfb_win32/DIBSectionBuffer.cxx
@@ -52,39 +52,28 @@ void DIBSectionBuffer::setPF(const Pixel
if (!pf.trueColour)
throw rfb::Exception("palette format not supported");
format = pf;
- recreateBuffer();
+ setSize(width(), height());
}
-void DIBSectionBuffer::setSize(int w, int h) {
- if (width_ == w && height_ == h) {
- vlog.debug("size unchanged by setSize()");
- return;
- }
- width_ = w;
- height_ = h;
- recreateBuffer();
-}
-
-
inline void initMaxAndShift(DWORD mask, int* max, int* shift) {
for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1;
(*max) = (rdr::U16)mask;
}
-void DIBSectionBuffer::recreateBuffer() {
+void DIBSectionBuffer::setSize(int w, int h) {
HBITMAP new_bitmap = 0;
rdr::U8* new_data = 0;
- if (width_ && height_ && (format.depth != 0)) {
+ if (w && h && (format.depth != 0)) {
BitmapInfo bi;
memset(&bi, 0, sizeof(bi));
UINT iUsage = DIB_RGB_COLORS;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = format.bpp;
- bi.bmiHeader.biSizeImage = (format.bpp / 8) * width_ * height_;
+ bi.bmiHeader.biSizeImage = (format.bpp / 8) * w * h;
bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biWidth = width_;
- bi.bmiHeader.biHeight = -height_;
+ bi.bmiHeader.biWidth = w;
+ bi.bmiHeader.biHeight = -h;
bi.bmiHeader.biCompression = (format.bpp > 8) ? BI_BITFIELDS : BI_RGB;
bi.mask.red = format.pixelFromRGB((rdr::U16)~0, 0, 0);
bi.mask.green = format.pixelFromRGB(0, (rdr::U16)~0, 0);
@@ -115,12 +104,12 @@ void DIBSectionBuffer::recreateBuffer()
if (device) {
BitmapDC src_dev(device, bitmap);
BitmapDC dest_dev(device, new_bitmap);
- BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
+ BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);
} else {
WindowDC wndDC(window);
BitmapDC src_dev(wndDC, bitmap);
BitmapDC dest_dev(wndDC, new_bitmap);
- BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY);
+ BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY);
}
}
@@ -128,17 +117,17 @@ void DIBSectionBuffer::recreateBuffer()
// Delete the old bitmap
DeleteObject(bitmap);
bitmap = 0;
- data = 0;
+ setBuffer(0, 0, NULL, 0);
}
if (new_bitmap) {
int bpp, depth;
int redMax, greenMax, blueMax;
int redShift, greenShift, blueShift;
+ int new_stride;
// Set up the new bitmap
bitmap = new_bitmap;
- data = new_data;
// Determine the *actual* DIBSection format
DIBSECTION ds;
@@ -147,14 +136,16 @@ void DIBSectionBuffer::recreateBuffer()
// Correct the "stride" of the DIB
// *** This code DWORD aligns each row - is that right???
- stride = width_;
- int bytesPerRow = stride * format.bpp/8;
+ new_stride = w;
+ int bytesPerRow = new_stride * format.bpp/8;
if (bytesPerRow % 4) {
bytesPerRow += 4 - (bytesPerRow % 4);
- stride = (bytesPerRow * 8) / format.bpp;
- vlog.info("adjusting DIB stride: %d to %d", width_, stride);
+ new_stride = (bytesPerRow * 8) / format.bpp;
+ vlog.info("adjusting DIB stride: %d to %d", w, new_stride);
}
+ setBuffer(w, h, new_data, new_stride);
+
// Calculate the PixelFormat for the DIB
bpp = depth = ds.dsBm.bmBitsPixel;
++++++ 0003-Restrict-PixelBuffer-dimensions-to-safe-values.patch ++++++
>From 996356b6c65ca165ee1ea46a571c32a1dc3c3821 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 15:21:03 +0200
Subject: [PATCH] Restrict PixelBuffer dimensions to safe values
We do a lot of calculations based on pixel coordinates and we need
to make sure they do not overflow. Restrict the maximum dimensions
we support rather than try to switch over all calculations to use
64 bit integers.
This prevents attackers from from injecting code by specifying a
huge framebuffer size and relying on the values overflowing to
access invalid areas of the heap.
This primarily affects the client which gets both the screen
dimensions and the pixel contents from the remote side. But the
server might also be affected as a client can adjust the screen
dimensions, as can applications inside the session.
Issue found by Pavel Cheremushkin from Kaspersky Lab.
---
common/rfb/PixelBuffer.cxx | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx
index 0aa67744..fe406b96 100644
--- a/common/rfb/PixelBuffer.cxx
+++ b/common/rfb/PixelBuffer.cxx
@@ -31,6 +31,14 @@ using namespace rdr;
static LogWriter vlog("PixelBuffer");
+// We do a lot of byte offset calculations that assume the result fits
+// inside a signed 32 bit integer. Limit the maximum size of pixel
+// buffers so that these calculations never overflow.
+
+const int maxPixelBufferWidth = 16384;
+const int maxPixelBufferHeight = 16384;
+const int maxPixelBufferStride = 16384;
+
// -=- Generic pixel buffer class
@@ -108,6 +116,11 @@ void PixelBuffer::getImage(const PixelFormat& pf, void*
imageBuf,
void PixelBuffer::setSize(int width, int height)
{
+ if ((width < 0) || (width > maxPixelBufferWidth))
+ throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested",
width);
+ if ((height < 0) || (height > maxPixelBufferHeight))
+ throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested",
height);
+
width_ = width;
height_ = height;
}
@@ -340,6 +353,15 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect&
r, int* stride_) cons
void FullFramePixelBuffer::setBuffer(int width, int height,
rdr::U8* data_, int stride_)
{
+ if ((width < 0) || (width > maxPixelBufferWidth))
+ throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested",
width);
+ if ((height < 0) || (height > maxPixelBufferHeight))
+ throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested",
height);
+ if ((stride_ < 0) || (stride_ > maxPixelBufferStride) || (stride_ < width))
+ throw rfb::Exception("Invalid PixelBuffer stride of %d pixels requested",
stride_);
+ if ((width != 0) && (height != 0) && (data_ == NULL))
+ throw rfb::Exception("PixelBuffer requested without a valid memory area");
+
ModifiablePixelBuffer::setSize(width, height);
stride = stride_;
data = data_;
--
2.16.4
++++++ 0004-Add-write-protection-to-OffsetPixelBuffer.patch ++++++
>From 9f615301aba1cc54a749950bf9462c5a85217bc4 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 15:25:30 +0200
Subject: [PATCH] Add write protection to OffsetPixelBuffer
No one should every try to write to this buffer. Enforce that by
throwing an exception if any one tries to get a writeable pointer
to the data.
---
common/rfb/EncodeManager.cxx | 6 ++++++
common/rfb/EncodeManager.h | 3 +++
2 files changed, 9 insertions(+)
diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx
index 54f7102b..92ac5676 100644
--- a/common/rfb/EncodeManager.cxx
+++ b/common/rfb/EncodeManager.cxx
@@ -28,6 +28,7 @@
#include <rfb/SMsgWriter.h>
#include <rfb/UpdateTracker.h>
#include <rfb/LogWriter.h>
+#include <rfb/Exception.h>
#include <rfb/RawEncoder.h>
#include <rfb/RREEncoder.h>
@@ -1053,6 +1054,11 @@ void EncodeManager::OffsetPixelBuffer::update(const
PixelFormat& pf,
setBuffer(width, height, (rdr::U8*)data_, stride_);
}
+rdr::U8* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& r, int*
stride)
+{
+ throw rfb::Exception("Invalid write attempt to OffsetPixelBuffer");
+}
+
// Preprocessor generated, optimised methods
#define BPP 8
diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h
index bdae9063..f8201c34 100644
--- a/common/rfb/EncodeManager.h
+++ b/common/rfb/EncodeManager.h
@@ -148,6 +148,9 @@ namespace rfb {
void update(const PixelFormat& pf, int width, int height,
const rdr::U8* data_, int stride);
+
+ private:
+ virtual rdr::U8* getBufferRW(const Rect& r, int* stride);
};
OffsetPixelBuffer offsetPixelBuffer;
--
2.16.4
++++++ 0005-Handle-empty-Tight-gradient-rects.patch ++++++
>From b4ada8d0c6dac98c8b91fc64d112569a8ae5fb95 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 15:36:42 +0200
Subject: [PATCH] Handle empty Tight gradient rects
We always assumed there would be one pixel per row so a rect with
a zero width would result in us writing to unknown memory.
This could theoretically be used by a malicious server to inject
code in to the viewer process.
Issue found by Pavel Cheremushkin from Kaspersky Lab.
---
common/rfb/tightDecode.h | 37 +++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h
index b6e86ed5..8f77aebd 100644
--- a/common/rfb/tightDecode.h
+++ b/common/rfb/tightDecode.h
@@ -56,15 +56,17 @@ TightDecoder::FilterGradient24(const rdr::U8 *inbuf,
int rectWidth = r.width();
for (y = 0; y < rectHeight; y++) {
- /* First pixel in a row */
- for (c = 0; c < 3; c++) {
- pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];
- thisRow[c] = pix[c];
- }
- pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+ for (x = 0; x < rectWidth; x++) {
+ /* First pixel in a row */
+ if (x == 0) {
+ for (c = 0; c < 3; c++) {
+ pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c];
+ thisRow[c] = pix[c];
+ }
+ pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+ continue;
+ }
- /* Remaining pixels of a row */
- for (x = 1; x < rectWidth; x++) {
for (c = 0; c < 3; c++) {
est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
if (est[c] > 0xff) {
@@ -103,17 +105,20 @@ void TightDecoder::FilterGradient(const rdr::U8* inbuf,
int rectWidth = r.width();
for (y = 0; y < rectHeight; y++) {
- /* First pixel in a row */
- pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);
- for (c = 0; c < 3; c++)
- pix[c] += prevRow[c];
+ for (x = 0; x < rectWidth; x++) {
+ /* First pixel in a row */
+ if (x == 0) {
+ pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1);
+ for (c = 0; c < 3; c++)
+ pix[c] += prevRow[c];
- memcpy(thisRow, pix, sizeof(pix));
+ memcpy(thisRow, pix, sizeof(pix));
- pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+ pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1);
+
+ continue;
+ }
- /* Remaining pixels of a row */
- for (x = 1; x < rectWidth; x++) {
for (c = 0; c < 3; c++) {
est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
if (est[c] > 255) {
--
2.16.4
++++++ 0006-Add-unit-test-for-PixelFormat-sanity-checks.patch ++++++
>From 014c5012377519d7f0add23ebac077ccd882aa9f Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 15:59:51 +0200
Subject: [PATCH] Add unit test for PixelFormat sanity checks
---
common/rfb/PixelFormat.cxx | 3 +-
tests/unit/CMakeLists.txt | 3 ++
tests/unit/pixelformat.cxx | 114 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/pixelformat.cxx
Index: tigervnc-1.9.0/common/rfb/PixelFormat.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/PixelFormat.cxx
+++ tigervnc-1.9.0/common/rfb/PixelFormat.cxx
@@ -81,7 +81,8 @@ PixelFormat::PixelFormat(int b, int d, b
redMax(rm), greenMax(gm), blueMax(bm),
redShift(rs), greenShift(gs), blueShift(bs)
{
- assert(isSane());
+ if (!isSane())
+ throw Exception("invalid pixel format");
updateState();
}
Index: tigervnc-1.9.0/tests/unit/pixelformat.cxx
===================================================================
--- /dev/null
+++ tigervnc-1.9.0/tests/unit/pixelformat.cxx
@@ -0,0 +1,114 @@
+/* Copyright 2019 Pierre Ossman <[email protected]> for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <stdio.h>
+
+#include <rfb/PixelFormat.h>
+#include <rfb/Exception.h>
+
+static void doTest(bool should_fail, int b, int d, bool e, bool t,
+ int rm, int gm, int bm, int rs, int gs, int bs)
+{
+ rfb::PixelFormat* pf;
+
+ printf("PixelFormat(%d, %d, %s, %s, %d, %d, %d, %d, %d, %d): ",
+ b, d, e ? "true" : "false", t ? "true": "false",
+ rm, gm, bm, rs, gs, bs);
+
+ try {
+ pf = new rfb::PixelFormat(b, d, e, t, rm, gm, bm, rs, gs, bs);
+ } catch(rfb::Exception &e) {
+ if (should_fail)
+ printf("OK");
+ else
+ printf("FAILED");
+ printf("\n");
+ fflush(stdout);
+ return;
+ }
+
+ delete pf;
+
+ if (should_fail)
+ printf("FAILED");
+ else
+ printf("OK");
+ printf("\n");
+ fflush(stdout);
+}
+
+int main(int argc, char** argv)
+{
+ /* Normal true color formats */
+
+ doTest(false, 32, 24, false, true, 255, 255, 255, 0, 8, 16);
+ doTest(false, 32, 24, false, true, 255, 255, 255, 24, 16, 8);
+
+ doTest(false, 16, 16, false, true, 15, 31, 15, 0, 5, 11);
+
+ doTest(false, 8, 8, false, true, 3, 7, 3, 0, 2, 5);
+
+ /* Excessive bpp */
+
+ doTest(false, 32, 16, false, true, 15, 31, 15, 0, 5, 11);
+
+ doTest(false, 16, 16, false, true, 15, 31, 15, 0, 5, 11);
+
+ doTest(false, 32, 8, false, true, 3, 7, 3, 0, 2, 5);
+
+ doTest(false, 16, 8, false, true, 3, 7, 3, 0, 2, 5);
+
+ /* Colour map */
+
+ doTest(false, 8, 8, false, false, 0, 0, 0, 0, 0, 0);
+
+ /* Invalid bpp */
+
+ doTest(true, 64, 24, false, true, 255, 255, 255, 0, 8, 16);
+
+ doTest(true, 18, 16, false, true, 15, 31, 15, 0, 5, 11);
+
+ doTest(true, 3, 3, false, true, 1, 1, 1, 0, 1, 2);
+
+ /* Invalid depth */
+
+ doTest(true, 16, 24, false, true, 15, 31, 15, 0, 5, 11);
+
+ doTest(true, 8, 24, false, true, 3, 7, 3, 0, 2, 5);
+ doTest(true, 8, 16, false, true, 3, 7, 3, 0, 2, 5);
+
+ doTest(true, 32, 24, false, false, 0, 0, 0, 0, 0, 0);
+
+ /* Invalid max values */
+
+ doTest(true, 32, 24, false, true, 254, 255, 255, 0, 8, 16);
+ doTest(true, 32, 24, false, true, 255, 253, 255, 0, 8, 16);
+ doTest(true, 32, 24, false, true, 255, 255, 252, 0, 8, 16);
+
+ doTest(true, 32, 24, false, true, 511, 127, 127, 0, 16, 20);
+ doTest(true, 32, 24, false, true, 127, 511, 127, 0, 4, 20);
+ doTest(true, 32, 24, false, true, 127, 127, 511, 0, 4, 8);
+
+ /* Overlapping channels */
+
+ doTest(true, 32, 24, false, true, 255, 255, 255, 0, 7, 16);
+ doTest(true, 32, 24, false, true, 255, 255, 255, 0, 8, 15);
+ doTest(true, 32, 24, false, true, 255, 255, 255, 0, 16, 7);
+
+ return 0;
+}
++++++ 0007-Fix-depth-sanity-test-in-PixelFormat.patch ++++++
>From f1b9b868ec943d51ef631f53a095d48d3f178f4f Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 16:01:44 +0200
Subject: [PATCH] Fix depth sanity test in PixelFormat
---
common/rfb/PixelFormat.cxx | 2 +-
tests/unit/pixelformat.cxx | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx
index 0be4d1da..2d8142d1 100644
--- a/common/rfb/PixelFormat.cxx
+++ b/common/rfb/PixelFormat.cxx
@@ -679,7 +679,7 @@ bool PixelFormat::isSane(void)
return false;
totalBits = bits(redMax) + bits(greenMax) + bits(blueMax);
- if (totalBits > bpp)
+ if (totalBits > depth)
return false;
if (((redMax << redShift) & (greenMax << greenShift)) != 0)
diff --git a/tests/unit/pixelformat.cxx b/tests/unit/pixelformat.cxx
index 4eb45281..7b6087f7 100644
--- a/tests/unit/pixelformat.cxx
+++ b/tests/unit/pixelformat.cxx
@@ -104,6 +104,10 @@ int main(int argc, char** argv)
doTest(true, 32, 24, false, true, 127, 511, 127, 0, 4, 20);
doTest(true, 32, 24, false, true, 127, 127, 511, 0, 4, 8);
+ /* Insufficient depth */
+
+ doTest(true, 32, 16, false, true, 255, 255, 255, 0, 8, 16);
+
/* Overlapping channels */
doTest(true, 32, 24, false, true, 255, 255, 255, 0, 7, 16);
--
2.16.4
++++++ 0008-Add-sanity-checks-for-PixelFormat-shift-values.patch ++++++
>From cd1d650c532a46e95a1229dffaf281c76a50cdfe Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 10 Sep 2019 16:07:50 +0200
Subject: [PATCH] Add sanity checks for PixelFormat shift values
Otherwise we might be tricked in to reading and writing things at
incorrect offsets for pixels which ultimately could result in an
attacker writing things to the stack or heap and executing things
they shouldn't.
This only affects the server as the client never uses the pixel
format suggested by th server.
Issue found by Pavel Cheremushkin from Kaspersky Lab.
---
common/rfb/PixelFormat.cxx | 7 +++++++
tests/unit/pixelformat.cxx | 6 ++++++
2 files changed, 13 insertions(+)
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx
index 2d8142d1..789c43ed 100644
--- a/common/rfb/PixelFormat.cxx
+++ b/common/rfb/PixelFormat.cxx
@@ -682,6 +682,13 @@ bool PixelFormat::isSane(void)
if (totalBits > depth)
return false;
+ if ((bits(redMax) + redShift) > bpp)
+ return false;
+ if ((bits(greenMax) + greenShift) > bpp)
+ return false;
+ if ((bits(blueMax) + blueShift) > bpp)
+ return false;
+
if (((redMax << redShift) & (greenMax << greenShift)) != 0)
return false;
if (((redMax << redShift) & (blueMax << blueShift)) != 0)
diff --git a/tests/unit/pixelformat.cxx b/tests/unit/pixelformat.cxx
index 7b6087f7..46fecfb4 100644
--- a/tests/unit/pixelformat.cxx
+++ b/tests/unit/pixelformat.cxx
@@ -108,6 +108,12 @@ int main(int argc, char** argv)
doTest(true, 32, 16, false, true, 255, 255, 255, 0, 8, 16);
+ /* Invalid shift values */
+
+ doTest(true, 32, 24, false, true, 255, 255, 255, 25, 8, 16);
+ doTest(true, 32, 24, false, true, 255, 255, 255, 0, 25, 16);
+ doTest(true, 32, 24, false, true, 255, 255, 255, 0, 8, 25);
+
/* Overlapping channels */
doTest(true, 32, 24, false, true, 255, 255, 255, 0, 7, 16);
--
2.16.4
++++++ 0009-Remove-unused-FixedMemOutStream.patch ++++++
>From 4ff58f0acaeb566b79ae12cf013b376eaaaab834 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Mon, 23 Sep 2019 10:09:31 +0200
Subject: [PATCH] Remove unused FixedMemOutStream
---
common/rdr/FixedMemOutStream.h | 52 ------------------------------------------
1 file changed, 52 deletions(-)
delete mode 100644 common/rdr/FixedMemOutStream.h
diff --git a/common/rdr/FixedMemOutStream.h b/common/rdr/FixedMemOutStream.h
deleted file mode 100644
index e4ec52cb..00000000
--- a/common/rdr/FixedMemOutStream.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-//
-// A FixedMemOutStream writes to a buffer of a fixed length.
-//
-
-#ifndef __RDR_FIXEDMEMOUTSTREAM_H__
-#define __RDR_FIXEDMEMOUTSTREAM_H__
-
-#include <rdr/OutStream.h>
-#include <rdr/Exception.h>
-
-namespace rdr {
-
- class FixedMemOutStream : public OutStream {
-
- public:
-
- FixedMemOutStream(void* buf, int len) {
- ptr = start = (U8*)buf;
- end = start + len;
- }
-
- int length() { return ptr - start; }
- void reposition(int pos) { ptr = start + pos; }
- const void* data() { return (const void*)start; }
-
- private:
-
- int overrun(int itemSize, int nItems) { throw EndOfStream(); }
- U8* start;
- };
-
-}
-
-#endif
--
2.16.4
++++++ 0010-Use-size_t-for-lengths-in-stream-objects.patch ++++++
++++ 1427 lines (skipped)
++++++ 0011-Be-defensive-about-overflows-in-stream-objects.patch ++++++
>From 75e6e0653a48baf474fd45d78b1da53e2f324642 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Tue, 24 Sep 2019 09:41:07 +0200
Subject: [PATCH] Be defensive about overflows in stream objects
We use a lot of lengths given to us over the network, so be more
paranoid about them causing an overflow as otherwise an attacker
might trick us in to overwriting other memory.
This primarily affects the client which often gets lengths from the
server, but there are also some scenarios where the server might
theoretically be vulnerable.
Issue found by Pavel Cheremushkin from Kaspersky Lab.
---
common/rdr/FdInStream.cxx | 8 +++++---
common/rdr/FdOutStream.cxx | 7 ++++---
common/rdr/FileInStream.cxx | 8 +++++---
common/rdr/HexInStream.cxx | 8 +++++---
common/rdr/HexOutStream.cxx | 6 ++++--
common/rdr/InStream.h | 24 +++++++++++++-----------
common/rdr/MemOutStream.h | 4 ++++
common/rdr/OutStream.h | 24 +++++++++++++-----------
common/rdr/RandomStream.cxx | 6 ++++--
common/rdr/TLSInStream.cxx | 10 ++++++----
common/rdr/TLSOutStream.cxx | 6 ++++--
common/rdr/ZlibInStream.cxx | 6 ++++--
common/rdr/ZlibOutStream.cxx | 6 ++++--
13 files changed, 75 insertions(+), 48 deletions(-)
diff --git a/common/rdr/FdInStream.cxx b/common/rdr/FdInStream.cxx
index 9e84ab7a..1730d6d1 100644
--- a/common/rdr/FdInStream.cxx
+++ b/common/rdr/FdInStream.cxx
@@ -136,7 +136,7 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems,
bool wait)
ptr = start;
size_t bytes_to_read;
- while (end < start + itemSize) {
+ while ((size_t)(end - start) < itemSize) {
bytes_to_read = start + bufSize - end;
if (!timing) {
// When not timing, we must be careful not to read too much
@@ -152,8 +152,10 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems,
bool wait)
end += n;
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx
index 1757dc35..f5d07e4b 100644
--- a/common/rdr/FdOutStream.cxx
+++ b/common/rdr/FdOutStream.cxx
@@ -149,9 +149,10 @@ size_t FdOutStream::overrun(size_t itemSize, size_t nItems)
}
}
- // Can we fit all the items asked for?
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/FileInStream.cxx b/common/rdr/FileInStream.cxx
index 94f5db88..bdb05a3a 100644
--- a/common/rdr/FileInStream.cxx
+++ b/common/rdr/FileInStream.cxx
@@ -68,7 +68,7 @@ size_t FileInStream::overrun(size_t itemSize, size_t nItems,
bool wait)
ptr = b;
- while (end < b + itemSize) {
+ while ((size_t)(end - b) < itemSize) {
size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file);
if (n == 0) {
if (ferror(file))
@@ -80,8 +80,10 @@ size_t FileInStream::overrun(size_t itemSize, size_t nItems,
bool wait)
end += b + sizeof(b) - end;
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/HexInStream.cxx b/common/rdr/HexInStream.cxx
index 8f939889..a6bc92cd 100644
--- a/common/rdr/HexInStream.cxx
+++ b/common/rdr/HexInStream.cxx
@@ -91,7 +91,7 @@ size_t HexInStream::overrun(size_t itemSize, size_t nItems,
bool wait) {
offset += ptr - start;
ptr = start;
- while (end < ptr + itemSize) {
+ while ((size_t)(end - ptr) < itemSize) {
size_t n = in_stream.check(2, 1, wait);
if (n == 0) return 0;
const U8* iptr = in_stream.getptr();
@@ -110,8 +110,10 @@ size_t HexInStream::overrun(size_t itemSize, size_t
nItems, bool wait) {
end += length;
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/HexOutStream.cxx b/common/rdr/HexOutStream.cxx
index 7232514c..eac2eff8 100644
--- a/common/rdr/HexOutStream.cxx
+++ b/common/rdr/HexOutStream.cxx
@@ -102,8 +102,10 @@ HexOutStream::overrun(size_t itemSize, size_t nItems) {
writeBuffer();
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/InStream.h b/common/rdr/InStream.h
index 14ecf093..f71a4d9e 100644
--- a/common/rdr/InStream.h
+++ b/common/rdr/InStream.h
@@ -43,12 +43,15 @@ namespace rdr {
inline size_t check(size_t itemSize, size_t nItems=1, bool wait=true)
{
- if (ptr + itemSize * nItems > end) {
- if (ptr + itemSize > end)
- return overrun(itemSize, nItems, wait);
+ size_t nAvail;
+
+ if (itemSize > (size_t)(end - ptr))
+ return overrun(itemSize, nItems, wait);
+
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
- nItems = (end - ptr) / itemSize;
- }
return nItems;
}
@@ -93,13 +96,12 @@ namespace rdr {
// readBytes() reads an exact number of bytes.
void readBytes(void* data, size_t length) {
- U8* dataPtr = (U8*)data;
- U8* dataEnd = dataPtr + length;
- while (dataPtr < dataEnd) {
- size_t n = check(1, dataEnd - dataPtr);
- memcpy(dataPtr, ptr, n);
+ while (length > 0) {
+ size_t n = check(1, length);
+ memcpy(data, ptr, n);
ptr += n;
- dataPtr += n;
+ data = (U8*)data + n;
+ length -= n;
}
}
diff --git a/common/rdr/MemOutStream.h b/common/rdr/MemOutStream.h
index 4a815b30..b56bac3a 100644
--- a/common/rdr/MemOutStream.h
+++ b/common/rdr/MemOutStream.h
@@ -23,6 +23,7 @@
#ifndef __RDR_MEMOUTSTREAM_H__
#define __RDR_MEMOUTSTREAM_H__
+#include <rdr/Exception.h>
#include <rdr/OutStream.h>
namespace rdr {
@@ -65,6 +66,9 @@ namespace rdr {
if (len < (size_t)(end - start) * 2)
len = (end - start) * 2;
+ if (len < (size_t)(end - start))
+ throw Exception("Overflow in MemOutStream::overrun()");
+
U8* newStart = new U8[len];
memcpy(newStart, start, ptr - start);
ptr = newStart + (ptr - start);
diff --git a/common/rdr/OutStream.h b/common/rdr/OutStream.h
index 11aafd2d..0f60ccc1 100644
--- a/common/rdr/OutStream.h
+++ b/common/rdr/OutStream.h
@@ -46,12 +46,15 @@ namespace rdr {
inline size_t check(size_t itemSize, size_t nItems=1)
{
- if (ptr + itemSize * nItems > end) {
- if (ptr + itemSize > end)
- return overrun(itemSize, nItems);
+ size_t nAvail;
+
+ if (itemSize > (size_t)(end - ptr))
+ return overrun(itemSize, nItems);
+
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
- nItems = (end - ptr) / itemSize;
- }
return nItems;
}
@@ -91,13 +94,12 @@ namespace rdr {
// writeBytes() writes an exact number of bytes.
void writeBytes(const void* data, size_t length) {
- const U8* dataPtr = (const U8*)data;
- const U8* dataEnd = dataPtr + length;
- while (dataPtr < dataEnd) {
- size_t n = check(1, dataEnd - dataPtr);
- memcpy(ptr, dataPtr, n);
+ while (length > 0) {
+ size_t n = check(1, length);
+ memcpy(ptr, data, n);
ptr += n;
- dataPtr += n;
+ data = (U8*)data + n;
+ length -= n;
}
}
diff --git a/common/rdr/RandomStream.cxx b/common/rdr/RandomStream.cxx
index d5f1cc85..1be9b251 100644
--- a/common/rdr/RandomStream.cxx
+++ b/common/rdr/RandomStream.cxx
@@ -126,8 +126,10 @@ size_t RandomStream::overrun(size_t itemSize, size_t
nItems, bool wait) {
*(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx
index d0f94263..3e1172f1 100644
--- a/common/rdr/TLSInStream.cxx
+++ b/common/rdr/TLSInStream.cxx
@@ -43,7 +43,7 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void*
data, size_t size)
return -1;
}
- if (in->getend() - in->getptr() < (ptrdiff_t)size)
+ if ((size_t)(in->getend() - in->getptr()) < size)
size = in->getend() - in->getptr();
in->readBytes(data, size);
@@ -92,15 +92,17 @@ size_t TLSInStream::overrun(size_t itemSize, size_t nItems,
bool wait)
end -= ptr - start;
ptr = start;
- while (end < start + itemSize) {
+ while ((size_t)(end - start) < itemSize) {
size_t n = readTLS((U8*) end, start + bufSize - end, wait);
if (!wait && n == 0)
return 0;
end += n;
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx
index 30c456fe..7d7c3b56 100644
--- a/common/rdr/TLSOutStream.cxx
+++ b/common/rdr/TLSOutStream.cxx
@@ -100,8 +100,10 @@ size_t TLSOutStream::overrun(size_t itemSize, size_t
nItems)
flush();
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/ZlibInStream.cxx b/common/rdr/ZlibInStream.cxx
index e2f971c7..9fcfaf6b 100644
--- a/common/rdr/ZlibInStream.cxx
+++ b/common/rdr/ZlibInStream.cxx
@@ -113,8 +113,10 @@ size_t ZlibInStream::overrun(size_t itemSize, size_t
nItems, bool wait)
return 0;
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
diff --git a/common/rdr/ZlibOutStream.cxx b/common/rdr/ZlibOutStream.cxx
index 26a11315..7a0d692c 100644
--- a/common/rdr/ZlibOutStream.cxx
+++ b/common/rdr/ZlibOutStream.cxx
@@ -130,8 +130,10 @@ size_t ZlibOutStream::overrun(size_t itemSize, size_t
nItems)
}
}
- if (itemSize * nItems > (size_t)(end - ptr))
- nItems = (end - ptr) / itemSize;
+ size_t nAvail;
+ nAvail = (end - ptr) / itemSize;
+ if (nAvail < nItems)
+ return nAvail;
return nItems;
}
--
2.16.4
++++++ 0012-Add-unit-tests-for-PixelFormat.is888-detection.patch ++++++
>From 91bdaa6c87a7f311163b5f1e4bbcd9de584968cd Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Wed, 2 Oct 2019 16:05:34 +0200
Subject: [PATCH] Add unit tests for PixelFormat.is888() detection
---
tests/unit/pixelformat.cxx | 60 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 59 insertions(+), 1 deletion(-)
diff --git a/tests/unit/pixelformat.cxx b/tests/unit/pixelformat.cxx
index 46fecfb4..cfae2f9d 100644
--- a/tests/unit/pixelformat.cxx
+++ b/tests/unit/pixelformat.cxx
@@ -52,8 +52,31 @@ static void doTest(bool should_fail, int b, int d, bool e,
bool t,
fflush(stdout);
}
-int main(int argc, char** argv)
+static void do888Test(bool expected, int b, int d, bool e, bool t,
+ int rm, int gm, int bm, int rs, int gs, int bs)
+{
+ rfb::PixelFormat* pf;
+
+ printf("PixelFormat(%d, %d, %s, %s, %d, %d, %d, %d, %d, %d): ",
+ b, d, e ? "true" : "false", t ? "true": "false",
+ rm, gm, bm, rs, gs, bs);
+
+ pf = new rfb::PixelFormat(b, d, e, t, rm, gm, bm, rs, gs, bs);
+
+ if (pf->is888() == expected)
+ printf("OK");
+ else
+ printf("FAILED");
+ printf("\n");
+ fflush(stdout);
+
+ delete pf;
+}
+
+static void sanityTests()
{
+ printf("Sanity checks:\n\n");
+
/* Normal true color formats */
doTest(false, 32, 24, false, true, 255, 255, 255, 0, 8, 16);
@@ -120,5 +143,40 @@ int main(int argc, char** argv)
doTest(true, 32, 24, false, true, 255, 255, 255, 0, 8, 15);
doTest(true, 32, 24, false, true, 255, 255, 255, 0, 16, 7);
+ printf("\n");
+}
+
+void is888Tests()
+{
+ printf("Simple format detection:\n\n");
+
+ /* Positive cases */
+
+ do888Test(true, 32, 24, false, true, 255, 255, 255, 0, 8, 16);
+ do888Test(true, 32, 24, false, true, 255, 255, 255, 24, 16, 8);
+ do888Test(true, 32, 24, false, true, 255, 255, 255, 24, 8, 0);
+
+ /* Low depth */
+
+ do888Test(false, 32, 16, false, true, 15, 31, 15, 0, 8, 16);
+ do888Test(false, 32, 8, false, true, 3, 7, 3, 0, 8, 16);
+
+ /* Low bpp and depth */
+
+ do888Test(false, 16, 16, false, true, 15, 31, 15, 0, 5, 11);
+ do888Test(false, 8, 8, false, true, 3, 7, 3, 0, 2, 5);
+
+ /* Colour map */
+
+ do888Test(false, 8, 8, false, false, 0, 0, 0, 0, 0, 0);
+
+ printf("\n");
+}
+
+int main(int argc, char** argv)
+{
+ sanityTests();
+ is888Tests();
+
return 0;
}
--
2.16.4
++++++ 0013-Handle-pixel-formats-with-odd-shift-values.patch ++++++
>From 05e28490873a861379c943bf616614b78b558b89 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Wed, 2 Oct 2019 16:06:08 +0200
Subject: [PATCH] Handle pixel formats with odd shift values
Our fast paths assume that each channel fits in to a separate byte.
That means the shift needs to be a multiple of 8. Start actually
checking this so that a client cannot trip us up and possibly cause
incorrect code exection.
Issue found by Pavel Cheremushkin from Kaspersky Lab.
---
common/rfb/PixelFormat.cxx | 6 ++++++
tests/unit/pixelformat.cxx | 6 ++++++
2 files changed, 12 insertions(+)
diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx
index 789c43ed..1b4ab1ba 100644
--- a/common/rfb/PixelFormat.cxx
+++ b/common/rfb/PixelFormat.cxx
@@ -206,6 +206,12 @@ bool PixelFormat::is888(void) const
return false;
if (blueMax != 255)
return false;
+ if ((redShift & 0x7) != 0)
+ return false;
+ if ((greenShift & 0x7) != 0)
+ return false;
+ if ((blueShift & 0x7) != 0)
+ return false;
return true;
}
diff --git a/tests/unit/pixelformat.cxx b/tests/unit/pixelformat.cxx
index cfae2f9d..2e0c0bbb 100644
--- a/tests/unit/pixelformat.cxx
+++ b/tests/unit/pixelformat.cxx
@@ -170,6 +170,12 @@ void is888Tests()
do888Test(false, 8, 8, false, false, 0, 0, 0, 0, 0, 0);
+ /* Odd shifts */
+
+ do888Test(false, 32, 24, false, true, 255, 255, 255, 0, 8, 18);
+ do888Test(false, 32, 24, false, true, 255, 255, 255, 0, 11, 24);
+ do888Test(false, 32, 24, false, true, 255, 255, 255, 4, 16, 24);
+
printf("\n");
}
--
2.16.4
++++++ 10-libvnc.conf ++++++
# This file contains configuration of libvnc.so module
#
# To get libvnc.so module working, do this:
# 1. run "vncpasswd" as root user
# 2. uncomment configuration lines below
#
# Please note you can specify any option which Xvnc accepts.
# Refer to `Xvnc -help` output for detailed list of options.
#Section "Module"
# Load "vnc"
#EndSection
#Section "Screen"
# Identifier "Screen0"
# Option "SecurityTypes" "VncAuth"
# Option "PasswordFile" "/root/.vnc/passwd"
#EndSection
++++++ U_0001-Properly-store-certificate-exceptions.patch ++++++
>From b30f10c681ec87720cff85d490f67098568a9cba Mon Sep 17 00:00:00 2001
From: Pierre Ossman <[email protected]>
Date: Thu, 21 May 2020 21:10:38 +0200
Subject: [PATCH] Properly store certificate exceptions
The previous method stored the certificates as authorities, meaning that
the owner of that certificate could impersonate any server it wanted
after a client had added an exception.
Handle this more properly by only storing exceptions for specific
hostname/certificate combinations, the same way browsers or SSH does
things.
---
common/rfb/CSecurityTLS.cxx | 163 ++++++++++++++++++++------------------------
1 file changed, 73 insertions(+), 90 deletions(-)
Index: tigervnc-1.9.0/common/rfb/CSecurityTLS.cxx
===================================================================
--- tigervnc-1.9.0.orig/common/rfb/CSecurityTLS.cxx
+++ tigervnc-1.9.0/common/rfb/CSecurityTLS.cxx
@@ -232,22 +232,6 @@ void CSecurityTLS::setParam()
if (*cafile &&
gnutls_certificate_set_x509_trust_file(cert_cred,cafile,GNUTLS_X509_FMT_PEM) <
0)
throw AuthFailureException("load of CA cert failed");
- /* Load previously saved certs */
- char *homeDir = NULL;
- int err;
- if (getvnchomedir(&homeDir) == -1)
- vlog.error("Could not obtain VNC home directory path");
- else {
- CharArray caSave(strlen(homeDir) + 19 + 1);
- sprintf(caSave.buf, "%sx509_savedcerts.pem", homeDir);
- delete [] homeDir;
-
- err = gnutls_certificate_set_x509_trust_file(cert_cred, caSave.buf,
- GNUTLS_X509_FMT_PEM);
- if (err < 0)
- vlog.debug("Failed to load saved server certificates from %s",
caSave.buf);
- }
-
if (*crlfile &&
gnutls_certificate_set_x509_crl_file(cert_cred,crlfile,GNUTLS_X509_FMT_PEM) < 0)
throw AuthFailureException("load of CRL failed");
@@ -272,7 +256,10 @@ void CSecurityTLS::checkSession()
const gnutls_datum_t *cert_list;
unsigned int cert_list_size = 0;
int err;
+
+ char *homeDir;
gnutls_datum_t info;
+ size_t len;
if (anon)
return;
@@ -315,13 +302,13 @@ void CSecurityTLS::checkSession()
throw AuthFailureException("decoding of certificate failed");
if (gnutls_x509_crt_check_hostname(crt, client->getServerName()) == 0) {
- char buf[255];
+ CharArray text;
vlog.debug("hostname mismatch");
- snprintf(buf, sizeof(buf), "Hostname (%s) does not match any certificate, "
- "do you want to continue?",
client->getServerName());
- buf[sizeof(buf) - 1] = '\0';
- if (!msg->showMsgBox(UserMsgBox::M_YESNO, "hostname mismatch", buf))
- throw AuthFailureException("hostname mismatch");
+ text.format("Hostname (%s) does not match the server certificate, "
+ "do you want to continue?", client->getServerName());
+ if (!msg->showMsgBox(UserMsgBox::M_YESNO,
+ "Certificate hostname mismatch", text.buf))
+ throw AuthFailureException("Certificate hostname mismatch");
}
if (status == 0) {
@@ -346,89 +333,81 @@ void CSecurityTLS::checkSession()
throw AuthFailureException("Invalid status of server certificate
verification");
}
- vlog.debug("Saved server certificates don't match");
-
- if (gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info)) {
- /*
- * GNUTLS doesn't correctly export gnutls_free symbol which is
- * a function pointer. Linking with Visual Studio 2008 Express will
- * fail when you call gnutls_free().
- */
-#if WIN32
- free(info.data);
-#else
- gnutls_free(info.data);
-#endif
- throw AuthFailureException("Could not find certificate to display");
+ /* Certificate is fine, except we don't know the issuer, so TOFU time */
+ homeDir = NULL;
+ if (getvnchomedir(&homeDir) == -1) {
+ throw AuthFailureException("Could not obtain VNC home directory "
+ "path for known hosts storage");
+ }
+
+ CharArray dbPath(strlen(homeDir) + 16 + 1);
+ sprintf(dbPath.buf, "%sx509_known_hosts", homeDir);
+ delete [] homeDir;
+
+ err = gnutls_verify_stored_pubkey(dbPath.buf, NULL,
+ client->getServerName(), NULL,
+ GNUTLS_CRT_X509, &cert_list[0], 0);
+
+ /* Previously known? */
+ if (err == GNUTLS_E_SUCCESS) {
+ vlog.debug("Server certificate found in known hosts file");
+ gnutls_x509_crt_deinit(crt);
+ return;
}
- size_t out_size = 0;
- char *out_buf = NULL;
- char *certinfo = NULL;
- int len = 0;
-
- vlog.debug("certificate issuer unknown");
-
- len = snprintf(NULL, 0, "This certificate has been signed by an unknown "
- "authority:\n\n%s\n\nDo you want to save it and "
- "continue?\n ", info.data);
- if (len < 0)
- AuthFailureException("certificate decoding error");
-
- vlog.debug("%s", info.data);
-
- certinfo = new char[len];
- if (certinfo == NULL)
- throw AuthFailureException("Out of memory");
-
- snprintf(certinfo, len, "This certificate has been signed by an unknown "
- "authority:\n\n%s\n\nDo you want to save it and "
- "continue? ", info.data);
-
- for (int i = 0; i < len - 1; i++)
- if (certinfo[i] == ',' && certinfo[i + 1] == ' ')
- certinfo[i] = '\n';
-
- if (!msg->showMsgBox(UserMsgBox::M_YESNO, "certificate issuer unknown",
- certinfo)) {
- delete [] certinfo;
- throw AuthFailureException("certificate issuer unknown");
- }
-
- delete [] certinfo;
-
- if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, NULL, &out_size)
- == GNUTLS_E_SHORT_MEMORY_BUFFER)
- AuthFailureException("Out of memory");
-
- // Save cert
- out_buf = new char[out_size];
- if (out_buf == NULL)
- AuthFailureException("Out of memory");
-
- if (gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, out_buf, &out_size) < 0)
- AuthFailureException("certificate issuer unknown, and certificate "
- "export failed");
-
- char *homeDir = NULL;
- if (getvnchomedir(&homeDir) == -1)
- vlog.error("Could not obtain VNC home directory path");
- else {
- FILE *f;
- CharArray caSave(strlen(homeDir) + 1 + 19);
- sprintf(caSave.buf, "%sx509_savedcerts.pem", homeDir);
- delete [] homeDir;
- f = fopen(caSave.buf, "a+");
- if (!f)
- msg->showMsgBox(UserMsgBox::M_OK, "certificate save failed",
- "Could not save the certificate");
- else {
- fprintf(f, "%s\n", out_buf);
- fclose(f);
- }
+ if ((err != GNUTLS_E_NO_CERTIFICATE_FOUND) &&
+ (err != GNUTLS_E_CERTIFICATE_KEY_MISMATCH)) {
+ throw AuthFailureException("Could not load known hosts database");
}
- delete [] out_buf;
+ if (gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_ONELINE, &info))
+ throw AuthFailureException("Could not find certificate to display");
+
+ len = strlen((char*)info.data);
+ for (size_t i = 0; i < len - 1; i++) {
+ if (info.data[i] == ',' && info.data[i + 1] == ' ')
+ info.data[i] = '\n';
+ }
+
+ /* New host */
+ if (err == GNUTLS_E_NO_CERTIFICATE_FOUND) {
+ CharArray text;
+
+ vlog.debug("Server host not previously known");
+ vlog.debug("%s", info.data);
+
+ text.format("This certificate has been signed by an unknown "
+ "authority:\n\n%s\n\nSomeone could be trying to "
+ "impersonate the site and you should not "
+ "continue.\n\nDo you want to make an exception "
+ "for this server?", info.data);
+
+ if (!msg->showMsgBox(UserMsgBox::M_YESNO,
+ "Unknown certificate issuer",
+ text.buf))
+ throw AuthFailureException("Unknown certificate issuer");
+ } else if (err == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
+ CharArray text;
+
+ vlog.debug("Server host key mismatch");
+ vlog.debug("%s", info.data);
+
+ text.format("This host is previously known with a different "
+ "certificate, and the new certificate has been "
+ "signed by an unknown authority:\n\n%s\n\nSomeone "
+ "could be trying to impersonate the site and you "
+ "should not continue.\n\nDo you want to make an "
+ "exception for this server?", info.data);
+
+ if (!msg->showMsgBox(UserMsgBox::M_YESNO,
+ "Unexpected server certificate",
+ text.buf))
+ throw AuthFailureException("Unexpected server certificate");
+ }
+
+ if (gnutls_store_pubkey(dbPath.buf, NULL, client->getServerName(),
+ NULL, GNUTLS_CRT_X509, &cert_list[0], 0, 0))
+ vlog.error("Failed to store server certificate to known hosts database");
gnutls_x509_crt_deinit(crt);
/*
++++++ U_0002-Properly-store-certificate-exceptions-in-Java-viewer.patch ++++++
>From f029745f63ac7d22fb91639b2cb5b3ab56134d6e Mon Sep 17 00:00:00 2001
From: "Brian P. Hinz" <[email protected]>
Date: Tue, 8 Sep 2020 10:13:32 +0200
Subject: [PATCH] Properly store certificate exceptions in Java viewer
Like the native viewer, the Java viewer didn't store certificate
exceptions properly. Whilst not as bad as the native viewer, it still
failed to check that a stored certificate wouldn't be maliciously used
for another server. In practice this can in most cases be used to
impersonate another server.
Handle this like the native viewer by storing exceptions for a specific
hostname/certificate combination.
---
java/com/tigervnc/rfb/CSecurityTLS.java | 164 ++++++++++++++++++++------------
1 file changed, 101 insertions(+), 63 deletions(-)
Index: tigervnc-1.9.0/java/com/tigervnc/rfb/CSecurityTLS.java
===================================================================
--- tigervnc-1.9.0.orig/java/com/tigervnc/rfb/CSecurityTLS.java
+++ tigervnc-1.9.0/java/com/tigervnc/rfb/CSecurityTLS.java
@@ -41,6 +41,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -107,12 +108,6 @@ public class CSecurityTLS extends CSecur
X509CRL.setDefaultStr(getDefaultCRL());
}
-// FIXME:
-// Need to shutdown the connection cleanly
-
-// FIXME?
-// add a finalizer method that calls shutdown
-
public boolean processMsg(CConnection cc) {
is = (FdInStream)cc.getInStream();
os = (FdOutStream)cc.getOutStream();
@@ -257,8 +252,13 @@ public class CSecurityTLS extends CSecur
{
Collection<? extends Certificate> certs = null;
X509Certificate cert = chain[0];
+ String pk =
+ Base64.getEncoder().encodeToString(cert.getPublicKey().getEncoded());
try {
cert.checkValidity();
+ verifyHostname(cert);
+ } catch(CertificateParsingException e) {
+ throw new SystemException(e.getMessage());
} catch(CertificateNotYetValidException e) {
throw new AuthFailureException("server certificate has not been
activated");
} catch(CertificateExpiredException e) {
@@ -267,73 +267,111 @@ public class CSecurityTLS extends CSecur
"do you want to continue?"))
throw new AuthFailureException("server certificate has expired");
}
- String thumbprint = getThumbprint(cert);
File vncDir = new File(FileUtils.getVncHomeDir());
- File certFile = new File(vncDir, "x509_savedcerts.pem");
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- if (vncDir.exists() && certFile.exists() && certFile.canRead()) {
- InputStream certStream = new MyFileInputStream(certFile);
- certs = cf.generateCertificates(certStream);
- for (Certificate c : certs)
- if (thumbprint.equals(getThumbprint((X509Certificate)c)))
- return;
- }
+ if (!vncDir.exists())
+ throw new AuthFailureException("Could not obtain VNC home directory "+
+ "path for known hosts storage");
+ File dbPath = new File(vncDir, "x509_known_hosts");
+ String info =
+ " Subject: "+cert.getSubjectX500Principal().getName()+"\n"+
+ " Issuer: "+cert.getIssuerX500Principal().getName()+"\n"+
+ " Serial Number: "+cert.getSerialNumber()+"\n"+
+ " Version: "+cert.getVersion()+"\n"+
+ " Signature Algorithm: "+cert.getPublicKey().getAlgorithm()+"\n"+
+ " Not Valid Before: "+cert.getNotBefore()+"\n"+
+ " Not Valid After: "+cert.getNotAfter()+"\n"+
+ " SHA-1 Fingerprint: "+getThumbprint(cert)+"\n";
try {
- verifyHostname(cert);
- tm.checkServerTrusted(chain, authType);
- } catch (java.lang.Exception e) {
- if (e.getCause() instanceof CertPathBuilderException) {
- String certinfo =
- "This certificate has been signed by an unknown authority\n"+
- "\n"+
- " Subject: "+cert.getSubjectX500Principal().getName()+"\n"+
- " Issuer: "+cert.getIssuerX500Principal().getName()+"\n"+
- " Serial Number: "+cert.getSerialNumber()+"\n"+
- " Version: "+cert.getVersion()+"\n"+
- " Signature Algorithm: "+cert.getPublicKey().getAlgorithm()+"\n"+
- " Not Valid Before: "+cert.getNotBefore()+"\n"+
- " Not Valid After: "+cert.getNotAfter()+"\n"+
- " SHA1 Fingerprint: "+getThumbprint(cert)+"\n"+
- "\n"+
- "Do you want to save it and continue?";
- if (!msg.showMsgBox(YES_NO_OPTION, "certificate issuer unknown",
- certinfo)) {
- throw new AuthFailureException("certificate issuer unknown");
- }
- if (certs == null || !certs.contains(cert)) {
- byte[] der = cert.getEncoded();
- String pem = DatatypeConverter.printBase64Binary(der);
- pem = pem.replaceAll("(.{64})", "$1\n");
- FileWriter fw = null;
- try {
- if (!vncDir.exists())
- vncDir.mkdir();
- if (!certFile.exists() && !certFile.createNewFile()) {
- vlog.error("Certificate save failed.");
- } else {
- fw = new FileWriter(certFile.getAbsolutePath(), true);
- fw.write("-----BEGIN CERTIFICATE-----\n");
- fw.write(pem+"\n");
- fw.write("-----END CERTIFICATE-----\n");
- }
- } catch (IOException ioe) {
- msg.showMsgBox(OK_OPTION, "certificate save failed",
- "Could not save the certificate");
- } finally {
- try {
- if (fw != null)
- fw.close();
- } catch(IOException ioe2) {
- throw new Exception(ioe2.getMessage());
+ if (dbPath.exists()) {
+ FileReader db = new FileReader(dbPath);
+ BufferedReader dbBuf = new BufferedReader(db);
+ String line;
+ String server = client.getServerName().toLowerCase();
+ while ((line = dbBuf.readLine())!=null) {
+ String fields[] = line.split("\\|");
+ if (fields.length==6) {
+ if (server.equals(fields[2]) && pk.equals(fields[5])) {
+ vlog.debug("Server certificate found in known hosts file");
+ dbBuf.close();
+ return;
+ } else if (server.equals(fields[2]) && !pk.equals(fields[5]) ||
+ !server.equals(fields[2]) && pk.equals(fields[5])) {
+ throw new CertStoreException();
}
}
}
+ dbBuf.close();
+ }
+ tm.checkServerTrusted(chain, authType);
+ } catch (IOException e) {
+ throw new AuthFailureException("Could not load known hosts database");
+ } catch (CertStoreException e) {
+ vlog.debug("Server host key mismatch");
+ vlog.debug(info);
+ String text =
+ "This host is previously known with a different "+
+ "certificate, and the new certificate has been "+
+ "signed by an unknown authority\n"+
+ "\n"+info+"\n"+
+ "Someone could be trying to impersonate the site and you should not
continue.\n"+
+ "\n"+
+ "Do you want to make an exception for this server?";
+ if (!msg.showMsgBox(YES_NO_OPTION, "Unexpected certificate issuer",
text))
+ throw new AuthFailureException("Unexpected certificate issuer");
+ store_pubkey(dbPath, client.getServerName().toLowerCase(), pk);
+ } catch (java.lang.Exception e) {
+ if (e.getCause() instanceof CertPathBuilderException) {
+ vlog.debug("Server host not previously known");
+ vlog.debug(info);
+ String text =
+ "This certificate has been signed by an unknown authority\n"+
+ "\n"+info+"\n"+
+ "Someone could be trying to impersonate the site and you should
not continue.\n"+
+ "\n"+
+ "Do you want to make an exception for this server?";
+ if (!msg.showMsgBox(YES_NO_OPTION, "Unknown certificate issuer",
text))
+ throw new AuthFailureException("Unknown certificate issuer");
+ store_pubkey(dbPath, client.getServerName().toLowerCase(), pk);
} else {
throw new SystemException(e.getMessage());
}
}
}
+ private void store_pubkey(File dbPath, String serverName, String pk)
+ {
+ ArrayList<String> lines = new ArrayList<String>();
+ File vncDir = new File(FileUtils.getVncHomeDir());
+ try {
+ if (dbPath.exists()) {
+ FileReader db = new FileReader(dbPath);
+ BufferedReader dbBuf = new BufferedReader(db);
+ String line;
+ while ((line = dbBuf.readLine())!=null) {
+ String fields[] = line.split("\\|");
+ if (fields.length==6)
+ if (!serverName.equals(fields[2]) && !pk.equals(fields[5]))
+ lines.add(line);
+ }
+ dbBuf.close();
+ }
+ } catch (IOException e) {
+ throw new AuthFailureException("Could not load known hosts database");
+ }
+ try {
+ if (!dbPath.exists())
+ dbPath.createNewFile();
+ FileWriter fw = new FileWriter(dbPath.getAbsolutePath(), false);
+ Iterator i = lines.iterator();
+ while (i.hasNext())
+ fw.write((String)i.next()+"\n");
+ fw.write("|g0|"+serverName+"|*|0|"+pk+"\n");
+ fw.close();
+ } catch (IOException e) {
+ vlog.error("Failed to store server certificate to known hosts
database");
+ }
+ }
+
public X509Certificate[] getAcceptedIssuers ()
{
return tm.getAcceptedIssuers();
@@ -389,12 +427,13 @@ public class CSecurityTLS extends CSecur
}
Object[] answer = {"YES", "NO"};
int ret = JOptionPane.showOptionDialog(null,
- "Hostname verification failed. Do you want to continue?",
- "Hostname Verification Failure",
+ "Hostname ("+client.getServerName()+") does not match the"+
+ " server certificate, do you want to continue?",
+ "Certificate hostname mismatch",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, answer, answer[0]);
if (ret != JOptionPane.YES_OPTION)
- throw new WarningException("Hostname verification failed.");
+ throw new WarningException("Certificate hostname mismatch.");
} catch (CertificateParsingException e) {
throw new SystemException(e.getMessage());
} catch (InvalidNameException e) {
++++++ U_Avoid-potential-crash-when-replacing-buffer-in-Plain.patch ++++++
>From a752d8fd7a0622e11dda72f690d4fea8cb913178 Mon Sep 17 00:00:00 2001
From: Jan Grulich <[email protected]>
Date: Mon, 1 Oct 2018 10:17:20 +0200
Subject: [PATCH 1/5] Avoid potential crash when replacing buffer in
PlainPasswd
---
common/rfb/util.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/rfb/util.h b/common/rfb/util.h
index b678b890..9e59bd37 100644
--- a/common/rfb/util.h
+++ b/common/rfb/util.h
@@ -50,7 +50,7 @@ namespace rfb {
CharArray() : buf(0) {}
CharArray(char* str) : buf(str) {} // note: assumes ownership
CharArray(size_t len) {
- buf = new char[len];
+ buf = new char[len]();
}
~CharArray() {
delete [] buf;
--
2.16.4
++++++ U_viewer-reset-ctrl-alt-to-menu-state-on-focus.patch ++++++
>From 9f83180219380c690fb743182308bc2d534b8b1b Mon Sep 17 00:00:00 2001
From: Dominique Martinet <[email protected]>
Date: Sun, 8 Jul 2018 02:15:43 +0900
Subject: [PATCH] viewer: reset ctrl / alt to menu state on focus
Setting Ctrl or Alt key on menu only sends the key press, and the
state is lost when focus is lost and recovered.
This checks the menu variable and sends the keys again if needed.
---
vncviewer/Viewport.cxx | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 4e23dc8c..317f06b2 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -635,6 +635,12 @@ int Viewport::handle(int event)
exit_vncviewer(e.str());
}
+ // Resend Ctrl/Alt if needed
+ if (menuCtrlKey)
+ handleKeyPress(0x1d, XK_Control_L);
+ if (menuAltKey)
+ handleKeyPress(0x38, XK_Alt_L);
+
// Yes, we would like some focus please!
return 1;
--
2.16.4
++++++ index.vnc ++++++
<!--
index.vnc - default HTML page for TigerVNC Java viewer applet, to be
used with Xvnc. On any file ending in .vnc, the HTTP server embedded in
Xvnc will substitute the following variables when preceded by a dollar:
USER, DESKTOP, DISPLAY, APPLETWIDTH, APPLETHEIGHT, WIDTH, HEIGHT, PORT,
Use two dollar signs ($$) to get a dollar sign in the generated
HTML page.
-->
<HTML>
<TITLE>
$USER's $DESKTOP desktop ($DISPLAY)
</TITLE>
<APPLET CODE="com.tigervnc.vncviewer.VncViewer" ARCHIVE="VncViewer.jar"
WIDTH="$APPLETWIDTH" HEIGHT="$APPLETHEIGHT">
<PARAM NAME="Port" VALUE="$PORT">
<PARAM NAME="Embed" VALUE="true">
<PARAM NAME="AlwaysShowServerDialog" VALUE="false">
</APPLET>
<BR>
<A href="http://www.tigervnc.org/">TigerVNC site</A>
</HTML>
++++++ n_correct_path_in_desktop_file.patch ++++++
Our /usr/bin/vncviewer is symlink to alternatives. This desktop file is named
specifically "TigerVNC Viewer", so lets start /usr/bin/vncviewer-tigervnc, no
matter what the currently selected alternative is.
Index: tigervnc-1.9.0/vncviewer/vncviewer.desktop.in.in
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/vncviewer.desktop.in.in
+++ tigervnc-1.9.0/vncviewer/vncviewer.desktop.in.in
@@ -2,7 +2,7 @@
Name=TigerVNC Viewer
GenericName=Remote Desktop Viewer
Comment=Connect to VNC server and display remote desktop
-Exec=@BIN_DIR@/vncviewer
+Exec=@BIN_DIR@/vncviewer-tigervnc
Icon=tigervnc
Terminal=false
Type=Application
++++++ n_tigervnc-date-time.patch ++++++
Index: tigervnc-1.9.0/unix/xserver/hw/vnc/buildtime.c
===================================================================
--- tigervnc-1.9.0.orig/unix/xserver/hw/vnc/buildtime.c
+++ tigervnc-1.9.0/unix/xserver/hw/vnc/buildtime.c
@@ -15,4 +15,4 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-char buildtime[] = __DATE__ " " __TIME__;
+char buildtime[] = "??? ?? ???? ??:??:??";
Index: tigervnc-1.9.0/unix/vncconfig/buildtime.c
===================================================================
--- tigervnc-1.9.0.orig/unix/vncconfig/buildtime.c
+++ tigervnc-1.9.0/unix/vncconfig/buildtime.c
@@ -15,4 +15,4 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-char buildtime[] = __DATE__ " " __TIME__;
+char buildtime[] = "??? ?? ???? ??:??:??";
Index: tigervnc-1.9.0/unix/x0vncserver/buildtime.c
===================================================================
--- tigervnc-1.9.0.orig/unix/x0vncserver/buildtime.c
+++ tigervnc-1.9.0/unix/x0vncserver/buildtime.c
@@ -15,4 +15,4 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-char buildtime[] = __DATE__ " " __TIME__;
+char buildtime[] = "??? ?? ???? ??:??:??";
Index: tigervnc-1.9.0/win/winvnc/buildTime.cxx
===================================================================
--- tigervnc-1.9.0.orig/win/winvnc/buildTime.cxx
+++ tigervnc-1.9.0/win/winvnc/buildTime.cxx
@@ -15,4 +15,4 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
-const char* buildTime = "Built on " __DATE__ " at " __TIME__;
+const char* buildTime = "Built on ??? ?? ???? at ??:??:??";
Index: tigervnc-1.9.0/CMakeLists.txt
===================================================================
--- tigervnc-1.9.0.orig/CMakeLists.txt
+++ tigervnc-1.9.0/CMakeLists.txt
@@ -42,12 +42,6 @@ if(MSVC)
message(FATAL_ERROR "TigerVNC cannot be built with Visual Studio. Please
use MinGW")
endif()
-if(NOT BUILD_TIMESTAMP)
- set(BUILD_TIMESTAMP "")
- execute_process(COMMAND "date" "+%Y-%m-%d %H:%M" OUTPUT_VARIABLE
BUILD_TIMESTAMP)
- string(REGEX REPLACE "\n" "" BUILD_TIMESTAMP ${BUILD_TIMESTAMP})
-endif()
-
# Default to optimised builds instead of debug ones. Our code has no bugs ;)
# (CMake makes it fairly easy to toggle this back to Debug if needed)
if(NOT CMAKE_BUILD_TYPE)
Index: tigervnc-1.9.0/vncviewer/vncviewer.cxx
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/vncviewer.cxx
+++ tigervnc-1.9.0/vncviewer/vncviewer.cxx
@@ -98,11 +98,9 @@ static const char *about_text()
// time.
snprintf(buffer, sizeof(buffer),
_("TigerVNC Viewer %d-bit v%s\n"
- "Built on: %s\n"
"Copyright (C) 1999-%d TigerVNC Team and many others (see
README.rst)\n"
"See http://www.tigervnc.org for information on TigerVNC."),
- (int)sizeof(size_t)*8, PACKAGE_VERSION,
- BUILD_TIMESTAMP, 2018);
+ (int)sizeof(size_t)*8, PACKAGE_VERSION, 2018);
return buffer;
}
++++++ tigervnc-clean-pressed-key-on-exit.patch ++++++
Index: tigervnc-1.9.0/vncviewer/DesktopWindow.cxx
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/DesktopWindow.cxx
+++ tigervnc-1.9.0/vncviewer/DesktopWindow.cxx
@@ -207,6 +207,8 @@ DesktopWindow::~DesktopWindow()
delete statsGraph;
+ delete viewport;
+
// FLTK automatically deletes all child widgets, so we shouldn't touch
// them ourselves here
}
Index: tigervnc-1.9.0/vncviewer/Viewport.cxx
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/Viewport.cxx
+++ tigervnc-1.9.0/vncviewer/Viewport.cxx
@@ -189,6 +189,18 @@ Viewport::Viewport(int w, int h, const r
Viewport::~Viewport()
{
+ // Send release for every pressed key
+ for(DownMap::iterator iter = downKeySym.begin(); iter != downKeySym.end();
++iter) {
+ try {
+ if (iter->first > 0xff)
+ cc->writer()->writeKeyEvent(iter->second, 0, false);
+ else
+ cc->writer()->writeKeyEvent(iter->second, iter->first, false);
+ } catch (rdr::Exception& e) {
+ // ignore
+ }
+ }
+
// Unregister all timeouts in case they get a change tro trigger
// again later when this object is already gone.
Fl::remove_timeout(handlePointerTimeout, this);
Index: tigervnc-1.9.0/vncviewer/vncviewer.cxx
===================================================================
--- tigervnc-1.9.0.orig/vncviewer/vncviewer.cxx
+++ tigervnc-1.9.0/vncviewer/vncviewer.cxx
@@ -107,6 +107,8 @@ static const char *about_text()
return buffer;
}
+static CConn *cc;
+
void exit_vncviewer(const char *error)
{
// Prioritise the first error we get as that is probably the most
@@ -177,6 +179,16 @@ static void CleanupSignalHandler(int sig
// CleanupSignalHandler allows C++ object cleanup to happen because it calls
// exit() rather than the default which is to abort.
vlog.info(_("Termination signal %d has been received. TigerVNC Viewer will
now exit."), sig);
+ delete cc;
+ exit(1);
+}
+
+static int CleanupXIOErrorHandler(Display *dpy)
+{
+ // CleanupSignalHandler allows C++ object cleanup to happen because it calls
+ // exit() rather than the default which is to abort.
+ vlog.info("XErrorHandler called");
+ delete cc;
exit(1);
}
@@ -566,6 +578,9 @@ int main(int argc, char** argv)
XkbSetDetectableAutoRepeat(fl_display, True, NULL);
#endif
+ fl_open_display();
+ XSetIOErrorHandler(CleanupXIOErrorHandler);
+
CSecurity::upg = &dlg;
#ifdef HAVE_GNUTLS
CSecurityTLS::msg = &dlg;
@@ -651,7 +666,7 @@ int main(int argc, char** argv)
#endif
}
- CConn *cc = new CConn(vncServerName, sock);
+ cc = new CConn(vncServerName, sock);
while (!exitMainloop)
run_mainloop();
++++++ tigervnc-https.firewalld ++++++
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>VNC over HTTPS</short>
<description>The xvnc-novnc servers a web-based VNC viewer over HTTPS. Allows
accessing VNC using any modern browser. It displays VNC display
:1.</description>
<port protocol="tcp" port="5801"/>
</service>
++++++ tigervnc-newfbsize.patch ++++++
Index: tigervnc-1.6.0/vncviewer/CConn.cxx
===================================================================
--- tigervnc-1.6.0.orig/vncviewer/CConn.cxx
+++ tigervnc-1.6.0/vncviewer/CConn.cxx
@@ -438,6 +438,8 @@ void CConn::dataRect(const Rect& r, int
if (encoding != encodingCopyRect)
lastServerEncoding = encoding;
+ if (encoding == pseudoEncodingDesktopSize)
+ setDesktopSize( r.width(), r.height() );
CConnection::dataRect(r, encoding);
++++++ tigervnc.firewalld ++++++
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>VNC display :1</short>
<description>VNC is protocol for remote desktop. The TigerVNC service and the
vncmanager service use VNC display number :1.</description>
<port protocol="tcp" port="5901"/>
</service>
++++++ u_build_libXvnc_as_separate_library.patch ++++++
Author: Michal Srb <[email protected]>
Patch-Mainline: To be upstreamed
Subject: [PATCH] Build libXvnc as separate library.
So it can be used by others, not only vncconfig.
diff --git a/unix/vncconfig/CMakeLists.txt b/unix/vncconfig/CMakeLists.txt
index 959681f..5fe1fb8 100644
--- a/unix/vncconfig/CMakeLists.txt
+++ b/unix/vncconfig/CMakeLists.txt
@@ -3,13 +3,25 @@ include_directories(${X11_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/common)
include_directories(${CMAKE_SOURCE_DIR}/unix/tx)
+include(GNUInstallDirs)
+
+add_library(Xvnc SHARED
+ vncExt.c)
+
+set_target_properties(Xvnc
+ PROPERTIES
+ VERSION 1.0.0
+ SOVERSION 1
+)
+
add_executable(vncconfig
buildtime.c
- vncExt.c
vncconfig.cxx
QueryConnectDialog.cxx)
-target_link_libraries(vncconfig tx rfb network rdr ${X11_LIBRARIES})
+target_link_libraries(vncconfig tx rfb network rdr Xvnc ${X11_LIBRARIES})
install(TARGETS vncconfig DESTINATION ${BIN_DIR})
+install(TARGETS Xvnc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RENAME
libXvnc.so)
install(FILES vncconfig.man DESTINATION ${MAN_DIR}/man1 RENAME vncconfig.1)
+install(FILES vncExt.h DESTINATION ${X11_INCLUDE_DIR}/X11/extensions RENAME
Xvnc.h)
++++++ u_change-button-layout-in-ServerDialog.patch ++++++
Patch-mainline: To be upstreamed
References: bnc#1084865
Author: Michal Srb <[email protected]>
Subject: Change button layout in ServerDialog.
To fit strings in languages with longer words...
---
vncviewer/ServerDialog.cxx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/vncviewer/ServerDialog.cxx b/vncviewer/ServerDialog.cxx
index de67f87b..0a8aa775 100644
--- a/vncviewer/ServerDialog.cxx
+++ b/vncviewer/ServerDialog.cxx
@@ -53,7 +53,7 @@ ServerDialog::ServerDialog()
serverName = new Fl_Input(x, y, w() - margin*2 - server_label_width,
INPUT_HEIGHT, _("VNC server:"));
- int adjust = (w() - 20) / 4;
+ int adjust = (w() - 20) / 3;
int button_width = adjust - margin/2;
x = margin;
@@ -76,6 +76,8 @@ ServerDialog::ServerDialog()
x = 0;
y += margin/2 + BUTTON_HEIGHT;
+ adjust = (w() - 20) / 4;
+ button_width = adjust - margin/2;
divider = new Fl_Box(x, y, w(), 2);
divider->box(FL_THIN_DOWN_FRAME);
--
2.13.6
++++++ u_tigervnc-add-autoaccept-parameter.patch ++++++
Index: tigervnc-1.9.0/java/com/tigervnc/rfb/CSecurityTLS.java
===================================================================
--- tigervnc-1.9.0.orig/java/com/tigervnc/rfb/CSecurityTLS.java
+++ tigervnc-1.9.0/java/com/tigervnc/rfb/CSecurityTLS.java
@@ -66,6 +66,9 @@ public class CSecurityTLS extends CSecur
public static StringParameter X509CRL
= new StringParameter("X509CRL",
"X509 CRL file", "",
Configuration.ConfigurationObject.ConfViewer);
+ public static StringParameter x509autoaccept
+ = new StringParameter("x509autoaccept",
+ "X509 Certificate SHA-1 fingerprint", "",
Configuration.ConfigurationObject.ConfViewer);
public static UserMsgBox msg;
private void initGlobal()
@@ -85,6 +88,7 @@ public class CSecurityTLS extends CSecur
setDefaults();
cafile = X509CA.getData();
crlfile = X509CRL.getData();
+ certautoaccept = x509autoaccept.getData();
}
public static String getDefaultCA() {
@@ -266,6 +270,7 @@ public class CSecurityTLS extends CSecur
"do you want to continue?"))
throw new AuthFailureException("server certificate has expired");
}
+ String thumbprint = getThumbprint(cert);
File vncDir = new File(FileUtils.getVncHomeDir());
if (!vncDir.exists())
throw new AuthFailureException("Could not obtain VNC home directory "+
@@ -320,6 +325,9 @@ public class CSecurityTLS extends CSecur
store_pubkey(dbPath, client.getServerName().toLowerCase(), pk);
} catch (java.lang.Exception e) {
if (e.getCause() instanceof CertPathBuilderException) {
+ if (certautoaccept != null &&
thumbprint.equalsIgnoreCase(certautoaccept)) {
+ return;
+ }
vlog.debug("Server host not previously known");
vlog.debug(info);
String text =
@@ -509,7 +517,7 @@ public class CSecurityTLS extends CSecur
private SSLEngineManager manager;
private boolean anon;
- private String cafile, crlfile;
+ private String cafile, crlfile, certautoaccept;
private FdInStream is;
private FdOutStream os;
Index: tigervnc-1.9.0/java/com/tigervnc/vncviewer/VncViewer.java
===================================================================
--- tigervnc-1.9.0.orig/java/com/tigervnc/vncviewer/VncViewer.java
+++ tigervnc-1.9.0/java/com/tigervnc/vncviewer/VncViewer.java
@@ -393,6 +393,8 @@ public class VncViewer extends javax.swi
// Called right after zero-arg constructor in applet mode
setLookAndFeel();
setBackground(Color.white);
+
+ SecurityClient.setDefaults();
applet = this;
vncServerName.put(loadAppletParameters(applet).toCharArray()).flip();
if (embed.getValue()) {
++++++ u_tigervnc-cve-2014-8240.patch ++++++
Patch-Mainline: To be upstreamed
References: bnc#900896 CVE-2014-8240
Signed-off-by: Michal Srb <[email protected]>
Index: tigervnc-1.8.0/unix/x0vncserver/Image.cxx
===================================================================
--- tigervnc-1.8.0.orig/unix/x0vncserver/Image.cxx
+++ tigervnc-1.8.0/unix/x0vncserver/Image.cxx
@@ -80,6 +80,14 @@ void Image::Init(int width, int height)
xim = XCreateImage(dpy, vis, DefaultDepth(dpy, DefaultScreen(dpy)),
ZPixmap, 0, 0, width, height, BitmapPad(dpy), 0);
+ if (xim->bytes_per_line <= 0 ||
+ xim->height <= 0 ||
+ xim->height >= INT_MAX / xim->bytes_per_line) {
+ vlog.error("Invalid display size");
+ XDestroyImage(xim);
+ exit(1);
+ }
+
xim->data = (char *)malloc(xim->bytes_per_line * xim->height);
if (xim->data == NULL) {
vlog.error("malloc() failed");
@@ -254,6 +262,17 @@ void ShmImage::Init(int width, int heigh
delete shminfo;
shminfo = NULL;
return;
+ }
+
+ if (xim->bytes_per_line <= 0 ||
+ xim->height <= 0 ||
+ xim->height >= INT_MAX / xim->bytes_per_line) {
+ vlog.error("Invalid display size");
+ XDestroyImage(xim);
+ xim = NULL;
+ delete shminfo;
+ shminfo = NULL;
+ return;
}
shminfo->shmid = shmget(IPC_PRIVATE,
++++++ u_tigervnc-ignore-epipe-on-write.patch ++++++
Author: Michal Srb <[email protected]>
Subject: Ignore EPIPE on write.
Patch-Mainline: To be upstreamed
References: bnc#864676
If the VNC server closes connection after our last read and before this write,
we will report error message about EPIPE.
This situation is no error, however, we should quit normally same as when we
find out that connection was closed during read.
Index: common/rdr/FdOutStream.cxx
===================================================================
--- common/rdr/FdOutStream.cxx.orig
+++ common/rdr/FdOutStream.cxx
@@ -204,8 +204,12 @@ int FdOutStream::writeWithTimeout(const
#endif
} while (n < 0 && (errno == EINTR));
- if (n < 0)
- throw SystemException("write", errno);
+ if (n < 0) {
+ if(errno == EPIPE)
+ n = length; // Ignore EPIPE and fake successfull write, it doesn't
matter that we are writing to closed socket, we will find out once we try to
read from it.
+ else
+ throw SystemException("write", errno);
+ }
gettimeofday(&lastWrite, NULL);
++++++ u_tigervnc_update_default_vncxstartup.patch ++++++
Author: Michal Srb <[email protected]>
References: bnc#956537
Subject: Update default vnc xstartup script.
Index: tigervnc-1.6.0/unix/vncserver
===================================================================
--- tigervnc-1.6.0.orig/unix/vncserver
+++ tigervnc-1.6.0/unix/vncserver
@@ -61,27 +61,31 @@ $defaultXStartup
= ("#!/bin/sh\n\n".
"unset SESSION_MANAGER\n".
"unset DBUS_SESSION_BUS_ADDRESS\n".
- "OS=`uname -s`\n".
- "if [ \$OS = 'Linux' ]; then\n".
- " case \"\$WINDOWMANAGER\" in\n".
- " \*gnome\*)\n".
- " if [ -e /etc/SuSE-release ]; then\n".
- " PATH=\$PATH:/opt/gnome/bin\n".
- " export PATH\n".
- " fi\n".
- " ;;\n".
- " esac\n".
+ "\n".
+ "userclientrc=\$HOME/.xinitrc\n".
+ "sysclientrc=/etc/X11/xinit/xinitrc\n".
+ "\n".
+ "if [ -f \"\$userclientrc\" ]; then\n".
+ " client=\"\$userclientrc\"\n".
+ "elif [ -f \"\$sysclientrc\" ]; then\n".
+ " client=\"\$sysclientrc\"\n".
"fi\n".
- "if [ -x /etc/X11/xinit/xinitrc ]; then\n".
- " exec /etc/X11/xinit/xinitrc\n".
+ "\n".
+ "if [ -x \"\$client\" ]; then\n".
+ " exec \"\$client\"\n".
"fi\n".
- "if [ -f /etc/X11/xinit/xinitrc ]; then\n".
- " exec sh /etc/X11/xinit/xinitrc\n".
+ "if [ -f \"\$client\" ]; then\n".
+ " exec sh \"\$client\"\n".
"fi\n".
+ "\n".
"[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n".
"xsetroot -solid grey\n".
"xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n".
- "twm &\n");
+ "if [ -x /usr/bin/twm ]; then\n".
+ " /usr/bin/twm &\n".
+ "else\n".
+ " echo \"No window manager found. You should install a window manager
to get properly working VNC session.\"\n".
+ "fi\n");
$defaultConfig
= ("## Supported server options to pass to vncserver upon invocation can
be listed\n".
++++++ vnc-httpd.susefirewall ++++++
## Name: VNC mini-HTTP server
## Description: Opens the VNC HTTP ports so that browsers can connect.
TCP="5800:5899"
++++++ vnc-server.susefirewall ++++++
## Name: VNC
## Description: Opens VNC server ports so that viewers can connect.
TCP="5900:5999"
++++++ vnc.pam ++++++
#%PAM-1.0
auth include common-auth
account include common-account
password include common-password
session include common-session
++++++ vnc.reg ++++++
#############################################################################
#
# OpenSLP registration file
#
# register VNC remote logins via kdm
# You need also to allow remote logins
#
#############################################################################
# Register VNC service for krdc (KDE VNC client in kdenetwork)
service:remotedesktop.kde:vnc://$HOSTNAME:5901,en,65535
tcp-port=5901
description=VNC remote login [1024x768]
# Register VNC service for krdc (KDE VNC client in kdenetwork)
service:remotedesktop.kde:vnc://$HOSTNAME:5902,en,65535
tcp-port=5902
description=VNC remote login [1280x1024]
# Register VNC service for krdc (KDE VNC client in kdenetwork)
service:remotedesktop.kde:vnc://$HOSTNAME:5903,en,65535
tcp-port=5903
description=VNC remote login [1600x1200]
# Register VNC service for Java clients
# Can be used with every Web browser with enabled Java
service:remotedesktop.java:http://$HOSTNAME:5801,en,65535
tcp-port=5801
description=VNC remote login [1024x768]
# Register VNC service for Java clients
# Can be used with every Web browser with enabled Java
service:remotedesktop.java:http://$HOSTNAME:5802,en,65535
tcp-port=5802
description=VNC remote login [1280x1024]
# Register VNC service for Java clients
# Can be used with every Web browser with enabled Java
service:remotedesktop.java:http://$HOSTNAME:5803,en,65535
tcp-port=5803
description=VNC remote login [1600x1200]
++++++ vncpasswd.arg ++++++
#!/bin/sh
# Compatibility replacement for vncpasswd.arg.
if [ $# -ne 2 ]; then
echo "Usage: $0 file password"
exit 1
fi
echo "$2" | vncpasswd -f > "$1"
++++++ with-vnc-key.sh ++++++
#!/bin/bash
# Wrapper that makes sure /etc/vnc/tls.{key,cert} exist before executing given
command.
TLSKEY=/etc/vnc/tls.key
TLSCERT=/etc/vnc/tls.cert
if test -s $TLSKEY -a -s $TLSCERT; then
# Execute the command we were given.
exec "$@"
fi
(
# Wait for lock on the key file. We must not proceed while someone else is
creating it.
flock 200
# If the key file doesn't exist or has zero size (because it doubles as
lock), generate it.
if ! test -s $TLSKEY ; then
(umask 077 && openssl genrsa -out $TLSKEY 2048) >&200
chown vnc:vnc $TLSKEY
fi
# If the cert file doesn't exist, generate it.
if ! test -e $TLSCERT ; then
# Keeping it short, because hostname could be long and max CN is 64
characters
CN="VNC service on `hostname`"
CN=${CN:0:64}
openssl req -new -x509 -extensions usr_cert -key $TLSKEY -out $TLSCERT
-days 7305 -subj "/CN=$CN/"
chown vnc:vnc $TLSCERT
fi
) 200>>$TLSKEY 2>/dev/null
# Execute the command we were given.
exec "$@"
++++++ x11vnc ++++++
#!/usr/bin/env python
# This is wrapper for x0vncserver that translate most common x11vnc arguments
# to x0vncserver's arguments
import argparse
import socket
import os
import sys
def is_port_free(port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
sock.close()
return True
except socket.error as e:
return False
def find_free_port(starting_port):
for port in range(starting_port, 6000):
if is_port_free(port):
return port
return None
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-help', '-h', action='help')
parser.add_argument('--version', '-V', action='store_true')
parser.add_argument('-storepasswd', nargs=2)
parser.add_argument('-display')
parser.add_argument('-auth')
parser.add_argument('-N', action='store_true')
parser.add_argument('-rfbport', type=int)
parser.add_argument('-autoport', type=int, default=5900)
parser.add_argument('-6', dest='yes6', action='store_true')
parser.add_argument('-no6', action='store_true')
#parser.add_argument('-once', action='store_true') # TODO: Add support to
x0vncserver
parser.add_argument('-forever', '-many', action='store_true')
parser.add_argument('-viewonly', action='store_true')
#parser.add_argument('-shared', action='store_true') # TODO?
parser.add_argument('-alwaysshared', action='store_true')
parser.add_argument('-nevershared', action='store_true')
parser.add_argument('-dontdisconnect', action='store_true')
#parser.add_argument('-timeout', nargs=1, type=int) # TODO?
parser.add_argument('-clip')
parser.add_argument('-deferupdate', type=int)
parser.add_argument('-noshm', action='store_true')
#parser.add_argument('-allow', nargs=1) # TODO?
#parser.add_argument('-localhost') # TODO?
parser.add_argument('-rfbauth')
parser.add_argument('-nopw', action='store_true')
parser.add_argument('-unixpw')
# Accepted, but ignored arguments
ignored_arguments = ['-v', '-verbose', '-q', '-quiet']
parser.add_argument(*ignored_arguments, dest='ignored_argument',
action='store_true')
print('Warning: x11vnc is deprecated in favor of x0vncserver.')
print(' This is a wrapper that maps the most common set of x11vnc')
print(' arguments to x0vncserver arguments.')
print()
print(' Use x0vncserver directly if you want encrypted connection.')
print()
args = parser.parse_args()
# Warnings
if args.ignored_argument:
print('Warning: x11vnc wrapper accepts but ignores following arguments:')
print(', '.join(ignored_arguments))
# vncpasswd
if args.storepasswd:
(password, passwdfile) = args.storepasswd
os.execlp('vncpasswd.arg', 'vncpasswd.arg', passwdfile, password)
# x0vncserver
new_args = ['x0vncserver']
default_security_type = 'None'
security_type = default_security_type
if args.version:
new_args.append('-version')
if args.display:
new_args.append('-display')
new_args.append(args.display)
if args.auth:
os.environ['XAUTHORITY'] = args.auth
if args.N:
display = args.display or os.environ['DISPLAY']
if not display:
print('No display set')
sys.exit(1)
port = int(display.split(':')[-1]) + 5900
if is_port_free(port):
new_args.append('-rfbport')
new_args.append(str(port))
else:
print('Port %d is already used'%port)
sys.exit(1)
if args.rfbport:
new_args.append('-rfbport')
new_args.append(str(args.rfbport))
else:
port = find_free_port(args.autoport)
new_args.append('-rfbport')
new_args.append(str(port))
if args.yes6:
new_args.append('-UseIPv6')
if args.no6:
new_args.append('-UseIPv6=0')
if args.forever:
# This is default in x0vncserver
pass
if args.viewonly:
new_args.append('-AcceptKeyEvents=0')
new_args.append('-AcceptPointerEvents=0')
new_args.append('-AcceptCutText=0')
new_args.append('-AcceptSetDesktopSize=0')
if args.alwaysshared:
new_args.append('-AlwaysShared')
if args.nevershared:
new_args.append('-NeverShared')
if args.dontdisconnect:
new_args.append('-DisconnectClients=0')
else:
new_args.append('-DisconnectClients')
if args.clip:
new_args.append('-Geometry')
new_args.append(args.clip)
if args.deferupdate:
new_args.append('-DeferUpdate')
new_args.append(str(args.deferupdate))
if args.noshm:
new_args.append('-UseSHM=0')
if args.rfbauth:
security_type = 'VncAuth'
new_args.append('-PasswordFile')
new_args.append(args.rfbauth)
if args.unixpw:
security_type = 'Plain'
new_args.append('-PlainUsers')
new_args.append(args.unixpw)
new_args.append('-SecurityTypes')
new_args.append(security_type)
if not args.nopw:
# Note: This is the same warning as the original x11vnc gives
if security_type == default_security_type:
print("""
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
#@ @#
#@ ** WARNING ** WARNING ** WARNING ** WARNING ** @#
#@ @#
#@ YOU ARE RUNNING X11VNC WITHOUT A PASSWORD!! @#
#@ @#
#@ This means anyone with network access to this computer @#
#@ may be able to view and control your desktop. @#
#@ @#
#@ >>> If you did not mean to do this Press CTRL-C now!! <<< @#
#@ @#
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
""")
os.execvp('x0vncserver', new_args)
++++++ xvnc-novnc.service ++++++
[Unit]
Description=noVNC Web Server
Requires=xvnc.target
After=xvnc.target
[Service]
ExecStart=/usr/lib/vnc/with-vnc-key.sh /usr/bin/websockify --key
/etc/vnc/tls.key --cert /etc/vnc/tls.cert --web /usr/share/novnc --inetd
localhost:5901
User=vnc
StandardInput=socket
StandardError=syslog
++++++ xvnc-novnc.socket ++++++
[Unit]
Description=noVNC Web Server
[Socket]
ListenStream=5801
Accept=False
[Install]
WantedBy=sockets.target
++++++ xvnc.socket ++++++
[Unit]
Description=Xvnc Server
Before=xvnc.target
Wants=xvnc.target
[Socket]
ListenStream=5901
Accept=yes
[Install]
WantedBy=sockets.target
++++++ xvnc.target ++++++
[Unit]
Description=System VNC service
++++++ [email protected] ++++++
[Unit]
Description=Xvnc Server
[Service]
ExecStart=/usr/lib/vnc/with-vnc-key.sh /usr/bin/Xvnc -noreset -inetd -once
-query localhost -geometry 1024x768 -securitytypes X509None,None -X509Key
/etc/vnc/tls.key -X509Cert /etc/vnc/tls.cert -log *:syslog:30 -extension MIT-SHM
User=vnc
StandardInput=socket
StandardOutput=socket
StandardError=syslog