]> source.dussan.org Git - tigervnc.git/commitdiff
vncconfig: add option to force view-only remote client connections 1670/head
authorCarlos Santos <casantos@redhat.com>
Wed, 29 Nov 2023 21:52:52 +0000 (18:52 -0300)
committerCarlos Santos <casantos@redhat.com>
Fri, 26 Apr 2024 14:28:07 +0000 (11:28 -0300)
Specifies that the server must ignore all keyboard or mouse events sent
by the client.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2180903
Signed-off-by: Carlos Santos <casantos@redhat.com>
17 files changed:
common/rfb/SConnection.cxx
common/rfb/SConnection.h
common/rfb/VNCSConnectionST.cxx
common/rfb/VNCSConnectionST.h
common/rfb/VNCServer.h
common/rfb/VNCServerST.cxx
common/rfb/VNCServerST.h
tests/perf/encperf.cxx
unix/vncconfig/vncExt.c
unix/vncconfig/vncExt.h
unix/vncconfig/vncconfig.cxx
unix/vncconfig/vncconfig.man
unix/xserver/hw/vnc/XserverDesktop.cc
unix/xserver/hw/vnc/XserverDesktop.h
unix/xserver/hw/vnc/vncExt.c
unix/xserver/hw/vnc/vncExtInit.cc
unix/xserver/hw/vnc/vncExtInit.h

index 462c34c2e6813282402d38ecd223f2ce98aac468..7a930af560bdfaa6b7a1afda5dcba9e9b468052b 100644 (file)
@@ -43,12 +43,12 @@ using namespace rfb;
 
 static LogWriter vlog("SConnection");
 
-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(AccessNone), hasRemoteClipboard(false),
+    accessRights(accessRights), hasRemoteClipboard(false),
     hasLocalClipboard(false),
     unsolicitedClipboardAttempt(false)
 {
@@ -242,7 +242,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
index fb8b0b4cb08222f9b04364fd0d4be295201544d8..cc88cd1e64126788381f6fbb43f595cfcef582e8 100644 (file)
@@ -43,7 +43,7 @@ namespace rfb {
   class SConnection : public SMsgHandler {
   public:
 
-    SConnection();
+    SConnection(AccessRights accessRights);
     virtual ~SConnection();
 
     // Methods to initialise the connection
@@ -176,6 +176,9 @@ 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.
index 906f5f66c1af45771b24d1bede0cf5ee3fc67568..f1194eb69a0eeb62fc6521222c178ed77ce6d910 100644 (file)
@@ -51,8 +51,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),
index edc0391edcde5e2b93cff77278ba34dac03bd20c..2f117a7579438d71451ec6d7fe75551974d7f297 100644 (file)
@@ -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
index 6d75f8f84f933b4b8b9f53731cc2bf2a311e24bd..cf14bd86215a8025b01920298243311e9a870fc6 100644 (file)
@@ -39,7 +39,9 @@ namespace rfb {
     //   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;
+    //   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
index edf23a4f2106c037becf413e72d7d1fe8101af32..fb4210680c85aea0b7d50a5b3be0d551ef03ff77 100644 (file)
@@ -132,7 +132,7 @@ VNCServerST::~VNCServerST()
 
 // 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?
@@ -163,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();
 }
index 4a8efa465c78cdc1c77a2dae0ef55f33136a8428..d303831e8dc605fa47d72fcb0fe84bc4e49d8fef 100644 (file)
@@ -56,7 +56,8 @@ namespace rfb {
     // 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
index 55fa386eb155e2c21afb985c0b57db624c223d13..388dcc95595b99ba567eda5c7479dd34c86411ba 100644 (file)
@@ -41,6 +41,8 @@
 #include <rdr/OutStream.h>
 #include <rdr/FileInStream.h>
 
+#include <rfb/AccessRights.h>
+
 #include <rfb/PixelFormat.h>
 
 #include <rfb/CConnection.h>
@@ -303,6 +305,7 @@ void Manager::getStats(double& ratio, unsigned long long& encodedBytes,
 }
 
 SConn::SConn()
+: SConnection(rfb::AccessDefault)
 {
   out = new DummyOutStream;
   setStreams(NULL, out);
index f19123b8899b05a1bd1814d93ba99ecfe05cd15f..4ec671b885dba995519243cd35b78061ad0c4466 100644 (file)
@@ -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);
index 2b24469e34969f47403287c93d0cb0a9891de2bf..4383248c9f49eebc0cef24abd5e885ed4b73928a 100644 (file)
@@ -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
index f39e9934ae3c765f99435edd4397934dd6e7e748..e0c9928a92a01bf89357301706d32cf4a76ce57b 100644 (file)
@@ -177,8 +177,8 @@ static void usage()
 {
   fprintf(stderr,"usage: %s [parameters]\n",
           programName);
-  fprintf(stderr,"       %s [parameters] -connect <host>[:<port>]\n",
-          programName);
+  fprintf(stderr,"       %s [parameters] -connect "
+          "[-view-only] <host>[:<port>]\n", programName);
   fprintf(stderr,"       %s [parameters] -disconnect\n", programName);
   fprintf(stderr,"       %s [parameters] [-set] <Xvnc-param>=<value> ...\n",
           programName);
@@ -240,13 +240,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) {
index ed9ddda4b17026c5e111e0285bff759181023cdd..b07c02f463a4b26c521ca3b081a5a2daaefd9492 100644 (file)
@@ -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
index a2160a72146989f7080b22371a3812990114bb79..4cf37937badc8692722bfd18361bf7bd4239f138 100644 (file)
@@ -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);
 }
 
index a42b5440f11b085f163b5762c80288cc35e8d0ac..9cc5bf792e96b82146ba868fffdc7e750353f8d1 100644 (file)
@@ -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
index 89c105503f1163c73eb88e2b839d219b40e242d4..e98275c2c89ed6b6dbca3c530614f3ccd316d7a6 100644 (file)
@@ -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;
index 1dfe76d7418e56dfdcb6e3efdfc9cbaeb6114532..b260e62664e1d84b723d35a05d203958339d6e43 100644 (file)
@@ -267,7 +267,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");
         }
       }
@@ -343,7 +343,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 {
@@ -362,7 +362,9 @@ int vncConnectClient(const char *addr)
 
   try {
     network::Socket* sock = new network::TcpSocket(host.c_str(), port);
-    desktop[0]->addClient(sock, true);
+    vlog.info("Reverse connection: %s:%d%s", host.c_str(), port,
+              viewOnly ? " (view only)" : "");
+    desktop[0]->addClient(sock, true, (bool)viewOnly);
   } catch (rdr::Exception& e) {
     vlog.error("Reverse connection: %s",e.str());
     return -1;
index c317d8a2160de8f257eb74ed6e3186778a150319..333e32a90d7b9447fd16bf91a9de2153f70642a1 100644 (file)
@@ -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);