diff options
author | Jesse Luehrs <doy@tozt.net> | 2020-04-07 00:15:40 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2020-04-07 00:15:40 -0400 |
commit | 0f13f2c6d11934bbaceca4dac4c3ba428aae72b7 (patch) | |
tree | 167026cd6eec33d2e752edfefa023ecd11072998 | |
parent | 95da8880e311d4932fd50febab6ef093e5915051 (diff) | |
download | rbw-0f13f2c6d11934bbaceca4dac4c3ba428aae72b7.tar.gz rbw-0f13f2c6d11934bbaceca4dac4c3ba428aae72b7.zip |
make the command line tool automatically spawn the agent
-rw-r--r-- | Cargo.lock | 157 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/bin/agent.rs | 83 | ||||
-rw-r--r-- | src/bin/rbw.rs | 18 |
4 files changed, 202 insertions, 64 deletions
@@ -33,6 +33,15 @@ dependencies = [ ] [[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -42,6 +51,12 @@ dependencies = [ ] [[package]] +name = "anyhow" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" + +[[package]] name = "arc-swap" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -150,6 +165,12 @@ dependencies = [ ] [[package]] +name = "boxfnonce" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" + +[[package]] name = "bumpalo" version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -253,6 +274,16 @@ dependencies = [ ] [[package]] +name = "daemonize" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815" +dependencies = [ + "boxfnonce", + "libc", +] + +[[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -305,6 +336,19 @@ dependencies = [ ] [[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -332,16 +376,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -506,6 +540,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] name = "hyper" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -739,6 +782,19 @@ dependencies = [ ] [[package]] +name = "nix" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "void", +] + +[[package]] name = "num_cpus" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -862,6 +918,12 @@ dependencies = [ ] [[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] name = "quote" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -944,17 +1006,19 @@ name = "rbw" version = "0.1.0" dependencies = [ "aes", + "anyhow", "base64 0.11.0", "block-modes", "clap", + "daemonize", "directories", - "fs2", + "env_logger", "hkdf", "hmac", + "log", + "nix", "pbkdf2", "reqwest", - "rpassword", - "rprompt", "serde", "serde_json", "sha2", @@ -981,6 +1045,24 @@ dependencies = [ ] [[package]] +name = "regex" +version = "1.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" + +[[package]] name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1026,22 +1108,6 @@ dependencies = [ ] [[package]] -name = "rpassword" -version = "4.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f" -dependencies = [ - "libc", - "winapi 0.3.8", -] - -[[package]] -name = "rprompt" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b386f4748bdae2aefc96857f5fda07647f851d089420e577831e2a14b45230f8" - -[[package]] name = "rust-argon2" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1246,6 +1312,15 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1255,6 +1330,15 @@ dependencies = [ ] [[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1420,6 +1504,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] name = "want" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1542,6 +1632,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] +name = "winapi-util" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +dependencies = [ + "winapi 0.3.8", +] + +[[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6,17 +6,19 @@ edition = "2018" [dependencies] aes = "*" +anyhow = "*" base64 = "*" block-modes = "*" clap = "*" +daemonize = "*" directories = "*" -fs2 = "*" +env_logger = "*" hkdf = "*" hmac = "*" +log = "*" +nix = "*" pbkdf2 = "*" reqwest = { version = "*", features = ["blocking", "json"] } -rpassword = "*" -rprompt = "*" serde = { version = "*", features = ["derive"] } serde_json = "*" sha2 = "*" diff --git a/src/bin/agent.rs b/src/bin/agent.rs index 50b13a1..f21abcc 100644 --- a/src/bin/agent.rs +++ b/src/bin/agent.rs @@ -1,35 +1,15 @@ -use fs2::FileExt as _; -use std::io::Write as _; use tokio::io::AsyncBufReadExt as _; use tokio::stream::StreamExt as _; -fn make_pidfile() -> std::fs::File { +fn make_socket() -> anyhow::Result<tokio::net::UnixListener> { let runtime_dir = rbw::dirs::runtime_dir(); - std::fs::create_dir_all(&runtime_dir).unwrap(); - - let mut fh = std::fs::OpenOptions::new() - .write(true) - .create(true) - .open(runtime_dir.join("pidfile")) - .unwrap(); - - fh.try_lock_exclusive().unwrap(); - - fh.set_len(0).unwrap(); - fh.write_all(format!("{}", std::process::id()).as_bytes()) - .unwrap(); - - fh -} - -fn make_socket() -> tokio::net::UnixListener { - let runtime_dir = rbw::dirs::runtime_dir(); - std::fs::create_dir_all(&runtime_dir).unwrap(); + std::fs::create_dir_all(&runtime_dir)?; let path = runtime_dir.join("socket"); - std::fs::remove_file(&path).unwrap(); - - tokio::net::UnixListener::bind(path).unwrap() + std::fs::remove_file(&path)?; + let sock = tokio::net::UnixListener::bind(&path)?; + log::debug!("listening on socket {}", path.to_string_lossy()); + Ok(sock) } async fn ensure_login(state: std::sync::Arc<tokio::sync::RwLock<State>>) { @@ -181,10 +161,49 @@ impl Agent { } } -#[tokio::main] -async fn main() { - let _lock = make_pidfile(); - let listener = make_socket(); - let mut agent = Agent::new(); - agent.run(listener).await; +fn main() { + env_logger::from_env( + env_logger::Env::default().default_filter_or("info"), + ) + .init(); + + let runtime_dir = rbw::dirs::runtime_dir(); + std::fs::create_dir_all(&runtime_dir).unwrap(); + + let (r, w) = nix::unistd::pipe().unwrap(); + let res = daemonize::Daemonize::new() + .pid_file(runtime_dir.join("pidfile")) + .exit_action(move || { + nix::unistd::close(w).unwrap(); + let mut buf = [0; 1]; + nix::unistd::read(r, &mut buf).unwrap(); + nix::unistd::close(r).unwrap(); + }) + .start(); + nix::unistd::close(r).unwrap(); + + match res { + Ok(_) => (), + Err(e) => { + match e { + daemonize::DaemonizeError::LockPidfile(_) => { + // this means that there is already an agent running, so + // return a special exit code to allow the cli to detect + // this case and not error out + std::process::exit(23); + } + _ => panic!("failed to daemonize: {}", e), + } + } + } + + tokio::runtime::Runtime::new().unwrap().block_on(async { + let listener = make_socket(); + + nix::unistd::write(w, &[0]).unwrap(); + nix::unistd::close(w).unwrap(); + + let mut agent = Agent::new(); + agent.run(listener.unwrap()).await; + }) } diff --git a/src/bin/rbw.rs b/src/bin/rbw.rs index 910350b..a110176 100644 --- a/src/bin/rbw.rs +++ b/src/bin/rbw.rs @@ -1,5 +1,21 @@ use std::io::Write as _; +fn ensure_agent() { + let agent_path = std::env::var("RBW_AGENT"); + let agent_path = agent_path + .as_ref() + .map(|s| s.as_str()) + .unwrap_or("rbw-agent"); + let status = std::process::Command::new(agent_path).status().unwrap(); + if !status.success() { + if let Some(code) = status.code() { + if code != 23 { + panic!("failed to run agent: {}", status); + } + } + } +} + fn send(msg: &rbw::agent::Message) { let mut sock = std::os::unix::net::UnixStream::connect( rbw::dirs::runtime_dir().join("socket"), @@ -80,6 +96,8 @@ fn main() { .subcommand(clap::SubCommand::with_name("purge")) .get_matches(); + ensure_agent(); + match matches.subcommand() { ("login", Some(_)) => login(), ("unlock", Some(_)) => unlock(), |