mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2024-12-26 00:29:42 +01:00
Apply read-only perms upon connecting
This commit is contained in:
parent
9a5afc5a62
commit
263d05a296
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user