rewrite helper
This commit is contained in:
parent
a5c0840a59
commit
a264f4c9eb
133
src/cli.rs
133
src/cli.rs
@ -2,26 +2,19 @@ use crate::error::*;
|
||||
use crate::luks::{Fido2LuksToken, LuksDevice};
|
||||
use crate::util::sha256;
|
||||
use crate::*;
|
||||
pub use cli_args::Args;
|
||||
use cli_args::*;
|
||||
|
||||
use structopt::clap::Shell;
|
||||
use structopt::StructOpt;
|
||||
|
||||
use ctap::{FidoCredential, FidoErrorKind};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write;
|
||||
use std::iter::FromIterator;
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
||||
pub use cli_args::Args;
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use structopt::clap::Shell;
|
||||
use structopt::StructOpt;
|
||||
|
||||
fn read_pin() -> Fido2LuksResult<String> {
|
||||
util::read_password("Authenticator PIN", false)
|
||||
@ -86,6 +79,43 @@ pub fn extend_creds_device(
|
||||
Ok(Vec::from_iter(additional.into_iter()))
|
||||
}
|
||||
|
||||
pub fn get_input(
|
||||
secret: &SecretParameters,
|
||||
authenticator: &AuthenticatorParameters,
|
||||
interactive: bool,
|
||||
q: &str,
|
||||
verify: bool,
|
||||
) -> Fido2LuksResult<(Option<String>, [u8; 32])> {
|
||||
let password_helper = secret
|
||||
.password_helper
|
||||
.as_ref()
|
||||
.map(|helper| move || helper.obtain());
|
||||
let salt = &secret.salt;
|
||||
Ok(if interactive {
|
||||
(
|
||||
if authenticator.pin {
|
||||
Some(util::read_password("PIN", false)?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
salt.obtain_sha256(Some(|| util::read_password(q, verify)))?,
|
||||
)
|
||||
} else {
|
||||
match (authenticator.pin, authenticator.pin_prefixed) {
|
||||
(true, false) => (
|
||||
Some(util::read_password("PIN", false)?),
|
||||
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))
|
||||
})
|
||||
})?,
|
||||
(false, _) => (None, salt.obtain_sha256(password_helper)?),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn read_password_pin_prefixed(
|
||||
prefixed: impl Fn() -> Fido2LuksResult<String>,
|
||||
) -> Fido2LuksResult<(Option<String>, [u8; 32])> {
|
||||
@ -136,29 +166,8 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
secret,
|
||||
device,
|
||||
} => {
|
||||
let (pin, salt) = match (
|
||||
&secret.password_helper,
|
||||
authenticator.pin,
|
||||
authenticator.pin_prefixed,
|
||||
args.interactive,
|
||||
) {
|
||||
(Some(phelper), true, true, false) => {
|
||||
read_password_pin_prefixed(|| phelper.obtain())?
|
||||
}
|
||||
(Some(phelper), false, false, false) => {
|
||||
(None, secret.salt.obtain_sha256(&phelper)?)
|
||||
}
|
||||
|
||||
(phelper, pin, _, _) => (
|
||||
if pin { Some(read_pin()?) } else { None },
|
||||
match phelper {
|
||||
None | Some(PasswordHelper::Stdin) => {
|
||||
util::read_password_hashed("Password", false)
|
||||
}
|
||||
Some(phelper) => secret.salt.obtain_sha256(&phelper),
|
||||
}?,
|
||||
),
|
||||
};
|
||||
let (pin, salt) =
|
||||
get_input(&secret, &authenticator, args.interactive, "Password", false)?;
|
||||
let credentials = if let Some(dev) = device {
|
||||
extend_creds_device(
|
||||
credentials
|
||||
@ -222,31 +231,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
};
|
||||
|
||||
let inputs = |q: &str, verify: bool| -> Fido2LuksResult<(Option<String>, [u8; 32])> {
|
||||
Ok(
|
||||
match (
|
||||
&secret.password_helper,
|
||||
authenticator.pin,
|
||||
authenticator.pin_prefixed,
|
||||
args.interactive,
|
||||
) {
|
||||
(Some(phelper), true, true, false) => {
|
||||
read_password_pin_prefixed(|| phelper.obtain())?
|
||||
}
|
||||
(Some(phelper), false, false, false) => {
|
||||
(None, secret.salt.obtain_sha256(&phelper)?)
|
||||
}
|
||||
|
||||
(_phelper, pin, _, _) => (
|
||||
if pin { Some(read_pin()?) } else { None },
|
||||
match &secret.password_helper {
|
||||
None | Some(PasswordHelper::Stdin) => {
|
||||
util::read_password_hashed(q, verify)
|
||||
}
|
||||
Some(phelper) => secret.salt.obtain_sha256(&phelper),
|
||||
}?,
|
||||
),
|
||||
},
|
||||
)
|
||||
get_input(&secret, &authenticator, args.interactive, q, verify)
|
||||
};
|
||||
|
||||
let other_secret = |salt_q: &str,
|
||||
@ -375,31 +360,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
retries,
|
||||
} => {
|
||||
let inputs = |q: &str, verify: bool| -> Fido2LuksResult<(Option<String>, [u8; 32])> {
|
||||
Ok(
|
||||
match (
|
||||
&secret.password_helper,
|
||||
authenticator.pin,
|
||||
authenticator.pin_prefixed,
|
||||
args.interactive,
|
||||
) {
|
||||
(Some(phelper), true, true, false) => {
|
||||
read_password_pin_prefixed(|| phelper.obtain())?
|
||||
}
|
||||
(Some(phelper), false, false, false) => {
|
||||
(None, secret.salt.obtain_sha256(&phelper)?)
|
||||
}
|
||||
|
||||
(phelper, pin, _, _) => (
|
||||
if pin { Some(read_pin()?) } else { None },
|
||||
match &phelper {
|
||||
None | Some(PasswordHelper::Stdin) => {
|
||||
util::read_password_hashed(q, verify)
|
||||
}
|
||||
Some(phelper) => secret.salt.obtain_sha256(&phelper),
|
||||
}?,
|
||||
),
|
||||
},
|
||||
)
|
||||
get_input(&secret, &authenticator, args.interactive, q, verify)
|
||||
};
|
||||
|
||||
// Cow shouldn't be necessary
|
||||
|
@ -55,11 +55,17 @@ impl fmt::Display for SecretInput {
|
||||
}
|
||||
|
||||
impl SecretInput {
|
||||
pub fn obtain_string(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<String> {
|
||||
pub fn obtain_string(
|
||||
&self,
|
||||
password_helper: Option<impl FnOnce() -> Fido2LuksResult<String>>,
|
||||
) -> Fido2LuksResult<String> {
|
||||
Ok(String::from_utf8(self.obtain(password_helper)?)?)
|
||||
}
|
||||
|
||||
pub fn obtain(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<Vec<u8>> {
|
||||
pub fn obtain(
|
||||
&self,
|
||||
password_helper: Option<impl FnOnce() -> Fido2LuksResult<String>>,
|
||||
) -> Fido2LuksResult<Vec<u8>> {
|
||||
let mut secret = Vec::new();
|
||||
match self {
|
||||
SecretInput::File { path } => {
|
||||
@ -67,16 +73,22 @@ impl SecretInput {
|
||||
let mut do_io = || File::open(path)?.read_to_end(&mut secret);
|
||||
do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?;
|
||||
}
|
||||
SecretInput::AskPassword => {
|
||||
secret.extend_from_slice(password_helper.obtain()?.as_bytes())
|
||||
}
|
||||
SecretInput::AskPassword => secret.extend_from_slice(
|
||||
password_helper.ok_or_else(|| Fido2LuksError::AskPassError {
|
||||
cause: AskPassError::FailedHelper,
|
||||
})?()?
|
||||
.as_bytes(),
|
||||
),
|
||||
|
||||
SecretInput::String(s) => secret.extend_from_slice(s.as_bytes()),
|
||||
}
|
||||
Ok(secret)
|
||||
}
|
||||
|
||||
pub fn obtain_sha256(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<[u8; 32]> {
|
||||
pub fn obtain_sha256(
|
||||
&self,
|
||||
password_helper: Option<impl FnOnce() -> Fido2LuksResult<String>>,
|
||||
) -> Fido2LuksResult<[u8; 32]> {
|
||||
let mut digest = digest::Context::new(&digest::SHA256);
|
||||
match self {
|
||||
SecretInput::File { path } => {
|
||||
@ -198,7 +210,7 @@ mod test {
|
||||
fn input_salt_obtain() {
|
||||
assert_eq!(
|
||||
SecretInput::String("abc".into())
|
||||
.obtain_sha256(&PasswordHelper::Stdin)
|
||||
.obtain_sha256(None)
|
||||
.unwrap(),
|
||||
[
|
||||
186, 120, 22, 191, 143, 1, 207, 234, 65, 65, 64, 222, 93, 174, 34, 35, 176, 3, 97,
|
||||
|
@ -54,6 +54,8 @@ pub enum AskPassError {
|
||||
IO(io::Error),
|
||||
#[fail(display = "provided passwords don't match")]
|
||||
Mismatch,
|
||||
#[fail(display = "failed to call password helper")]
|
||||
FailedHelper,
|
||||
}
|
||||
|
||||
#[derive(Debug, Fail)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user