Add support for relaying unix sockets

This commit is contained in:
Lauri Kasanen
2023-02-16 15:51:26 +02:00
parent 61613c4e65
commit 3bae812364
18 changed files with 333 additions and 0 deletions

View File

@@ -88,6 +88,9 @@ namespace rfb {
virtual void clearLocalClipboards() {}
virtual void receivedUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len) {}
protected:
virtual ~SDesktop() {}
};

View File

@@ -98,6 +98,9 @@ namespace rfb {
virtual void udpUpgrade(const char *resp) = 0;
virtual void udpDowngrade(const bool) = 0;
virtual void subscribeUnixRelay(const char *name) = 0;
virtual void unixRelay(const char *name, const rdr::U8 *buf, const unsigned len) = 0;
ConnParams cp;
};
}

View File

@@ -100,6 +100,12 @@ void SMsgReader::readMsg()
case msgTypeUpgradeToUdp:
readUpgradeToUdp();
break;
case msgTypeSubscribeUnixRelay:
readSubscribeUnixRelay();
break;
case msgTypeUnixRelay:
readUnixRelay();
break;
default:
fprintf(stderr, "unknown message type %d\n", msgType);
throw Exception("unknown message type");
@@ -357,3 +363,42 @@ void SMsgReader::readUpgradeToUdp()
handler->udpUpgrade(resp);
}
void SMsgReader::readSubscribeUnixRelay()
{
const rdr::U8 namelen = is->readU8();
char name[64];
if (namelen >= sizeof(name)) {
vlog.error("Ignoring subscribe with too large name");
is->skip(namelen);
return;
}
is->readBytes(name, namelen);
name[namelen] = '\0';
handler->subscribeUnixRelay(name);
}
void SMsgReader::readUnixRelay()
{
const rdr::U8 namelen = is->readU8();
char name[64];
if (namelen >= sizeof(name)) {
vlog.error("Ignoring relay packet with too large name");
is->skip(namelen);
return;
}
is->readBytes(name, namelen);
name[namelen] = '\0';
const rdr::U32 len = is->readU32();
rdr::U8 buf[1024 * 1024];
if (len >= sizeof(buf)) {
vlog.error("Ignoring relay packet with too large data");
is->skip(len);
return ;
}
is->readBytes(buf, len);
handler->unixRelay(name, buf, len);
}

View File

@@ -65,6 +65,9 @@ namespace rfb {
void readUpgradeToUdp();
void readSubscribeUnixRelay();
void readUnixRelay();
SMsgHandler* handler;
rdr::InStream* is;
};

View File

@@ -749,3 +749,29 @@ void SMsgWriter::writeUdpUpgrade(const char *resp)
endMsg();
}
void SMsgWriter::writeSubscribeUnixRelay(const bool success, const char *msg)
{
startMsg(msgTypeSubscribeUnixRelay);
const rdr::U8 len = strlen(msg);
os->writeU8(success);
os->writeU8(len);
os->writeBytes(msg, len);
endMsg();
}
void SMsgWriter::writeUnixRelay(const char *name, const rdr::U8 *buf, const unsigned len)
{
startMsg(msgTypeUnixRelay);
const rdr::U8 namelen = strlen(name);
os->writeU8(namelen);
os->writeBytes(name, namelen);
os->writeU32(len);
os->writeBytes(buf, len);
endMsg();
}

View File

@@ -129,6 +129,9 @@ namespace rfb {
void writeUdpUpgrade(const char *resp);
void writeSubscribeUnixRelay(const bool success, const char *msg);
void writeUnixRelay(const char *name, const rdr::U8 *buf, const unsigned len);
protected:
void startMsg(int type);
void endMsg();

View File

@@ -51,6 +51,8 @@ static Cursor emptyCursor(0, 0, Point(0, 0), NULL);
extern rfb::BoolParameter disablebasicauth;
extern "C" char unixrelaynames[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
bool reverse)
: upgradingToUdp(false), sock(s), reverseConnection(reverse),
@@ -73,6 +75,10 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
memset(bstats_total, 0, sizeof(bstats_total));
gettimeofday(&connStart, NULL);
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++)
unixRelaySubscriptions[i][0] = '\0';
// Check their permissions, if applicable
kasmpasswdpath[0] = '\0';
wordexp_t wexp;
@@ -1780,3 +1786,54 @@ void VNCSConnectionST::udpDowngrade(const bool byServer)
vlog.info("Client %s downgrading from udp by %s", sock->getPeerAddress(),
byServer ? "the server" : "its own request");
}
void VNCSConnectionST::subscribeUnixRelay(const char *name)
{
bool read, write, owner;
if (!getPerms(read, write, owner) || !write) {
// Need write permissions to subscribe
writer()->writeSubscribeUnixRelay(false, "No permissions");
vlog.info("Client tried to subscribe to unix channel %s without permissions", name);
return;
}
unsigned i;
bool found = false;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(name, unixrelaynames[i])) {
found = true;
break;
}
}
if (!found) {
writer()->writeSubscribeUnixRelay(false, "No such unix channel");
vlog.info("Client tried to subscribe to nonexistent unix channel %s", name);
return;
}
writer()->writeSubscribeUnixRelay(true, "Ok");
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!unixRelaySubscriptions[i][0]) {
strcpy(unixRelaySubscriptions[i], name);
break;
}
}
}
void VNCSConnectionST::unixRelay(const char *name, const rdr::U8 *buf, const unsigned len)
{
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(unixRelaySubscriptions[i], name)) {
server->desktop->receivedUnixRelayData(name, buf, len);
return;
}
}
}
void VNCSConnectionST::sendUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len)
{
writer()->writeUnixRelay(name, buf, len);
}

View File

@@ -33,6 +33,7 @@
#include <rfb/EncodeManager.h>
#include <rfb/SConnection.h>
#include <rfb/Timer.h>
#include <rfb/unixRelayLimits.h>
namespace rfb {
class VNCServerST;
@@ -200,6 +201,18 @@ namespace rfb {
bool upgradingToUdp;
bool isSubscribedToUnixRelay(const char *name) const {
unsigned i;
for (i = 0; i < MAX_UNIX_RELAYS; i++) {
if (!strcmp(unixRelaySubscriptions[i], name))
return true;
}
return false;
}
virtual void sendUnixRelayData(const char name[], const unsigned char *buf,
const unsigned len);
private:
// SConnection callbacks
@@ -222,6 +235,8 @@ namespace rfb {
virtual void handleClipboardAnnounce(bool available);
virtual void handleClipboardAnnounceBinary(const unsigned num, const char mimes[][32]);
virtual void udpUpgrade(const char *resp);
virtual void subscribeUnixRelay(const char *name);
virtual void unixRelay(const char *name, const rdr::U8 *buf, const unsigned len);
virtual void supportsLocalCursor();
virtual void supportsFence();
virtual void supportsContinuousUpdates();
@@ -324,6 +339,8 @@ namespace rfb {
bool frameTracking;
uint32_t udpFramesSinceFull;
char unixRelaySubscriptions[MAX_UNIX_RELAYS][MAX_UNIX_RELAY_NAME_LEN];
};
}
#endif

View File

@@ -1244,3 +1244,15 @@ void VNCServerST::refreshClients()
(*i)->add_changed_all();
}
}
void VNCServerST::sendUnixRelayData(const char name[],
const unsigned char *buf, const unsigned len)
{
// For each client subscribed to this channel, send the data to them
std::list<VNCSConnectionST*>::iterator i;
for (i = clients.begin(); i != clients.end(); i++) {
if ((*i)->isSubscribedToUnixRelay(name)) {
(*i)->sendUnixRelayData(name, buf, len);
}
}
}

View File

@@ -198,6 +198,7 @@ namespace rfb {
const char mimes[][32]);
void refreshClients();
void sendUnixRelayData(const char name[], const unsigned char *buf, const unsigned len);
protected:

View File

@@ -33,6 +33,8 @@ namespace rfb {
const int msgTypeRequestFrameStats = 179;
const int msgTypeBinaryClipboard = 180;
const int msgTypeUpgradeToUdp = 181;
const int msgTypeSubscribeUnixRelay = 182;
const int msgTypeUnixRelay = 183;
const int msgTypeServerFence = 248;
@@ -54,6 +56,8 @@ namespace rfb {
// same as the other direction
//const int msgTypeBinaryClipboard = 180;
//const int msgTypeUpgradeToUdp = 181;
//const int msgTypeSubscribeUnixRelay = 182;
//const int msgTypeUnixRelay = 183;
const int msgTypeClientFence = 248;

View File

@@ -0,0 +1,7 @@
#ifndef UNIX_RELAY_LIMITS_H
#define UNIX_RELAY_LIMITS_H
#define MAX_UNIX_RELAYS 4
#define MAX_UNIX_RELAY_NAME_LEN 64
#endif