This commit is contained in:
parent
6c2f5fc7ec
commit
ce43cf857d
106
src/cli.rs
106
src/cli.rs
@ -12,8 +12,10 @@ use std::io::Write;
|
||||
use std::process::exit;
|
||||
use std::thread;
|
||||
|
||||
use crate::luks::LuksDevice;
|
||||
use crate::util::sha256;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashSet;
|
||||
use std::time::SystemTime;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
@ -282,6 +284,41 @@ pub enum Command {
|
||||
/// Check if an authenticator is connected
|
||||
#[structopt(name = "connected")]
|
||||
Connected,
|
||||
Token(TokenCommand),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum TokenCommand {
|
||||
/// List all tokens associated with the specified device
|
||||
List {
|
||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||
device: PathBuf,
|
||||
},
|
||||
/// Add credential to a keyslot
|
||||
Add {
|
||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||
device: PathBuf,
|
||||
#[structopt(flatten)]
|
||||
credentials: Credentials,
|
||||
/// Slot to which the credentials will be added
|
||||
#[structopt(long = "slot", env = "FIDO2LUKS_DEVICE_SLOT")]
|
||||
slot: u32,
|
||||
},
|
||||
/// Remove credentials from token(s)
|
||||
Remove {
|
||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||
device: PathBuf,
|
||||
#[structopt(flatten)]
|
||||
credentials: Credentials,
|
||||
/// Token from which the credentials will be removed
|
||||
#[structopt(long = "token")]
|
||||
token: Option<u32>,
|
||||
},
|
||||
/// Remove all unassigned tokens
|
||||
GC {
|
||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||
device: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn parse_cmdline() -> Args {
|
||||
@ -371,7 +408,9 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
secret.salt.obtain(&secret.password_helper)
|
||||
}
|
||||
};
|
||||
let other_secret = |salt_q: &str, verify: bool| -> Fido2LuksResult<(Vec<u8>, Option<FidoCredential>)> {
|
||||
let other_secret = |salt_q: &str,
|
||||
verify: bool|
|
||||
-> Fido2LuksResult<(Vec<u8>, Option<FidoCredential>)> {
|
||||
match other_secret {
|
||||
OtherSecret {
|
||||
keyfile: Some(file),
|
||||
@ -386,7 +425,10 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
pin.as_deref(),
|
||||
)
|
||||
.map(|(secret, cred)| (secret[..].to_vec(), Some(cred)))?),
|
||||
_ => Ok((util::read_password(salt_q, verify)?.as_bytes().to_vec(), None)),
|
||||
_ => Ok((
|
||||
util::read_password(salt_q, verify)?.as_bytes().to_vec(),
|
||||
None,
|
||||
)),
|
||||
}
|
||||
};
|
||||
let secret = |verify: bool| -> Fido2LuksResult<([u8; 32], FidoCredential)> {
|
||||
@ -399,9 +441,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
};
|
||||
// Non overlap
|
||||
match &args.command {
|
||||
Command::AddKey {
|
||||
exclusive, ..
|
||||
} => {
|
||||
Command::AddKey { exclusive, .. } => {
|
||||
let (existing_secret, _) = other_secret("Current password", false)?;
|
||||
let (new_secret, cred) = secret(true)?;
|
||||
let added_slot = luks::add_key(
|
||||
@ -542,5 +582,61 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
||||
}
|
||||
_ => exit(1),
|
||||
},
|
||||
Command::Token(cmd) => match cmd {
|
||||
TokenCommand::List { device } => {
|
||||
let mut dev = LuksDevice::load(device)?;
|
||||
let mut creds = Vec::new();
|
||||
for token in dev.tokens()? {
|
||||
let (id, token) = token?;
|
||||
for cred in token.credential.iter() {
|
||||
if !creds.contains(cred) {
|
||||
creds.push(cred.clone());
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"{}:\n\tSlots: {}\n\tCredentials: {}",
|
||||
id,
|
||||
if token.keyslots.is_empty() {
|
||||
"None".into()
|
||||
} else {
|
||||
token.keyslots.join(",")
|
||||
},
|
||||
token
|
||||
.credential
|
||||
.iter()
|
||||
.map(|cred| format!(
|
||||
"{} ({})",
|
||||
cred,
|
||||
creds.iter().position(|c| c == cred).unwrap().to_string()
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
TokenCommand::GC { device } => {
|
||||
let mut dev = LuksDevice::load(device)?;
|
||||
let mut creds: HashSet<String> = HashSet::new();
|
||||
let mut remove = Vec::new();
|
||||
for token in dev.tokens()? {
|
||||
let (id, token) = token?;
|
||||
if token.keyslots.is_empty() {
|
||||
creds.extend(token.credential);
|
||||
remove.push(id);
|
||||
}
|
||||
}
|
||||
for id in remove.iter().rev() {
|
||||
dev.remove_token(*id)?;
|
||||
}
|
||||
println!(
|
||||
"Removed {} tokens, affected credentials: {}",
|
||||
remove.len(),
|
||||
creds.into_iter().collect::<Vec<_>>().join(",")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,9 @@ impl LuksDevice {
|
||||
}
|
||||
|
||||
pub fn remove_token(&mut self, token: u32) -> Fido2LuksResult<()> {
|
||||
self.device.token_handle().json_set(TokenInput::RemoveToken(token))?;
|
||||
self.device
|
||||
.token_handle()
|
||||
.json_set(TokenInput::RemoveToken(token))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user