From 338eb93bfc184d741561de11fc4da90b478d6e33 Mon Sep 17 00:00:00 2001 From: Michael Mikovsky <77305074+Astatin3@users.noreply.github.com> Date: Sat, 20 Dec 2025 18:19:08 -0700 Subject: [PATCH] Restructure some of the folder structure in unshell-server --- core-modules/client/Cargo.toml | 2 +- core-modules/client/build.sh | 8 +- core-modules/client/src/lib.rs | 2 + unshell-lib/src/announcement.rs | 2 - unshell-lib/src/config/mod.rs | 2 +- .../src/module/manager_announcement.rs | 11 +- unshell-payload/Cargo.toml | 14 +-- unshell-payload/build.sh | 15 ++- unshell-payload/src/main.rs | 67 ++++++----- unshell-server/src/{api/app.rs => api.rs} | 6 +- unshell-server/src/api/mod.rs | 20 ---- .../src/{api/auth.rs => auth/mod.rs} | 9 +- unshell-server/src/{api => auth}/structs.rs | 0 unshell-server/src/config/mod.rs | 5 - unshell-server/src/lib.rs | 22 +++- unshell-server/src/logger.rs | 105 +----------------- unshell-server/src/server/database.rs | 2 +- unshell-server/src/server/tree2.rs | 4 +- 18 files changed, 98 insertions(+), 198 deletions(-) rename unshell-server/src/{api/app.rs => api.rs} (97%) delete mode 100644 unshell-server/src/api/mod.rs rename unshell-server/src/{api/auth.rs => auth/mod.rs} (96%) rename unshell-server/src/{api => auth}/structs.rs (100%) diff --git a/core-modules/client/Cargo.toml b/core-modules/client/Cargo.toml index 8604d92..f0f940a 100644 --- a/core-modules/client/Cargo.toml +++ b/core-modules/client/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib"] [features] log_debug = ["unshell-lib/log_debug"] -obfuscate = ["unshell-lib/obfuscate"] +obfuscate = ["unshell-lib/obfuscate", "unshell-obfuscate/obfuscate"] [dependencies] unshell-lib = {path = "../../unshell-lib", default-featues = false} diff --git a/core-modules/client/build.sh b/core-modules/client/build.sh index a450f26..6c719cb 100755 --- a/core-modules/client/build.sh +++ b/core-modules/client/build.sh @@ -1,3 +1,5 @@ +cargo clean + OBFUSCATION_KEY=abc123abc \ cargo build --release @@ -10,8 +12,10 @@ declare -a headers=( ".shstrtab" #- Section header string table (only needed by tools like readelf) ".note.gnu.bu" ".note.gnu.build-id" # - Build ID note ".eh_frame" ".eh_frame_hdr" # Exception handling info (can break C++ exceptions if removed) - ".gnu.version" ".gnu.version_r" # Symbol versioning (may be needed for some shared libraries) - ".gnu.hash" # Hash table for symbol lookup optimization + ".gnu.version" + #".gnu.version_r" + # Symbol versioning (may be needed for some shared libraries) + #".gnu.hash" # Hash table for symbol lookup optimization ) # TODO: Implement FAKE section header comments and information diff --git a/core-modules/client/src/lib.rs b/core-modules/client/src/lib.rs index 2526bcf..0eb4ed5 100644 --- a/core-modules/client/src/lib.rs +++ b/core-modules/client/src/lib.rs @@ -15,6 +15,8 @@ use unshell_lib::{ use crate::client_runtime::ClientRuntime; +pub use unshell_lib::logger::setup_logger; + pub extern "C" fn test1() { warn!("Test1 called xxxxxxxxxxx"); } diff --git a/unshell-lib/src/announcement.rs b/unshell-lib/src/announcement.rs index d8d328f..bdfe954 100644 --- a/unshell-lib/src/announcement.rs +++ b/unshell-lib/src/announcement.rs @@ -1,7 +1,5 @@ use bincode::{Decode, Encode}; -use crate::config::RuntimeConfig; - /// Mostly temporary server message type #[derive(Clone, Debug, Encode, Decode)] pub enum Announcement { diff --git a/unshell-lib/src/config/mod.rs b/unshell-lib/src/config/mod.rs index 49f068d..b314960 100644 --- a/unshell-lib/src/config/mod.rs +++ b/unshell-lib/src/config/mod.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, fmt::Debug}; // use bincode::{Decode, Encode}; // use serde::{Deserialize, Serialize}; -use bincode::{Decode, Encode}; +// use bincode::{Decode, Encode}; use crate::{ModuleError, ModuleRuntime}; diff --git a/unshell-lib/src/module/manager_announcement.rs b/unshell-lib/src/module/manager_announcement.rs index f6a3820..b612916 100644 --- a/unshell-lib/src/module/manager_announcement.rs +++ b/unshell-lib/src/module/manager_announcement.rs @@ -5,12 +5,11 @@ impl Manager { match announcement { Announcement::TestAnnouncement(str) => { println!("Got test announcement: {}", str) - } - // Announcement::GetRuntimes => todo!(), - // Announcement::GetRuntimesAck(_) => todo!(), - // Announcement::StartRuntime(runtime_config) => todo!(), - // Announcement::StartRuntimeAck(_) => todo!(), - _ => {} + } // Announcement::GetRuntimes => todo!(), + // Announcement::GetRuntimesAck(_) => todo!(), + // Announcement::StartRuntime(runtime_config) => todo!(), + // Announcement::StartRuntimeAck(_) => todo!(), + // _ => {} } } } diff --git a/unshell-payload/Cargo.toml b/unshell-payload/Cargo.toml index 1a1d716..b4780d8 100644 --- a/unshell-payload/Cargo.toml +++ b/unshell-payload/Cargo.toml @@ -22,10 +22,10 @@ unshell-lib = {path = "../unshell-lib", default-features = false} unshell-obfuscate = {path = "../unshell-obfuscate"} [profile.release] -strip = true # Strip symbols from the binary -opt-level = "z" # Optimize for size -lto = true # Link tree optimization -codegen-units = 1 -panic = "abort" -debug = false # Remove debug -trim-paths="all" +# strip = true # Strip symbols from the binary +# opt-level = "z" # Optimize for size +# lto = true # Link tree optimization +# codegen-units = 1 +# panic = "abort" +# debug = false # Remove debug +# trim-paths="all" diff --git a/unshell-payload/build.sh b/unshell-payload/build.sh index 176567c..a3170f8 100755 --- a/unshell-payload/build.sh +++ b/unshell-payload/build.sh @@ -3,9 +3,12 @@ # cargo run --no-default-features $@ --release # $(ls ../*/target/release/*.so) OBFUSCATION_KEY=abc123abc \ -RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none" \ -cargo +nightly build \ - -Z build-std=std,panic_abort \ - -Z build-std-features="optimize_for_size" \ - $@ \ - --profile release + +cargo build $@ --profile release + +# RUSTFLAGS="-Zlocation-detail=none -Zfmt-debug=none" \ +# cargo +nightly build \ +# -Z build-std=std,panic_abort \ +# -Z build-std-features="optimize_for_size" \ +# $@ \ +# --profile release diff --git a/unshell-payload/src/main.rs b/unshell-payload/src/main.rs index bca8354..30f1b33 100644 --- a/unshell-payload/src/main.rs +++ b/unshell-payload/src/main.rs @@ -1,10 +1,10 @@ -use std::collections::HashMap; +use std::{any::Any, collections::HashMap, fs::File, io::Read}; use static_init::dynamic; use unshell_lib::{ ModuleError, config::{PayloadConfig, RuntimeConfig}, - module::Manager, + module::{Manager, Module}, }; use unshell_obfuscate::{obs, symbol}; @@ -34,36 +34,43 @@ fn main() { debug!("Initialized"); - match || -> Result<(), ModuleError> { - // let args = std::env::args(); - - // TEMPORARY, load the module paths from command line args. - // let mut modules = Vec::new(); - // for arg in args.skip(1) { - // debug!("Loading module: {}", arg); - - // let mut file = File::open(arg).map_err(|e| ModuleError::Error(e.to_string().into()))?; - // let mut buffer = Vec::new(); - // file.read_to_end(&mut buffer) - // .map_err(|e| ModuleError::Error(e.to_string().into()))?; - - // modules.push(Module::new_bytes(&buffer)?) - - // // modules.push(Module::new(&arg)?) - // } - - // let modules = vec - - // Run the manager, this is blocking. - let manager = Manager::start(&PAYLOAD_CONFIG, Vec::new()); - - Manager::join(manager); - - Ok(()) - }() { + match run() { Ok(_) => {} Err(e) => { - debug!("ERROR! {:?}", e); + error!("ERROR! '{:?}'", e); } } } + +fn run() -> Result<(), Box> { + let args = std::env::args(); + + // TEMPORARY, load the module paths from command line args. + let mut modules = Vec::new(); + for arg in args.skip(1) { + // debug!("Loading module: {}", arg); + + // let mut file = File::open(arg).map_err(|e| ModuleError::Error(e.to_string().into()))?; + // let mut buffer = Vec::new(); + // file.read_to_end(&mut buffer) + // .map_err(|e| ModuleError::Error(e.to_string().into()))?; + + debug!("Initializing module: {}", arg); + let module = Module::new(&arg)?; + + modules.push(module); + + // modules.push(Module::new(&arg)?) + } + + // let modules = vec + + debug!("Starting manager..."); + + // Run the manager, this is blocking. + let manager = Manager::start(&PAYLOAD_CONFIG, modules); + + Manager::join(manager); + + Ok(()) +} diff --git a/unshell-server/src/api/app.rs b/unshell-server/src/api.rs similarity index 97% rename from unshell-server/src/api/app.rs rename to unshell-server/src/api.rs index 6162ff8..4bd4534 100644 --- a/unshell-server/src/api/app.rs +++ b/unshell-server/src/api.rs @@ -9,11 +9,7 @@ use unshell_lib::{debug, info}; // axum_extra:: -use crate::{ - api::{auth, structs::CurrentUser}, - logger::Logger, - server::Server, -}; +use crate::{auth, auth::structs::CurrentUser, logger::Logger, server::Server}; macro_rules! route_get { ($router:expr, $path:expr, $func:expr) => {{ diff --git a/unshell-server/src/api/mod.rs b/unshell-server/src/api/mod.rs deleted file mode 100644 index 3243df0..0000000 --- a/unshell-server/src/api/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -use chrono::Duration; -use jsonwebtoken::{DecodingKey, EncodingKey}; -use static_init::dynamic; -extern crate unshell_lib; - -pub mod app; -mod auth; -mod structs; - -pub use structs::CurrentUser; - -static EXPIRE_DURATION: Duration = Duration::hours(12); - -#[dynamic] -static JWT_SECRET: String = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); - -#[dynamic] -static JWT_ENCODING_KEY: EncodingKey = EncodingKey::from_secret(JWT_SECRET.as_bytes()); -#[dynamic] -static JWT_DECODING_KEY: DecodingKey = DecodingKey::from_secret(JWT_SECRET.as_bytes()); diff --git a/unshell-server/src/api/auth.rs b/unshell-server/src/auth/mod.rs similarity index 96% rename from unshell-server/src/api/auth.rs rename to unshell-server/src/auth/mod.rs index c7dba3b..4d9c19a 100644 --- a/unshell-server/src/api/auth.rs +++ b/unshell-server/src/auth/mod.rs @@ -1,3 +1,5 @@ +pub mod structs; + use axum::{ body::Body, extract::{Json, Request}, @@ -10,10 +12,9 @@ use jsonwebtoken::{Header, TokenData, Validation, decode, encode}; use serde_json::{Value, json}; use unshell_lib::{debug, info}; -use crate::api::{ - EXPIRE_DURATION, JWT_DECODING_KEY, JWT_ENCODING_KEY, - structs::{AuthError, Cliams, CurrentUser, SignInData}, -}; +use crate::{EXPIRE_DURATION, JWT_DECODING_KEY, JWT_ENCODING_KEY}; + +use structs::{AuthError, Cliams, CurrentUser, SignInData}; pub fn hash_password(password: &str) -> Result { let hash = hash(password, DEFAULT_COST)?; diff --git a/unshell-server/src/api/structs.rs b/unshell-server/src/auth/structs.rs similarity index 100% rename from unshell-server/src/api/structs.rs rename to unshell-server/src/auth/structs.rs diff --git a/unshell-server/src/config/mod.rs b/unshell-server/src/config/mod.rs index 8fd0470..af92e9c 100644 --- a/unshell-server/src/config/mod.rs +++ b/unshell-server/src/config/mod.rs @@ -1,8 +1,4 @@ mod blob; -// pub mod interface; - -pub use blob::Blob; -// pub use interface::InterfaceWrapper; use std::{ collections::HashMap, @@ -27,7 +23,6 @@ struct ComponentMetadata { // Other components that can be pointed to by this component #[serde(default)] child_components: Vec, - // config: Option>, } #[derive(Default, Debug, Clone, serde::Deserialize, serde::Serialize)] diff --git a/unshell-server/src/lib.rs b/unshell-server/src/lib.rs index d3bd7e4..30c4a16 100644 --- a/unshell-server/src/lib.rs +++ b/unshell-server/src/lib.rs @@ -1,15 +1,14 @@ -// #![macro_use] - mod api; +mod auth; mod config; pub mod logger; mod modules; mod server; -pub use api::app::start_api; - pub use server::Server; +use static_init::dynamic; + #[static_init::dynamic] pub static DATABASE_TREES: Vec<&'static str> = vec!["users"]; @@ -24,3 +23,18 @@ pub static SERVER_CONFIG: unshell_lib::config::PayloadConfig = unshell_lib::conf components: Vec::new(), runtime_config: Vec::new(), }; + +// Constants for server config +pub use api::start_api; +use chrono::Duration; +use jsonwebtoken::{DecodingKey, EncodingKey}; + +static EXPIRE_DURATION: Duration = Duration::hours(12); + +#[dynamic] +static JWT_SECRET: String = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); + +#[dynamic] +static JWT_ENCODING_KEY: EncodingKey = EncodingKey::from_secret(JWT_SECRET.as_bytes()); +#[dynamic] +static JWT_DECODING_KEY: DecodingKey = DecodingKey::from_secret(JWT_SECRET.as_bytes()); diff --git a/unshell-server/src/logger.rs b/unshell-server/src/logger.rs index 4037d59..81836d1 100644 --- a/unshell-server/src/logger.rs +++ b/unshell-server/src/logger.rs @@ -1,42 +1,33 @@ use axum::extract::{Path, State}; use axum::{Extension, Json}; use chrono::Local; -use unshell_lib::debug; -// use lazy_static::lazy_static; use std::fs::{self, File, OpenOptions}; use std::io::{BufRead, BufReader, Write}; use std::path::PathBuf; +use unshell_lib::debug; use crate::Server; -use crate::api::CurrentUser; +use crate::auth::structs::CurrentUser; -// --- Constants --- -/// The directory where log files will be stored. const LOG_DIR: &str = "logs"; -/// The maximum number of logs to return in one call to `poll_logs`. const LOG_COUNT: usize = 100; /// The full path to the log file. /// Initialized once based on the startup time. #[static_init::dynamic] static LOG_FILE_PATH: PathBuf = { - // 1. Determine the log directory path let log_dir_path = PathBuf::from(LOG_DIR); - // 2. Create the log directory if it does not exist if let Err(e) = fs::create_dir_all(&log_dir_path) { eprintln!("Error creating log directory {:?}: {}", log_dir_path, e); - // Panic or handle error as appropriate for your application's needs - // Panicking here to ensure the logger can't be used if the path is invalid/unwritable + panic!("Failed to initialize log directory."); } - // 3. Generate the unique filename based on the current local time let now = Local::now(); let filename = format!("{}.log", now.format("%Y%m%d_%H%M%S")); - // 4. Combine the directory path and the filename log_dir_path.join(filename) }; @@ -44,19 +35,9 @@ static LOG_FILE_PATH: PathBuf = { pub struct Logger; impl Logger { - /// Writes a log entry to the current log file. - /// - /// The log entry includes a timestamp and the provided message. - /// - /// # Arguments - /// - /// * `message` - The string content of the log entry. pub fn log(message: String) { - // 1. Format the complete log line with timestamp let log_line = format!("{}\n", message); - // 2. Open the file in append mode, creating it if it doesn't exist. - // The file path is guaranteed to be valid due to the `lazy_static` initialization. match OpenOptions::new() .create(true) .append(true) @@ -74,65 +55,38 @@ impl Logger { } } - /// Reads and returns the most recent logs from the file. - /// - /// The total number of logs returned is limited by `LOG_COUNT`. - /// The `offset` determines how far back in history to start reading. - /// - /// # Arguments - /// - /// * `offset` - The number of most recent logs to skip. - /// - /// # Returns - /// - /// A `Vec` containing the logs, or an empty `Vec` on failure. pub fn poll_logs(offset: usize) -> Vec { - // Array of String is not a idiomatic return type in Rust, - // so we return a Vector, which serves the same purpose. - // The size constraint (LOG_COUNT) is applied internally. match File::open(&*LOG_FILE_PATH) { Ok(file) => { let reader = BufReader::new(file); - - // Collect all lines into a vector let lines: Vec = reader .lines() .filter_map(|line| line.ok()) // Ignore lines that fail to read .collect(); - // Determine the starting index for the slice (from the end of the vector) - // This logic correctly handles the offset and LOG_COUNT limits. - let total_lines = lines.len(); if offset >= total_lines { - // Offset is past the beginning of the file, return nothing return Vec::new(); } - // Start from the end, minus the offset, minus the number of logs to read. - // We use checked subtraction to prevent panic if it would result in a negative number. let start_index = total_lines .checked_sub(offset) .and_then(|i| i.checked_sub(LOG_COUNT)) - .unwrap_or(0); // If either subtraction fails, start from 0 + .unwrap_or(0); - // End index is determined by subtracting the offset from the total length. let end_index = total_lines.checked_sub(offset).unwrap_or(total_lines); - // Get the slice of the lines let slice = &lines[start_index..end_index]; slice.iter().cloned().collect() } Err(e) => { - // Return an empty vector and print an error message if the file cannot be read eprintln!("Error reading log file {:?}: {}", *LOG_FILE_PATH, e); Vec::new() } } } - // Route the "keys" api for each tree pub async fn poll_logs_api( State(_): State, Extension(_): Extension, @@ -144,54 +98,3 @@ impl Logger { Json(serde_json::to_value(result).unwrap()) } } - -// --- Example Usage --- - -// fn main() { -// // Write some logs -// Logger::log("Application started.".to_string()); -// Logger::log("Configuration loaded.".to_string()); - -// for i in 1..=20 { -// Logger::log(format!("Processing request #{}", i)); -// } - -// Logger::log("Task completed.".to_string()); - -// // --- Test 1: Get the 10 most recent logs (offset 0) --- -// println!("--- Most Recent Logs (LOG_COUNT={}) ---", LOG_COUNT); -// let recent_logs = Logger::poll_logs(0); -// for log in &recent_logs { -// println!("{}", log); -// } - -// // The output should be: -// // [timestamp] Task completed. -// // [timestamp] Processing request #20 -// // [timestamp] Processing request #19 -// // ... -// // [timestamp] Processing request #12 - -// println!( -// "\n--- Logs from the past (Offset 15, LOG_COUNT={}) ---", -// LOG_COUNT -// ); -// // --- Test 2: Skip the 15 most recent logs, then get the next 10 --- -// let historical_logs = Logger::poll_logs(15); -// for log in &historical_logs { -// println!("{}", log); -// } - -// // The output should be: -// // [timestamp] Processing request #6 -// // [timestamp] Processing request #5 -// // ... -// // [timestamp] Application started. - -// println!("\n--- Testing a high offset (Offset 100) ---"); -// // --- Test 3: Test an offset that goes beyond the log file length --- -// let empty_logs = Logger::poll_logs(100); -// if empty_logs.is_empty() { -// println!("Correctly returned empty set for high offset."); -// } -// } diff --git a/unshell-server/src/server/database.rs b/unshell-server/src/server/database.rs index 9dee922..441fe24 100644 --- a/unshell-server/src/server/database.rs +++ b/unshell-server/src/server/database.rs @@ -8,7 +8,7 @@ use serde_json::Value; use sled::Tree; use unshell_lib::{debug, error}; -use crate::{api::CurrentUser, server::Server}; +use crate::{auth::structs::CurrentUser, server::Server}; impl Server { fn get_tree(&self, tree_name: &str) -> Result { diff --git a/unshell-server/src/server/tree2.rs b/unshell-server/src/server/tree2.rs index 46279dd..f20d7e7 100644 --- a/unshell-server/src/server/tree2.rs +++ b/unshell-server/src/server/tree2.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use axum::{ Extension, Json, extract::{Path, State}, @@ -8,7 +6,7 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use unshell_lib::debug; -use crate::{Server, api::CurrentUser}; +use crate::{Server, auth::structs::CurrentUser}; pub trait Tree { fn is_folder() -> bool {