131 lines
4.5 KiB
Rust
131 lines
4.5 KiB
Rust
use std::fmt;
|
|
use std::io;
|
|
use yubikey::{piv::RetiredSlotId, Serial};
|
|
|
|
use crate::util::slot_to_ui;
|
|
|
|
pub enum Error {
|
|
CustomManagementKey,
|
|
InvalidFlagCommand(String, String),
|
|
InvalidFlagTui(String),
|
|
InvalidPinLength,
|
|
InvalidPinPolicy(String),
|
|
InvalidSlot(u8),
|
|
InvalidTouchPolicy(String),
|
|
Io(io::Error),
|
|
MultipleCommands,
|
|
MultipleYubiKeys,
|
|
NoEmptySlots(Serial),
|
|
NoMatchingSerial(Serial),
|
|
SlotHasNoIdentity(RetiredSlotId),
|
|
SlotIsNotEmpty(RetiredSlotId),
|
|
TimedOut,
|
|
UseListForSingleSlot,
|
|
YubiKey(yubikey::Error),
|
|
}
|
|
|
|
impl From<io::Error> for Error {
|
|
fn from(e: io::Error) -> Self {
|
|
Error::Io(e)
|
|
}
|
|
}
|
|
|
|
impl From<yubikey::Error> for Error {
|
|
fn from(e: yubikey::Error) -> Self {
|
|
Error::YubiKey(e)
|
|
}
|
|
}
|
|
|
|
// Rust only supports `fn main() -> Result<(), E: Debug>`, so we implement `Debug`
|
|
// manually to provide the error output we want.
|
|
impl fmt::Debug for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Error::CustomManagementKey => {
|
|
writeln!(f, "Custom unprotected management keys are not supported.")?
|
|
}
|
|
Error::InvalidFlagCommand(flag, command) => {
|
|
writeln!(f, "Flag '{}' cannot be used with '{}'.", flag, command)?
|
|
}
|
|
Error::InvalidFlagTui(flag) => writeln!(
|
|
f,
|
|
"Flag '{}' cannot be used with the interactive interface.",
|
|
flag
|
|
)?,
|
|
Error::InvalidPinLength => writeln!(f, "The PIN needs to be 1-8 characters.")?,
|
|
Error::InvalidPinPolicy(s) => writeln!(
|
|
f,
|
|
"Invalid PIN policy '{}' (expected [always, once, never]).",
|
|
s
|
|
)?,
|
|
Error::InvalidSlot(slot) => writeln!(
|
|
f,
|
|
"Invalid slot '{}' (expected number between 1 and 20).",
|
|
slot
|
|
)?,
|
|
Error::InvalidTouchPolicy(s) => writeln!(
|
|
f,
|
|
"Invalid touch policy '{}' (expected [always, cached, never]).",
|
|
s
|
|
)?,
|
|
Error::Io(e) => writeln!(f, "Failed to set up YubiKey: {}", e)?,
|
|
Error::MultipleCommands => writeln!(
|
|
f,
|
|
"Only one of --generate, --identity, --list, --list-all can be specified."
|
|
)?,
|
|
Error::MultipleYubiKeys => writeln!(
|
|
f,
|
|
"Multiple YubiKeys are plugged in. Use --serial to select a single YubiKey."
|
|
)?,
|
|
Error::NoEmptySlots(serial) => {
|
|
writeln!(f, "YubiKey with serial {} has no empty slots.", serial)?
|
|
}
|
|
Error::NoMatchingSerial(serial) => {
|
|
writeln!(f, "Could not find YubiKey with serial {}.", serial)?
|
|
}
|
|
Error::SlotHasNoIdentity(slot) => writeln!(
|
|
f,
|
|
"Slot {} does not contain an age identity or compatible key.",
|
|
slot_to_ui(slot)
|
|
)?,
|
|
Error::SlotIsNotEmpty(slot) => writeln!(
|
|
f,
|
|
"Slot {} is not empty. Use --force to overwrite the slot.",
|
|
slot_to_ui(slot)
|
|
)?,
|
|
Error::TimedOut => {
|
|
writeln!(f, "Timed out while waiting for a YubiKey to be inserted.")?
|
|
}
|
|
Error::UseListForSingleSlot => {
|
|
writeln!(f, "Use --list to print the recipient for a single slot.")?
|
|
}
|
|
Error::YubiKey(e) => match e {
|
|
yubikey::Error::NotFound => {
|
|
writeln!(f, "Please insert the YubiKey you want to set up")?
|
|
}
|
|
yubikey::Error::WrongPin { tries } => writeln!(
|
|
f,
|
|
"Invalid PIN ({} tries remaining before it is blocked)",
|
|
tries
|
|
)?,
|
|
e => {
|
|
writeln!(f, "Error while communicating with YubiKey: {}", e)?;
|
|
use std::error::Error;
|
|
if let Some(inner) = e.source() {
|
|
writeln!(f, "Cause: {}", inner)?;
|
|
}
|
|
}
|
|
},
|
|
}
|
|
writeln!(f)?;
|
|
writeln!(
|
|
f,
|
|
"[ Did this not do what you expected? Could an error be more useful? ]"
|
|
)?;
|
|
write!(
|
|
f,
|
|
"[ Tell us: https://str4d.xyz/age-plugin-yubikey/report ]"
|
|
)
|
|
}
|
|
}
|