feat: v1.7.1

This commit is contained in:
2023-08-26 14:16:09 +08:00
parent 4b6352759b
commit 8e2dce9b39
3 changed files with 124 additions and 18 deletions

View File

@@ -1,13 +1,23 @@
use clap::{App, ArgMatches, SubCommand};
use clap::{App, Arg, ArgMatches, SubCommand};
use rust_util::util_clap::{Command, CommandError};
use rust_util::XResult;
use spki::der::Encode;
use tabled::{Table, Tabled};
use x509_parser::parse_x509_certificate;
use yubikey::{Certificate, YubiKey};
use yubikey::piv::SlotId;
use crate::pivutil::get_algorithm_id;
#[derive(Tabled)]
struct PivSlot {
name: String,
id: String,
algorithm: String,
subject: String,
}
pub struct CommandImpl;
impl Command for CommandImpl {
@@ -15,9 +25,14 @@ impl Command for CommandImpl {
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("PIV subcommand")
.arg(Arg::with_name("table").long("table").help("Show table"))
.arg(Arg::with_name("all").long("all").help("Show all"))
}
fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError {
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let show_table = sub_arg_matches.is_present("table");
let show_all = sub_arg_matches.is_present("all");
let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
success!("Name: {}", yk.name());
information!("Version: {}", yk.version());
@@ -42,35 +57,53 @@ impl Command for CommandImpl {
Err(e) => failure!("Get PIV keys failed: {}", e)
}
let mut piv_slots = vec![];
for slot in yubikey::piv::SLOTS {
print_summary_info(&mut yk, slot).ok();
print_summary_info(&mut yk, slot, &mut piv_slots, show_all, show_table).ok();
}
if show_table {
println!("{}", Table::new(piv_slots).to_string());
}
Ok(None)
}
}
fn print_summary_info(yubikey: &mut YubiKey, slot: SlotId) -> XResult<()> {
fn print_summary_info(yubikey: &mut YubiKey, slot: SlotId, piv_slots: &mut Vec<PivSlot>, show_all: bool, show_table: bool) -> XResult<()> {
let slot_id: u8 = slot.into();
let cert = match Certificate::read(yubikey, slot) {
Ok(c) => c,
Err(e) => {
warning!("Slot: {:?}, id: {:x}, certificate not found", slot, slot_id);
if show_all {
if show_table {
piv_slots.push(PivSlot {
name: slot.to_string(),
id: format!("{:x}", slot_id),
algorithm: "N/A".to_string(),
subject: "N/A".to_string(),
});
} else {
warning!("Slot: {:?}, id: {:x}, certificate not found", slot, slot_id);
}
}
return simple_error!("error reading certificate in slot {:?}: {}", slot, e);
}
};
let buf_vec = cert.cert.to_der()?;
let buf: &[u8] = buf_vec.as_ref();
if buf.is_empty() {
warning!("Slot: {:?}, id: {:x}, certificate buffer empty", slot, slot_id);
let algorithm_id = get_algorithm_id(&cert.cert.tbs_certificate.subject_public_key_info)
.map(|aid| format!("{:?}", aid))
.unwrap_or_else(|e| format!("Error: {}", e));
let cert_subject = match parse_x509_certificate(&buf_vec) {
Ok((_rem, cert)) => cert.subject.to_string(),
_ => cert.cert.tbs_certificate.subject.to_string(),
};
if show_table {
piv_slots.push(PivSlot {
name: slot.to_string(),
id: format!("{:x}", slot_id),
algorithm: algorithm_id,
subject: cert_subject,
});
} else {
let slot_id: u8 = slot.into();
let algorithm_id = get_algorithm_id(&cert.cert.tbs_certificate.subject_public_key_info)
.map(|aid| format!("{:?}", aid))
.unwrap_or_else(|e| format!("Error: {}", e));
let cert_subject = match parse_x509_certificate(buf) {
Ok((_rem, cert)) => cert.subject.to_string(),
_ => cert.cert.tbs_certificate.subject.to_string(),
};
success!("Slot: {:?}, id: {:x}, algorithm: {}, subject: {}", slot, slot_id, algorithm_id, cert_subject);
}