From 4d30b8cf0df79a6391935e5f1a999e9331a23f38 Mon Sep 17 00:00:00 2001 From: Rakesh Mandal/LGSI Platform Core Team Date: Thu, 2 Jan 2025 19:27:11 +0530 Subject: [PATCH] Added Support for Reverse VNC Added Support for Password Authentication Using a Single Tile in Tight, Raw, and ZRLE Encodings --- include/auth/vncauth.h | 9 ++ include/common.h | 20 +++- include/fb.h | 2 + include/neatvnc.h | 10 ++ meson.build | 5 + src/auth/common.c | 3 + src/auth/vncauth.c | 193 +++++++++++++++++++++++++++++++ src/display.c | 2 +- src/enc/raw.c | 10 +- src/enc/tight.c | 127 +++++++++++--------- src/enc/zrle.c | 107 +++++++++-------- src/fb.c | 32 +++++- src/server.c | 256 +++++++++++++++++++++++++++++++++++++++-- src/stream/interface.c | 1 + src/stream/tcp.c | 6 + 15 files changed, 661 insertions(+), 122 deletions(-) create mode 100644 include/auth/vncauth.h create mode 100644 src/auth/vncauth.c diff --git a/include/auth/vncauth.h b/include/auth/vncauth.h new file mode 100644 index 00000000..aa8c6fc8 --- /dev/null +++ b/include/auth/vncauth.h @@ -0,0 +1,9 @@ +#pragma once + +#define CHALLENGESIZE 16 +#define KEYSIZE 8 + +struct nvnc_client; + +int vnc_auth_handle_message(struct nvnc_client* client); +void genRandomBytes(unsigned char *bytes); diff --git a/include/common.h b/include/common.h index e0b87c28..9cfa5d40 100644 --- a/include/common.h +++ b/include/common.h @@ -41,11 +41,14 @@ #define MAX_CUT_TEXT_SIZE 10000000 #define MAX_CLIENT_UNSOLICITED_TEXT_SIZE 20971520 #define MAX_SECURITY_TYPES 32 +#define MAX_CHALLENGESIZE 32 enum nvnc_client_state { VNC_CLIENT_STATE_ERROR = -1, VNC_CLIENT_STATE_WAITING_FOR_VERSION = 0, VNC_CLIENT_STATE_WAITING_FOR_SECURITY, + VNC_CLIENT_STATE_WAITING_FOR_CHALLENGE, + #ifdef ENABLE_TLS VNC_CLIENT_STATE_WAITING_FOR_VENCRYPT_VERSION, VNC_CLIENT_STATE_WAITING_FOR_VENCRYPT_SUBTYPE, @@ -135,6 +138,19 @@ struct nvnc_client { struct bwe* bwe; int32_t inflight_bytes; + struct { + size_t challenge_len; + uint8_t challenge[MAX_CHALLENGESIZE]; + } vnc_auth; + + struct vncAuthData + { + char* password; + bool authEnabled; + bool VNCmode; + }; + struct vncAuthData* auth; + #ifdef HAVE_CRYPTO struct crypto_key* apple_dh_secret; @@ -142,7 +158,7 @@ struct nvnc_client { enum crypto_hash_type hash_type; enum crypto_cipher_type cipher_type; size_t challenge_len; - uint8_t challenge[32]; + uint8_t challenge[MAX_CHALLENGESIZE]; struct crypto_rsa_pub_key* pub; } rsa; #endif @@ -170,6 +186,7 @@ struct nvnc { nvnc_key_fn key_code_fn; nvnc_pointer_fn pointer_fn; nvnc_fb_req_fn fb_req_fn; + nvnc_on_encoder_fn on_encode_fn; nvnc_client_fn new_client_fn; nvnc_cut_text_fn cut_text_fn; struct cut_text ext_clipboard_provide_msg; @@ -185,6 +202,7 @@ struct nvnc { enum nvnc_auth_flags auth_flags; nvnc_auth_fn auth_fn; void* auth_ud; + nvnc_notifyserverReady_fn notify_fn; #ifdef ENABLE_TLS gnutls_certificate_credentials_t tls_creds; diff --git a/include/fb.h b/include/fb.h index 0bcc9890..8c571306 100644 --- a/include/fb.h +++ b/include/fb.h @@ -31,6 +31,7 @@ struct nvnc_fb { enum nvnc_fb_type type; int ref; int hold_count; + pthread_mutex_t lock; nvnc_fb_release_fn on_release; void* release_context; bool is_external; @@ -53,3 +54,4 @@ void nvnc_fb_hold(struct nvnc_fb* fb); void nvnc_fb_release(struct nvnc_fb* fb); int nvnc_fb_map(struct nvnc_fb* fb); void nvnc_fb_unmap(struct nvnc_fb* fb); +int nvnc_ref_count(struct nvnc_fb *fb); diff --git a/include/neatvnc.h b/include/neatvnc.h index 78d9f97b..d4022455 100644 --- a/include/neatvnc.h +++ b/include/neatvnc.h @@ -104,6 +104,7 @@ enum nvnc_log_level { enum nvnc_auth_flags { NVNC_AUTH_REQUIRE_AUTH = 1 << 0, NVNC_AUTH_REQUIRE_ENCRYPTION = 1 << 1, + NVNC_ENABLE_PASSWORD_AUTH = 1 << 2, }; struct nvnc_log_data { @@ -119,10 +120,12 @@ typedef void (*nvnc_pointer_fn)(struct nvnc_client*, uint16_t x, uint16_t y, typedef void (*nvnc_fb_req_fn)(struct nvnc_client*, bool is_incremental, uint16_t x, uint16_t y, uint16_t width, uint16_t height); +typedef void (*nvnc_on_encoder_fn)(struct nvnc_client*, const char* rfb_encoding); typedef void (*nvnc_client_fn)(struct nvnc_client*); typedef void (*nvnc_damage_fn)(struct pixman_region16* damage, void* userdata); typedef bool (*nvnc_auth_fn)(const char* username, const char* password, void* userdata); +typedef void (*nvnc_get_client_password_fn)(void *password); typedef void (*nvnc_cut_text_fn)(struct nvnc_client*, const char* text, uint32_t len); typedef void (*nvnc_fb_release_fn)(struct nvnc_fb*, void* context); @@ -132,6 +135,7 @@ typedef void (*nvnc_cleanup_fn)(void* userdata); typedef void (*nvnc_log_fn)(const struct nvnc_log_data*, const char* message); typedef bool (*nvnc_desktop_layout_fn)( struct nvnc_client*, const struct nvnc_desktop_layout*); +typedef void (*nvnc_notifyserverReady_fn)(bool res); extern const char nvnc_version[]; @@ -139,6 +143,8 @@ struct nvnc* nvnc_open(const char* addr, uint16_t port); struct nvnc* nvnc_open_unix(const char *addr); struct nvnc* nvnc_open_websocket(const char* addr, uint16_t port); struct nvnc* nvnc_open_from_fd(int fd); +struct nvnc* nvnc_reverse_open(const char* addr, uint16_t port); +void start_tcp_connection(struct nvnc* server); void nvnc_close(struct nvnc* self); void nvnc_add_display(struct nvnc*, struct nvnc_display*); @@ -166,14 +172,17 @@ void nvnc_set_key_fn(struct nvnc* self, nvnc_key_fn); void nvnc_set_key_code_fn(struct nvnc* self, nvnc_key_fn); void nvnc_set_pointer_fn(struct nvnc* self, nvnc_pointer_fn); void nvnc_set_fb_req_fn(struct nvnc* self, nvnc_fb_req_fn); +void nvnc_set_encode_event_fn(struct nvnc* self, nvnc_on_encoder_fn); void nvnc_set_new_client_fn(struct nvnc* self, nvnc_client_fn); void nvnc_set_client_cleanup_fn(struct nvnc_client* self, nvnc_client_fn fn); void nvnc_set_cut_text_fn(struct nvnc*, nvnc_cut_text_fn fn); void nvnc_set_desktop_layout_fn(struct nvnc* self, nvnc_desktop_layout_fn); +void nvnc_set_notifyServerReady_fn(struct nvnc* self, nvnc_notifyserverReady_fn); bool nvnc_has_auth(void); int nvnc_enable_auth(struct nvnc* self, enum nvnc_auth_flags flags, nvnc_auth_fn, void* userdata); +void nvnc_enable_vnc_auth(struct nvnc* self, nvnc_get_client_password_fn); int nvnc_set_tls_creds(struct nvnc* self, const char* privkey_path, const char* cert_path); int nvnc_set_rsa_creds(struct nvnc* self, const char* private_key_path); @@ -222,6 +231,7 @@ struct nvnc_display* nvnc_display_new(uint16_t x_pos, uint16_t y_pos); void nvnc_display_ref(struct nvnc_display*); void nvnc_display_unref(struct nvnc_display*); + struct nvnc* nvnc_display_get_server(const struct nvnc_display*); void nvnc_display_feed_buffer(struct nvnc_display*, struct nvnc_fb*, diff --git a/meson.build b/meson.build index e75ac36f..ccdd4d6f 100644 --- a/meson.build +++ b/meson.build @@ -58,6 +58,7 @@ gmp = dependency('gmp', required: get_option('nettle')) zlib = dependency('zlib') gbm = dependency('gbm', required: get_option('gbm')) libdrm = dependency('libdrm', required: get_option('h264')) +openssl_dep = dependency('openssl', required: true) libavcodec = dependency('libavcodec', required: get_option('h264')) libavfilter = dependency('libavfilter', required: get_option('h264')) @@ -75,6 +76,7 @@ inc = include_directories('include') sources = [ 'src/auth/common.c', + 'src/auth/vncauth.c', 'src/server.c', 'src/vec.c', 'src/enc/zrle.c', @@ -107,6 +109,7 @@ dependencies = [ aml, zlib, libdrm_inc, + openssl_dep ] enable_websocket = false @@ -143,6 +146,8 @@ if nettle.found() and hogweed.found() and gmp.found() ] endif +config.set('ENABLE_PASSWORD_AUTH', true) + if host_system == 'linux' and get_option('systemtap') and cc.has_header('sys/sdt.h') config.set('HAVE_USDT', true) endif diff --git a/src/auth/common.c b/src/auth/common.c index 53512a56..ceca5a90 100644 --- a/src/auth/common.c +++ b/src/auth/common.c @@ -32,6 +32,9 @@ int security_handshake_failed(struct nvnc_client* client, const char* username, char buffer[256]; + if(client->server->notify_fn) //if reverse is set this code hits in the auth failure case + client->server->notify_fn(false); + client->state = VNC_CLIENT_STATE_ERROR; uint32_t* result = (uint32_t*)buffer; diff --git a/src/auth/vncauth.c b/src/auth/vncauth.c new file mode 100644 index 00000000..00a0df90 --- /dev/null +++ b/src/auth/vncauth.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include "common.h" +#include "stream/stream.h" +#include "auth/auth.h" +#include "auth/vncauth.h" +#include + + +static unsigned char reverseByte(unsigned char b) +{ + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + +int encrypt_des(void *encrypted, int *encrypted_len, const unsigned char deskey[8], const void *plain, const size_t plain_len) +{ + int res = 0; + EVP_CIPHER_CTX *ctx; + unsigned char reversedKey[8]; + + for (int i = 0; i < 8; i++) + { + reversedKey[i] = reverseByte(deskey[i]); + } + if(!(ctx = EVP_CIPHER_CTX_new())) + { + nvnc_log(NVNC_LOG_ERROR, "EVP_CIPHER_CTX_new() failed"); + goto onFailure; + } + + if(!EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, reversedKey, NULL)) + { + nvnc_log(NVNC_LOG_ERROR, "EVP_EncryptInit_ex() failed"); + goto onFailure; + } + if(!EVP_EncryptUpdate(ctx, encrypted, encrypted_len, plain, plain_len)) + { + nvnc_log(NVNC_LOG_ERROR, "EVP_EncryptUpdate() failed"); + goto onFailure; + } + res = 1; + + onFailure: + EVP_CIPHER_CTX_free(ctx); + return res; +} + +void genRandomBytes(unsigned char *bytes) +{ + if (!bytes) + return; + + static bool s_srandom_called = false; + + if (!s_srandom_called) + { + srandom((unsigned int)time(NULL) ^ (unsigned int)getpid()); + s_srandom_called = true; + } + + int i = 0; + for (i = 0; i < CHALLENGESIZE; i++) + { + bytes[i] = (unsigned char)(random() & 255); + nvnc_log(NVNC_LOG_DEBUG, "genRandomBytes: %u", bytes[i]); + } +} + +void encryptBytes(uint8_t *bytes, char *passwd) +{ + if (!bytes) + return; + if (!passwd) + return; + unsigned char key[8]; + unsigned int i; + int out_len; + + /* key is simply password padded with nulls */ + for (i = 0; i < 8; i++) + { + if (i < strlen(passwd)) + { + key[i] = passwd[i]; + } + else + { + key[i] = 0; + } + } + + uint8_t newin[16]; + unsigned char encryptedPasswd[8]; + memcpy(newin, bytes, 16); + + uint8_t outBuf[CHALLENGESIZE]; + if(encrypt_des(bytes,&out_len, key, newin, CHALLENGESIZE ) != 1) + { + nvnc_log(NVNC_LOG_DEBUG, "encryptBytes failed"); + } +} + +bool compare_challenges(struct nvnc_client *cl, const char *response, int len) +{ + nvnc_log(NVNC_LOG_DEBUG, "compare_challenges called"); + + if (!cl) + return false; + if (!response) + return false; + + char **passwds; + int i = 0; + uint8_t auth_tmp[CHALLENGESIZE]; + memcpy((char *)auth_tmp, (char *)cl->vnc_auth.challenge, CHALLENGESIZE); + + for (int i = 0; i < CHALLENGESIZE; i++) + { + nvnc_log(NVNC_LOG_DEBUG, "0x%02X ", auth_tmp[i]); + } + nvnc_log(NVNC_LOG_DEBUG, " password is: %s\n", cl->auth->password); + + encryptBytes(auth_tmp, cl->auth->password); + + if (memcmp(auth_tmp, response, len) == 0) + { + nvnc_log(NVNC_LOG_DEBUG, "Password comparision passed"); + return true; + } + + nvnc_log(NVNC_LOG_ERROR, "Password comparision failed"); + return false; +} + +static int on_vnc_auth_des_challenge_message(struct nvnc_client *client) +{ + if (!client) + { + nvnc_log(NVNC_LOG_ERROR, "Client is NULL"); + return 0; + } + + if (!client->msg_buffer) + { + nvnc_log(NVNC_LOG_ERROR, "Message buffer is NULL"); + return 0; + } + + if (client->buffer_len < client->buffer_index + CHALLENGESIZE) + { + nvnc_log(NVNC_LOG_WARNING, "Buffer index out of bounds"); + return 0; + } + + nvnc_log(NVNC_LOG_DEBUG, "on_vnc_auth_des_challenge_message called"); + + uint8_t response[CHALLENGESIZE]; + memcpy(response, client->msg_buffer + client->buffer_index, CHALLENGESIZE); + response[CHALLENGESIZE] = '\0'; + + if (!compare_challenges(client, (const char *)response, CHALLENGESIZE)) + { + security_handshake_failed(client, "", "Invalid password"); + } + else + { + security_handshake_ok(client, ""); + client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT; + } + + return CHALLENGESIZE; +} + +int vnc_auth_handle_message(struct nvnc_client *client) +{ + nvnc_log(NVNC_LOG_DEBUG, "vnc_auth_handle_message called"); + if (!client) + return 0; + + switch (client->state) + { + case VNC_CLIENT_STATE_WAITING_FOR_CHALLENGE: + return on_vnc_auth_des_challenge_message(client); + default:; + } + + nvnc_log(NVNC_LOG_DEBUG, "Unhandled client state: %d", client->state); + return 0; +} diff --git a/src/display.c b/src/display.c index 81bc67f0..ff869962 100644 --- a/src/display.c +++ b/src/display.c @@ -35,7 +35,7 @@ static void nvnc_display__on_resampler_done(struct nvnc_fb* fb, DTRACE_PROBE2(neatvnc, nvnc_display__on_resampler_done, self, fb->pts); - if (self->buffer) { + if (self->buffer && self->buffer != fb) { nvnc_fb_release(self->buffer); nvnc_fb_unref(self->buffer); } diff --git a/src/enc/raw.c b/src/enc/raw.c index 806f0743..6f6c83ea 100644 --- a/src/enc/raw.c +++ b/src/enc/raw.c @@ -169,8 +169,8 @@ static void raw_encoder_on_done(void* obj) struct raw_encoder* self = ctx->parent; assert(ctx->result); - - aml_unref(self->work); + if(self->work) + aml_unref(self->work); self->work = NULL; encoder_finish_frame(&self->encoder, ctx->result); @@ -240,6 +240,8 @@ static int raw_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, sizeof(ctx->output_format)); ctx->x_pos = self->encoder.x_pos; ctx->y_pos = self->encoder.y_pos; + if (!ctx->fb || nvnc_ref_count(ctx->fb) < 1) + return -1; nvnc_fb_ref(ctx->fb); nvnc_fb_hold(ctx->fb); pixman_region_copy(&ctx->damage, damage); @@ -248,12 +250,14 @@ static int raw_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, if (rc < 0) { aml_unref(self->work); self->work = NULL; + nvnc_fb_release(ctx->fb); + nvnc_fb_unref(ctx->fb); } - return rc; } struct encoder_impl encoder_impl_raw = { + .flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE, .destroy = raw_encoder_destroy, .set_output_format = raw_encoder_set_output_format, .encode = raw_encoder_encode, diff --git a/src/enc/tight.c b/src/enc/tight.c index c2261b14..52f8b7a8 100644 --- a/src/enc/tight.c +++ b/src/enc/tight.c @@ -52,7 +52,7 @@ #define TSL 64 /* Tile Side Length */ -#define MAX_TILE_SIZE (2 * TSL * TSL * 4) +static int MAX_TILE_SIZE = 0; struct encoder* tight_encoder_new(uint16_t width, uint16_t height); @@ -75,6 +75,8 @@ struct tight_encoder { struct rfb_pixel_format dfmt; struct rfb_pixel_format sfmt; struct nvnc_fb* fb; + struct nvnc_fb* current_fb; + uint64_t pts; uint32_t n_rects; @@ -96,7 +98,7 @@ struct tight_tile { enum tight_tile_state state; size_t size; uint8_t type; - char buffer[MAX_TILE_SIZE]; + char* buffer; }; struct tight_zs_worker_ctx { @@ -136,17 +138,23 @@ static inline struct tight_tile* tight_tile(struct tight_encoder* self, static inline uint32_t tight_tile_width(struct tight_encoder* self, uint32_t x) { - return x + TSL > self->width ? self->width - x : TSL; + if(!self) + return 0; + return self->width; } static inline uint32_t tight_tile_height(struct tight_encoder* self, uint32_t y) { - return y + TSL > self->height ? self->height - y : TSL; + if(!self) + return 0; + return self->height; } static int tight_init_zs_worker(struct tight_encoder* self, int index) { + if(!self) + return -1; struct tight_zs_worker_ctx* ctx = calloc(1, sizeof(*ctx)); if (!ctx) return -1; @@ -175,33 +183,41 @@ static int tight_encoder_resize(struct tight_encoder* self, uint32_t width, self->width = width; self->height = height; - self->grid_width = UDIV_UP(width, 64); - self->grid_height = UDIV_UP(height, 64); - - if (self->grid) + self->grid_width = 1; + self->grid_height = 1; + if (self->grid) { + if (self->grid->buffer) + free(self->grid->buffer); free(self->grid); + } self->grid = calloc(self->grid_width * self->grid_height, sizeof(*self->grid)); - return self->grid ? 0 : -1; + if(!self->grid) + return -1; + self->grid->buffer = (char*) calloc(MAX_TILE_SIZE, sizeof(char)); + if (!self->grid->buffer) + { + free(self->grid); // Clean up previously allocated memory for the grid + self->grid = NULL; // Set grid to NULL to avoid dangling pointer + return -1; // Buffer allocation failed + } + return 0; // Successfully resized } static int tight_encoder_init(struct tight_encoder* self, uint32_t width, uint32_t height) { + if(!self) + return -1; + MAX_TILE_SIZE = width*height*4; memset(self, 0, sizeof(*self)); if (tight_encoder_resize(self, width, height) < 0) return -1; tight_encoder_init_stream(&self->zs[0]); - tight_encoder_init_stream(&self->zs[1]); - tight_encoder_init_stream(&self->zs[2]); - tight_encoder_init_stream(&self->zs[3]); tight_init_zs_worker(self, 0); - tight_init_zs_worker(self, 1); - tight_init_zs_worker(self, 2); - tight_init_zs_worker(self, 3); aml_require_workers(aml_get_default(), 1); @@ -212,43 +228,39 @@ static int tight_encoder_init(struct tight_encoder* self, uint32_t width, static void tight_encoder_destroy(struct tight_encoder* self) { - aml_unref(self->zs_worker[3]); - aml_unref(self->zs_worker[2]); - aml_unref(self->zs_worker[1]); aml_unref(self->zs_worker[0]); - deflateEnd(&self->zs[3]); - deflateEnd(&self->zs[2]); - deflateEnd(&self->zs[1]); deflateEnd(&self->zs[0]); - - free(self->grid); + if(self->grid) + { + if(self->grid->buffer) + free(self->grid->buffer); + free(self->grid); + } } static int tight_apply_damage(struct tight_encoder* self, struct pixman_region16* damage) { + if(!self) + return -1; int n_damaged = 0; /* Align damage to tile grid */ for (uint32_t y = 0; y < self->grid_height; ++y) for (uint32_t x = 0; x < self->grid_width; ++x) { struct pixman_box16 box = { - .x1 = x * TSL, - .y1 = y * TSL, - .x2 = (x + 1) * TSL, - .y2 = (y + 1) * TSL, + .x1 = x * self->width, + .y1 = y * self->height, + .x2 = (x + 1) * self->width, + .y2 = (y + 1) * self->height, }; pixman_region_overlap_t overlap = pixman_region_contains_rectangle(damage, &box); - if (overlap != PIXMAN_REGION_OUT) { ++n_damaged; tight_tile(self, x, y)->state = TIGHT_TILE_DAMAGED; - } else { - tight_tile(self, x, y)->state = TIGHT_TILE_READY; - } } return n_damaged; @@ -352,6 +364,8 @@ static int tight_encode_tile_jpeg(struct tight_encoder* self, struct tight_tile* tile, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { + if(!self) + return -1; tile->type = TIGHT_JPEG; unsigned char* buffer = NULL; @@ -410,8 +424,12 @@ static void tight_encode_tile(struct tight_encoder* self, uint32_t x = gx * TSL; uint32_t y = gy * TSL; - uint32_t width = tight_tile_width(self, x); - uint32_t height = tight_tile_height(self, y); + uint32_t width = self->width; + uint32_t height = self->height; + MAX_TILE_SIZE = width*height*4; + if(!tile->buffer) { + return; + } tile->size = 0; @@ -432,24 +450,18 @@ static void do_tight_zs_work(void* obj) { struct tight_zs_worker_ctx* ctx = aml_get_userdata(obj); struct tight_encoder* self = ctx->encoder; + self->fb = self->current_fb; int index = ctx->index; - - for (uint32_t y = 0; y < self->grid_height; ++y) - for (uint32_t x = index; x < self->grid_width; x += 4) - if (tight_tile(self, x, y)->state == TIGHT_TILE_DAMAGED) - tight_encode_tile(self, x, y); + tight_encode_tile(self, 0, 0); } static void on_tight_zs_work_done(void* obj) { struct tight_zs_worker_ctx* ctx = aml_get_userdata(obj); struct tight_encoder* self = ctx->encoder; - - if (--self->n_jobs == 0) { - nvnc_fb_release(self->fb); - nvnc_fb_unref(self->fb); - schedule_tight_finish(self); - } + nvnc_fb_release(self->fb); + nvnc_fb_unref(self->fb); + schedule_tight_finish(self); encoder_unref(&self->encoder); } @@ -469,9 +481,8 @@ static int tight_schedule_zs_work(struct tight_encoder* self, int index) static int tight_schedule_encoding_jobs(struct tight_encoder* self) { - for (int i = 0; i < 4; ++i) - if (tight_schedule_zs_work(self, i) < 0) - return -1; + if (tight_schedule_zs_work(self, 0) < 0) + return -1; return 0; } @@ -532,6 +543,8 @@ static void on_tight_finished(void* obj) static int schedule_tight_finish(struct tight_encoder* self) { + if(!self) + return -1; encoder_ref(&self->encoder); struct aml_work* work = aml_work_new(do_tight_finish, on_tight_finished, @@ -578,7 +591,8 @@ static void tight_encoder_set_output_format(struct encoder* encoder, static void tight_encoder_set_quality(struct encoder* encoder, int value) { struct tight_encoder* self = tight_encoder(encoder); - self->quality = value; + if(self) + self->quality = value; } static int tight_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, @@ -593,7 +607,7 @@ static int tight_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, rc = rfb_pixfmt_from_fourcc(&self->sfmt, nvnc_fb_get_fourcc_format(fb)); assert(rc == 0); - self->fb = fb; + self->current_fb = fb; self->pts = nvnc_fb_get_pts(fb); rc = nvnc_fb_map(self->fb); @@ -609,13 +623,15 @@ static int tight_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, self->n_rects = tight_apply_damage(self, damage); assert(self->n_rects > 0); - nvnc_fb_ref(self->fb); - nvnc_fb_hold(self->fb); + if (!self->current_fb || nvnc_ref_count(self->current_fb) < 1) + return -1; + nvnc_fb_ref(self->current_fb); + nvnc_fb_hold(self->current_fb); - if (tight_schedule_encoding_jobs(self) < 0) { - nvnc_fb_release(self->fb); - nvnc_fb_unref(self->fb); - vec_destroy(&self->dst); + if (tight_schedule_encoding_jobs(self) < 0) + { + nvnc_fb_release(self->current_fb); + nvnc_fb_unref(self->current_fb); return -1; } @@ -623,6 +639,7 @@ static int tight_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, } struct encoder_impl encoder_impl_tight = { + .flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE, .destroy = tight_encoder_destroy_wrapper, .set_output_format = tight_encoder_set_output_format, .set_quality = tight_encoder_set_quality, diff --git a/src/enc/zrle.c b/src/enc/zrle.c index 503c7381..ac1f2b1a 100644 --- a/src/enc/zrle.c +++ b/src/enc/zrle.c @@ -43,15 +43,18 @@ struct zrle_encoder { struct rfb_pixel_format output_format; + z_stream zs; + struct aml_work* work; +}; + +struct zrle_encoder_work { + struct zrle_encoder* parent; + struct rfb_pixel_format output_format; struct nvnc_fb* current_fb; struct pixman_region16 current_damage; struct encoded_frame *current_result; int n_rects; - - z_stream zs; - - struct aml_work* work; }; struct encoder_impl encoder_impl_zrle; @@ -236,7 +239,7 @@ static int zrle_deflate(struct vec* dst, const struct vec* src, z_stream* zs, return 0; } -static int zrle_encode_box(struct zrle_encoder* self, struct vec* out, +static int zrle_encode_box(struct zrle_encoder_work* self, struct vec* out, const struct rfb_pixel_format* dst_fmt, const struct nvnc_fb* fb, const struct rfb_pixel_format* src_fmt, int x, int y, @@ -247,8 +250,8 @@ static int zrle_encode_box(struct zrle_encoder* self, struct vec* out, int src_bpp = src_fmt->bits_per_pixel / 8; struct vec in; - uint16_t x_pos = self->encoder.x_pos; - uint16_t y_pos = self->encoder.y_pos; + uint16_t x_pos = self->parent->encoder.x_pos; + uint16_t y_pos = self->parent->encoder.y_pos; uint8_t* tile = malloc(TILE_LENGTH * TILE_LENGTH * 4); if (!tile) @@ -304,7 +307,7 @@ static int zrle_encode_box(struct zrle_encoder* self, struct vec* out, #undef CHUNK } -static int zrle_encode_frame(struct zrle_encoder* self, z_stream* zs, +static int zrle_encode_frame(struct zrle_encoder_work* self, z_stream* zs, struct vec* dst, const struct rfb_pixel_format* dst_fmt, struct nvnc_fb* src, const struct rfb_pixel_format* src_fmt, struct pixman_region16* region) @@ -342,7 +345,7 @@ static int zrle_encode_frame(struct zrle_encoder* self, z_stream* zs, static void zrle_encoder_do_work(void* obj) { - struct zrle_encoder* self = aml_get_userdata(obj); + struct zrle_encoder_work* self = aml_get_userdata(obj); int rc __attribute__((unused)); struct nvnc_fb* fb = self->current_fb; @@ -350,6 +353,8 @@ static void zrle_encoder_do_work(void* obj) // TODO: Calculate the ideal buffer size based on the size of the // damaged area. + if(!fb) + return; size_t buffer_size = nvnc_fb_get_stride(fb) * nvnc_fb_get_height(fb) * nvnc_fb_get_pixel_size(fb); @@ -361,7 +366,7 @@ static void zrle_encoder_do_work(void* obj) rc = rfb_pixfmt_from_fourcc(&src_fmt, nvnc_fb_get_fourcc_format(fb)); assert(rc == 0); - rc = zrle_encode_frame(self, &self->zs, &dst, &self->output_format, fb, + rc = zrle_encode_frame(self, &self->parent->zs, &dst, &self->output_format, fb, &src_fmt, &self->current_damage); assert(rc == 0); @@ -376,26 +381,13 @@ static void zrle_encoder_do_work(void* obj) static void zrle_encoder_on_done(void* obj) { - struct zrle_encoder* self = aml_get_userdata(obj); - - assert(self->current_result); - - nvnc_fb_release(self->current_fb); - nvnc_fb_unref(self->current_fb); - self->current_fb = NULL; - - pixman_region_clear(&self->current_damage); - - struct encoded_frame* result = self->current_result; - self->current_result = NULL; - - aml_unref(self->work); + struct zrle_encoder_work* ctx = aml_get_userdata(obj); + struct zrle_encoder* self = ctx->parent; + assert(ctx->current_result); + if(self->work) + aml_unref(self->work); self->work = NULL; - - encoder_finish_frame(&self->encoder, result); - - encoded_frame_unref(result); - encoder_unref(&self->encoder); + encoder_finish_frame(&self->encoder, ctx->current_result); } struct encoder* zrle_encoder_new(void) @@ -415,8 +407,6 @@ struct encoder* zrle_encoder_new(void) if (rc != Z_OK) goto deflate_failure; - pixman_region_init(&self->current_damage); - return (struct encoder*)self; deflate_failure: @@ -427,12 +417,9 @@ struct encoder* zrle_encoder_new(void) static void zrle_encoder_destroy(struct encoder* encoder) { struct zrle_encoder* self = zrle_encoder(encoder); - pixman_region_fini(&self->current_damage); deflateEnd(&self->zs); if (self->work) aml_unref(self->work); - if (self->current_result) - encoded_frame_unref(self->current_result); free(self); } @@ -443,40 +430,64 @@ static void zrle_encoder_set_output_format(struct encoder* encoder, memcpy(&self->output_format, pixfmt, sizeof(self->output_format)); } +static void zrle_encoder_work_destroy(void* obj) +{ + struct zrle_encoder_work* ctx = obj; + if(ctx->current_fb) + { + nvnc_fb_release(ctx->current_fb); + nvnc_fb_unref(ctx->current_fb); + } + + pixman_region_fini(&ctx->current_damage); + if (ctx->current_result) + encoded_frame_unref(ctx->current_result); + encoder_unref(&ctx->parent->encoder); + free(ctx); +} + static int zrle_encoder_encode(struct encoder* encoder, struct nvnc_fb* fb, struct pixman_region16* damage) { + if(!fb) + return -1; struct zrle_encoder* self = zrle_encoder(encoder); - - assert(!self->current_fb); + struct zrle_encoder_work* ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return -1; self->work = aml_work_new(zrle_encoder_do_work, zrle_encoder_on_done, - self, NULL); + ctx, zrle_encoder_work_destroy); if (!self->work) + { + free(ctx); + return -1; + } + encoder_ref(encoder); + ctx->parent = self; + ctx->current_fb = fb; + memcpy(&ctx->output_format, &self->output_format, + sizeof(ctx->output_format)); + if (!ctx->current_fb || nvnc_ref_count(ctx->current_fb) < 1) return -1; - self->current_fb = fb; - nvnc_fb_ref(self->current_fb); - nvnc_fb_hold(self->current_fb); - pixman_region_copy(&self->current_damage, damage); - - encoder_ref(&self->encoder); + nvnc_fb_ref(ctx->current_fb); + nvnc_fb_hold(ctx->current_fb); + pixman_region_copy(&ctx->current_damage, damage); int rc = aml_start(aml_get_default(), self->work); if (rc < 0) { - encoder_unref(&self->encoder); aml_unref(self->work); self->work = NULL; - pixman_region_clear(&self->current_damage); - nvnc_fb_release(self->current_fb); - nvnc_fb_unref(self->current_fb); - self->current_fb = NULL; + nvnc_fb_release(ctx->current_fb); + nvnc_fb_unref(ctx->current_fb); } return rc; } struct encoder_impl encoder_impl_zrle = { + .flags = ENCODER_IMPL_FLAG_IGNORES_DAMAGE, .destroy = zrle_encoder_destroy, .set_output_format = zrle_encoder_set_output_format, .encode = zrle_encoder_encode, diff --git a/src/fb.c b/src/fb.c index ea680d8d..8836f450 100644 --- a/src/fb.c +++ b/src/fb.c @@ -22,7 +22,7 @@ #include #include #include - +#include #include "config.h" #ifdef HAVE_GBM @@ -40,7 +40,7 @@ struct nvnc_fb* nvnc_fb_new(uint16_t width, uint16_t height, struct nvnc_fb* fb = calloc(1, sizeof(*fb)); if (!fb) return NULL; - + pthread_mutex_init(&fb->lock, NULL); uint32_t bpp = pixel_size_from_fourcc(fourcc_format); fb->type = NVNC_FB_SIMPLE; @@ -172,7 +172,7 @@ uint64_t nvnc_fb_get_pts(const struct nvnc_fb* fb) static void nvnc__fb_free(struct nvnc_fb* fb) { nvnc_cleanup_fn cleanup = fb->common.cleanup_fn; - if (cleanup) + if (cleanup && fb->common.userdata) cleanup(fb->common.userdata); nvnc_fb_unmap(fb); @@ -192,21 +192,41 @@ static void nvnc__fb_free(struct nvnc_fb* fb) #endif break; } - + pthread_mutex_destroy(&fb->lock); free(fb); } +EXPORT +int nvnc_ref_count(struct nvnc_fb *fb) +{ + if (!fb) + return -1; + pthread_mutex_lock(&fb->lock); + int ref_count = fb->ref; // Read the reference count + pthread_mutex_unlock(&fb->lock); + + return ref_count; +} + EXPORT void nvnc_fb_ref(struct nvnc_fb* fb) { + if (!fb) + return; + pthread_mutex_lock(&fb->lock); fb->ref++; + pthread_mutex_unlock(&fb->lock); } EXPORT void nvnc_fb_unref(struct nvnc_fb* fb) { + if (!fb) + return; + pthread_mutex_lock(&fb->lock); // Lock the mutex before modifying ref if (fb && --fb->ref == 0) nvnc__fb_free(fb); + pthread_mutex_unlock(&fb->lock); // Unlock the mutex } EXPORT @@ -230,7 +250,11 @@ void nvnc_fb_set_pts(struct nvnc_fb* fb, uint64_t pts) void nvnc_fb_hold(struct nvnc_fb* fb) { + if (!fb) + return; + pthread_mutex_lock(&fb->lock); // Lock the mutex before modifying hold_count fb->hold_count++; + pthread_mutex_unlock(&fb->lock); // Unlock the mutex } void nvnc_fb_release(struct nvnc_fb* fb) diff --git a/src/server.c b/src/server.c index 0c79a5ca..b938e629 100644 --- a/src/server.c +++ b/src/server.c @@ -54,6 +54,9 @@ #include #include #include +#include + +#include "auth/vncauth.h" #ifdef ENABLE_TLS #include @@ -65,7 +68,7 @@ #include "auth/apple-dh.h" #include "auth/rsa-aes.h" #endif - +#define MAX_IP_SIZE 32 #ifndef DRM_FORMAT_INVALID #define DRM_FORMAT_INVALID 0 #endif @@ -143,7 +146,7 @@ static void client_drain_encoder(struct nvnc_client* client) /* Letting the encoder finish is the simplest way to free its * in-flight resources. */ - int64_t timeout = 1000000; // µs + int64_t timeout = 2000000; // µs int64_t remaining = timeout; int64_t start_time = gettime_us(CLOCK_MONOTONIC); @@ -256,13 +259,20 @@ static int handle_unsupported_version(struct nvnc_client* client) static void init_security_types(struct nvnc* server) { -#define ADD_SECURITY_TYPE(type) \ - assert(server->n_security_types < MAX_SECURITY_TYPES); \ - server->security_types[server->n_security_types++] = (type); + assert(server); + #define ADD_SECURITY_TYPE(type) \ + assert(server->n_security_types < MAX_SECURITY_TYPES); \ + server->security_types[server->n_security_types++] = (type); if (server->n_security_types > 0) return; +#ifdef ENABLE_PASSWORD_AUTH + if (server->auth_flags & NVNC_ENABLE_PASSWORD_AUTH) + { + ADD_SECURITY_TYPE(RFB_SECURITY_TYPE_VNC_AUTH);//send this only when authentication/reverseconnection is enabled + } +#endif if (server->auth_flags & NVNC_AUTH_REQUIRE_AUTH) { assert(server->auth_fn); @@ -348,8 +358,19 @@ static int on_version_message(struct nvnc_client* client) return 12; } +static void rfbVncAuthSendChallenge(struct nvnc_client* client) +{ + if(!client) + return; + genRandomBytes(client->vnc_auth.challenge); + + stream_write(client->net_stream, client->vnc_auth.challenge,CHALLENGESIZE, NULL, NULL); +} + static int on_security_message(struct nvnc_client* client) { + if(!client) + return 0; if (client->buffer_len - client->buffer_index < 1) return 0; @@ -368,6 +389,11 @@ static int on_security_message(struct nvnc_client* client) security_handshake_ok(client, NULL); client->state = VNC_CLIENT_STATE_WAITING_FOR_INIT; break; + case RFB_SECURITY_TYPE_VNC_AUTH: + rfbVncAuthSendChallenge(client); + client->auth =(struct vncAuthData*)client->server->auth_ud; + client->state = VNC_CLIENT_STATE_WAITING_FOR_CHALLENGE; + break; #ifdef ENABLE_TLS case RFB_SECURITY_TYPE_VENCRYPT: vencrypt_send_version(client); @@ -498,6 +524,8 @@ static int on_init_message(struct nvnc_client* client) client, client->min_rtt / 1000); client->state = VNC_CLIENT_STATE_READY; + if(client->server->notify_fn) //if reverse is set this code hits in the success case + client->server->notify_fn(true); return sizeof(shared_flag); } @@ -822,6 +850,10 @@ static bool ensure_encoder(struct nvnc_client* client, const struct nvnc_fb *fb) nvnc_log(NVNC_LOG_INFO, "Choosing %s encoding for client %p", encoding_to_string(encoding), client); + nvnc_on_encoder_fn encode_fn = server->on_encode_fn; + if (encode_fn) + encode_fn(client, encoding_to_string(encoding)); + return true; } @@ -1909,6 +1941,8 @@ static int try_read_client_message(struct nvnc_client* client) return on_version_message(client); case VNC_CLIENT_STATE_WAITING_FOR_SECURITY: return on_security_message(client); + case VNC_CLIENT_STATE_WAITING_FOR_CHALLENGE: + return vnc_auth_handle_message(client); case VNC_CLIENT_STATE_WAITING_FOR_INIT: return on_init_message(client); #ifdef ENABLE_TLS @@ -1993,6 +2027,98 @@ static void on_client_event(struct stream* stream, enum stream_event event) client->buffer_index = 0; } +EXPORT +void start_tcp_connection(struct nvnc* server) +{ + if(!server) + return; + + struct nvnc_client* client = calloc(1, sizeof(*client)); + if (!client) + return; + + client->server = server; + client->quality = 10; /* default to lossless */ + client->led_state = -1; /* trigger sending of initial state */ + client->min_rtt = INT32_MAX; + client->bwe = bwe_create(INT32_MAX); + + /* default extended clipboard capabilities */ + client->ext_clipboard_caps = + RFB_EXT_CLIPBOARD_FORMAT_TEXT | + RFB_EXT_CLIPBOARD_ACTION_REQUEST | + RFB_EXT_CLIPBOARD_ACTION_NOTIFY | + RFB_EXT_CLIPBOARD_ACTION_PROVIDE; + + client->ext_clipboard_max_unsolicited_text_size = + MAX_CLIENT_UNSOLICITED_TEXT_SIZE; + + int fd = server->fd; + if (fd < 0) { + nvnc_log(NVNC_LOG_WARNING, "Failed to accept a connection"); + goto accept_failure; + } + + int one = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); + +#ifdef ENABLE_WEBSOCKET + if (server->socket_type == NVNC__SOCKET_WEBSOCKET) + { + client->net_stream = stream_ws_new(fd, on_client_event, client); + } + else +#endif + { + client->net_stream = stream_new(fd, on_client_event, client); + } + + if (!client->net_stream) { + nvnc_log(NVNC_LOG_WARNING, "OOM"); + goto stream_failure; + } + + if (!server->display->buffer) { + nvnc_log(NVNC_LOG_WARNING, "No display buffer has been set"); + goto buffer_failure; + } + + pixman_region_init(&client->damage); + + struct rcbuf* payload = rcbuf_from_string(RFB_VERSION_MESSAGE); + if (!payload) { + nvnc_log(NVNC_LOG_WARNING, "OOM"); + goto payload_failure; + } + + client->last_ping_time = gettime_us(CLOCK_MONOTONIC); + stream_send(client->net_stream, payload, NULL, NULL); + + LIST_INSERT_HEAD(&server->clients, client, link); + + client->state = VNC_CLIENT_STATE_WAITING_FOR_VERSION; + + char ip_address[MAX_IP_SIZE]; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + nvnc_client_get_address(client, (struct sockaddr*)&addr, &addrlen); + sockaddr_to_string(ip_address, sizeof(ip_address), + (struct sockaddr*)&addr); + nvnc_log(NVNC_LOG_INFO, "New client connection from %s: %p", + ip_address, client); + + return; + +payload_failure: + pixman_region_fini(&client->damage); +buffer_failure: + stream_destroy(client->net_stream); +stream_failure: + close(fd); +accept_failure: + free(client); +} + static void on_connection(void* obj) { struct nvnc* server = aml_get_userdata(obj); @@ -2060,7 +2186,7 @@ static void on_connection(void* obj) client->state = VNC_CLIENT_STATE_WAITING_FOR_VERSION; - char ip_address[256]; + char ip_address[MAX_IP_SIZE]; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); nvnc_client_get_address(client, (struct sockaddr*)&addr, &addrlen); @@ -2196,6 +2322,94 @@ static int bind_address(const char* name, uint16_t port, return -1; } +bool setNonBlocking(int sock) +{ + int flags = fcntl(sock, F_GETFL); + if(flags < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) { + nvnc_log(NVNC_LOG_WARNING, "failed to set non blocking"); + return false; + } + return true; +} + +static int connect_to_address(const char* address, uint16_t port, enum nvnc__socket_type type) +{ + nvnc_log(NVNC_LOG_WARNING, "connect_to_address vnc "); + int fd = socket(AF_INET, (type == NVNC__SOCKET_TCP) ? SOCK_STREAM : SOCK_DGRAM, 0); + if (fd < 0) { + perror("Failed to create socket"); + return -1; + } + + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + + if (inet_pton(AF_INET, address, &server_addr.sin_addr) <= 0) { + perror("Invalid address"); + close(fd); + return -1; + } + + if (connect(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + perror("Connection failed"); + nvnc_log(NVNC_LOG_WARNING, "Connection failed vnc "); + close(fd); + return -1; + } + nvnc_log(NVNC_LOG_WARNING, "returns fd"); + return fd; +} + +static struct nvnc* open_reverse_vnc(const char* address, uint16_t port, enum nvnc__socket_type type) +{ + nvnc__log_init(); + nvnc_log(NVNC_LOG_WARNING, "open_reverse_vnc vnc "); + + aml_require_workers(aml_get_default(), -1); + + struct nvnc* self = calloc(1, sizeof(*self)); + if (!self) + return NULL; + + self->socket_type = type; + strcpy(self->name, DEFAULT_NAME); + LIST_INIT(&self->clients); + // Modify this part to connect to the remote VNC server (viewer) + self->fd = connect_to_address(address, port, type); + if (self->fd < 0) + { + nvnc_log(NVNC_LOG_WARNING, "connect_to_address failed"); + goto connect_failure; + } + + nvnc_log(NVNC_LOG_DEBUG, "vnc connected to client ip"); + + if(!setNonBlocking(self->fd)) + { + nvnc_log(NVNC_LOG_WARNING, "setNonBlocking failed"); + return NULL; + } + + int one = 1; + setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); + //ToDO: monitor socket + + nvnc_log(NVNC_LOG_DEBUG, "open_reverse_vnc 2153 calls start_tcp_connection"); + + return self; + +poll_start_failure: + aml_unref(self->poll_handle); +handle_failure: + close(self->fd); +connect_failure: + free(self); + + return NULL; +} + static struct nvnc* open_common(const char* address, uint16_t port, int fd, enum nvnc__socket_type type) { @@ -2259,6 +2473,13 @@ struct nvnc* nvnc_open_websocket(const char *address, uint16_t port) #endif } +EXPORT +struct nvnc* nvnc_reverse_open(const char* addr, uint16_t port) +{ + nvnc_log(NVNC_LOG_INFO, "nvnc_reverse_open vnc"); + return open_reverse_vnc(addr, port, NVNC__SOCKET_TCP); +} + EXPORT struct nvnc* nvnc_open_unix(const char* address) { @@ -2306,8 +2527,8 @@ void nvnc_close(struct nvnc* self) while (!LIST_EMPTY(&self->clients)) client_close(LIST_FIRST(&self->clients)); - - aml_stop(aml_get_default(), self->poll_handle); + if(self->poll_handle) + aml_stop(aml_get_default(), self->poll_handle); // Do not unlink an externally managed fd. if(self->socket_type != NVNC__SOCKET_FROM_FD) { unlink_fd_path(self->fd); @@ -2327,7 +2548,7 @@ void nvnc_close(struct nvnc* self) #endif free(self->ext_clipboard_provide_msg.buffer); - +if(self->poll_handle) aml_unref(self->poll_handle); free(self); } @@ -2572,6 +2793,12 @@ void nvnc_set_key_fn(struct nvnc* self, nvnc_key_fn fn) self->key_fn = fn; } +EXPORT +void nvnc_set_notifyServerReady_fn(struct nvnc* self, nvnc_notifyserverReady_fn fn) +{ + self->notify_fn = fn; +} + EXPORT void nvnc_set_key_code_fn(struct nvnc* self, nvnc_key_fn fn) { @@ -2590,9 +2817,17 @@ void nvnc_set_fb_req_fn(struct nvnc* self, nvnc_fb_req_fn fn) self->fb_req_fn = fn; } +EXPORT +void nvnc_set_encode_event_fn(struct nvnc* self, nvnc_on_encoder_fn fn) +{ + if(!self) return; + self->on_encode_fn = fn; +} + EXPORT void nvnc_set_new_client_fn(struct nvnc* self, nvnc_client_fn fn) { + if(!self) return; self->new_client_fn = fn; } @@ -2803,7 +3038,8 @@ EXPORT int nvnc_enable_auth(struct nvnc* self, enum nvnc_auth_flags flags, nvnc_auth_fn auth_fn, void* userdata) { -#if defined(ENABLE_TLS) || defined(HAVE_CRYPTO) +#if defined(ENABLE_TLS) || defined(HAVE_CRYPTO) || defined(ENABLE_PASSWORD_AUTH) + nvnc_log(NVNC_LOG_INFO, "Entered nvnc_enable_auth"); self->auth_flags = flags; self->auth_fn = auth_fn; self->auth_ud = userdata; diff --git a/src/stream/interface.c b/src/stream/interface.c index 15b68e14..30414e73 100644 --- a/src/stream/interface.c +++ b/src/stream/interface.c @@ -33,6 +33,7 @@ void stream_destroy(struct stream* self) int stream_send(struct stream* self, struct rcbuf* payload, stream_req_fn on_done, void* userdata) { + assert(self); assert(self->impl && self->impl->send); return self->impl->send(self, payload, on_done, userdata); } diff --git a/src/stream/tcp.c b/src/stream/tcp.c index 53d8237b..b1e67dd7 100644 --- a/src/stream/tcp.c +++ b/src/stream/tcp.c @@ -39,6 +39,7 @@ static_assert(sizeof(struct stream) <= STREAM_ALLOC_SIZE, int stream_tcp_close(struct stream* self) { + if(!self) return -1; if (self->state == STREAM_STATE_CLOSED) return -1; @@ -60,6 +61,7 @@ int stream_tcp_close(struct stream* self) void stream_tcp_destroy(struct stream* self) { + if(!self) return; vec_destroy(&self->tmp_buf); stream_close(self); aml_unref(self->handler); @@ -156,6 +158,7 @@ static int stream_tcp__flush(struct stream* self) static void stream_tcp__on_readable(struct stream* self) { + if(!self) return; switch (self->state) { case STREAM_STATE_NORMAL: /* fallthrough */ @@ -170,6 +173,7 @@ static void stream_tcp__on_readable(struct stream* self) static void stream_tcp__on_writable(struct stream* self) { + if(!self) return; switch (self->state) { case STREAM_STATE_NORMAL: /* fallthrough */ @@ -183,6 +187,7 @@ static void stream_tcp__on_writable(struct stream* self) static void stream_tcp__on_event(void* obj) { + if(!obj) return; struct stream* self = aml_get_userdata(obj); uint32_t events = aml_get_revents(obj); @@ -278,6 +283,7 @@ static struct stream_impl impl = { int stream_tcp_init(struct stream* self, int fd, stream_event_fn on_event, void* userdata) { + if(!self) return -1; self->impl = &impl, self->fd = fd; self->on_event = on_event;