diff --git a/include/common.h b/include/common.h index 5d10ca0..627c306 100644 --- a/include/common.h +++ b/include/common.h @@ -22,6 +22,7 @@ #define MAX_EXEC_COMMAND_LEN 1024 #define MAX_CLIENTS 64 #define LOG_FILE "messages.log" +#define MAX_LOG_SIZE (10 * 1024 * 1024) /* 10 MiB */ #define HOST_KEY_FILE "host_key" #define TNT_DEFAULT_STATE_DIR "." diff --git a/src/message.c b/src/message.c index fff9f1f..8e8667c 100644 --- a/src/message.c +++ b/src/message.c @@ -227,7 +227,16 @@ int message_save(const message_t *msg) { rc = -1; } + /* Rotate if the log exceeds MAX_LOG_SIZE */ + long file_size = ftell(fp); fclose(fp); + + if (file_size > MAX_LOG_SIZE) { + char backup_path[PATH_MAX + 4]; + snprintf(backup_path, sizeof(backup_path), "%s.1", log_path); + rename(log_path, backup_path); + } + pthread_mutex_unlock(&g_message_file_lock); return rc; } diff --git a/src/ssh_server.c b/src/ssh_server.c index 15f4fb6..95af633 100644 --- a/src/ssh_server.c +++ b/src/ssh_server.c @@ -895,7 +895,7 @@ static int parse_tail_count(const char *args, int *count) { return 0; } - if (strncmp(args, "-n", 2) == 0 && isspace((unsigned char)args[2])) { + if (strncmp(args, "-n", 2) == 0) { args += 2; while (*args && isspace((unsigned char)*args)) { args++; @@ -1170,21 +1170,28 @@ static void execute_command(client_t *client) { " w \n"); } else { bool found = false; + client_t *target = NULL; pthread_rwlock_rdlock(&g_room->lock); for (int i = 0; i < g_room->client_count; i++) { if (strcmp(g_room->clients[i]->username, target_name) == 0) { - char whisper[MAX_MESSAGE_LEN]; - snprintf(whisper, sizeof(whisper), - "\r\n\033[35m[whisper from %s]: %s\033[0m\r\n", - client->username, rest); - client_send(g_room->clients[i], whisper, strlen(whisper)); - g_room->clients[i]->redraw_pending = true; + target = g_room->clients[i]; + client_addref(target); found = true; break; } } pthread_rwlock_unlock(&g_room->lock); + if (target) { + char whisper[MAX_MESSAGE_LEN]; + snprintf(whisper, sizeof(whisper), + "\r\n\033[35m[whisper from %s]: %s\033[0m\r\n", + client->username, rest); + client_send(target, whisper, strlen(whisper)); + target->redraw_pending = true; + client_release(target); + } + if (found) { buffer_appendf(output, sizeof(output), &pos, "Whisper sent to %s\n", target_name); @@ -1648,6 +1655,12 @@ cleanup: release_ip_connection(client->client_ip); + /* Remove channel callbacks before releasing refs to prevent use-after-free + * if a callback fires between the two releases. */ + if (client->channel && client->channel_cb) { + ssh_remove_channel_callbacks(client->channel, client->channel_cb); + } + /* Release the callback reference (paired with addref before install_client_channel_callbacks) */ client_release(client);