From 45289fbdbcd48a547ee20a73d7bbf8851d1641ee Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Tue, 23 Jul 2024 15:22:34 +0200 Subject: [PATCH] Revert "1.14.0" This reverts commit 55f47bf052ad6808a9d345205a411029f4e5d4a0. Rescheduled for RHEL 9.6. --- .gitignore | 1 - sources | 2 +- ...o-force-view-only-remote-connections.patch | 1113 +++++++++++++++++ ...support-username-alias-in-plainusers.patch | 135 ++ ...se-dup-to-get-available-fd-for-inetd.patch | 17 + tigervnc-xserver120.patch | 185 +-- tigervnc.spec | 31 +- 7 files changed, 1351 insertions(+), 133 deletions(-) create mode 100644 tigervnc-add-option-to-force-view-only-remote-connections.patch create mode 100644 tigervnc-support-username-alias-in-plainusers.patch create mode 100644 tigervnc-use-dup-to-get-available-fd-for-inetd.patch diff --git a/.gitignore b/.gitignore index b505e48..447fa6f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,3 @@ 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 c9abbc7..0a5c2a0 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (tigervnc-1.14.0.tar.gz) = ee36f0aa40957274fb00fd755624a8bea80432d797d6c183645ed1251058ab30594d2261693b5655c5ca85a22e53f93029eeccc51fe86780398d1a017fa2311c +SHA512 (tigervnc-1.13.1.tar.gz) = 9190dbcd3b57ba52286c158c0675104d68463d7e3ea8e23493514b64451ddb511f3daf0f177339bc231155daea376d9c8dc58216663e10aa12f67468f4559da5 diff --git a/tigervnc-add-option-to-force-view-only-remote-connections.patch b/tigervnc-add-option-to-force-view-only-remote-connections.patch new file mode 100644 index 0000000..0414f48 --- /dev/null +++ b/tigervnc-add-option-to-force-view-only-remote-connections.patch @@ -0,0 +1,1113 @@ +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-support-username-alias-in-plainusers.patch b/tigervnc-support-username-alias-in-plainusers.patch new file mode 100644 index 0000000..abf4eda --- /dev/null +++ b/tigervnc-support-username-alias-in-plainusers.patch @@ -0,0 +1,135 @@ +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 new file mode 100644 index 0000000..0e0f794 --- /dev/null +++ b/tigervnc-use-dup-to-get-available-fd-for-inetd.patch @@ -0,0 +1,17 @@ +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-xserver120.patch b/tigervnc-xserver120.patch index 9bc5182..e7eae3c 100644 --- a/tigervnc-xserver120.patch +++ b/tigervnc-xserver120.patch @@ -1,39 +1,43 @@ -diff --git a/configure.ac b/configure.ac -index 0909cc5b4..c01873200 100644 ---- a/configure.ac -+++ b/configure.ac +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 @@ -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]) -@@ -1735,6 +1736,14 @@ if test "x$XVFB" = xyes; then +@@ -1863,6 +1864,10 @@ 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"]) -+ -+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 + +@@ -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 hw/dmx/man/Makefile hw/vfb/Makefile hw/vfb/man/Makefile @@ -41,98 +45,47 @@ index 0909cc5b4..c01873200 100644 hw/xnest/Makefile hw/xnest/man/Makefile hw/xwin/Makefile -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@ +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 - 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 + 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 + -+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 - + /* 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); diff --git a/tigervnc.spec b/tigervnc.spec index 109b924..2499a4f 100644 --- a/tigervnc.spec +++ b/tigervnc.spec @@ -4,8 +4,8 @@ %global modulename vncsession Name: tigervnc -Version: 1.14.0 -Release: 1%{?dist} +Version: 1.13.1 +Release: 10%{?dist} Summary: A TigerVNC remote display system %global _hardened_build 1 @@ -26,6 +26,9 @@ 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 # Upstreamable patches Patch80: tigervnc-dont-get-pointer-position-for-floating-device.patch @@ -73,13 +76,11 @@ 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: pkgconfig(fontutil) -BuildRequires: pkgconfig(xkbcomp) +BuildRequires: xorg-x11-font-utils BuildRequires: xorg-x11-server-devel BuildRequires: xorg-x11-server-source BuildRequires: xorg-x11-util-macros @@ -187,18 +188,21 @@ for all in `find . -type f -perm -001`; do chmod -x "$all" done # Xorg patches -%patch -P100 -p1 -b .xserver120-rebased -%patch -P101 -p1 -b .rpath +%patch100 -p1 -b .xserver120-rebased +%patch101 -p1 -b .rpath popd # Tigervnc patches -%patch -P1 -p1 -b .use-gnome-as-default-session -%patch -P2 -p1 -b .vncsession-restore-script-systemd-service +%patch1 -p1 -b .use-gnome-as-default-session +%patch2 -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 # Upstreamable patches -%patch -P80 -p1 -b .dont-get-pointer-position-for-floating-device +%patch80 -p1 -b .dont-get-pointer-position-for-floating-device %build %ifarch sparcv9 sparc64 s390 s390x @@ -231,10 +235,11 @@ autoreconf -fiv --with-fontdir=%{_datadir}/X11/fonts \ --with-xkb-output=%{_localstatedir}/lib/xkb \ --enable-install-libxf86config \ - --enable-glx --disable-dri --enable-dri2 --enable-dri3 \ + --enable-glx --disable-dri --enable-dri2 --disable-dri3 \ --disable-unit-tests \ --disable-config-hal \ --disable-config-udev \ + --with-dri-driver-path=%{_libdir}/dri \ --without-dtrace \ --disable-devel-docs \ --disable-selective-werror @@ -380,10 +385,6 @@ 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-1 -- 1.14.0 - Resolves: RHEL-45316 - * Tue May 28 2024 Jan Grulich - 1.13.1-10 - vncconfig: add option to force view-only remote client connections Resolves: RHEL-12144