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