From 95da8880e311d4932fd50febab6ef093e5915051 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 6 Apr 2020 22:40:00 -0400 Subject: start moving to an actual cli app --- src/agent.rs | 17 ++++++++ src/bin/agent.rs | 32 ++++---------- src/bin/rbw.rs | 125 +++++++++++++++++++++++++++++++++++++++---------------- src/lib.rs | 1 + 4 files changed, 116 insertions(+), 59 deletions(-) create mode 100644 src/agent.rs (limited to 'src') diff --git a/src/agent.rs b/src/agent.rs new file mode 100644 index 0000000..4b9ac20 --- /dev/null +++ b/src/agent.rs @@ -0,0 +1,17 @@ +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub struct Message { + pub tty: Option, + pub action: Action, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +#[serde(tag = "type")] +pub enum Action { + Login, + Unlock, + Sync, + Decrypt { cipherstring: String }, + // add + // update + // remove +} diff --git a/src/bin/agent.rs b/src/bin/agent.rs index 6b73f56..50b13a1 100644 --- a/src/bin/agent.rs +++ b/src/bin/agent.rs @@ -3,24 +3,6 @@ use std::io::Write as _; use tokio::io::AsyncBufReadExt as _; use tokio::stream::StreamExt as _; -#[derive(serde::Deserialize, Debug)] -struct Message { - tty: Option, - action: Action, -} - -#[derive(serde::Deserialize, Debug)] -#[serde(tag = "type")] -enum Action { - Login, - Unlock, - Sync, - Decrypt { cipherstring: String }, - // add - // update - // remove -} - fn make_pidfile() -> std::fs::File { let runtime_dir = rbw::dirs::runtime_dir(); std::fs::create_dir_all(&runtime_dir).unwrap(); @@ -135,12 +117,16 @@ async fn handle_sock( let mut lines = buf.lines(); while let Some(line) = lines.next().await { let line = line.unwrap(); - let msg: Message = serde_json::from_str(&line).unwrap(); + let msg: rbw::agent::Message = serde_json::from_str(&line).unwrap(); match msg.action { - Action::Login => login(state.clone(), msg.tty.as_deref()).await, - Action::Unlock => unlock(state.clone(), msg.tty.as_deref()).await, - Action::Sync => sync(state.clone()).await, - Action::Decrypt { cipherstring } => { + rbw::agent::Action::Login => { + login(state.clone(), msg.tty.as_deref()).await + } + rbw::agent::Action::Unlock => { + unlock(state.clone(), msg.tty.as_deref()).await + } + rbw::agent::Action::Sync => sync(state.clone()).await, + rbw::agent::Action::Decrypt { cipherstring } => { decrypt(state.clone(), &cipherstring).await } } diff --git a/src/bin/rbw.rs b/src/bin/rbw.rs index 6c9bb11..910350b 100644 --- a/src/bin/rbw.rs +++ b/src/bin/rbw.rs @@ -1,44 +1,97 @@ -extern crate rbw; +use std::io::Write as _; -fn main() { - let client = - rbw::api::Client::new_self_hosted("https://bitwarden.tozt.net"); +fn send(msg: &rbw::agent::Message) { + let mut sock = std::os::unix::net::UnixStream::connect( + rbw::dirs::runtime_dir().join("socket"), + ) + .unwrap(); + sock.write_all(serde_json::to_string(msg).unwrap().as_bytes()) + .unwrap(); +} - let email = rprompt::prompt_reply_stderr("Email: ").unwrap(); - let password = rpassword::prompt_password_stderr("Password: ").unwrap(); +fn login() { + send(&rbw::agent::Message { + tty: std::env::var("TTY").ok(), + action: rbw::agent::Action::Login, + }) +} - let iterations = client.prelogin(&email).unwrap(); - let identity = - rbw::identity::Identity::new(&email, &password, iterations).unwrap(); +fn unlock() { + send(&rbw::agent::Message { + tty: std::env::var("TTY").ok(), + action: rbw::agent::Action::Unlock, + }) +} - let (access_token, _refresh_token, protected_key) = client - .login(&identity.email, &identity.master_password_hash) - .unwrap(); +fn sync() { + send(&rbw::agent::Message { + tty: std::env::var("TTY").ok(), + action: rbw::agent::Action::Sync, + }) +} - let protected_key = - rbw::cipherstring::CipherString::new(&protected_key).unwrap(); - let master_key = protected_key - .decrypt(&identity.enc_key, &identity.mac_key) - .unwrap(); +fn list() { + todo!() +} + +fn get() { + todo!() +} + +fn add() { + todo!() +} + +fn generate() { + todo!() +} + +fn edit() { + todo!() +} + +fn remove() { + todo!() +} + +fn lock() { + todo!() +} + +fn purge() { + todo!() +} + +fn main() { + let matches = clap::App::new("rbw") + .about("unofficial bitwarden cli") + .author(clap::crate_authors!()) + .version(clap::crate_version!()) + .subcommand(clap::SubCommand::with_name("login")) + .subcommand(clap::SubCommand::with_name("unlock")) + .subcommand(clap::SubCommand::with_name("sync")) + .subcommand(clap::SubCommand::with_name("list")) + .subcommand(clap::SubCommand::with_name("get")) + .subcommand(clap::SubCommand::with_name("add")) + .subcommand(clap::SubCommand::with_name("generate")) + .subcommand(clap::SubCommand::with_name("edit")) + .subcommand(clap::SubCommand::with_name("remove")) + .subcommand(clap::SubCommand::with_name("lock")) + .subcommand(clap::SubCommand::with_name("purge")) + .get_matches(); - let enc_key = &master_key[0..32]; - let mac_key = &master_key[32..64]; - - let (_, ciphers) = client.sync(&access_token).unwrap(); - for cipher in ciphers { - let secret_name = - rbw::cipherstring::CipherString::new(&cipher.name).unwrap(); - let name = secret_name.decrypt(enc_key, mac_key).unwrap(); - let secret_username = - rbw::cipherstring::CipherString::new(&cipher.login.username) - .unwrap(); - let username = secret_username.decrypt(enc_key, mac_key).unwrap(); - let secret_password = - rbw::cipherstring::CipherString::new(&cipher.login.password) - .unwrap(); - let password = secret_password.decrypt(enc_key, mac_key).unwrap(); - println!("{}:", String::from_utf8(name).unwrap()); - println!(" Username: {}", String::from_utf8(username).unwrap()); - println!(" Password: {}", String::from_utf8(password).unwrap()); + match matches.subcommand() { + ("login", Some(_)) => login(), + ("unlock", Some(_)) => unlock(), + ("sync", Some(_)) => sync(), + ("list", Some(_)) => list(), + ("get", Some(_)) => get(), + ("add", Some(_)) => add(), + ("generate", Some(_)) => generate(), + ("edit", Some(_)) => edit(), + ("remove", Some(_)) => remove(), + ("lock", Some(_)) => lock(), + ("purge", Some(_)) => purge(), + _ => unimplemented!(), } } diff --git a/src/lib.rs b/src/lib.rs index 175c37f..996098e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![allow(clippy::similar_names)] pub mod actions; +pub mod agent; pub mod api; pub mod cipherstring; pub mod dirs; -- cgit v1.2.3-54-g00ecf