aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-06 22:40:00 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-06 22:40:00 -0400
commit95da8880e311d4932fd50febab6ef093e5915051 (patch)
tree72cef6b73a05e37f76f3f3d7a56ba204afa690e1
parent8b655f36b868cb023dcdd1ff712de80a59ccbdb1 (diff)
downloadrbw-95da8880e311d4932fd50febab6ef093e5915051.tar.gz
rbw-95da8880e311d4932fd50febab6ef093e5915051.zip
start moving to an actual cli app
-rw-r--r--Cargo.lock63
-rw-r--r--Cargo.toml1
-rw-r--r--src/agent.rs17
-rw-r--r--src/bin/agent.rs32
-rw-r--r--src/bin/rbw.rs125
-rw-r--r--src/lib.rs1
6 files changed, 180 insertions, 59 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d7c2ae7..59dff78 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -33,6 +33,15 @@ dependencies = [
]
[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi 0.3.8",
+]
+
+[[package]]
name = "arc-swap"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -51,6 +60,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi 0.3.8",
+]
+
+[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -166,6 +186,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
+name = "clap"
+version = "2.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -911,6 +946,7 @@ dependencies = [
"aes",
"base64 0.11.0",
"block-modes",
+ "clap",
"directories",
"fs2",
"hkdf",
@@ -1173,6 +1209,12 @@ dependencies = [
]
[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
name = "subtle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1204,6 +1246,15 @@ dependencies = [
]
[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1319,6 +1370,12 @@ dependencies = [
]
[[package]]
+name = "unicode-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+
+[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1351,6 +1408,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
[[package]]
+name = "vec_map"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+
+[[package]]
name = "version_check"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index d4743ff..cfd4bfb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
aes = "*"
base64 = "*"
block-modes = "*"
+clap = "*"
directories = "*"
fs2 = "*"
hkdf = "*"
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<String>,
+ 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<String>,
- 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;