Resolve KASM-2238 "Feature/ freeze session"
This commit is contained in:
@@ -53,18 +53,21 @@ namespace network {
|
||||
uint8_t *netGetScreenshot(uint16_t w, uint16_t h,
|
||||
const uint8_t q, const bool dedup,
|
||||
uint32_t &len, uint8_t *staging);
|
||||
uint8_t netAddUser(const char name[], const char pw[], const bool write, const bool owner);
|
||||
uint8_t netAddUser(const char name[], const char pw[],
|
||||
const bool read, const bool write, const bool owner);
|
||||
uint8_t netRemoveUser(const char name[]);
|
||||
uint8_t netUpdateUser(const char name[], const uint64_t mask,
|
||||
const char password[],
|
||||
const bool write, const bool owner);
|
||||
const bool read, const bool write, const bool owner);
|
||||
uint8_t netAddOrUpdateUser(const struct kasmpasswd_entry_t *entry);
|
||||
void netGetUsers(const char **ptr);
|
||||
void netGetBottleneckStats(char *buf, uint32_t len);
|
||||
void netGetFrameStats(char *buf, uint32_t len);
|
||||
void netResetFrameStatsCall();
|
||||
uint8_t netServerFrameStatsReady();
|
||||
|
||||
enum USER_ACTION {
|
||||
NONE,
|
||||
WANT_FRAME_STATS_SERVERONLY,
|
||||
WANT_FRAME_STATS_ALL,
|
||||
WANT_FRAME_STATS_OWNER,
|
||||
|
||||
@@ -24,6 +24,7 @@ enum USER_UPDATE_MASK {
|
||||
USER_UPDATE_WRITE_MASK = 1 << 0,
|
||||
USER_UPDATE_OWNER_MASK = 1 << 1,
|
||||
USER_UPDATE_PASSWORD_MASK = 1 << 2,
|
||||
USER_UPDATE_READ_MASK = 1 << 3,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -264,7 +264,8 @@ uint8_t *GetAPIMessager::netGetScreenshot(uint16_t w, uint16_t h,
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[], const bool write,
|
||||
uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[],
|
||||
const bool read, const bool write,
|
||||
const bool owner) {
|
||||
if (strlen(name) >= USERNAME_LEN) {
|
||||
vlog.error("Username too long");
|
||||
@@ -289,6 +290,7 @@ uint8_t GetAPIMessager::netAddUser(const char name[], const char pw[], const boo
|
||||
act.data.password[PASSWORD_LEN - 1] = '\0';
|
||||
act.data.owner = owner;
|
||||
act.data.write = write;
|
||||
act.data.read = read;
|
||||
|
||||
if (pthread_mutex_lock(&userMutex))
|
||||
return 0;
|
||||
@@ -367,7 +369,7 @@ uint8_t GetAPIMessager::netRemoveUser(const char name[]) {
|
||||
|
||||
uint8_t GetAPIMessager::netUpdateUser(const char name[], const uint64_t mask,
|
||||
const char password[],
|
||||
const bool write, const bool owner) {
|
||||
const bool read, const bool write, const bool owner) {
|
||||
if (strlen(name) >= USERNAME_LEN) {
|
||||
vlog.error("Username too long");
|
||||
return 0;
|
||||
@@ -391,6 +393,8 @@ uint8_t GetAPIMessager::netUpdateUser(const char name[], const uint64_t mask,
|
||||
unsigned s;
|
||||
for (s = 0; s < set->num; s++) {
|
||||
if (!strcmp(set->entries[s].user, name)) {
|
||||
if (mask & USER_UPDATE_READ_MASK)
|
||||
set->entries[s].read = read;
|
||||
if (mask & USER_UPDATE_WRITE_MASK)
|
||||
set->entries[s].write = write;
|
||||
if (mask & USER_UPDATE_OWNER_MASK)
|
||||
@@ -487,8 +491,9 @@ void GetAPIMessager::netGetUsers(const char **outptr) {
|
||||
for (s = 0; s < set->num; s++) {
|
||||
JSON_escape(set->entries[s].user, escapeduser);
|
||||
|
||||
fprintf(f, " { \"user\": \"%s\", \"write\": %s, \"owner\": %s }",
|
||||
fprintf(f, " { \"user\": \"%s\", \"read\": %s, \"write\": %s, \"owner\": %s }",
|
||||
escapeduser,
|
||||
set->entries[s].read ? "true" : "false",
|
||||
set->entries[s].write ? "true" : "false",
|
||||
set->entries[s].owner ? "true" : "false");
|
||||
|
||||
@@ -687,6 +692,15 @@ out:
|
||||
pthread_mutex_unlock(&frameStatMutex);
|
||||
}
|
||||
|
||||
void GetAPIMessager::netResetFrameStatsCall() {
|
||||
if (pthread_mutex_lock(&frameStatMutex))
|
||||
return;
|
||||
|
||||
serverFrameStats.inprogress = 0;
|
||||
|
||||
pthread_mutex_unlock(&frameStatMutex);
|
||||
}
|
||||
|
||||
uint8_t GetAPIMessager::netRequestFrameStats(USER_ACTION what, const char *client) {
|
||||
// Return 1 for success
|
||||
action_data act;
|
||||
|
||||
@@ -443,10 +443,10 @@ static uint8_t *screenshotCb(void *messager, uint16_t w, uint16_t h, const uint8
|
||||
}
|
||||
|
||||
static uint8_t adduserCb(void *messager, const char name[], const char pw[],
|
||||
const uint8_t write, const uint8_t owner)
|
||||
const uint8_t read, const uint8_t write, const uint8_t owner)
|
||||
{
|
||||
GetAPIMessager *msgr = (GetAPIMessager *) messager;
|
||||
return msgr->netAddUser(name, pw, write, owner);
|
||||
return msgr->netAddUser(name, pw, read, write, owner);
|
||||
}
|
||||
|
||||
static uint8_t removeCb(void *messager, const char name[])
|
||||
@@ -457,10 +457,10 @@ static uint8_t removeCb(void *messager, const char name[])
|
||||
|
||||
static uint8_t updateUserCb(void *messager, const char name[], const uint64_t mask,
|
||||
const char password[],
|
||||
const uint8_t write, const uint8_t owner)
|
||||
const uint8_t read, const uint8_t write, const uint8_t owner)
|
||||
{
|
||||
GetAPIMessager *msgr = (GetAPIMessager *) messager;
|
||||
return msgr->netUpdateUser(name, mask, password, write, owner);
|
||||
return msgr->netUpdateUser(name, mask, password, read, write, owner);
|
||||
}
|
||||
|
||||
static uint8_t addOrUpdateUserCb(void *messager, const struct kasmpasswd_entry_t *entry)
|
||||
@@ -487,6 +487,12 @@ static void frameStatsCb(void *messager, char *buf, uint32_t len)
|
||||
msgr->netGetFrameStats(buf, len);
|
||||
}
|
||||
|
||||
static void resetFrameStatsCb(void *messager)
|
||||
{
|
||||
GetAPIMessager *msgr = (GetAPIMessager *) messager;
|
||||
msgr->netResetFrameStatsCall();
|
||||
}
|
||||
|
||||
static uint8_t requestFrameStatsNoneCb(void *messager)
|
||||
{
|
||||
GetAPIMessager *msgr = (GetAPIMessager *) messager;
|
||||
@@ -632,6 +638,7 @@ WebsocketListener::WebsocketListener(const struct sockaddr *listenaddr,
|
||||
settings.getUsersCb = getUsersCb;
|
||||
settings.bottleneckStatsCb = bottleneckStatsCb;
|
||||
settings.frameStatsCb = frameStatsCb;
|
||||
settings.resetFrameStatsCb = resetFrameStatsCb;
|
||||
|
||||
settings.requestFrameStatsNoneCb = requestFrameStatsNoneCb;
|
||||
settings.requestFrameStatsOwnerCb = requestFrameStatsOwnerCb;
|
||||
|
||||
@@ -150,14 +150,13 @@ struct kasmpasswd_t *parseJsonUsers(const char *data) {
|
||||
|
||||
if (e->type & cJSON_True)
|
||||
entry->owner = 1;
|
||||
/* } else field("read") {
|
||||
start = end + 3;
|
||||
} else field("read") {
|
||||
if (!(e->type & (cJSON_False | cJSON_True)))
|
||||
goto fail;
|
||||
|
||||
if (e->type & cJSON_True)
|
||||
entry->read = 1;
|
||||
*/
|
||||
|
||||
} else {
|
||||
//printf("Unknown field '%.*s'\n", len, start);
|
||||
goto fail;
|
||||
|
||||
@@ -216,10 +216,10 @@ ws_ctx_t *ws_socket(ws_ctx_t *ctx, int socket) {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
ws_ctx_t *ws_socket_ssl(ws_ctx_t *ctx, int socket, char * certfile, char * keyfile) {
|
||||
ws_ctx_t *ws_socket_ssl(ws_ctx_t *ctx, int socket, const char * certfile, const char * keyfile) {
|
||||
int ret;
|
||||
char msg[1024];
|
||||
char * use_keyfile;
|
||||
const char * use_keyfile;
|
||||
ws_socket(ctx, socket);
|
||||
|
||||
if (keyfile && (keyfile[0] != '\0')) {
|
||||
@@ -292,7 +292,7 @@ void ws_socket_free(ws_ctx_t *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
int ws_b64_ntop(const unsigned char const * src, size_t srclen, char * dst, size_t dstlen) {
|
||||
int ws_b64_ntop(const unsigned char * const src, size_t srclen, char * dst, size_t dstlen) {
|
||||
int len = 0;
|
||||
int total_len = 0;
|
||||
|
||||
@@ -327,7 +327,7 @@ int ws_b64_ntop(const unsigned char const * src, size_t srclen, char * dst, size
|
||||
return len;
|
||||
}
|
||||
|
||||
int ws_b64_pton(const char const * src, unsigned char * dst, size_t dstlen) {
|
||||
int ws_b64_pton(const char * const src, unsigned char * dst, size_t dstlen) {
|
||||
int len = 0;
|
||||
int total_len = 0;
|
||||
int pending = 0;
|
||||
@@ -724,14 +724,14 @@ int gen_md5(headers_t *headers, char *target) {
|
||||
static void gen_sha1(headers_t *headers, char *target) {
|
||||
SHA_CTX c;
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
int r;
|
||||
//int r;
|
||||
|
||||
SHA1_Init(&c);
|
||||
SHA1_Update(&c, headers->key1, strlen(headers->key1));
|
||||
SHA1_Update(&c, HYBI_GUID, 36);
|
||||
SHA1_Final(hash, &c);
|
||||
|
||||
r = ws_b64_ntop(hash, sizeof hash, target, HYBI10_ACCEPTHDRLEN);
|
||||
/*r =*/ ws_b64_ntop(hash, sizeof hash, target, HYBI10_ACCEPTHDRLEN);
|
||||
//assert(r == HYBI10_ACCEPTHDRLEN - 1);
|
||||
}
|
||||
|
||||
@@ -1021,7 +1021,8 @@ static uint8_t ownerapi_post(ws_ctx_t *ws_ctx, const char *in) {
|
||||
goto nope;
|
||||
}
|
||||
|
||||
uint64_t mask = USER_UPDATE_WRITE_MASK | USER_UPDATE_OWNER_MASK;
|
||||
uint64_t mask = USER_UPDATE_READ_MASK | USER_UPDATE_WRITE_MASK |
|
||||
USER_UPDATE_OWNER_MASK;
|
||||
|
||||
if (set->entries[s].password[0]) {
|
||||
struct crypt_data cdata;
|
||||
@@ -1035,6 +1036,7 @@ static uint8_t ownerapi_post(ws_ctx_t *ws_ctx, const char *in) {
|
||||
|
||||
if (!settings.updateUserCb(settings.messager, set->entries[s].user, mask,
|
||||
set->entries[s].password,
|
||||
set->entries[s].read,
|
||||
set->entries[s].write, set->entries[s].owner)) {
|
||||
wserr("Invalid params to update_user\n");
|
||||
goto nope;
|
||||
@@ -1173,7 +1175,7 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
}
|
||||
} else entry("/api/create_user") {
|
||||
char decname[1024] = "", decpw[1024] = "";
|
||||
uint8_t write = 0, owner = 0;
|
||||
uint8_t read = 0, write = 0, owner = 0;
|
||||
|
||||
param = parse_get(args, "name", &len);
|
||||
if (len) {
|
||||
@@ -1195,6 +1197,12 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
strcpy(decpw, encrypted);
|
||||
}
|
||||
|
||||
param = parse_get(args, "read", &len);
|
||||
if (len && isalpha(param[0])) {
|
||||
if (!strncmp(param, "true", len))
|
||||
read = 1;
|
||||
}
|
||||
|
||||
param = parse_get(args, "write", &len);
|
||||
if (len && isalpha(param[0])) {
|
||||
if (!strncmp(param, "true", len))
|
||||
@@ -1210,7 +1218,7 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
if (!decname[0] || !decpw[0])
|
||||
goto nope;
|
||||
|
||||
if (!settings.adduserCb(settings.messager, decname, decpw, write, owner)) {
|
||||
if (!settings.adduserCb(settings.messager, decname, decpw, read, write, owner)) {
|
||||
wserr("Invalid params to create_user\n");
|
||||
goto nope;
|
||||
}
|
||||
@@ -1267,6 +1275,14 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
goto nope;
|
||||
|
||||
uint64_t mask = 0;
|
||||
uint8_t myread = 0;
|
||||
param = parse_get(args, "read", &len);
|
||||
if (len && isalpha(param[0])) {
|
||||
mask |= USER_UPDATE_READ_MASK;
|
||||
if (!strncmp(param, "true", len))
|
||||
myread = 1;
|
||||
}
|
||||
|
||||
uint8_t mywrite = 0;
|
||||
param = parse_get(args, "write", &len);
|
||||
if (len && isalpha(param[0])) {
|
||||
@@ -1283,7 +1299,8 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
myowner = 1;
|
||||
}
|
||||
|
||||
if (!settings.updateUserCb(settings.messager, decname, mask, "", mywrite, myowner)) {
|
||||
if (!settings.updateUserCb(settings.messager, decname, mask, "",
|
||||
myread, mywrite, myowner)) {
|
||||
wserr("Invalid params to update_user\n");
|
||||
goto nope;
|
||||
}
|
||||
@@ -1370,14 +1387,25 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
goto nope;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
usleep(10 * 1000);
|
||||
if (settings.serverFrameStatsReadyCb(settings.messager))
|
||||
break;
|
||||
unsigned waits;
|
||||
{
|
||||
uint8_t failed = 1;
|
||||
for (waits = 0; waits < 500; waits++) { // wait up to 10s
|
||||
usleep(20 * 1000);
|
||||
if (settings.serverFrameStatsReadyCb(settings.messager)) {
|
||||
failed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
wserr("Main thread didn't respond, aborting (bug!)\n");
|
||||
settings.resetFrameStatsCb(settings.messager);
|
||||
goto timeout;
|
||||
}
|
||||
}
|
||||
|
||||
if (waitfor) {
|
||||
unsigned waits;
|
||||
for (waits = 0; waits < 20; waits++) { // wait up to 2s
|
||||
if (settings.getClientFrameStatsNumCb(settings.messager) >= waitfor)
|
||||
break;
|
||||
@@ -1403,6 +1431,7 @@ static uint8_t ownerapi(ws_ctx_t *ws_ctx, const char *in) {
|
||||
#undef entry
|
||||
|
||||
return ret;
|
||||
|
||||
nope:
|
||||
sprintf(buf, "HTTP/1.1 400 Bad Request\r\n"
|
||||
"Server: KasmVNC/4.0\r\n"
|
||||
@@ -1412,6 +1441,16 @@ nope:
|
||||
"400 Bad Request");
|
||||
ws_send(ws_ctx, buf, strlen(buf));
|
||||
return 1;
|
||||
|
||||
timeout:
|
||||
sprintf(buf, "HTTP/1.1 503 Service Unavailable\r\n"
|
||||
"Server: KasmVNC/4.0\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"503 Service Unavailable");
|
||||
ws_send(ws_ctx, buf, strlen(buf));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ws_ctx_t *do_handshake(int sock, const char *ip) {
|
||||
@@ -1696,7 +1735,7 @@ out:
|
||||
}
|
||||
|
||||
void *start_server(void *unused) {
|
||||
int csock, pid;
|
||||
int csock;
|
||||
struct sockaddr_in cli_addr;
|
||||
socklen_t clilen;
|
||||
|
||||
@@ -1706,7 +1745,6 @@ void *start_server(void *unused) {
|
||||
while (1) {
|
||||
clilen = sizeof(cli_addr);
|
||||
pipe_error = 0;
|
||||
pid = 0;
|
||||
do {
|
||||
csock = accept(settings.listen_sock,
|
||||
(struct sockaddr *) &cli_addr,
|
||||
|
||||
@@ -84,14 +84,15 @@ typedef struct {
|
||||
const uint8_t dedup,
|
||||
uint32_t *len, uint8_t *staging);
|
||||
uint8_t (*adduserCb)(void *messager, const char name[], const char pw[],
|
||||
const uint8_t write, const uint8_t owner);
|
||||
const uint8_t read, const uint8_t write, const uint8_t owner);
|
||||
uint8_t (*removeCb)(void *messager, const char name[]);
|
||||
uint8_t (*updateUserCb)(void *messager, const char name[], const uint64_t mask,
|
||||
const char password[],
|
||||
const uint8_t write, const uint8_t owner);
|
||||
const uint8_t read, const uint8_t write, const uint8_t owner);
|
||||
uint8_t (*addOrUpdateUserCb)(void *messager, const struct kasmpasswd_entry_t *entry);
|
||||
void (*bottleneckStatsCb)(void *messager, char *buf, uint32_t len);
|
||||
void (*frameStatsCb)(void *messager, char *buf, uint32_t len);
|
||||
void (*resetFrameStatsCb)(void *messager);
|
||||
|
||||
uint8_t (*requestFrameStatsNoneCb)(void *messager);
|
||||
uint8_t (*requestFrameStatsOwnerCb)(void *messager);
|
||||
|
||||
Reference in New Issue
Block a user