From 914eb84321fabe318d9824478066ea2519143b3b Mon Sep 17 00:00:00 2001 From: Dhanuka Warusadura Date: Thu, 24 Oct 2024 13:06:46 +0530 Subject: [PATCH] server: Load and dispatch login/default collection This change loads and dispatches the login/default collection/keyring into the object tree. This change also adds, --login command line option to oo7-daemon. -l, --login option will read a password from stdin, and use it to unlock the login keyring. Note: currently -l option will only load the login keyring and not perform anything related to unlocking the keyring. Signed-off-by: Dhanuka Warusadura --- Cargo.lock | 2 ++ server/Cargo.toml | 2 ++ server/src/error.rs | 12 +++++++++++ server/src/main.rs | 28 +++++++++++++++++++++++- server/src/service.rs | 50 +++++++++++++++++++++++++++---------------- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57f3d1c11..f03cd9188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1086,7 +1086,9 @@ dependencies = [ name = "oo7-daemon" version = "0.3.0" dependencies = [ + "clap", "oo7", + "rpassword", "serde", "tokio", "tracing", diff --git a/server/Cargo.toml b/server/Cargo.toml index 4afd4c176..57dd34da3 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -9,7 +9,9 @@ rust-version.workspace = true version.workspace = true [dependencies] +clap.workspace = true oo7 = { workspace = true, features = ["unstable"] } +rpassword = "7.3" serde.workspace = true tokio = { workspace = true, features = ["full"] } tracing = "0.1" diff --git a/server/src/error.rs b/server/src/error.rs index 71c07f7bd..38a922dee 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -6,6 +6,10 @@ pub enum Error { Portal(oo7::portal::Error), // Zbus error Zbus(zbus::Error), + // IO error + IO(std::io::Error), + // Empty password error + EmptyPassword, } impl From for Error { @@ -20,11 +24,19 @@ impl From for Error { } } +impl From for Error { + fn from(err: std::io::Error) -> Self { + Self::IO(err) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Portal(err) => write!(f, "Portal error {err}"), Self::Zbus(err) => write!(f, "Zbus error {err}"), + Self::IO(err) => write!(f, "IO error {err}"), + Self::EmptyPassword => write!(f, "Login password can't be empty"), } } } diff --git a/server/src/main.rs b/server/src/main.rs index 2e957c10e..8d2307303 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -6,18 +6,44 @@ mod service; mod service_manager; mod session; +use clap::Parser; +use oo7::portal::Secret; use service::Service; use crate::error::Error; const BINARY_NAME: &str = env!("CARGO_BIN_NAME"); +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Args { + #[arg( + short = 'l', + long, + default_value_t = false, + help = "Read a password from stdin, and use it to unlock the login keyring." + )] + login: bool, +} + #[tokio::main] async fn main() -> Result<(), Error> { tracing_subscriber::fmt::init(); + let args = Args::parse(); + let mut secret: Option = None; + + if args.login { + let password = rpassword::prompt_password("Enter the login password: ")?; + if password.is_empty() { + tracing::error!("Login password can't be empty."); + return Err(Error::EmptyPassword); + } + secret = Some(Secret::from(password.into_bytes())); + } + tracing::info!("Starting {}", BINARY_NAME); - Service::run().await?; + Service::run(secret).await?; std::future::pending::<()>().await; diff --git a/server/src/service.rs b/server/src/service.rs index 0cc01ba13..846a881e5 100644 --- a/server/src/service.rs +++ b/server/src/service.rs @@ -20,10 +20,10 @@ use crate::{ collection::Collection, error::Error, service_manager::ServiceManager, session::Session, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Service { // Properties - collections: Mutex>, + collections: Arc>>, // Other attributes manager: Arc>, #[allow(unused)] @@ -128,7 +128,7 @@ impl Service { } impl Service { - pub async fn run() -> Result<(), Error> { + pub async fn run(secret: Option) -> Result<(), Error> { let connection = zbus::connection::Builder::session()? .name(oo7::dbus::api::Service::DESTINATION.as_deref().unwrap())? .build() @@ -140,29 +140,41 @@ impl Service { connection: connection.clone(), }; - // Load session collection - let session = service.fetch_session().await?; - - // Dispatch Service object_server - .at(oo7::dbus::api::Service::PATH.as_deref().unwrap(), service) + .at( + oo7::dbus::api::Service::PATH.as_deref().unwrap(), + service.clone(), + ) .await?; - // Dispatch session collection - object_server.at(session.path().clone(), session).await?; - Ok(()) - } + let mut collections = service.collections.lock().await; + + if let Some(secret) = secret { + let collection = Collection::new( + "login", + "default", + Arc::clone(&service.manager), + Arc::new(Keyring::open("login", secret).await?), + ); + collections.push(collection.path().clone()); + object_server + .at(collection.path().clone(), collection) + .await?; + } - pub async fn fetch_session(&self) -> Result { - let secret = Secret::random(); - let session = Collection::new( + let collection = Collection::new( "session", "session", - Arc::clone(&self.manager), - Arc::new(Keyring::temporary(secret).await?), + Arc::clone(&service.manager), + Arc::new(Keyring::temporary(Secret::random()).await?), ); - self.collections.lock().await.push(session.path().clone()); + collections.push(collection.path().clone()); + object_server + .at(collection.path().clone(), collection) + .await?; - Ok(session) + drop(collections); + + Ok(()) } }