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

View File

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

View File

@ -147,6 +147,8 @@ pub struct Args {
/// Request passwords via Stdin instead of using the password helper /// Request passwords via Stdin instead of using the password helper
#[structopt(short = "i", long = "interactive")] #[structopt(short = "i", long = "interactive")]
pub interactive: bool, pub interactive: bool,
#[structopt(short = "v", long = "verbose")]
pub verbose: bool,
#[structopt(subcommand)] #[structopt(subcommand)]
pub command: Command, 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.as_mut().copy_from_slice(digest.finish().as_ref());
secret secret
} }
pub fn read_password_tty(q: &str, verify: bool) -> Fido2LuksResult<String> {
pub fn read_password(q: &str, verify: bool) -> Fido2LuksResult<String> { read_password(q, verify, true)
match rpassword::read_password_from_tty(Some(&[q, ": "].join("")))? { }
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 ref pass
if verify if verify
&& &rpassword::read_password_from_tty(Some(&[q, "(again): "].join(" ")))? && &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>> { pub fn read_keyfile<P: Into<PathBuf>>(path: P) -> Fido2LuksResult<Vec<u8>> {
let mut file = File::open(path.into())?; let mut file = File::open(path.into())?;
let mut key = Vec::new(); let mut key = Vec::new();