From 368570592f6f2f31631f20c3afd2c1f373a7ba61 Mon Sep 17 00:00:00 2001 From: veeso Date: Sat, 22 Mar 2025 13:44:02 +0100 Subject: [PATCH] feat(cli): added `--wno-keyring` flag to disable keyring closes #308 --- CHANGELOG.md | 1 + Cargo.lock | 3 ++ Cargo.toml | 9 ++-- site/html/get-started.html | 2 +- src/activity_manager.rs | 31 ++++++----- src/cli.rs | 5 ++ src/main.rs | 12 ++++- src/system/bookmarks_client.rs | 95 +++++++++++++++++----------------- src/system/keys/mod.rs | 6 --- 9 files changed, 91 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33d9436..01b0a4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Released on ?? +- [issue 308](https://github.com/veeso/termscp/issues/308): added `--wno-keyring` flag to disable keyring - [issue 316](https://github.com/veeso/termscp/issues/316): Local directory path is not switching to what's specified in the bookmark. Now the local directory path is correctly set following this hierarchy: 1. Local directory path specified for the host bridge 2. Local directory path specified in the bookmark diff --git a/Cargo.lock b/Cargo.lock index c80cac6..4bedecb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1125,6 +1125,7 @@ dependencies = [ "futures-util", "num", "once_cell", + "openssl", "rand 0.8.5", ] @@ -2334,6 +2335,7 @@ dependencies = [ "byteorder", "dbus-secret-service", "log", + "openssl", "security-framework 2.11.1", "security-framework 3.2.0", "windows-sys 0.59.0", @@ -2472,6 +2474,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" dependencies = [ + "cc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index baa6350..d0e5463 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,10 +41,11 @@ dirs = "^6" edit = "^0.1" filetime = "^0.2" hostname = "^0.4" -keyring = { version = "^3", optional = true, features = [ +keyring = { version = "^3", features = [ "apple-native", "windows-native", "sync-secret-service", + "vendored", ] } lazy-regex = "^3" lazy_static = "^1" @@ -92,11 +93,11 @@ vergen-git2 = { version = "1", features = ["build", "cargo", "rustc", "si"] } [features] -default = ["smb", "with-keyring"] +default = ["smb", "keyring"] github-actions = [] isolated-tests = [] -smb = ["remotefs-smb"] -with-keyring = ["keyring"] +smb = ["dep:remotefs-smb"] +keyring = [] [target."cfg(not(target_os = \"macos\"))".dependencies] remotefs-smb = { version = "^0.3", optional = true } diff --git a/site/html/get-started.html b/site/html/get-started.html index fd74621..b66bb23 100644 --- a/site/html/get-started.html +++ b/site/html/get-started.html @@ -157,7 +157,7 @@ sudo dpkg -i termscp.deb
cargo install --locked --no-default-features --features smb termscp

-
cargo install --locked --no-default-features --features with-keyring termscp
+
cargo install --locked --no-default-features --features keyring termscp
diff --git a/src/activity_manager.rs b/src/activity_manager.rs index c48852b..faf617c 100644 --- a/src/activity_manager.rs +++ b/src/activity_manager.rs @@ -50,7 +50,7 @@ pub struct ActivityManager { impl ActivityManager { /// Initializes a new Activity Manager - pub fn new(ticks: Duration) -> Result { + pub fn new(ticks: Duration, keyring: bool) -> Result { // Prepare Context // Initialize configuration client let (config_client, error_config): (ConfigClient, Option) = @@ -61,7 +61,7 @@ impl ActivityManager { (ConfigClient::degraded(), Some(err)) } }; - let (bookmarks_client, error_bookmark) = match Self::init_bookmarks_client() { + let (bookmarks_client, error_bookmark) = match Self::init_bookmarks_client(keyring) { Ok(cli) => (cli, None), Err(err) => (None, Some(err)), }; @@ -447,7 +447,7 @@ impl ActivityManager { // -- misc - fn init_bookmarks_client() -> Result, String> { + fn init_bookmarks_client(keyring: bool) -> Result, String> { // Get config dir match environment::init_config_dir() { Ok(path) => { @@ -456,16 +456,21 @@ impl ActivityManager { let bookmarks_file: PathBuf = environment::get_bookmarks_paths(config_dir_path.as_path()); // Initialize client - BookmarksClient::new(bookmarks_file.as_path(), config_dir_path.as_path(), 16) - .map(Option::Some) - .map_err(|e| { - format!( - "Could not initialize bookmarks (at \"{}\", \"{}\"): {}", - bookmarks_file.display(), - config_dir_path.display(), - e - ) - }) + BookmarksClient::new( + bookmarks_file.as_path(), + config_dir_path.as_path(), + 16, + keyring, + ) + .map(Option::Some) + .map_err(|e| { + format!( + "Could not initialize bookmarks (at \"{}\", \"{}\"): {}", + bookmarks_file.display(), + config_dir_path.display(), + e + ) + }) } else { Ok(None) } diff --git a/src/cli.rs b/src/cli.rs index 0aef632..840a18b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -60,6 +60,9 @@ pub struct Args { /// print version #[argh(switch, short = 'v')] pub version: bool, + /// disable keyring support + #[argh(switch)] + pub wno_keyring: bool, // -- positional #[argh(positional, description = "address1 address2 local-wrkdir")] pub positional: Vec, @@ -94,6 +97,7 @@ pub struct LoadThemeArgs { pub struct RunOpts { pub remote: RemoteArgs, + pub keyring: bool, pub ticks: Duration, pub log_level: LogLevel, pub task: Task, @@ -127,6 +131,7 @@ impl Default for RunOpts { Self { remote: RemoteArgs::default(), ticks: Duration::from_millis(10), + keyring: true, log_level: LogLevel::Info, task: Task::Activity(NextActivity::Authentication), } diff --git a/src/main.rs b/src/main.rs index a7e9e70..77c08f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,6 +76,7 @@ fn parse_args(args: Args) -> Result { Some(ArgsSubcommands::Config(_)) => RunOpts::config(), None => { let mut run_opts: RunOpts = RunOpts::default(); + // Version if args.version { run_opts.task = Task::Version; @@ -87,6 +88,10 @@ fn parse_args(args: Args) -> Result { } else if args.quiet { run_opts.log_level = LogLevel::Off; } + // set keyring + if args.wno_keyring { + run_opts.keyring = false; + } // Match ticks run_opts.ticks = Duration::from_millis(args.ticks); // Remote argument @@ -124,7 +129,9 @@ fn run(run_opts: RunOpts) -> MainResult<()> { match run_opts.task { Task::ImportTheme(theme) => run_import_theme(&theme), Task::InstallUpdate => run_install_update(), - Task::Activity(activity) => run_activity(activity, run_opts.ticks, run_opts.remote), + Task::Activity(activity) => { + run_activity(activity, run_opts.ticks, run_opts.remote, run_opts.keyring) + } Task::Version => print_version(), } } @@ -168,9 +175,10 @@ fn run_activity( activity: NextActivity, ticks: Duration, remote_args: RemoteArgs, + keyring: bool, ) -> MainResult<()> { // Create activity manager (and context too) - let mut manager: ActivityManager = match ActivityManager::new(ticks) { + let mut manager: ActivityManager = match ActivityManager::new(ticks, keyring) { Ok(m) => m, Err(err) => { eprintln!("Could not start activity manager: {err}"); diff --git a/src/system/bookmarks_client.rs b/src/system/bookmarks_client.rs index 0f2ad50..cdd2eea 100644 --- a/src/system/bookmarks_client.rs +++ b/src/system/bookmarks_client.rs @@ -10,7 +10,6 @@ use std::string::ToString; use std::time::SystemTime; use super::keys::filestorage::FileStorage; -#[cfg(feature = "with-keyring")] use super::keys::keyringstorage::KeyringStorage; use super::keys::{KeyStorage, KeyStorageError}; // Local @@ -39,42 +38,13 @@ impl BookmarksClient { bookmarks_file: &Path, storage_path: &Path, recents_size: usize, + keyring: bool, ) -> Result { // Create default hosts let default_hosts: UserHosts = UserHosts::default(); debug!("Setting up bookmarks client..."); - // Make a key storage (with-keyring) - #[cfg(feature = "with-keyring")] - let (key_storage, service_id): (Box, &str) = { - debug!("Setting up KeyStorage"); - let username: String = whoami::username(); - let storage: KeyringStorage = KeyringStorage::new(username.as_str()); - // Check if keyring storage is supported - #[cfg(not(test))] - let app_name: &str = "termscp"; - #[cfg(test)] // NOTE: when running test, add -test - let app_name: &str = "termscp-test"; - match storage.is_supported() { - true => { - debug!("Using KeyringStorage"); - (Box::new(storage), app_name) - } - false => { - warn!("KeyringStorage is not supported; using FileStorage"); - (Box::new(FileStorage::new(storage_path)), "bookmarks") - } - } - }; - // Make a key storage (wno-keyring) - #[cfg(not(feature = "with-keyring"))] - let (key_storage, service_id): (Box, &str) = { - #[cfg(not(test))] - let app_name: &str = "bookmarks"; - #[cfg(test)] // NOTE: when running test, add -test - let app_name: &str = "bookmarks-test"; - debug!("Using FileStorage"); - (Box::new(FileStorage::new(storage_path)), app_name) - }; + // Get key storage + let (key_storage, service_id) = Self::keyring(storage_path, keyring); // Load key let key: String = match key_storage.get_key(service_id) { Ok(k) => { @@ -130,6 +100,37 @@ impl BookmarksClient { Ok(client) } + /// Get the key storage + fn keyring(storage_path: &Path, keyring: bool) -> (Box, &'static str) { + if keyring && cfg!(feature = "keyring") { + debug!("Setting up KeyStorage"); + let username: String = whoami::username(); + let storage: KeyringStorage = KeyringStorage::new(username.as_str()); + // Check if keyring storage is supported + #[cfg(not(test))] + let app_name: &str = "termscp"; + #[cfg(test)] // NOTE: when running test, add -test + let app_name: &str = "termscp-test"; + match storage.is_supported() { + true => { + debug!("Using KeyringStorage"); + (Box::new(storage), app_name) + } + false => { + warn!("KeyringStorage is not supported; using FileStorage"); + (Box::new(FileStorage::new(storage_path)), "bookmarks") + } + } + } else { + #[cfg(not(test))] + let app_name: &str = "bookmarks"; + #[cfg(test)] // NOTE: when running test, add -test + let app_name: &str = "bookmarks-test"; + debug!("Using FileStorage"); + (Box::new(FileStorage::new(storage_path)), app_name) + } + } + /// Iterate over bookmarks keys pub fn iter_bookmarks(&self) -> impl Iterator + '_ { Box::new(self.hosts.bookmarks.keys()) @@ -389,7 +390,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Verify client assert_eq!(client.hosts.bookmarks.len(), 0); assert_eq!(client.hosts.recents.len(), 0); @@ -405,7 +406,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add some bookmarks client.add_bookmark( "raspberry", @@ -430,7 +431,7 @@ mod tests { let key: String = client.key.clone(); // Re-initialize a client let client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Verify it loaded parameters correctly assert_eq!(client.key, key); let bookmark = ftparams_to_tup(client.get_bookmark("raspberry").unwrap()); @@ -453,7 +454,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add s3 bookmark client.add_bookmark("my-bucket", make_s3_ftparams(), true); // Verify bookmark @@ -473,7 +474,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add s3 bookmark client.add_bookmark("my-bucket", make_s3_ftparams(), false); // Verify bookmark @@ -494,7 +495,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add s3 bookmark client.add_recent(make_s3_ftparams()); // Verify bookmark @@ -517,7 +518,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_bookmark( "raspberry", @@ -568,7 +569,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_bookmark( "", @@ -589,7 +590,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_bookmark( "raspberry", @@ -617,7 +618,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_recent(make_generic_ftparams( FileTransferProtocol::Sftp, @@ -653,7 +654,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_recent(make_generic_ftparams( FileTransferProtocol::Sftp, @@ -680,7 +681,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 2).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 2, true).unwrap(); // Add recent, wait 1 second for each one (cause the name depends on time) // 1 client.add_recent(make_generic_ftparams( @@ -748,7 +749,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); // Add bookmark client.add_bookmark( "", @@ -769,7 +770,7 @@ mod tests { let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path()); // Initialize a new bookmarks client let mut client: BookmarksClient = - BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16).unwrap(); + BookmarksClient::new(cfg_path.as_path(), key_path.as_path(), 16, true).unwrap(); client.key = "MYSUPERSECRETKEY".to_string(); assert_eq!( client.decrypt_str("z4Z6LpcpYqBW4+bkIok+5A==").ok().unwrap(), diff --git a/src/system/keys/mod.rs b/src/system/keys/mod.rs index 77e0686..57874dd 100644 --- a/src/system/keys/mod.rs +++ b/src/system/keys/mod.rs @@ -4,29 +4,24 @@ // Storages pub mod filestorage; -#[cfg(feature = "with-keyring")] pub mod keyringstorage; // ext -#[cfg(feature = "with-keyring")] use keyring::Error as KeyringError; use thiserror::Error; /// defines the error type for the `KeyStorage` #[derive(Debug, Error)] pub enum KeyStorageError { - #[cfg(feature = "with-keyring")] #[error("Key has a bad syntax")] BadSytax, #[error("Provider service error")] ProviderError, #[error("No such key")] NoSuchKey, - #[cfg(feature = "with-keyring")] #[error("keyring error: {0}")] KeyringError(KeyringError), } -#[cfg(feature = "with-keyring")] impl From for KeyStorageError { fn from(e: KeyringError) -> Self { Self::KeyringError(e) @@ -58,7 +53,6 @@ mod tests { #[test] fn test_system_keys_mod_errors() { - #[cfg(feature = "with-keyring")] assert_eq!( KeyStorageError::BadSytax.to_string(), String::from("Key has a bad syntax")