move cli into module

This commit is contained in:
shimun 2020-09-05 17:17:58 +02:00
parent 7596019042
commit ff509d75b0
Signed by: shimun
GPG Key ID: E81D8382DC2F971B
5 changed files with 70 additions and 45 deletions

View File

@ -1,10 +1,10 @@
use crate::cli::config::*;
use crate::*; use crate::*;
use structopt::clap::AppSettings; use structopt::clap::AppSettings;
use structopt::StructOpt; use structopt::StructOpt;
use failure::_core::fmt::{Display, Error, Formatter}; use std::fmt::{Display, Error, Formatter};
use failure::_core::str::FromStr; use std::str::FromStr;
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct HexEncoded(pub Vec<u8>); pub struct HexEncoded(pub Vec<u8>);
@ -112,7 +112,7 @@ pub struct SecretParameters {
env = "FIDO2LUKS_SALT", env = "FIDO2LUKS_SALT",
default_value = "ask" default_value = "ask"
)] )]
pub salt: InputSalt, pub salt: SecretInput,
/// Script used to obtain passwords, overridden by --interactive flag /// Script used to obtain passwords, overridden by --interactive flag
#[structopt( #[structopt(
name = "password-helper", name = "password-helper",

View File

@ -10,33 +10,33 @@ use std::process::Command;
use std::str::FromStr; use std::str::FromStr;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum InputSalt { pub enum SecretInput {
AskPassword, AskPassword,
String(String), String(String),
File { path: PathBuf }, File { path: PathBuf },
} }
impl Default for InputSalt { impl Default for SecretInput {
fn default() -> Self { fn default() -> Self {
InputSalt::AskPassword SecretInput::AskPassword
} }
} }
impl From<&str> for InputSalt { impl From<&str> for SecretInput {
fn from(s: &str) -> Self { fn from(s: &str) -> Self {
let mut parts = s.split(':'); let mut parts = s.split(':');
match parts.next() { match parts.next() {
Some("ask") | Some("Ask") => InputSalt::AskPassword, Some("ask") | Some("Ask") => SecretInput::AskPassword,
Some("file") => InputSalt::File { Some("file") => SecretInput::File {
path: parts.collect::<Vec<_>>().join(":").into(), path: parts.collect::<Vec<_>>().join(":").into(),
}, },
Some("string") => InputSalt::String(parts.collect::<Vec<_>>().join(":")), Some("string") => SecretInput::String(parts.collect::<Vec<_>>().join(":")),
_ => Self::default(), _ => Self::default(),
} }
} }
} }
impl FromStr for InputSalt { impl FromStr for SecretInput {
type Err = Fido2LuksError; type Err = Fido2LuksError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
@ -44,21 +44,42 @@ impl FromStr for InputSalt {
} }
} }
impl fmt::Display for InputSalt { impl fmt::Display for SecretInput {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str(&match self { f.write_str(&match self {
InputSalt::AskPassword => "ask".to_string(), SecretInput::AskPassword => "ask".to_string(),
InputSalt::String(s) => ["string", s].join(":"), SecretInput::String(s) => ["string", s].join(":"),
InputSalt::File { path } => ["file", path.display().to_string().as_str()].join(":"), SecretInput::File { path } => ["file", path.display().to_string().as_str()].join(":"),
}) })
} }
} }
impl InputSalt { impl SecretInput {
pub fn obtain(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<[u8; 32]> { pub fn obtain_string(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<String> {
Ok(String::from_utf8(self.obtain(password_helper)?)?)
}
pub fn obtain(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<Vec<u8>> {
let mut secret = Vec::new();
match self {
SecretInput::File { path } => {
//TODO: replace with try_blocks
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::String(s) => secret.extend_from_slice(s.as_bytes()),
}
Ok(secret)
}
pub fn obtain_sha256(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<[u8; 32]> {
let mut digest = digest::Context::new(&digest::SHA256); let mut digest = digest::Context::new(&digest::SHA256);
match self { match self {
InputSalt::File { path } => { SecretInput::File { path } => {
let mut do_io = || { let mut do_io = || {
let mut reader = File::open(path)?; let mut reader = File::open(path)?;
let mut buf = [0u8; 512]; let mut buf = [0u8; 512];
@ -73,10 +94,7 @@ impl InputSalt {
}; };
do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?; do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?;
} }
InputSalt::AskPassword => { _ => digest.update(self.obtain(password_helper)?.as_slice()),
digest.update(password_helper.obtain()?.as_bytes());
}
InputSalt::String(s) => digest.update(s.as_bytes()),
} }
let mut salt = [0u8; 32]; let mut salt = [0u8; 32];
salt.as_mut().copy_from_slice(digest.finish().as_ref()); salt.as_mut().copy_from_slice(digest.finish().as_ref());
@ -157,23 +175,29 @@ mod test {
#[test] #[test]
fn input_salt_from_str() { fn input_salt_from_str() {
assert_eq!( assert_eq!(
"file:/tmp/abc".parse::<InputSalt>().unwrap(), "file:/tmp/abc".parse::<SecretInput>().unwrap(),
InputSalt::File { SecretInput::File {
path: "/tmp/abc".into() path: "/tmp/abc".into()
} }
); );
assert_eq!( assert_eq!(
"string:abc".parse::<InputSalt>().unwrap(), "string:abc".parse::<SecretInput>().unwrap(),
InputSalt::String("abc".into()) SecretInput::String("abc".into())
);
assert_eq!(
"ask".parse::<SecretInput>().unwrap(),
SecretInput::AskPassword
);
assert_eq!(
"lol".parse::<SecretInput>().unwrap(),
SecretInput::default()
); );
assert_eq!("ask".parse::<InputSalt>().unwrap(), InputSalt::AskPassword);
assert_eq!("lol".parse::<InputSalt>().unwrap(), InputSalt::default());
} }
#[test] #[test]
fn input_salt_obtain() { fn input_salt_obtain() {
assert_eq!( assert_eq!(
InputSalt::String("abc".into()) SecretInput::String("abc".into())
.obtain(&PasswordHelper::Stdin) .obtain(&PasswordHelper::Stdin)
.unwrap(), .unwrap(),
[ [

View File

@ -1,25 +1,30 @@
use crate::cli_args::*;
use crate::error::*; 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::*;
use cli_args::*;
use config::*;
use structopt::clap::Shell; use structopt::clap::Shell;
use structopt::StructOpt; use structopt::StructOpt;
use ctap::{FidoCredential, FidoErrorKind}; use ctap::{FidoCredential, FidoErrorKind};
use failure::_core::str::FromStr;
use failure::_core::time::Duration;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::process::exit; use std::str::FromStr;
use std::thread; use std::thread;
use std::time::Duration;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::File; use std::fs::File;
use std::time::SystemTime; use std::time::SystemTime;
pub use cli_args::Args;
mod cli_args;
mod config;
fn read_pin(ap: &AuthenticatorParameters) -> Fido2LuksResult<String> { fn read_pin(ap: &AuthenticatorParameters) -> Fido2LuksResult<String> {
if let Some(src) = ap.pin_source.as_ref() { if let Some(src) = ap.pin_source.as_ref() {
let mut pin = String::new(); let mut pin = String::new();
@ -106,7 +111,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
let salt = if interactive || secret.password_helper == PasswordHelper::Stdin { let salt = if interactive || secret.password_helper == PasswordHelper::Stdin {
util::read_password_hashed("Password", false) util::read_password_hashed("Password", false)
} else { } else {
secret.salt.obtain(&secret.password_helper) secret.salt.obtain_sha256(&secret.password_helper)
}?; }?;
let (secret, _cred) = derive_secret( let (secret, _cred) = derive_secret(
credentials.ids.0.as_slice(), credentials.ids.0.as_slice(),
@ -150,7 +155,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
if interactive || secret.password_helper == PasswordHelper::Stdin { if interactive || secret.password_helper == PasswordHelper::Stdin {
util::read_password_hashed(q, verify) util::read_password_hashed(q, verify)
} else { } else {
secret.salt.obtain(&secret.password_helper) secret.salt.obtain_sha256(&secret.password_helper)
} }
}; };
let other_secret = |salt_q: &str, let other_secret = |salt_q: &str,
@ -267,7 +272,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
if interactive || secret.password_helper == PasswordHelper::Stdin { if interactive || secret.password_helper == PasswordHelper::Stdin {
util::read_password_hashed(q, verify) util::read_password_hashed(q, verify)
} else { } else {
secret.salt.obtain(&secret.password_helper) secret.salt.obtain_sha256(&secret.password_helper)
} }
}; };

View File

@ -1,5 +1,9 @@
use ctap::FidoError; use ctap::FidoError;
use libcryptsetup_rs::LibcryptErr;
use std::io; use std::io;
use std::io::ErrorKind;
use std::string::FromUtf8Error;
use Fido2LuksError::*;
pub type Fido2LuksResult<T> = Result<T, Fido2LuksError>; pub type Fido2LuksResult<T> = Result<T, Fido2LuksError>;
@ -81,11 +85,6 @@ impl From<LuksError> for Fido2LuksError {
} }
} }
use libcryptsetup_rs::LibcryptErr;
use std::io::ErrorKind;
use std::string::FromUtf8Error;
use Fido2LuksError::*;
impl From<FidoError> for Fido2LuksError { impl From<FidoError> for Fido2LuksError {
fn from(e: FidoError) -> Self { fn from(e: FidoError) -> Self {
AuthenticatorError { cause: e } AuthenticatorError { cause: e }

View File

@ -4,7 +4,6 @@ extern crate ctap_hmac as ctap;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
use crate::cli::*; use crate::cli::*;
use crate::config::*;
use crate::device::*; use crate::device::*;
use crate::error::*; use crate::error::*;
use std::io; use std::io;
@ -12,8 +11,6 @@ use std::path::PathBuf;
use std::process::exit; use std::process::exit;
mod cli; mod cli;
mod cli_args;
mod config;
mod device; mod device;
mod error; mod error;
mod luks; mod luks;