From ed0ea16f50f712074374512cf512cb93cf589cc6 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 19 Aug 2024 13:54:02 +0200 Subject: [PATCH] 1.14.0 Resolves: RHEL-45316 Move old log to log.old if present Resolves: RHEL-54294 Fix shared memory leak Resolves: RHEL-55768 --- .gitignore | 1 + sources | 2 +- ...g-coma-in-default-security-type-list.patch | 24 + ...o-force-view-only-remote-connections.patch | 1113 ----------------- tigervnc-correctly-handle-zrle-cursors.patch | 29 + ...isting-config-directory-in-vncpasswd.patch | 27 + ...support-username-alias-in-plainusers.patch | 135 -- ...se-dup-to-get-available-fd-for-inetd.patch | 17 - ...e-existing-log-to-log-old-if-present.patch | 0 tigervnc-xserver120.patch | 185 ++- tigervnc.spec | 47 +- 11 files changed, 227 insertions(+), 1353 deletions(-) create mode 100644 tigervnc-add-missing-coma-in-default-security-type-list.patch delete mode 100644 tigervnc-add-option-to-force-view-only-remote-connections.patch create mode 100644 tigervnc-correctly-handle-zrle-cursors.patch create mode 100644 tigervnc-handle-existing-config-directory-in-vncpasswd.patch delete mode 100644 tigervnc-support-username-alias-in-plainusers.patch delete mode 100644 tigervnc-use-dup-to-get-available-fd-for-inetd.patch create mode 100644 tigervnc-vncsession-move-existing-log-to-log-old-if-present.patch diff --git a/.gitignore b/.gitignore index 447fa6f..b505e48 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ tigervnc-1.0.90-20100721svn4113.tar.bz2 /tigervnc-1.11.0.tar.gz /tigervnc-1.12.0.tar.gz /tigervnc-1.13.1.tar.gz +/tigervnc-1.14.0.tar.gz diff --git a/sources b/sources index 0a5c2a0..c9abbc7 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (tigervnc-1.13.1.tar.gz) = 9190dbcd3b57ba52286c158c0675104d68463d7e3ea8e23493514b64451ddb511f3daf0f177339bc231155daea376d9c8dc58216663e10aa12f67468f4559da5 +SHA512 (tigervnc-1.14.0.tar.gz) = ee36f0aa40957274fb00fd755624a8bea80432d797d6c183645ed1251058ab30594d2261693b5655c5ca85a22e53f93029eeccc51fe86780398d1a017fa2311c diff --git a/tigervnc-add-missing-coma-in-default-security-type-list.patch b/tigervnc-add-missing-coma-in-default-security-type-list.patch new file mode 100644 index 0000000..cb426b6 --- /dev/null +++ b/tigervnc-add-missing-coma-in-default-security-type-list.patch @@ -0,0 +1,24 @@ +From 4f6a3521874da5a67fd746389cfa9b6199eb3582 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Mon, 29 Jul 2024 16:16:08 +0200 +Subject: [PATCH] Add missing comma in default security type list + +Otherwise it merges with the next entry, removing both of them from the +default list. +--- + common/rfb/SecurityClient.cxx | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/rfb/SecurityClient.cxx b/common/rfb/SecurityClient.cxx +index 12860662f..63e0cadc0 100644 +--- a/common/rfb/SecurityClient.cxx ++++ b/common/rfb/SecurityClient.cxx +@@ -60,7 +60,7 @@ StringParameter SecurityClient::secTypes + "X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone," + #endif + #ifdef HAVE_NETTLE +- "RA2,RA2_256,RA2ne,RA2ne_256,DH,MSLogonII" ++ "RA2,RA2_256,RA2ne,RA2ne_256,DH,MSLogonII," + #endif + "VncAuth,None", + ConfViewer); diff --git a/tigervnc-add-option-to-force-view-only-remote-connections.patch b/tigervnc-add-option-to-force-view-only-remote-connections.patch deleted file mode 100644 index 0414f48..0000000 --- a/tigervnc-add-option-to-force-view-only-remote-connections.patch +++ /dev/null @@ -1,1113 +0,0 @@ -From 2be25eac8a96b3910701052d768ee465def36d56 Mon Sep 17 00:00:00 2001 -From: Jan Grulich -Date: Tue, 28 May 2024 13:07:58 +0200 -Subject: vncconfig: add option to force view only remote client connections - - -diff --git a/common/network/Socket.h b/common/network/Socket.h -index 901bab1..576fe15 100644 ---- a/common/network/Socket.h -+++ b/common/network/Socket.h -@@ -111,41 +111,6 @@ namespace network { - SocketException(const char* text, int err_) : rdr::SystemException(text, err_) {} - }; - -- class SocketServer { -- public: -- virtual ~SocketServer() {} -- -- // addSocket() tells the server to serve the Socket. The caller -- // retains ownership of the Socket - the only way for the server -- // to discard a Socket is by calling shutdown() on it. -- // outgoing is set to true if the socket was created by connecting out -- // to another host, or false if the socket was created by accept()ing -- // an incoming connection. -- virtual void addSocket(network::Socket* sock, bool outgoing=false) = 0; -- -- // removeSocket() tells the server to stop serving the Socket. The -- // caller retains ownership of the Socket - the server must NOT -- // delete the Socket! This call is used mainly to cause per-Socket -- // resources to be freed. -- virtual void removeSocket(network::Socket* sock) = 0; -- -- // getSockets() gets a list of sockets. This can be used to generate an -- // fd_set for calling select(). -- virtual void getSockets(std::list* sockets) = 0; -- -- // processSocketReadEvent() tells the server there is a Socket read event. -- // The implementation can indicate that the Socket is no longer active -- // by calling shutdown() on it. The caller will then call removeSocket() -- // soon after processSocketEvent returns, to allow any pre-Socket -- // resources to be tidied up. -- virtual void processSocketReadEvent(network::Socket* sock) = 0; -- -- // processSocketReadEvent() tells the server there is a Socket write event. -- // This is only necessary if the Socket has been put in non-blocking -- // mode and needs this callback to flush the buffer. -- virtual void processSocketWriteEvent(network::Socket* sock) = 0; -- }; -- - } - - #endif // __NETWORK_SOCKET_H__ -diff --git a/common/rfb/AccessRights.cxx b/common/rfb/AccessRights.cxx -new file mode 100644 -index 0000000..65e6ce2 ---- /dev/null -+++ b/common/rfb/AccessRights.cxx -@@ -0,0 +1,36 @@ -+/* Copyright 2024 TigerVNC Team -+ * -+ * 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 "AccessRights.h" -+ -+namespace rfb -+{ -+ -+ // AccessRights values -+ const AccessRights AccessNone = 0x0000; -+ const AccessRights AccessView = 0x0001; -+ const AccessRights AccessKeyEvents = 0x0002; -+ const AccessRights AccessPtrEvents = 0x0004; -+ const AccessRights AccessCutText = 0x0008; -+ const AccessRights AccessSetDesktopSize = 0x0010; -+ const AccessRights AccessNonShared = 0x0020; -+ const AccessRights AccessDefault = 0x03ff; -+ const AccessRights AccessNoQuery = 0x0400; -+ const AccessRights AccessFull = 0xffff; -+ -+} /* namespace rfb */ -diff --git a/common/rfb/AccessRights.h b/common/rfb/AccessRights.h -new file mode 100644 -index 0000000..adf4393 ---- /dev/null -+++ b/common/rfb/AccessRights.h -@@ -0,0 +1,41 @@ -+/* Copyright 2024 TigerVNC Team -+ * -+ * 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. -+ */ -+ -+#ifndef COMMON_RFB_ACCESSRIGHTS_H_ -+#define COMMON_RFB_ACCESSRIGHTS_H_ -+ -+#include -+ -+namespace rfb -+{ -+ -+ typedef uint16_t AccessRights; -+ extern const AccessRights AccessNone; // No rights at all -+ extern const AccessRights AccessView; // View display contents -+ extern const AccessRights AccessKeyEvents; // Send key events -+ extern const AccessRights AccessPtrEvents; // Send pointer events -+ extern const AccessRights AccessCutText; // Send/receive clipboard events -+ extern const AccessRights AccessSetDesktopSize; // Change desktop size -+ extern const AccessRights AccessNonShared; // Exclusive access to the server -+ extern const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES -+ extern const AccessRights AccessNoQuery; // Connect without local user accepting -+ extern const AccessRights AccessFull; // All of the available AND FUTURE rights -+ -+} /* namespace rfb */ -+ -+#endif /* COMMON_RFB_ACCESSRIGHTS_H_ */ -diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt -index ea1954e..1603aa5 100644 ---- a/common/rfb/CMakeLists.txt -+++ b/common/rfb/CMakeLists.txt -@@ -3,6 +3,7 @@ include_directories(${JPEG_INCLUDE_DIR}) - include_directories(${PIXMAN_INCLUDE_DIRS}) - - add_library(rfb STATIC -+ AccessRights.cxx - Blacklist.cxx - Congestion.cxx - CConnection.cxx -diff --git a/common/rfb/SConnection.cxx b/common/rfb/SConnection.cxx -index 3587484..eaa1c6f 100644 ---- a/common/rfb/SConnection.cxx -+++ b/common/rfb/SConnection.cxx -@@ -42,24 +42,12 @@ using namespace rfb; - - static LogWriter vlog("SConnection"); - --// AccessRights values --const SConnection::AccessRights SConnection::AccessView = 0x0001; --const SConnection::AccessRights SConnection::AccessKeyEvents = 0x0002; --const SConnection::AccessRights SConnection::AccessPtrEvents = 0x0004; --const SConnection::AccessRights SConnection::AccessCutText = 0x0008; --const SConnection::AccessRights SConnection::AccessSetDesktopSize = 0x0010; --const SConnection::AccessRights SConnection::AccessNonShared = 0x0020; --const SConnection::AccessRights SConnection::AccessDefault = 0x03ff; --const SConnection::AccessRights SConnection::AccessNoQuery = 0x0400; --const SConnection::AccessRights SConnection::AccessFull = 0xffff; -- -- --SConnection::SConnection() -+SConnection::SConnection(AccessRights accessRights) - : readyForSetColourMapEntries(false), - is(0), os(0), reader_(0), writer_(0), ssecurity(0), - authFailureTimer(this, &SConnection::handleAuthFailureTimeout), - state_(RFBSTATE_UNINITIALISED), preferredEncoding(encodingRaw), -- accessRights(0x0000), clientClipboard(NULL), hasLocalClipboard(false), -+ accessRights(accessRights), clientClipboard(NULL), hasLocalClipboard(false), - unsolicitedClipboardAttempt(false) - { - defaultMajorVersion = 3; -@@ -252,7 +240,7 @@ bool SConnection::processSecurityMsg() - } - - state_ = RFBSTATE_QUERYING; -- setAccessRights(ssecurity->getAccessRights()); -+ setAccessRights(accessRights & ssecurity->getAccessRights()); - queryConnection(ssecurity->getUserName()); - - // If the connection got approved right away then we can continue -diff --git a/common/rfb/SConnection.h b/common/rfb/SConnection.h -index 38969c2..e8d9695 100644 ---- a/common/rfb/SConnection.h -+++ b/common/rfb/SConnection.h -@@ -27,6 +27,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -40,7 +41,7 @@ namespace rfb { - class SConnection : public SMsgHandler { - public: - -- SConnection(); -+ SConnection(AccessRights accessRights); - virtual ~SConnection(); - - // Methods to initialise the connection -@@ -173,20 +174,12 @@ namespace rfb { - // clipboard via handleClipboardRequest(). - virtual void sendClipboardData(const char* data); - -+ // getAccessRights() returns the access rights of a SConnection to the server. -+ AccessRights getAccessRights() { return accessRights; } -+ - // setAccessRights() allows a security package to limit the access rights - // of a SConnection to the server. How the access rights are treated - // is up to the derived class. -- -- typedef rdr::U16 AccessRights; -- static const AccessRights AccessView; // View display contents -- static const AccessRights AccessKeyEvents; // Send key events -- static const AccessRights AccessPtrEvents; // Send pointer events -- static const AccessRights AccessCutText; // Send/receive clipboard events -- static const AccessRights AccessSetDesktopSize; // Change desktop size -- static const AccessRights AccessNonShared; // Exclusive access to the server -- static const AccessRights AccessDefault; // The default rights, INCLUDING FUTURE ONES -- static const AccessRights AccessNoQuery; // Connect without local user accepting -- static const AccessRights AccessFull; // All of the available AND FUTURE rights - virtual void setAccessRights(AccessRights ar); - virtual bool accessCheck(AccessRights ar) const; - -diff --git a/common/rfb/SSecurity.h b/common/rfb/SSecurity.h -index cef2027..6ebdbdf 100644 ---- a/common/rfb/SSecurity.h -+++ b/common/rfb/SSecurity.h -@@ -63,7 +63,7 @@ namespace rfb { - // for this security type. - virtual const char* getUserName() const = 0; - -- virtual SConnection::AccessRights getAccessRights() const { return SConnection::AccessDefault; } -+ virtual AccessRights getAccessRights() const { return AccessDefault; } - - protected: - SConnection* sc; -diff --git a/common/rfb/SSecurityRSAAES.cxx b/common/rfb/SSecurityRSAAES.cxx -index 15d2e97..9d6da87 100644 ---- a/common/rfb/SSecurityRSAAES.cxx -+++ b/common/rfb/SSecurityRSAAES.cxx -@@ -74,7 +74,7 @@ SSecurityRSAAES::SSecurityRSAAES(SConnection* sc, rdr::U32 _secType, - keySize(_keySize), isAllEncrypted(_isAllEncrypted), secType(_secType), - serverKey(), clientKey(), - serverKeyN(NULL), serverKeyE(NULL), clientKeyN(NULL), clientKeyE(NULL), -- accessRights(SConnection::AccessDefault), -+ accessRights(AccessDefault), - rais(NULL), raos(NULL), rawis(NULL), rawos(NULL) - { - assert(keySize == 128 || keySize == 256); -@@ -580,12 +580,12 @@ void SSecurityRSAAES::verifyPass() - throw AuthFailureException("No password configured for VNC Auth"); - - if (strcmp(password.buf, passwd.buf) == 0) { -- accessRights = SConnection::AccessDefault; -+ accessRights = AccessDefault; - return; - } - - if (passwdReadOnly.buf && strcmp(password.buf, passwdReadOnly.buf) == 0) { -- accessRights = SConnection::AccessView; -+ accessRights = AccessView; - return; - } - -diff --git a/common/rfb/SSecurityRSAAES.h b/common/rfb/SSecurityRSAAES.h -index 17e0d40..17e1405 100644 ---- a/common/rfb/SSecurityRSAAES.h -+++ b/common/rfb/SSecurityRSAAES.h -@@ -39,7 +39,7 @@ namespace rfb { - virtual bool processMsg(); - virtual const char* getUserName() const; - virtual int getType() const { return secType; } -- virtual SConnection::AccessRights getAccessRights() const -+ virtual AccessRights getAccessRights() const - { - return accessRights; - } -@@ -82,7 +82,7 @@ namespace rfb { - - CharArray username; - CharArray password; -- SConnection::AccessRights accessRights; -+ AccessRights accessRights; - - rdr::InStream* rais; - rdr::OutStream* raos; -diff --git a/common/rfb/SSecurityStack.cxx b/common/rfb/SSecurityStack.cxx -index 8b1c2a4..9c0321d 100644 ---- a/common/rfb/SSecurityStack.cxx -+++ b/common/rfb/SSecurityStack.cxx -@@ -71,14 +71,14 @@ const char* SSecurityStack::getUserName() const - return c; - } - --SConnection::AccessRights SSecurityStack::getAccessRights() const -+AccessRights SSecurityStack::getAccessRights() const - { -- SConnection::AccessRights accessRights; -+ AccessRights accessRights; - - if (!state0 && !state1) - return SSecurity::getAccessRights(); - -- accessRights = SConnection::AccessFull; -+ accessRights = AccessFull; - - if (state0) - accessRights &= state0->getAccessRights(); -diff --git a/common/rfb/SSecurityStack.h b/common/rfb/SSecurityStack.h -index 8b412bd..cf7b10d 100644 ---- a/common/rfb/SSecurityStack.h -+++ b/common/rfb/SSecurityStack.h -@@ -32,7 +32,7 @@ namespace rfb { - virtual bool processMsg(); - virtual int getType() const { return type; }; - virtual const char* getUserName() const; -- virtual SConnection::AccessRights getAccessRights() const; -+ virtual AccessRights getAccessRights() const; - protected: - short state; - SSecurity* state0; -diff --git a/common/rfb/SSecurityVeNCrypt.cxx b/common/rfb/SSecurityVeNCrypt.cxx -index 70d50d2..45d63b4 100644 ---- a/common/rfb/SSecurityVeNCrypt.cxx -+++ b/common/rfb/SSecurityVeNCrypt.cxx -@@ -180,7 +180,7 @@ const char* SSecurityVeNCrypt::getUserName() const - return ssecurity->getUserName(); - } - --SConnection::AccessRights SSecurityVeNCrypt::getAccessRights() const -+AccessRights SSecurityVeNCrypt::getAccessRights() const - { - if (ssecurity == NULL) - return SSecurity::getAccessRights(); -diff --git a/common/rfb/SSecurityVeNCrypt.h b/common/rfb/SSecurityVeNCrypt.h -index afbf724..d1fa831 100644 ---- a/common/rfb/SSecurityVeNCrypt.h -+++ b/common/rfb/SSecurityVeNCrypt.h -@@ -37,7 +37,7 @@ namespace rfb { - virtual bool processMsg(); - virtual int getType() const { return chosenType; } - virtual const char* getUserName() const; -- virtual SConnection::AccessRights getAccessRights() const; -+ virtual AccessRights getAccessRights() const; - - protected: - SSecurity *ssecurity; -diff --git a/common/rfb/SSecurityVncAuth.cxx b/common/rfb/SSecurityVncAuth.cxx -index a19404d..fcce4b2 100644 ---- a/common/rfb/SSecurityVncAuth.cxx -+++ b/common/rfb/SSecurityVncAuth.cxx -@@ -54,7 +54,7 @@ VncAuthPasswdParameter SSecurityVncAuth::vncAuthPasswd - - SSecurityVncAuth::SSecurityVncAuth(SConnection* sc) - : SSecurity(sc), sentChallenge(false), -- pg(&vncAuthPasswd), accessRights(0) -+ pg(&vncAuthPasswd), accessRights(AccessNone) - { - } - -@@ -103,12 +103,12 @@ bool SSecurityVncAuth::processMsg() - throw AuthFailureException("No password configured for VNC Auth"); - - if (verifyResponse(passwd)) { -- accessRights = SConnection::AccessDefault; -+ accessRights = AccessDefault; - return true; - } - - if (passwdReadOnly.buf && verifyResponse(passwdReadOnly)) { -- accessRights = SConnection::AccessView; -+ accessRights = AccessView; - return true; - } - -diff --git a/common/rfb/SSecurityVncAuth.h b/common/rfb/SSecurityVncAuth.h -index 94d5aaf..b7448f4 100644 ---- a/common/rfb/SSecurityVncAuth.h -+++ b/common/rfb/SSecurityVncAuth.h -@@ -55,7 +55,7 @@ namespace rfb { - virtual bool processMsg(); - virtual int getType() const {return secTypeVncAuth;} - virtual const char* getUserName() const {return 0;} -- virtual SConnection::AccessRights getAccessRights() const { return accessRights; } -+ virtual AccessRights getAccessRights() const { return accessRights; } - static StringParameter vncAuthPasswdFile; - static VncAuthPasswdParameter vncAuthPasswd; - private: -@@ -65,7 +65,7 @@ namespace rfb { - rdr::U8 response[vncAuthChallengeSize]; - bool sentChallenge; - VncAuthPasswdGetter* pg; -- SConnection::AccessRights accessRights; -+ AccessRights accessRights; - }; - } - #endif -diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx -index 23024c5..441ad3b 100644 ---- a/common/rfb/VNCSConnectionST.cxx -+++ b/common/rfb/VNCSConnectionST.cxx -@@ -48,8 +48,9 @@ static LogWriter vlog("VNCSConnST"); - static Cursor emptyCursor(0, 0, Point(0, 0), NULL); - - VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s, -- bool reverse) -- : sock(s), reverseConnection(reverse), -+ bool reverse, AccessRights ar) -+ : SConnection(ar), -+ sock(s), reverseConnection(reverse), - inProcessMessages(false), - pendingSyncFence(false), syncFence(false), fenceFlags(0), - fenceDataLen(0), fenceData(NULL), congestionTimer(this), -diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h -index 72b0c52..66567a6 100644 ---- a/common/rfb/VNCSConnectionST.h -+++ b/common/rfb/VNCSConnectionST.h -@@ -40,7 +40,8 @@ namespace rfb { - class VNCSConnectionST : private SConnection, - public Timer::Callback { - public: -- VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse); -+ VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse, -+ AccessRights ar); - virtual ~VNCSConnectionST(); - - // SConnection methods -diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h -index 4535b56..a081f63 100644 ---- a/common/rfb/VNCServer.h -+++ b/common/rfb/VNCServer.h -@@ -23,17 +23,48 @@ - #ifndef __RFB_VNCSERVER_H__ - #define __RFB_VNCSERVER_H__ - --#include -- - #include - #include - #include - -+namespace network { class Socket; } -+ - namespace rfb { - -- class VNCServer : public UpdateTracker, -- public network::SocketServer { -+ class VNCServer : public UpdateTracker { - public: -+ // addSocket() tells the server to serve the Socket. The caller -+ // retains ownership of the Socket - the only way for the server -+ // to discard a Socket is by calling shutdown() on it. -+ // outgoing is set to true if the socket was created by connecting out -+ // to another host, or false if the socket was created by accept()ing -+ // an incoming connection. -+ // accessRights allows to set the access rights to the server. -+ virtual void addSocket(network::Socket* sock, bool outgoing=false, -+ AccessRights accessRights = AccessDefault) = 0; -+ -+ // removeSocket() tells the server to stop serving the Socket. The -+ // caller retains ownership of the Socket - the server must NOT -+ // delete the Socket! This call is used mainly to cause per-Socket -+ // resources to be freed. -+ virtual void removeSocket(network::Socket* sock) = 0; -+ -+ // getSockets() gets a list of sockets. This can be used to generate an -+ // fd_set for calling select(). -+ virtual void getSockets(std::list* sockets) = 0; -+ -+ // processSocketReadEvent() tells the server there is a Socket read event. -+ // The implementation can indicate that the Socket is no longer active -+ // by calling shutdown() on it. The caller will then call removeSocket() -+ // soon after processSocketEvent returns, to allow any pre-Socket -+ // resources to be tidied up. -+ virtual void processSocketReadEvent(network::Socket* sock) = 0; -+ -+ // processSocketReadEvent() tells the server there is a Socket write event. -+ // This is only necessary if the Socket has been put in non-blocking -+ // mode and needs this callback to flush the buffer. -+ virtual void processSocketWriteEvent(network::Socket* sock) = 0; -+ - // blockUpdates()/unblockUpdates() tells the server that the pixel buffer - // is currently in flux and may not be accessed. The attributes of the - // pixel buffer may still be accessed, but not the frame buffer itself. -diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx -index 411cfd5..6f7c039 100644 ---- a/common/rfb/VNCServerST.cxx -+++ b/common/rfb/VNCServerST.cxx -@@ -55,6 +55,8 @@ - #include - #include - -+#include -+ - #include - #include - #include -@@ -126,9 +128,9 @@ VNCServerST::~VNCServerST() - } - - --// SocketServer methods -+// VNCServer methods - --void VNCServerST::addSocket(network::Socket* sock, bool outgoing) -+void VNCServerST::addSocket(network::Socket* sock, bool outgoing, AccessRights accessRights) - { - // - Check the connection isn't black-marked - // *** do this in getSecurity instead? -@@ -161,7 +163,7 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing) - connectTimer.start(secsToMillis(rfb::Server::maxConnectionTime)); - disconnectTimer.stop(); - -- VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing); -+ VNCSConnectionST* client = new VNCSConnectionST(this, sock, outgoing, accessRights); - clients.push_front(client); - client->init(); - } -@@ -233,8 +235,6 @@ void VNCServerST::processSocketWriteEvent(network::Socket* sock) - throw rdr::Exception("invalid Socket in VNCServerST"); - } - --// VNCServer methods -- - void VNCServerST::blockUpdates() - { - blockCounter++; -@@ -677,7 +677,7 @@ void VNCServerST::queryConnection(VNCSConnectionST* client, - } - - // - Does the client have the right to bypass the query? -- if (client->accessCheck(SConnection::AccessNoQuery)) -+ if (client->accessCheck(AccessNoQuery)) - { - approveConnection(client->getSock(), true, NULL); - return; -@@ -690,7 +690,7 @@ void VNCServerST::clientReady(VNCSConnectionST* client, bool shared) - { - if (!shared) { - if (rfb::Server::disconnectClients && -- client->accessCheck(SConnection::AccessNonShared)) { -+ client->accessCheck(AccessNonShared)) { - // - Close all the other connected clients - slog.debug("non-shared connection - closing clients"); - closeClients("Non-shared connection requested", client->getSock()); -diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h -index 159e3a4..3610062 100644 ---- a/common/rfb/VNCServerST.h -+++ b/common/rfb/VNCServerST.h -@@ -51,12 +51,13 @@ namespace rfb { - virtual ~VNCServerST(); - - -- // Methods overridden from SocketServer -+ // Methods overridden from VNCServer - - // addSocket - // Causes the server to allocate an RFB-protocol management - // structure for the socket & initialise it. -- virtual void addSocket(network::Socket* sock, bool outgoing=false); -+ virtual void addSocket(network::Socket* sock, bool outgoing=false, -+ AccessRights ar=AccessDefault); - - // removeSocket - // Clean up any resources associated with the Socket -@@ -76,9 +77,6 @@ namespace rfb { - // Flush pending data from the Socket on to the network. - virtual void processSocketWriteEvent(network::Socket* sock); - -- -- // Methods overridden from VNCServer -- - virtual void blockUpdates(); - virtual void unblockUpdates(); - virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout); -diff --git a/tests/perf/encperf.cxx b/tests/perf/encperf.cxx -index 8fb9553..fa87b16 100644 ---- a/tests/perf/encperf.cxx -+++ b/tests/perf/encperf.cxx -@@ -41,6 +41,8 @@ - #include - #include - -+#include -+ - #include - - #include -@@ -134,7 +136,7 @@ public: - - void getStats(double&, unsigned long long&, unsigned long long&); - -- virtual void setAccessRights(AccessRights ar); -+ virtual void setAccessRights(rfb::AccessRights ar); - - virtual void setDesktopSize(int fb_width, int fb_height, - const rfb::ScreenSet& layout); -@@ -303,6 +305,7 @@ void Manager::getStats(double& ratio, unsigned long long& encodedBytes, - } - - SConn::SConn() -+: SConnection(rfb::AccessDefault) - { - out = new DummyOutStream; - setStreams(NULL, out); -@@ -329,7 +332,7 @@ void SConn::getStats(double& ratio, unsigned long long& bytes, - manager->getStats(ratio, bytes, rawEquivalent); - } - --void SConn::setAccessRights(AccessRights ar) -+void SConn::setAccessRights(rfb::AccessRights) - { - } - -diff --git a/unix/vncconfig/vncExt.c b/unix/vncconfig/vncExt.c -index f19123b..4ec671b 100644 ---- a/unix/vncconfig/vncExt.c -+++ b/unix/vncconfig/vncExt.c -@@ -228,7 +228,7 @@ Bool XVncExtSelectInput(Display* dpy, Window w, int mask) - return True; - } - --Bool XVncExtConnect(Display* dpy, const char* hostAndPort) -+Bool XVncExtConnect(Display* dpy, const char* hostAndPort, Bool viewOnly) - { - xVncExtConnectReq* req; - xVncExtConnectReply rep; -@@ -243,6 +243,7 @@ Bool XVncExtConnect(Display* dpy, const char* hostAndPort) - req->vncExtReqType = X_VncExtConnect; - req->length += (strLen + 3) >> 2; - req->strLen = strLen; -+ req->viewOnly = (CARD8)viewOnly; - Data(dpy, hostAndPort, strLen); - if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { - UnlockDisplay(dpy); -diff --git a/unix/vncconfig/vncExt.h b/unix/vncconfig/vncExt.h -index 2b24469..4383248 100644 ---- a/unix/vncconfig/vncExt.h -+++ b/unix/vncconfig/vncExt.h -@@ -46,7 +46,7 @@ char* XVncExtGetParamDesc(Display* dpy, const char* param); - char** XVncExtListParams(Display* dpy, int* nParams); - void XVncExtFreeParamList(char** list); - Bool XVncExtSelectInput(Display* dpy, Window w, int mask); --Bool XVncExtConnect(Display* dpy, const char* hostAndPort); -+Bool XVncExtConnect(Display* dpy, const char* hostAndPort, Bool viewOnly); - Bool XVncExtGetQueryConnect(Display* dpy, char** addr, - char** user, int* timeout, void** opaqueId); - Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve); -@@ -181,7 +181,7 @@ typedef struct { - CARD8 vncExtReqType; /* always VncExtConnect */ - CARD16 length B16; - CARD8 strLen; -- CARD8 pad0; -+ CARD8 viewOnly; - CARD16 pad1 B16; - } xVncExtConnectReq; - #define sz_xVncExtConnectReq 8 -diff --git a/unix/vncconfig/vncconfig.cxx b/unix/vncconfig/vncconfig.cxx -index 276d0e6..0d644ed 100644 ---- a/unix/vncconfig/vncconfig.cxx -+++ b/unix/vncconfig/vncconfig.cxx -@@ -177,8 +177,8 @@ static void usage() - { - fprintf(stderr,"usage: %s [parameters]\n", - programName); -- fprintf(stderr," %s [parameters] -connect [:]\n", -- programName); -+ fprintf(stderr," %s [parameters] -connect " -+ "[-view-only] [:]\n", programName); - fprintf(stderr," %s [parameters] -disconnect\n", programName); - fprintf(stderr," %s [parameters] [-set] = ...\n", - programName); -@@ -241,13 +241,18 @@ int main(int argc, char** argv) - if (i < argc) { - for (; i < argc; i++) { - if (strcmp(argv[i], "-connect") == 0) { -+ Bool viewOnly = False; - i++; -+ if (strcmp(argv[i], "-view-only") == 0) { -+ viewOnly = True; -+ i++; -+ } - if (i >= argc) usage(); -- if (!XVncExtConnect(dpy, argv[i])) { -+ if (!XVncExtConnect(dpy, argv[i], viewOnly)) { - fprintf(stderr,"connecting to %s failed\n",argv[i]); - } - } else if (strcmp(argv[i], "-disconnect") == 0) { -- if (!XVncExtConnect(dpy, "")) { -+ if (!XVncExtConnect(dpy, "", False)) { - fprintf(stderr,"disconnecting all clients failed\n"); - } - } else if (strcmp(argv[i], "-get") == 0) { -diff --git a/unix/vncconfig/vncconfig.man b/unix/vncconfig/vncconfig.man -index ed9ddda..b07c02f 100644 ---- a/unix/vncconfig/vncconfig.man -+++ b/unix/vncconfig/vncconfig.man -@@ -7,7 +7,7 @@ vncconfig \- configure and control a VNC server - .br - .B vncconfig - .RI [ parameters ] --.B \-connect -+.B \-connect \fP[\fB-view-only\fP] - .IR host [: port ] - .br - .B vncconfig -@@ -55,12 +55,13 @@ is no VNC extension. - - .SH OPTIONS - .TP --.B \-connect \fIhost\fP[:\fIport\fP] -+.B \-connect \fP[\fB-view-only\fP] \fIhost\fP[:\fIport\fP] - Tells an Xvnc server to make a "reverse" connection to a listening VNC viewer - (normally connections are made the other way round - the viewer connects to the - server). \fIhost\fP is the host where the listening viewer is running. If it's - not listening on the default port of 5500, you can specify \fIhost:port\fP --instead. -+instead. The \fB-view-only\fP option specifies that the server must ignore all -+keyboard or mouse events sent by the client. - . - .TP - .B \-disconnect -diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx -index f9c8109..6719c43 100644 ---- a/unix/x0vncserver/XDesktop.cxx -+++ b/unix/x0vncserver/XDesktop.cxx -@@ -26,6 +26,8 @@ - #include - #include - -+#include -+ - #include - - #include -diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc -index 603e1e5..5f08f10 100644 ---- a/unix/xserver/hw/vnc/XserverDesktop.cc -+++ b/unix/xserver/hw/vnc/XserverDesktop.cc -@@ -311,7 +311,7 @@ void XserverDesktop::handleSocketEvent(int fd, bool read, bool write) - - bool XserverDesktop::handleListenerEvent(int fd, - std::list* sockets, -- SocketServer* sockserv) -+ VNCServer* sockserv) - { - std::list::iterator i; - -@@ -332,7 +332,7 @@ bool XserverDesktop::handleListenerEvent(int fd, - } - - bool XserverDesktop::handleSocketEvent(int fd, -- SocketServer* sockserv, -+ VNCServer* sockserv, - bool read, bool write) - { - std::list sockets; -@@ -402,10 +402,10 @@ void XserverDesktop::blockHandler(int* timeout) - } - } - --void XserverDesktop::addClient(Socket* sock, bool reverse) -+void XserverDesktop::addClient(Socket* sock, bool reverse, bool viewOnly) - { - vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse); -- server->addSocket(sock, reverse); -+ server->addSocket(sock, reverse, viewOnly ? AccessView : AccessDefault); - vncSetNotifyFd(sock->getFd(), screenIndex, true, false); - } - -diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h -index 57ee808..1382677 100644 ---- a/unix/xserver/hw/vnc/XserverDesktop.h -+++ b/unix/xserver/hw/vnc/XserverDesktop.h -@@ -42,7 +42,7 @@ namespace rfb { - class VNCServerST; - } - --namespace network { class SocketListener; class Socket; class SocketServer; } -+namespace network { class SocketListener; class Socket; } - - class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, - public rfb::Timer::Callback { -@@ -72,7 +72,7 @@ public: - void add_copied(const rfb::Region &dest, const rfb::Point &delta); - void handleSocketEvent(int fd, bool read, bool write); - void blockHandler(int* timeout); -- void addClient(network::Socket* sock, bool reverse); -+ void addClient(network::Socket* sock, bool reverse, bool viewOnly); - void disconnectClients(); - - // QueryConnect methods called from X server code -@@ -107,9 +107,9 @@ public: - protected: - bool handleListenerEvent(int fd, - std::list* sockets, -- network::SocketServer* sockserv); -+ rfb::VNCServer* sockserv); - bool handleSocketEvent(int fd, -- network::SocketServer* sockserv, -+ rfb::VNCServer* sockserv, - bool read, bool write); - - virtual bool handleTimeout(rfb::Timer* t); -diff --git a/unix/xserver/hw/vnc/vncExt.c b/unix/xserver/hw/vnc/vncExt.c -index 89c1055..e98275c 100644 ---- a/unix/xserver/hw/vnc/vncExt.c -+++ b/unix/xserver/hw/vnc/vncExt.c -@@ -348,7 +348,7 @@ static int ProcVncExtConnect(ClientPtr client) - address[stuff->strLen] = 0; - - rep.success = 0; -- if (vncConnectClient(address) == 0) -+ if (vncConnectClient(address, (int)stuff->viewOnly) == 0) - rep.success = 1; - - rep.type = X_Reply; -diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc -index 8dbc048..2e0dc9e 100644 ---- a/unix/xserver/hw/vnc/vncExtInit.cc -+++ b/unix/xserver/hw/vnc/vncExtInit.cc -@@ -262,7 +262,7 @@ void vncExtensionInit(void) - - if (scr == 0 && vncInetdSock != -1 && listeners.empty()) { - network::Socket* sock = new network::TcpSocket(vncInetdSock); -- desktop[scr]->addClient(sock, false); -+ desktop[scr]->addClient(sock, false, false); - vlog.info("added inetd sock"); - } - } -@@ -338,7 +338,7 @@ void vncSendClipboardData(const char* data) - desktop[scr]->sendClipboardData(data); - } - --int vncConnectClient(const char *addr) -+int vncConnectClient(const char *addr, int viewOnly) - { - if (strlen(addr) == 0) { - try { -@@ -357,8 +357,10 @@ int vncConnectClient(const char *addr) - - try { - network::Socket* sock = new network::TcpSocket(host, port); -+ vlog.info("Reverse connection: %s:%d%s", host, port, -+ viewOnly ? " (view only)" : ""); - delete [] host; -- desktop[0]->addClient(sock, true); -+ desktop[0]->addClient(sock, true, (bool)viewOnly); - } catch (rdr::Exception& e) { - vlog.error("Reverse connection: %s",e.str()); - return -1; -diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h -index c317d8a..333e32a 100644 ---- a/unix/xserver/hw/vnc/vncExtInit.h -+++ b/unix/xserver/hw/vnc/vncExtInit.h -@@ -57,7 +57,7 @@ void vncRequestClipboard(void); - void vncAnnounceClipboard(int available); - void vncSendClipboardData(const char* data); - --int vncConnectClient(const char *addr); -+int vncConnectClient(const char *addr, int viewOnly); - - void vncGetQueryConnect(uint32_t *opaqueId, const char**username, - const char **address, int *timeout); -diff --git a/win/rfb_win32/SocketManager.cxx b/win/rfb_win32/SocketManager.cxx -index 5463b24..9c9a736 100644 ---- a/win/rfb_win32/SocketManager.cxx -+++ b/win/rfb_win32/SocketManager.cxx -@@ -24,8 +24,12 @@ - - #include - #include -+ -+#include -+ - #include - #include -+#include - #include - - using namespace rfb; -@@ -54,7 +58,7 @@ static void requestAddressChangeEvents(network::SocketListener* sock_) { - - - void SocketManager::addListener(network::SocketListener* sock_, -- network::SocketServer* srvr, -+ VNCServer* srvr, - AddressChangeNotifier* acn) { - WSAEVENT event = WSACreateEvent(); - long flags = FD_ACCEPT | FD_CLOSE; -@@ -102,7 +106,7 @@ void SocketManager::remListener(network::SocketListener* sock) { - } - - --void SocketManager::addSocket(network::Socket* sock_, network::SocketServer* srvr, bool outgoing) { -+void SocketManager::addSocket(network::Socket* sock_, VNCServer* srvr, bool outgoing) { - WSAEVENT event = WSACreateEvent(); - if (!event || !addEvent(event, this) || - (WSAEventSelect(sock_->getFd(), event, FD_READ | FD_CLOSE) == SOCKET_ERROR)) { -@@ -134,7 +138,7 @@ void SocketManager::remSocket(network::Socket* sock_) { - throw rdr::Exception("Socket not registered"); - } - --bool SocketManager::getDisable(network::SocketServer* srvr) -+bool SocketManager::getDisable(VNCServer* srvr) - { - std::map::iterator i; - for (i=listeners.begin(); i!=listeners.end(); i++) { -@@ -145,7 +149,7 @@ bool SocketManager::getDisable(network::SocketServer* srvr) - throw rdr::Exception("Listener not registered"); - } - --void SocketManager::setDisable(network::SocketServer* srvr, bool disable) -+void SocketManager::setDisable(VNCServer* srvr, bool disable) - { - bool found = false; - std::map::iterator i; -diff --git a/win/rfb_win32/SocketManager.h b/win/rfb_win32/SocketManager.h -index e5ca02e..809c470 100644 ---- a/win/rfb_win32/SocketManager.h -+++ b/win/rfb_win32/SocketManager.h -@@ -19,22 +19,28 @@ - // -=- SocketManager.h - - // Socket manager class for Win32. --// Passed a network::SocketListener and a network::SocketServer when -+// Passed a network::SocketListener and a rfb::VNCServer when - // constructed. Uses WSAAsyncSelect to get notifications of network - // connection attempts. When an incoming connection is received, --// the manager will call network::SocketServer::addClient(). If -+// the manager will call rfb::VNCServer::addClient(). If - // addClient returns true then the manager registers interest in - // network events on that socket, and calls --// network::SocketServer::processSocketEvent(). -+// rfb::VNCServer::processSocketEvent(). - - #ifndef __RFB_WIN32_SOCKET_MGR_H__ - #define __RFB_WIN32_SOCKET_MGR_H__ - - #include --#include - #include - -+namespace network { -+ class SocketListener; -+ class Socket; -+} -+ - namespace rfb { -+ class VNCServer; -+ - namespace win32 { - - class SocketManager : public EventManager, EventHandler { -@@ -52,21 +58,21 @@ namespace rfb { - }; - - // Add a listening socket. Incoming connections will be added to the supplied -- // SocketServer. -+ // VNCServer. - void addListener(network::SocketListener* sock_, -- network::SocketServer* srvr, -+ VNCServer* srvr, - AddressChangeNotifier* acn = 0); - - // Remove and delete a listening socket. - void remListener(network::SocketListener* sock); - - // Add an already-connected socket. Socket events will cause the supplied -- // SocketServer to be called. The socket must ALREADY BE REGISTERED with -- // the SocketServer. -- void addSocket(network::Socket* sock_, network::SocketServer* srvr, bool outgoing=true); -+ // VNCServer to be called. The socket must ALREADY BE REGISTERED with -+ // the VNCServer. -+ void addSocket(network::Socket* sock_, VNCServer* srvr, bool outgoing=true); - -- bool getDisable(network::SocketServer* srvr); -- void setDisable(network::SocketServer* srvr, bool disable); -+ bool getDisable(VNCServer* srvr); -+ void setDisable(VNCServer* srvr, bool disable); - - protected: - virtual int checkTimeouts(); -@@ -75,11 +81,11 @@ namespace rfb { - - struct ConnInfo { - network::Socket* sock; -- network::SocketServer* server; -+ VNCServer* server; - }; - struct ListenInfo { - network::SocketListener* sock; -- network::SocketServer* server; -+ VNCServer* server; - AddressChangeNotifier* notifier; - bool disable; - }; -diff --git a/win/winvnc/ManagedListener.cxx b/win/winvnc/ManagedListener.cxx -index a93ca29..1a27867 100644 ---- a/win/winvnc/ManagedListener.cxx -+++ b/win/winvnc/ManagedListener.cxx -@@ -45,7 +45,7 @@ ManagedListener::~ManagedListener() { - } - - --void ManagedListener::setServer(network::SocketServer* svr) { -+void ManagedListener::setServer(rfb::VNCServer* svr) { - if (svr == server) - return; - vlog.info("set server to %p", svr); -diff --git a/win/winvnc/ManagedListener.h b/win/winvnc/ManagedListener.h -index 39223c7..20503c3 100644 ---- a/win/winvnc/ManagedListener.h -+++ b/win/winvnc/ManagedListener.h -@@ -27,7 +27,7 @@ namespace winvnc { - - // -=- ManagedListener - // Wrapper class which simplifies the management of a listening socket -- // on a specified port, attached to a SocketManager and SocketServer. -+ // on a specified port, attached to a SocketManager and VNCServer. - // Reopens sockets & reconfigures filters & callbacks as appropriate. - // Handles addition/removal of Listeners from SocketManager internally. - -@@ -36,7 +36,7 @@ namespace winvnc { - ManagedListener(rfb::win32::SocketManager* mgr); - ~ManagedListener(); - -- void setServer(network::SocketServer* svr); -+ void setServer(rfb::VNCServer* svr); - void setPort(int port, bool localOnly=false); - void setFilter(const char* filter); - void setAddressChangeNotifier(rfb::win32::SocketManager::AddressChangeNotifier* acn); -@@ -49,7 +49,7 @@ namespace winvnc { - network::TcpFilter* filter; - rfb::win32::SocketManager* manager; - rfb::win32::SocketManager::AddressChangeNotifier* addrChangeNotifier; -- network::SocketServer* server; -+ rfb::VNCServer* server; - int port; - bool localOnly; - }; -diff --git a/win/winvnc/VNCServerWin32.cxx b/win/winvnc/VNCServerWin32.cxx -index 79769e9..b884352 100644 ---- a/win/winvnc/VNCServerWin32.cxx -+++ b/win/winvnc/VNCServerWin32.cxx -@@ -366,11 +366,11 @@ void VNCServerWin32::getConnInfo(ListConnInfo * listConn) - - if (!conn->authenticated()) - status = 3; -- else if (conn->accessCheck(rfb::SConnection::AccessPtrEvents | -- rfb::SConnection::AccessKeyEvents | -- rfb::SConnection::AccessView)) -+ else if (conn->accessCheck(rfb::AccessPtrEvents | -+ rfb::AccessKeyEvents | -+ rfb::AccessView)) - status = 0; -- else if (conn->accessCheck(rfb::SConnection::AccessView)) -+ else if (conn->accessCheck(rfb::AccessView)) - status = 1; - else - status = 2; -@@ -401,25 +401,25 @@ void VNCServerWin32::setConnStatus(ListConnInfo* listConn) - if (status == 3) { - conn->close(0); - } else { -- rfb::SConnection::AccessRights ar; -+ rfb::AccessRights ar; - -- ar = rfb::SConnection::AccessDefault; -+ ar = rfb::AccessDefault; - - switch (status) { - case 0: -- ar |= rfb::SConnection::AccessPtrEvents | -- rfb::SConnection::AccessKeyEvents | -- rfb::SConnection::AccessView; -+ ar |= rfb::AccessPtrEvents | -+ rfb::AccessKeyEvents | -+ rfb::AccessView; - break; - case 1: -- ar |= rfb::SConnection::AccessView; -- ar &= ~(rfb::SConnection::AccessPtrEvents | -- rfb::SConnection::AccessKeyEvents); -+ ar |= rfb::AccessView; -+ ar &= ~(rfb::AccessPtrEvents | -+ rfb::AccessKeyEvents); - break; - case 2: -- ar &= ~(rfb::SConnection::AccessPtrEvents | -- rfb::SConnection::AccessKeyEvents | -- rfb::SConnection::AccessView); -+ ar &= ~(rfb::AccessPtrEvents | -+ rfb::AccessKeyEvents | -+ rfb::AccessView); - break; - } - conn->setAccessRights(ar); diff --git a/tigervnc-correctly-handle-zrle-cursors.patch b/tigervnc-correctly-handle-zrle-cursors.patch new file mode 100644 index 0000000..1b17302 --- /dev/null +++ b/tigervnc-correctly-handle-zrle-cursors.patch @@ -0,0 +1,29 @@ +From 6d9017eeb364491cf2acdf1c7e61aee8dd198527 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Fri, 30 Aug 2024 16:15:09 +0200 +Subject: [PATCH] Correctly handle ZRLE cursors + +Cursor data has a depth of 32 bits and hence cannot use CPIXELs. + +This is a regression from baca73d. +--- + common/rfb/ZRLEDecoder.cxx | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/common/rfb/ZRLEDecoder.cxx b/common/rfb/ZRLEDecoder.cxx +index 474fd6ca1..e274a697a 100644 +--- a/common/rfb/ZRLEDecoder.cxx ++++ b/common/rfb/ZRLEDecoder.cxx +@@ -125,10 +125,10 @@ void ZRLEDecoder::zrleDecode(const Rect& r, rdr::InStream* is, + Pixel maxPixel = pf.pixelFromRGB((uint16_t)-1, (uint16_t)-1, (uint16_t)-1); + bool fitsInLS3Bytes = maxPixel < (1<<24); + bool fitsInMS3Bytes = (maxPixel & 0xff) == 0; +- bool isLowCPixel = (sizeof(T) == 4) && ++ bool isLowCPixel = (sizeof(T) == 4) && (pf.depth <= 24) && + ((fitsInLS3Bytes && pf.isLittleEndian()) || + (fitsInMS3Bytes && pf.isBigEndian())); +- bool isHighCPixel = (sizeof(T) == 4) && ++ bool isHighCPixel = (sizeof(T) == 4) && (pf.depth <= 24) && + ((fitsInLS3Bytes && pf.isBigEndian()) || + (fitsInMS3Bytes && pf.isLittleEndian())); + diff --git a/tigervnc-handle-existing-config-directory-in-vncpasswd.patch b/tigervnc-handle-existing-config-directory-in-vncpasswd.patch new file mode 100644 index 0000000..ea431f8 --- /dev/null +++ b/tigervnc-handle-existing-config-directory-in-vncpasswd.patch @@ -0,0 +1,27 @@ +From 445e0230cf4e939dcc59caf5d5f001c2f7b04da6 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Thu, 15 Aug 2024 14:24:42 +0200 +Subject: [PATCH] Handle existing config directory in vncpasswd + +This fixes commit a79c33d. +--- + unix/vncpasswd/vncpasswd.cxx | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx +index 6666955f1..9f794e129 100644 +--- a/unix/vncpasswd/vncpasswd.cxx ++++ b/unix/vncpasswd/vncpasswd.cxx +@@ -213,8 +213,10 @@ int main(int argc, char** argv) + exit(1); + } + if (os::mkdir_p(configDir, 0777) == -1) { +- fprintf(stderr, "Could not create VNC config directory: %s\n", strerror(errno)); +- exit(1); ++ if (errno != EEXIST) { ++ fprintf(stderr, "Could not create VNC config directory: %s\n", strerror(errno)); ++ exit(1); ++ } + } + snprintf(fname, sizeof(fname), "%s/passwd", configDir); + } diff --git a/tigervnc-support-username-alias-in-plainusers.patch b/tigervnc-support-username-alias-in-plainusers.patch deleted file mode 100644 index abf4eda..0000000 --- a/tigervnc-support-username-alias-in-plainusers.patch +++ /dev/null @@ -1,135 +0,0 @@ -diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx -index 6f65e87..3142ba3 100644 ---- a/common/rfb/SSecurityPlain.cxx -+++ b/common/rfb/SSecurityPlain.cxx -@@ -27,6 +27,8 @@ - #include - #if !defined(WIN32) && !defined(__APPLE__) - #include -+#include -+#include - #endif - #ifdef WIN32 - #include -@@ -45,21 +47,22 @@ StringParameter PasswordValidator::plainUsers - - bool PasswordValidator::validUser(const char* username) - { -- CharArray users(plainUsers.getValueStr()), user; -+ std::vector users; - -- while (users.buf) { -- strSplit(users.buf, ',', &user.buf, &users.buf); --#ifdef WIN32 -- if (0 == stricmp(user.buf, "*")) -- return true; -- if (0 == stricmp(user.buf, username)) -- return true; --#else -- if (!strcmp(user.buf, "*")) -- return true; -- if (!strcmp(user.buf, username)) -- return true; -+ users = split(plainUsers, ','); -+ -+ for (size_t i = 0; i < users.size(); i++) { -+ if (users[i] == "*") -+ return true; -+#if !defined(WIN32) && !defined(__APPLE__) -+ if (users[i] == "%u") { -+ struct passwd *pw = getpwnam(username); -+ if (pw && pw->pw_uid == getuid()) -+ return true; -+ } - #endif -+ if (users[i] == username) -+ return true; - } - return false; - } -diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx -index 649eb0b..cce73a0 100644 ---- a/common/rfb/util.cxx -+++ b/common/rfb/util.cxx -@@ -99,6 +99,26 @@ namespace rfb { - return false; - } - -+ std::vector split(const char* src, -+ const char delimiter) -+ { -+ std::vector out; -+ const char *start, *stop; -+ -+ start = src; -+ do { -+ stop = strchr(start, delimiter); -+ if (stop == NULL) { -+ out.push_back(start); -+ } else { -+ out.push_back(std::string(start, stop-start)); -+ start = stop + 1; -+ } -+ } while (stop != NULL); -+ -+ return out; -+ } -+ - bool strContains(const char* src, char c) { - int l=strlen(src); - for (int i=0; i - #include - -+#include -+#include -+ - struct timeval; - - #ifdef __GNUC__ -@@ -76,6 +79,10 @@ namespace rfb { - // that part of the string. Obviously, setting both to 0 is not useful... - bool strSplit(const char* src, const char limiter, char** out1, char** out2, bool fromEnd=false); - -+ // Splits a string with the specified delimiter -+ std::vector split(const char* src, -+ const char delimiter); -+ - // Returns true if src contains c - bool strContains(const char* src, char c); - -diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man -index c36ae34..78db730 100644 ---- a/unix/x0vncserver/x0vncserver.man -+++ b/unix/x0vncserver/x0vncserver.man -@@ -125,8 +125,8 @@ parameter instead. - .B \-PlainUsers \fIuser-list\fP - A comma separated list of user names that are allowed to authenticate via - any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP --to allow any user to authenticate using this security type. Default is to --deny all users. -+to allow any user to authenticate using this security type. Specify \fB%u\fP -+to allow the user of the server process. Default is to deny all users. - . - .TP - .B \-pam_service \fIname\fP, \-PAMService \fIname\fP -diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man -index ea87dea..e9fb654 100644 ---- a/unix/xserver/hw/vnc/Xvnc.man -+++ b/unix/xserver/hw/vnc/Xvnc.man -@@ -200,8 +200,8 @@ parameter instead. - .B \-PlainUsers \fIuser-list\fP - A comma separated list of user names that are allowed to authenticate via - any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP --to allow any user to authenticate using this security type. Default is to --deny all users. -+to allow any user to authenticate using this security type. Specify \fB%u\fP -+to allow the user of the server process. Default is to deny all users. - . - .TP - .B \-pam_service \fIname\fP, \-PAMService \fIname\fP diff --git a/tigervnc-use-dup-to-get-available-fd-for-inetd.patch b/tigervnc-use-dup-to-get-available-fd-for-inetd.patch deleted file mode 100644 index 0e0f794..0000000 --- a/tigervnc-use-dup-to-get-available-fd-for-inetd.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c -index f8141959..c5c36539 100644 ---- a/unix/xserver/hw/vnc/xvnc.c -+++ b/unix/xserver/hw/vnc/xvnc.c -@@ -366,8 +366,10 @@ ddxProcessArgument(int argc, char *argv[], int i) - if (strcmp(argv[i], "-inetd") == 0) { - int nullfd; - -- dup2(0, 3); -- vncInetdSock = 3; -+ if ((vncInetdSock = dup(0)) == -1) -+ FatalError -+ ("Xvnc error: failed to allocate a new file descriptor for -inetd: %s\n", strerror(errno)); -+ - - /* Avoid xserver >= 1.19's epoll-fd becoming fd 2 / stderr only to be - replaced by /dev/null by OsInit() because the pollfd is not diff --git a/tigervnc-vncsession-move-existing-log-to-log-old-if-present.patch b/tigervnc-vncsession-move-existing-log-to-log-old-if-present.patch new file mode 100644 index 0000000..e69de29 diff --git a/tigervnc-xserver120.patch b/tigervnc-xserver120.patch index e7eae3c..9bc5182 100644 --- a/tigervnc-xserver120.patch +++ b/tigervnc-xserver120.patch @@ -1,43 +1,39 @@ -diff -up xserver/configure.ac.xserver116-rebased xserver/configure.ac ---- xserver/configure.ac.xserver116-rebased 2016-09-29 13:14:45.595441590 +0200 -+++ xserver/configure.ac 2016-09-29 13:14:45.631442006 +0200 +diff --git a/configure.ac b/configure.ac +index 0909cc5b4..c01873200 100644 +--- a/configure.ac ++++ b/configure.ac @@ -74,6 +74,7 @@ dnl forcing an entire recompile.x AC_CONFIG_HEADERS(include/version-config.h) - + AM_PROG_AS +AC_PROG_CXX AC_PROG_LN_S LT_PREREQ([2.2]) LT_INIT([disable-static win32-dll]) -@@ -1863,6 +1864,10 @@ if test "x$XVFB" = xyes; then +@@ -1735,6 +1736,14 @@ if test "x$XVFB" = xyes; then AC_SUBST([XVFB_SYS_LIBS]) fi - + +dnl Xvnc DDX -+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"]) +AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"]) +AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"]) - - dnl Xnest DDX - -@@ -1898,6 +1903,8 @@ if test "x$XORG" = xauto; then - fi - AC_MSG_RESULT([$XORG]) - -+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) + - if test "x$XORG" = xyes; then - XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' - XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' -@@ -2116,7 +2123,6 @@ if test "x$XORG" = xyes; then - AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) - AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) - AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) -- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) - AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) - AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) - AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) -@@ -2691,6 +2697,7 @@ hw/dmx/Makefile ++PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no]) ++if test "x$GBM" = xyes; then ++ AC_DEFINE(HAVE_GBM, 1, [Have GBM support]) ++fi + + dnl Xnest DDX + +@@ -2058,7 +2067,6 @@ if test "x$GLAMOR" = xyes; then + [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])], + []) + +- PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no]) + if test "x$GBM" = xyes; then + AC_DEFINE(GLAMOR_HAS_GBM, 1, + [Build glamor with GBM-based EGL support]) +@@ -2523,6 +2531,7 @@ hw/dmx/Makefile hw/dmx/man/Makefile hw/vfb/Makefile hw/vfb/man/Makefile @@ -45,47 +41,98 @@ diff -up xserver/configure.ac.xserver116-rebased xserver/configure.ac hw/xnest/Makefile hw/xnest/man/Makefile hw/xwin/Makefile -diff -up xserver/hw/Makefile.am.xserver116-rebased xserver/hw/Makefile.am ---- xserver/hw/Makefile.am.xserver116-rebased 2016-09-29 13:14:45.601441659 +0200 -+++ xserver/hw/Makefile.am 2016-09-29 13:14:45.631442006 +0200 -@@ -38,7 +38,8 @@ SUBDIRS = \ - $(DMX_SUBDIRS) \ - $(KDRIVE_SUBDIRS) \ - $(XQUARTZ_SUBDIRS) \ -- $(XWAYLAND_SUBDIRS) -+ $(XWAYLAND_SUBDIRS) \ -+ vnc +diff --git a/dri3/Makefile.am b/dri3/Makefile.am +index e47a734e0..99c3718a5 100644 +--- a/dri3/Makefile.am ++++ b/dri3/Makefile.am +@@ -1,7 +1,7 @@ + noinst_LTLIBRARIES = libdri3.la + AM_CFLAGS = \ +- -DHAVE_XORG_CONFIG_H \ +- @DIX_CFLAGS@ @XORG_CFLAGS@ ++ @DIX_CFLAGS@ \ ++ @LIBDRM_CFLAGS@ - DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland - -diff --git xserver/mi/miinitext.c xserver/mi/miinitext.c -index 5596e21..003fc3c 100644 ---- xserver/mi/miinitext.c -+++ xserver/mi/miinitext.c -@@ -107,8 +107,15 @@ SOFTWARE. - #include "os.h" - #include "globals.h" - -+#ifdef TIGERVNC -+extern void vncExtensionInit(INITARGS); -+#endif + libdri3_la_SOURCES = \ + dri3.h \ +diff --git a/dri3/dri3.c b/dri3/dri3.c +index ba32facd7..191252969 100644 +--- a/dri3/dri3.c ++++ b/dri3/dri3.c +@@ -20,10 +20,6 @@ + * OF THIS SOFTWARE. + */ + +-#ifdef HAVE_XORG_CONFIG_H +-#include +-#endif +- + #include "dri3_priv.h" + + #include +diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h +index b087a9529..f319d1770 100644 +--- a/dri3/dri3_priv.h ++++ b/dri3/dri3_priv.h +@@ -23,6 +23,7 @@ + #ifndef _DRI3PRIV_H_ + #define _DRI3PRIV_H_ + ++#include "dix-config.h" + #include + #include "scrnintstr.h" + #include "misc.h" +diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c +index 958877efa..687168930 100644 +--- a/dri3/dri3_request.c ++++ b/dri3/dri3_request.c +@@ -20,10 +20,6 @@ + * OF THIS SOFTWARE. + */ + +-#ifdef HAVE_XORG_CONFIG_H +-#include +-#endif +- + #include "dri3_priv.h" + #include + #include +diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c +index b98259753..3c7e5bf60 100644 +--- a/dri3/dri3_screen.c ++++ b/dri3/dri3_screen.c +@@ -20,10 +20,6 @@ + * OF THIS SOFTWARE. + */ + +-#ifdef HAVE_XORG_CONFIG_H +-#include +-#endif +- + #include "dri3_priv.h" + #include + #include +diff --git a/hw/Makefile.am b/hw/Makefile.am +index 19895dc77..3ecfa8b7a 100644 +--- a/hw/Makefile.am ++++ b/hw/Makefile.am +@@ -44,3 +44,5 @@ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland + + relink: + $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done + - /* List of built-in (statically linked) extensions */ - static const ExtensionModule staticExtensions[] = { -+#ifdef TIGERVNC -+ {vncExtensionInit, "VNC-EXTENSION", NULL}, -+#endif - {GEExtensionInit, "Generic Event Extension", &noGEExtension}, - {ShapeExtensionInit, "SHAPE", NULL}, - #ifdef MITSHM ---- xserver/include/os.h~ 2016-10-03 09:07:29.000000000 +0200 -+++ xserver/include/os.h 2016-10-03 14:13:00.013654506 +0200 -@@ -621,7 +621,7 @@ - extern _X_EXPORT void - LogClose(enum ExitCode error); - extern _X_EXPORT Bool --LogSetParameter(LogParameter param, int value); -+LogSetParameter(enum _LogParameter param, int value); - extern _X_EXPORT void - LogVWrite(int verb, const char *f, va_list args) - _X_ATTRIBUTE_PRINTF(2, 0); ++SUBDIRS += vnc +diff --git a/include/dix-config.h.in b/include/dix-config.h.in +index f8fc67067..d53c4e72f 100644 +--- a/include/dix-config.h.in ++++ b/include/dix-config.h.in +@@ -83,6 +83,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_FCNTL_H + ++/* Have GBM support */ ++#undef HAVE_GBM ++ + /* Define to 1 if you have the `getdtablesize' function. */ + #undef HAVE_GETDTABLESIZE + diff --git a/tigervnc.spec b/tigervnc.spec index 281849a..9befb89 100644 --- a/tigervnc.spec +++ b/tigervnc.spec @@ -4,8 +4,8 @@ %global modulename vncsession Name: tigervnc -Version: 1.13.1 -Release: 11%{?dist} +Version: 1.14.0 +Release: 2%{?dist} Summary: A TigerVNC remote display system %global _hardened_build 1 @@ -26,10 +26,11 @@ Patch1: tigervnc-use-gnome-as-default-session.patch Patch2: tigervnc-vncsession-restore-script-systemd-service.patch # Upstream patches -Patch50: tigervnc-support-username-alias-in-plainusers.patch -Patch51: tigervnc-use-dup-to-get-available-fd-for-inetd.patch -Patch52: tigervnc-add-option-to-force-view-only-remote-connections.patch -Patch53: tigervnc-vncsession-use-bin-sh-when-shell-not-set.patch +Patch50: tigervnc-vncsession-use-bin-sh-when-shell-not-set.patch +Patch51: tigervnc-add-missing-coma-in-default-security-type-list.patch +Patch52: tigervnc-vncsession-move-existing-log-to-log-old-if-present.patch +Patch53: tigervnc-handle-existing-config-directory-in-vncpasswd.patch +Patch54: tigervnc-correctly-handle-zrle-cursors.patch # Upstreamable patches Patch80: tigervnc-dont-get-pointer-position-for-floating-device.patch @@ -77,11 +78,13 @@ BuildRequires: libXinerama-devel BuildRequires: libXt-devel BuildRequires: libXtst-devel BuildRequires: libdrm-devel +BuildRequires: mesa-libgbm-devel BuildRequires: libtool BuildRequires: libxkbfile-devel BuildRequires: libxshmfence-devel BuildRequires: mesa-libGL-devel -BuildRequires: xorg-x11-font-utils +BuildRequires: pkgconfig(fontutil) +BuildRequires: pkgconfig(xkbcomp) BuildRequires: xorg-x11-server-devel BuildRequires: xorg-x11-server-source BuildRequires: xorg-x11-util-macros @@ -189,22 +192,23 @@ for all in `find . -type f -perm -001`; do chmod -x "$all" done # Xorg patches -%patch100 -p1 -b .xserver120-rebased -%patch101 -p1 -b .rpath +%patch -P100 -p1 -b .xserver120-rebased +%patch -P101 -p1 -b .rpath popd # Tigervnc patches -%patch1 -p1 -b .use-gnome-as-default-session -%patch2 -p1 -b .vncsession-restore-script-systemd-service +%patch -P1 -p1 -b .use-gnome-as-default-session +%patch -P2 -p1 -b .vncsession-restore-script-systemd-service # Upstream patches -%patch50 -p1 -b .support-username-alias-in-plainusers -%patch51 -p1 -b .use-dup-to-get-available-fd-for-inetd -%patch52 -p1 -b .add-option-to-force-view-only-remote-connections -%patch53 -p1 -b .tigervnc-vncsession-use-bin-sh-when-shell-not-set +%patch -P50 -p1 -b .vncsession-use-bin-sh-when-shell-not-set +%patch -P51 -p1 -b .add-missing-coma-in-default-security-type-list +%patch -P52 -p1 -b .vncsession-move-existing-log-to-log-old-if-present +%patch -P53 -p1 -b .handle-existing-config-directory-in-vncpasswd +%patch -P54 -p1 -b .correctly-handle-zrle-cursors.patch # Upstreamable patches -%patch80 -p1 -b .dont-get-pointer-position-for-floating-device +%patch -P80 -p1 -b .dont-get-pointer-position-for-floating-device %build %ifarch sparcv9 sparc64 s390 s390x @@ -237,11 +241,10 @@ autoreconf -fiv --with-fontdir=%{_datadir}/X11/fonts \ --with-xkb-output=%{_localstatedir}/lib/xkb \ --enable-install-libxf86config \ - --enable-glx --disable-dri --enable-dri2 --disable-dri3 \ + --enable-glx --disable-dri --enable-dri2 --enable-dri3 \ --disable-unit-tests \ --disable-config-hal \ --disable-config-udev \ - --with-dri-driver-path=%{_libdir}/dri \ --without-dtrace \ --disable-devel-docs \ --disable-selective-werror @@ -387,6 +390,14 @@ fi %ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename} %changelog +* Tue Jul 23 2024 Jan Grulich - 1.14.0-2 +- 1.14.0 + Resolves: RHEL-45316 +- Move old log to log.old if present + Resolves: RHEL-54294 +- Fix shared memory leak + Resolves: RHEL-55768 + * Mon Aug 05 2024 Jan Grulich - 1.13.1-11 - vncsession: use /bin/sh if the user shell is not set Resolves: RHEL-50679