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 =
|
let dev =
|
||||||
|| -> luks::device::Result<CryptDeviceOpenBuilder> { luks::open(&device.canonicalize()?) };
|
|| -> luks::device::Result<CryptDeviceOpenBuilder> { luks::open(&device.canonicalize()?) };
|
||||||
|
|
||||||
let prev_key_info = rpassword::read_password_from_tty(Some(
|
let prev_key_info = util::read_password(
|
||||||
"Please enter your current password or path to a keyfile in order to add a new key: ",
|
"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() {
|
let prev_key = match prev_key_info.as_ref() {
|
||||||
"" => None,
|
"" => None,
|
||||||
keyfile if PathBuf::from(keyfile).exists() => {
|
keyfile if PathBuf::from(keyfile).exists() => Some(util::read_keyfile(keyfile)?),
|
||||||
let mut f = File::open(keyfile)?;
|
|
||||||
let mut key = Vec::new();
|
|
||||||
f.read_to_end(&mut key)?;
|
|
||||||
Some(key)
|
|
||||||
}
|
|
||||||
password => Some(Vec::from(password.as_bytes())),
|
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)
|
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> {
|
pub fn authenticator_connected() -> Fido2LuksResult<bool> {
|
||||||
Ok(!device::get_devices()?.is_empty())
|
Ok(!device::get_devices()?.is_empty())
|
||||||
}
|
}
|
||||||
@@ -131,6 +144,21 @@ pub enum Command {
|
|||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
secret_gen: SecretGeneration,
|
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
|
/// Open the LUKS device
|
||||||
#[structopt(name = "open")]
|
#[structopt(name = "open")]
|
||||||
Open {
|
Open {
|
||||||
@@ -188,6 +216,32 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
);
|
);
|
||||||
Ok(())
|
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 {
|
Command::Open {
|
||||||
device,
|
device,
|
||||||
name,
|
name,
|
||||||
|
@@ -132,23 +132,7 @@ impl PasswordHelper {
|
|||||||
use PasswordHelper::*;
|
use PasswordHelper::*;
|
||||||
match self {
|
match self {
|
||||||
Systemd => unimplemented!(),
|
Systemd => unimplemented!(),
|
||||||
Stdin => Ok(rpassword::read_password_from_tty(Some("Password: "))
|
Stdin => Ok(util::read_password("Password", true)?),
|
||||||
.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,
|
|
||||||
}
|
|
||||||
})?),
|
|
||||||
Script(password_helper) => {
|
Script(password_helper) => {
|
||||||
let mut helper_parts = password_helper.split(" ");
|
let mut helper_parts = password_helper.split(" ");
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ mod cli;
|
|||||||
mod config;
|
mod config;
|
||||||
mod device;
|
mod device;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod util;
|
||||||
|
|
||||||
fn open_container(device: &PathBuf, name: &str, secret: &[u8; 32]) -> Fido2LuksResult<()> {
|
fn open_container(device: &PathBuf, name: &str, secret: &[u8; 32]) -> Fido2LuksResult<()> {
|
||||||
let mut handle = luks::open(device.canonicalize()?)?.luks1()?;
|
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