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>pull/1670/head
@@ -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 |
@@ -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. |
@@ -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), |
@@ -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 |
@@ -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 |
@@ -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(); | |||
} |
@@ -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 |
@@ -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); |
@@ -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); |
@@ -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 |
@@ -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) { |
@@ -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 |
@@ -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); | |||
} | |||
@@ -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 |
@@ -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; |
@@ -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; |
@@ -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); |