mirror of
https://github.com/morgan9e/bitwarden-desktop-agent
synced 2026-04-14 00:04:06 +09:00
make --email optional, saved on enroll and reused on subsequent runs
This commit is contained in:
46
src/main.rs
46
src/main.rs
@@ -6,6 +6,9 @@ mod ipc;
|
||||
mod log;
|
||||
mod storage;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use sha2::{Digest, Sha256};
|
||||
use zeroize::Zeroize;
|
||||
@@ -18,7 +21,7 @@ use storage::get_backend;
|
||||
#[command(about = "Bitwarden desktop bridge agent")]
|
||||
struct Args {
|
||||
#[arg(long)]
|
||||
email: String,
|
||||
email: Option<String>,
|
||||
|
||||
#[arg(long)]
|
||||
password: Option<String>,
|
||||
@@ -39,6 +42,27 @@ struct Args {
|
||||
remove: bool,
|
||||
}
|
||||
|
||||
fn config_dir() -> PathBuf {
|
||||
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".into());
|
||||
PathBuf::from(home).join(".cache").join("com.bitwarden.desktop")
|
||||
}
|
||||
|
||||
fn config_path() -> PathBuf {
|
||||
config_dir().join("agent.conf")
|
||||
}
|
||||
|
||||
fn save_email(email: &str) {
|
||||
fs::create_dir_all(config_dir()).ok();
|
||||
fs::write(config_path(), email).ok();
|
||||
}
|
||||
|
||||
fn load_email() -> Option<String> {
|
||||
fs::read_to_string(config_path())
|
||||
.ok()
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty())
|
||||
}
|
||||
|
||||
fn user_hash(email: &str) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(email.to_lowercase().trim().as_bytes());
|
||||
@@ -48,7 +72,14 @@ fn user_hash(email: &str) -> String {
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let uid = user_hash(&args.email);
|
||||
|
||||
let email = args
|
||||
.email
|
||||
.clone()
|
||||
.or_else(load_email)
|
||||
.unwrap_or_else(|| log::fatal("no email provided (use --email on first run)"));
|
||||
|
||||
let uid = user_hash(&email);
|
||||
let store = get_backend(args.backend.as_deref());
|
||||
let prompt = get_prompter(args.askpass.as_deref());
|
||||
log::info(&format!("backend: {}", store.name()));
|
||||
@@ -56,9 +87,9 @@ fn main() {
|
||||
if args.remove {
|
||||
if store.has_key(&uid) {
|
||||
store.remove(&uid);
|
||||
log::info(&format!("key removed for {}", args.email));
|
||||
log::info(&format!("key removed for {email}"));
|
||||
} else {
|
||||
log::info(&format!("no key found for {}", args.email));
|
||||
log::info(&format!("no key found for {email}"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -76,8 +107,8 @@ fn main() {
|
||||
.or_else(|| prompt("master password:"))
|
||||
.unwrap_or_else(|| log::fatal("no password provided"));
|
||||
|
||||
log::info(&format!("logging in as {}", args.email));
|
||||
let (mut key_bytes, server_uid) = auth::login(&args.email, &pw, &args.server, &prompt);
|
||||
log::info(&format!("logging in as {email}"));
|
||||
let (mut key_bytes, server_uid) = auth::login(&email, &pw, &args.server, &prompt);
|
||||
log::info(&format!("authenticated, uid={server_uid}"));
|
||||
|
||||
let auth = prompt(&format!("choose {} password:", store.name()))
|
||||
@@ -92,10 +123,11 @@ fn main() {
|
||||
.store(&uid, &key_bytes, &auth)
|
||||
.unwrap_or_else(|e| log::fatal(&format!("store failed: {e}")));
|
||||
key_bytes.zeroize();
|
||||
save_email(&email);
|
||||
log::info(&format!("key sealed via {}", store.name()));
|
||||
log::info("wiped key from memory");
|
||||
} else {
|
||||
log::info(&format!("key ready for {}", args.email));
|
||||
log::info(&format!("key ready for {email}"));
|
||||
}
|
||||
|
||||
let mut bridge = BiometricBridge::new(store, uid, prompt);
|
||||
|
||||
Reference in New Issue
Block a user