verbose
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is failing

This commit is contained in:
shimun 2020-10-18 15:39:30 +02:00
parent 8e98bf024e
commit 2ed7f8141f
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
4 changed files with 81 additions and 24 deletions

View File

@ -17,7 +17,7 @@ use structopt::clap::Shell;
use structopt::StructOpt;
fn read_pin() -> Fido2LuksResult<String> {
util::read_password("Authenticator PIN", false)
util::read_password_tty("Authenticator PIN", false)
}
fn derive_secret(
@ -98,14 +98,11 @@ pub fn get_input(
} else {
None
},
salt.obtain_sha256(Some(|| util::read_password(q, verify)))?,
salt.obtain_sha256(Some(|| util::read_password_tty(q, verify)))?,
)
} else {
match (authenticator.pin, authenticator.pin_prefixed) {
(true, false) => (
Some(read_pin()?),
salt.obtain_sha256(password_helper)?,
),
(true, false) => (Some(read_pin()?), salt.obtain_sha256(password_helper)?),
(true, true) => read_password_pin_prefixed(|| {
salt.obtain(password_helper).and_then(|secret| {
String::from_utf8(secret).map_err(|e| Fido2LuksError::from(e))
@ -143,6 +140,11 @@ pub fn parse_cmdline() -> Args {
pub fn run_cli() -> Fido2LuksResult<()> {
let mut stdout = io::stdout();
let args = parse_cmdline();
let log = |message: &dyn Fn() -> String| {
if args.verbose {
eprintln!("{}", message());
}
};
match &args.command {
Command::Credential {
authenticator,
@ -168,7 +170,10 @@ pub fn run_cli() -> Fido2LuksResult<()> {
} => {
let (pin, salt) =
get_input(&secret, &authenticator, args.interactive, "Password", false)?;
let credentials = if let Some(dev) = device {
let credentials = if let Some(path) = device {
let mut dev = LuksDevice::load(path)?;
let luks2 = dev.is_luks2()?;
log(&|| format!("luks2 supported: {}", luks2));
extend_creds_device(
credentials
.ids
@ -176,17 +181,28 @@ pub fn run_cli() -> Fido2LuksResult<()> {
.map(|cs| cs.0)
.unwrap_or_default()
.as_slice(),
&mut LuksDevice::load(dev)?,
&mut dev,
)?
} else {
credentials.ids.clone().map(|cs| cs.0).unwrap_or_default()
};
let (secret, _cred) = derive_secret(
log(&|| {
format!(
"credentials: {}",
credentials
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ")
)
});
let (secret, cred) = derive_secret(
credentials.as_slice(),
&salt,
authenticator.await_time,
pin.as_deref(),
)?;
log(&|| format!("credential used: {}", hex::encode(&cred.id)));
if *binary {
stdout.write_all(&secret[..])?;
} else {
@ -216,6 +232,8 @@ pub fn run_cli() -> Fido2LuksResult<()> {
let luks2 = luks_dev.is_luks2()?;
log(&|| format!("luks2 supported: {}", luks2));
let credentials = if !luks.disable_token && luks2 {
extend_creds_device(
credentials
@ -229,7 +247,16 @@ pub fn run_cli() -> Fido2LuksResult<()> {
} else {
credentials.ids.clone().map(|cs| cs.0).unwrap_or_default()
};
log(&|| {
format!(
"credentials: {}",
credentials
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ")
)
});
let inputs = |q: &str, verify: bool| -> Fido2LuksResult<(Option<String>, [u8; 32])> {
get_input(&secret, &authenticator, args.interactive, q, verify)
};
@ -255,7 +282,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
.map(|(secret, cred)| (secret[..].to_vec(), Some(cred)))?)
}
_ => Ok((
util::read_password(salt_q, verify)?.as_bytes().to_vec(),
util::read_password_tty(salt_q, verify)?.as_bytes().to_vec(),
None,
)),
}
@ -284,6 +311,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
} else {
secret(true, &credentials)
}?;
log(&|| format!("credential used: {}", hex::encode(&cred.id)));
let added_slot = luks_dev.add_key(
&new_secret,
&existing_secret[..],
@ -341,6 +369,9 @@ pub fn run_cli() -> Fido2LuksResult<()> {
}
Ok(slot)
}?;
if let Some(cred) = cred {
log(&|| format!("credential used: {}", hex::encode(&cred.id)));
}
println!(
"Added to password to device {}, slot: {}",
luks.device.display(),
@ -377,21 +408,38 @@ pub fn run_cli() -> Fido2LuksResult<()> {
let mut retries = *retries;
let mut luks_dev = LuksDevice::load(&luks.device)?;
let luks2 = luks_dev.is_luks2()?;
log(&|| format!("luks2 supported: {}", luks2));
loop {
let slot = if let Some(ref credentials) = credentials.ids {
secret(Cow::Borrowed(&credentials.0)).and_then(|(secret, _cred)| {
log(&|| {
format!(
"credentials: {}",
credentials
.0
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ")
)
});
secret(Cow::Borrowed(&credentials.0)).and_then(|(secret, cred)| {
log(&|| format!("credential used: {}", hex::encode(&cred.id)));
luks_dev.activate(&name, &secret, luks.slot, *dry_run)
})
} else if luks_dev.is_luks2()? && !luks.disable_token {
} else if luks2 && !luks.disable_token {
luks_dev.activate_token(
&name,
Box::new(|credentials: Vec<String>| {
log(&|| format!("credentials: {}", credentials.join(", ")));
let creds = credentials
.into_iter()
.flat_map(|cred| HexEncoded::from_str(cred.as_ref()).ok())
.collect::<Vec<_>>();
secret(Cow::Owned(creds))
.map(|(secret, cred)| (secret, hex::encode(&cred.id)))
secret(Cow::Owned(creds)).map(|(secret, cred)| {
log(&|| format!("credential used: {}", hex::encode(&cred.id)));
(secret, hex::encode(&cred.id))
})
}),
luks.slot,
*dry_run,
@ -414,7 +462,10 @@ pub fn run_cli() -> Fido2LuksResult<()> {
retries -= 1;
eprintln!("{}", e);
}
res => break res.map(|_| ()),
Ok(slot) => {
log(&|| format!("keyslot: {}", slot));
break Ok(());
}
}
}
}

View File

@ -163,7 +163,7 @@ impl PasswordHelper {
use PasswordHelper::*;
match self {
Systemd => unimplemented!(),
Stdin => Ok(util::read_password("Password", true)?),
Stdin => Ok(util::read_password("Password", true, false)?),
Script(password_helper) => {
let password = Command::new("sh")
.arg("-c")

View File

@ -147,6 +147,8 @@ pub struct Args {
/// Request passwords via Stdin instead of using the password helper
#[structopt(short = "i", long = "interactive")]
pub interactive: bool,
#[structopt(short = "v", long = "verbose")]
pub verbose: bool,
#[structopt(subcommand)]
pub command: Command,
}

View File

@ -13,9 +13,17 @@ pub fn sha256(messages: &[&[u8]]) -> [u8; 32] {
secret.as_mut().copy_from_slice(digest.finish().as_ref());
secret
}
pub fn read_password(q: &str, verify: bool) -> Fido2LuksResult<String> {
match rpassword::read_password_from_tty(Some(&[q, ": "].join("")))? {
pub fn read_password_tty(q: &str, verify: bool) -> Fido2LuksResult<String> {
read_password(q, verify, true)
}
pub fn read_password(q: &str, verify: bool, tty: bool) -> Fido2LuksResult<String> {
let res = if tty {
rpassword::read_password_from_tty(Some(&[q, ": "].join("")))
} else {
print!("{}: ", q);
rpassword::read_password()
}?;
match res {
ref pass
if verify
&& &rpassword::read_password_from_tty(Some(&[q, "(again): "].join(" ")))?
@ -29,10 +37,6 @@ pub fn read_password(q: &str, verify: bool) -> Fido2LuksResult<String> {
}
}
pub fn read_password_hashed(q: &str, verify: bool) -> Fido2LuksResult<[u8; 32]> {
read_password(q, verify).map(|pass| sha256(&[pass.as_bytes()]))
}
pub fn read_keyfile<P: Into<PathBuf>>(path: P) -> Fido2LuksResult<Vec<u8>> {
let mut file = File::open(path.into())?;
let mut key = Vec::new();