From 50fad9ce92cc21cd4c5521da3f4f63a870808818 Mon Sep 17 00:00:00 2001 From: shimunn Date: Sun, 22 Sep 2019 18:42:38 +0200 Subject: [PATCH] add subcommand to remove key from device --- src/cli.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++------- src/config.rs | 18 +------------ src/main.rs | 1 + src/util.rs | 26 +++++++++++++++++++ 4 files changed, 91 insertions(+), 26 deletions(-) create mode 100644 src/util.rs diff --git a/src/cli.rs b/src/cli.rs index e58fedf..ad0b861 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -21,18 +21,14 @@ pub fn add_key_to_luks(device: PathBuf, secret: &[u8; 32], exclusive: bool) -> F let dev = || -> luks::device::Result { luks::open(&device.canonicalize()?) }; - let prev_key_info = rpassword::read_password_from_tty(Some( - "Please enter your current password or path to a keyfile in order to add a new key: ", - ))?; + let prev_key_info = util::read_password( + "Please enter your current password or path to a keyfile in order to add a new key", + false, + )?; let prev_key = match prev_key_info.as_ref() { "" => None, - keyfile if PathBuf::from(keyfile).exists() => { - let mut f = File::open(keyfile)?; - let mut key = Vec::new(); - f.read_to_end(&mut key)?; - Some(key) - } + keyfile if PathBuf::from(keyfile).exists() => Some(util::read_keyfile(keyfile)?), password => Some(Vec::from(password.as_bytes())), }; @@ -62,6 +58,23 @@ pub fn add_key_to_luks(device: PathBuf, secret: &[u8; 32], exclusive: bool) -> F Ok(slot) } +pub fn add_password_to_luks( + device: PathBuf, + secret: &[u8; 32], + new_secret: Box Fido2LuksResult>>, + add_password: bool, +) -> Fido2LuksResult { + let dev = luks::open(&device.canonicalize()?)?; + let mut handle = dev.luks1()?; + let prev_slot = if add_password { + Some(handle.add_keyslot(&secret[..], Some(&secret[..]), None)?) + } else { + None + }; + let slot = handle.update_keyslot(&new_secret()?[..], &secret[..], prev_slot)?; + Ok(slot) +} + pub fn authenticator_connected() -> Fido2LuksResult { Ok(!device::get_devices()?.is_empty()) } @@ -131,6 +144,21 @@ pub enum Command { #[structopt(flatten)] secret_gen: SecretGeneration, }, + + /// Replace a previously added key with a password + #[structopt(name = "replace-key")] + ReplaceKey { + #[structopt(env = "FIDO2LUKS_DEVICE")] + device: PathBuf, + /// Add the password and keep the key + #[structopt(short = "a", long = "add-password")] + add_password: bool, + /// Use a keyfile instead of a password + #[structopt(short = "d", long = "keyfile")] + keyfile: Option, + #[structopt(flatten)] + secret_gen: SecretGeneration, + }, /// Open the LUKS device #[structopt(name = "open")] Open { @@ -188,6 +216,32 @@ pub fn run_cli() -> Fido2LuksResult<()> { ); Ok(()) } + Command::ReplaceKey { + device, + add_password, + keyfile, + ref secret_gen, + } => { + let secret = secret_gen.patch(&args).obtain_secret()?; + let slot = add_password_to_luks( + device.clone(), + &secret, + if let Some(keyfile) = keyfile.clone() { + Box::new(move || util::read_keyfile(keyfile.clone())) + } else { + Box::new(|| { + util::read_password("Password to add", true).map(|p| p.as_bytes().to_vec()) + }) + }, + *add_password, + )?; + println!( + "Added to password to device {}, slot: {}", + device.display(), + slot + ); + Ok(()) + } Command::Open { device, name, diff --git a/src/config.rs b/src/config.rs index 9d3708c..a3dde17 100644 --- a/src/config.rs +++ b/src/config.rs @@ -132,23 +132,7 @@ impl PasswordHelper { use PasswordHelper::*; match self { Systemd => unimplemented!(), - Stdin => Ok(rpassword::read_password_from_tty(Some("Password: ")) - .map_err(|e| Fido2LuksError::AskPassError { - cause: AskPassError::IO(e), - }) - .and_then(|pass| { - match rpassword::read_password_from_tty(Some("Password again: ")).map_err(|e| { - Fido2LuksError::AskPassError { - cause: AskPassError::IO(e), - } - }) { - Ok(ref pass2) if &pass == pass2 => Ok(pass), - Ok(_) => Err(Fido2LuksError::AskPassError { - cause: error::AskPassError::Mismatch, - }), - e => e, - } - })?), + Stdin => Ok(util::read_password("Password", true)?), Script(password_helper) => { let mut helper_parts = password_helper.split(" "); diff --git a/src/main.rs b/src/main.rs index 96419c7..8ac5dd5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ mod cli; mod config; mod device; mod error; +mod util; fn open_container(device: &PathBuf, name: &str, secret: &[u8; 32]) -> Fido2LuksResult<()> { let mut handle = luks::open(device.canonicalize()?)?.luks1()?; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..516cd35 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,26 @@ +use crate::error::*; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; + +pub fn read_password(q: &str, verify: bool) -> Fido2LuksResult { + match rpassword::read_password_from_tty(Some(&[q, ": "].join("")))? { + ref pass + if verify + && &rpassword::read_password_from_tty(Some(&[q, "(again): "].join(" ")))? + != pass => + { + Err(Fido2LuksError::AskPassError { + cause: AskPassError::Mismatch, + })? + } + pass => Ok(pass), + } +} + +pub fn read_keyfile>(path: P) -> Fido2LuksResult> { + let mut file = File::open(path.into())?; + let mut key = Vec::new(); + file.read_to_end(&mut key)?; + Ok(key) +}