add subcommand to remove key from device
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
72
src/cli.rs
72
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<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,
|
||||
|
@@ -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(" ");
|
||||
|
||||
|
@@ -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
26
src/util.rs
Normal 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)
|
||||
}
|
Reference in New Issue
Block a user