Skip to content

Commit

Permalink
vncconfig: add option to force view-only remote client connections
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
casantos committed Apr 9, 2024
1 parent 253d65e commit 02992ec
Show file tree
Hide file tree
Showing 18 changed files with 49 additions and 29 deletions.
4 changes: 2 additions & 2 deletions common/rfb/SConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
5 changes: 4 additions & 1 deletion common/rfb/SConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace rfb {
class SConnection : public SMsgHandler {
public:

SConnection();
SConnection(AccessRights accessRights);
virtual ~SConnection();

// Methods to initialise the connection
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/SSecurity.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
using namespace rfb;

SSecurity::SSecurity(SConnection* sc)
: sc(sc), accessRights(AccessDefault)
: sc(sc), accessRights(sc->getAccessRights())
{
}

Expand Down
5 changes: 3 additions & 2 deletions common/rfb/VNCSConnectionST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
3 changes: 2 additions & 1 deletion common/rfb/VNCSConnectionST.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion common/rfb/VNCServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down Expand Up @@ -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();
}
Expand Down
3 changes: 2 additions & 1 deletion common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions tests/perf/encperf.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#include <rdr/OutStream.h>
#include <rdr/FileInStream.h>

#include <rfb/AccessRights.h>

#include <rfb/PixelFormat.h>

#include <rfb/CConnection.h>
Expand Down Expand Up @@ -303,6 +305,7 @@ void Manager::getStats(double& ratio, unsigned long long& encodedBytes,
}

SConn::SConn()
: SConnection(rfb::AccessDefault)
{
out = new DummyOutStream;
setStreams(NULL, out);
Expand Down
3 changes: 2 additions & 1 deletion unix/vncconfig/vncExt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions unix/vncconfig/vncExt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions unix/vncconfig/vncconfig.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 4 additions & 3 deletions unix/vncconfig/vncconfig.man
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions unix/xserver/hw/vnc/XserverDesktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion unix/xserver/hw/vnc/XserverDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
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
Expand Down
2 changes: 1 addition & 1 deletion unix/xserver/hw/vnc/vncExt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions unix/xserver/hw/vnc/vncExtInit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion unix/xserver/hw/vnc/vncExtInit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 02992ec

Please sign in to comment.