add subcommand to remove key from device
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2019-09-22 18:42:38 +02:00
parent de76f3f480
commit 50fad9ce92
4 changed files with 91 additions and 26 deletions

View File

@@ -21,18 +21,14 @@ pub fn add_key_to_luks(device: PathBuf, secret: &[u8; 32], exclusive: bool) -> F
let dev =
|| -> luks::device::Result<CryptDeviceOpenBuilder> { 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<dyn Fn() -> Fido2LuksResult<Vec<u8>>>,
add_password: bool,
) -> Fido2LuksResult<u8> {
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<bool> {
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<PathBuf>,
#[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,

View File

@@ -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(" ");

View File

@@ -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()?;

26
src/util.rs Normal file
View File

@@ -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<String> {
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<P: Into<PathBuf>>(path: P) -> Fido2LuksResult<Vec<u8>> {
let mut file = File::open(path.into())?;
let mut key = Vec::new();
file.read_to_end(&mut key)?;
Ok(key)
}