Apply read-only perms upon connecting

This commit is contained in:
Lauri Kasanen 2020-10-12 14:45:31 +03:00
parent 9a5afc5a62
commit 263d05a296
7 changed files with 91 additions and 9 deletions

View File

@ -123,11 +123,20 @@ WebSocket::WebSocket(int sock) : Socket(sock)
}
char* WebSocket::getPeerAddress() {
return rfb::strDup("websocket");
struct sockaddr_un addr;
socklen_t len = sizeof(struct sockaddr_un);
if (getpeername(getFd(), (struct sockaddr *) &addr, &len) != 0) {
vlog.error("unable to get peer name for socket");
return rfb::strDup("websocket");
}
return rfb::strDup(addr.sun_path + 1);
}
char* WebSocket::getPeerEndpoint() {
return rfb::strDup("websocket");
char buf[1024];
sprintf(buf, "%s::websocket", getPeerAddress());
return rfb::strDup(buf);
}
// -=- TcpSocket

View File

@ -107,7 +107,7 @@ ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len) {
ws_ctx_t *alloc_ws_ctx() {
ws_ctx_t *ctx;
if (! (ctx = malloc(sizeof(ws_ctx_t))) )
if (! (ctx = calloc(sizeof(ws_ctx_t), 1)) )
{ fatal("malloc()"); }
if (! (ctx->cin_buf = malloc(BUFSIZE)) )
@ -930,7 +930,8 @@ ws_ctx_t *do_handshake(int sock) {
for (i = 0; i < set->num; i++) {
if (!strcmp(set->entries[i].user, inuser)) {
found = 1; // TODO write to wctx
found = 1;
strcpy(ws_ctx->user, inuser);
snprintf(authbuf, 4096, "%s:%s", set->entries[i].user,
set->entries[i].password);
authbuf[4095] = '\0';
@ -1024,7 +1025,6 @@ void *subthread(void *ptr) {
const int csock = pass->csock;
wsthread_handler_id = pass->id;
free((void *) pass);
ws_ctx_t *ws_ctx;
@ -1034,11 +1034,14 @@ void *subthread(void *ptr) {
goto out; // Child process exits
}
memcpy(ws_ctx->ip, pass->ip, sizeof(pass->ip));
proxy_handler(ws_ctx);
if (pipe_error) {
handler_emsg("Closing due to SIGPIPE\n");
}
out:
free((void *) pass);
if (ws_ctx) {
ws_socket_free(ws_ctx);
@ -1074,12 +1077,13 @@ void *start_server(void *unused) {
error("ERROR on accept");
continue;
}
struct wspass_t *pass = calloc(1, sizeof(struct wspass_t));
inet_ntop(cli_addr.sin_family, &cli_addr.sin_addr, pass->ip, sizeof(pass->ip));
fprintf(stderr, " websocket %d: got client connection from %s\n",
settings.handler_id,
inet_ntoa(cli_addr.sin_addr));
pass->ip);
pthread_t tid;
struct wspass_t *pass = calloc(1, sizeof(struct wspass_t));
pass->id = settings.handler_id;
pass->csock = csock;
pthread_create(&tid, NULL, subthread, pass);

View File

@ -53,11 +53,15 @@ typedef struct {
char *cout_buf;
char *tin_buf;
char *tout_buf;
char user[32];
char ip[64];
} ws_ctx_t;
struct wspass_t {
int csock;
unsigned id;
char ip[64];
};
typedef struct {

View File

@ -227,7 +227,13 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
strcpy(addr.sun_path, ".KasmVNCSock");
addr.sun_path[0] = '\0';
struct sockaddr_un myaddr;
myaddr.sun_family = AF_UNIX;
sprintf(myaddr.sun_path, ".%s@%s", ws_ctx->user, ws_ctx->ip);
myaddr.sun_path[0] = '\0';
int tsock = socket(AF_UNIX, SOCK_STREAM, 0);
bind(tsock, (struct sockaddr *) &myaddr, sizeof(struct sockaddr_un));
handler_msg("connecting to VNC target\n");

View File

@ -1,4 +1,5 @@
include_directories(${CMAKE_SOURCE_DIR}/common ${JPEG_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/common ${JPEG_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/unix/kasmvncpasswd)
set(RFB_SOURCES
Blacklist.cxx

View File

@ -38,6 +38,9 @@
#include <ctype.h>
#include <stdlib.h>
#include <stdint.h>
#include <wordexp.h>
#include "kasmpasswd.h"
using namespace rfb;
@ -45,6 +48,8 @@ static LogWriter vlog("VNCSConnST");
static Cursor emptyCursor(0, 0, Point(0, 0), NULL);
extern rfb::StringParameter basicauth;
VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
bool reverse)
: sock(s), reverseConnection(reverse),
@ -65,6 +70,25 @@ VNCSConnectionST::VNCSConnectionST(VNCServerST* server_, network::Socket *s,
memset(bstats_total, 0, sizeof(bstats_total));
gettimeofday(&connStart, NULL);
// Check their permissions, if applicable
kasmpasswdpath[0] = '\0';
wordexp_t wexp;
if (!wordexp(rfb::Server::kasmPasswordFile, &wexp, WRDE_NOCMD))
strncpy(kasmpasswdpath, wexp.we_wordv[0], 4096);
kasmpasswdpath[4095] = '\0';
wordfree(&wexp);
user[0] = '\0';
const char *at = strchr(peerEndpoint.buf, '@');
if (at && at - peerEndpoint.buf > 1 && at - peerEndpoint.buf < 32) {
memcpy(user, peerEndpoint.buf, at - peerEndpoint.buf);
user[at - peerEndpoint.buf] = '\0';
}
bool write, owner;
if (!getPerms(write, owner) || !write)
accessRights = (accessRights & ~(AccessPtrEvents | AccessKeyEvents));
// Configure the socket
setSocketTimeouts();
lastEventTime = time(0);
@ -999,6 +1023,29 @@ bool VNCSConnectionST::isShiftPressed()
return false;
}
bool VNCSConnectionST::getPerms(bool &write, bool &owner) const
{
bool found = false;
const char *colon = strchr(basicauth, ':');
if (colon && !colon[1] && user[0]) {
struct kasmpasswd_t *set = readkasmpasswd(kasmpasswdpath);
unsigned i;
for (i = 0; i < set->num; i++) {
if (!strcmp(set->entries[i].user, user)) {
write = set->entries[i].write;
owner = set->entries[i].owner;
found = true;
break;
}
}
free(set->entries);
free(set);
}
return found;
}
void VNCSConnectionST::writeRTTPing()
{
char type;

View File

@ -184,7 +184,13 @@ namespace rfb {
// of a VNCSConnectioST to the server. These access rights are applied
// such that the actual rights granted are the minimum of the server's
// default access settings and the connection's access settings.
virtual void setAccessRights(AccessRights ar) {accessRights=ar;}
virtual void setAccessRights(AccessRights ar) {
accessRights = ar;
bool write, owner;
if (!getPerms(write, owner) || !write)
accessRights = (accessRights & ~(AccessPtrEvents | AccessKeyEvents));
}
// Timer callbacks
virtual bool handleTimeout(Timer* t);
@ -193,6 +199,8 @@ namespace rfb {
bool isShiftPressed();
bool getPerms(bool &write, bool &owner) const;
// Congestion control
void writeRTTPing();
bool isCongested();
@ -249,6 +257,9 @@ namespace rfb {
rdr::U64 bstats_total[BS_NUM];
struct timeval connStart;
char user[32];
char kasmpasswdpath[4096];
time_t lastEventTime;
time_t pointerEventTime;
Point pointerEventPos;