aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock157
-rw-r--r--Cargo.toml8
-rw-r--r--src/bin/agent.rs83
-rw-r--r--src/bin/rbw.rs18
4 files changed, 202 insertions, 64 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 59dff78..15e8451 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index cfd4bfb..fb4a51c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(),