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

74
Cargo.lock generated
View File

@@ -275,6 +275,12 @@ version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "bytecount"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@@ -314,7 +320,7 @@ dependencies = [
[[package]] [[package]]
name = "card-cli" name = "card-cli"
version = "1.7.0" version = "1.7.1"
dependencies = [ dependencies = [
"authenticator", "authenticator",
"base64 0.21.2", "base64 0.21.2",
@@ -339,6 +345,7 @@ dependencies = [
"simpledateformat", "simpledateformat",
"spki 0.7.2", "spki 0.7.2",
"ssh-agent", "ssh-agent",
"tabled",
"u2f", "u2f",
"x509", "x509",
"x509-parser", "x509-parser",
@@ -940,6 +947,12 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.19" version = "0.1.19"
@@ -1570,6 +1583,17 @@ dependencies = [
"sha2", "sha2",
] ]
[[package]]
name = "papergrid"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8"
dependencies = [
"bytecount",
"fnv",
"unicode-width",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.9.0" version = "0.9.0"
@@ -1771,6 +1795,30 @@ dependencies = [
"elliptic-curve", "elliptic-curve",
] ]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote 1.0.33",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote 1.0.33",
"version_check",
]
[[package]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.4.3" version = "0.4.3"
@@ -2430,6 +2478,30 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "tabled"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfe9c3632da101aba5131ed63f9eed38665f8b3c68703a6bb18124835c1a5d22"
dependencies = [
"papergrid",
"tabled_derive",
"unicode-width",
]
[[package]]
name = "tabled_derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote 1.0.33",
"syn 1.0.109",
]
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.8.0" version = "3.8.0"

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "card-cli" name = "card-cli"
version = "1.7.0" version = "1.7.1"
authors = ["Hatter Jiang <jht5945@gmail.com>"] authors = ["Hatter Jiang <jht5945@gmail.com>"]
edition = "2018" edition = "2018"
@@ -33,6 +33,7 @@ x509-parser = "0.15"
ssh-agent = { version = "0.2", features = ["agent"] } ssh-agent = { version = "0.2", features = ["agent"] }
p256 = { version = "0.13", features = ["pem", "ecdh"] } p256 = { version = "0.13", features = ["pem", "ecdh"] }
spki = { version = "0.7", features = ["pem"] } spki = { version = "0.7", features = ["pem"] }
tabled = "0.14.0"
#lazy_static = "1.4.0" #lazy_static = "1.4.0"
#ssh-key = "0.4.0" #ssh-key = "0.4.0"
#ctap-hid-fido2 = "2.1.3" #ctap-hid-fido2 = "2.1.3"

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::util_clap::{Command, CommandError};
use rust_util::XResult; use rust_util::XResult;
use spki::der::Encode; use spki::der::Encode;
use tabled::{Table, Tabled};
use x509_parser::parse_x509_certificate; use x509_parser::parse_x509_certificate;
use yubikey::{Certificate, YubiKey}; use yubikey::{Certificate, YubiKey};
use yubikey::piv::SlotId; use yubikey::piv::SlotId;
use crate::pivutil::get_algorithm_id; use crate::pivutil::get_algorithm_id;
#[derive(Tabled)]
struct PivSlot {
name: String,
id: String,
algorithm: String,
subject: String,
}
pub struct CommandImpl; pub struct CommandImpl;
impl Command for CommandImpl { impl Command for CommandImpl {
@@ -15,9 +25,14 @@ impl Command for CommandImpl {
fn subcommand<'a>(&self) -> App<'a, 'a> { fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("PIV subcommand") 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: {}"); let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}");
success!("Name: {}", yk.name()); success!("Name: {}", yk.name());
information!("Version: {}", yk.version()); information!("Version: {}", yk.version());
@@ -42,35 +57,53 @@ impl Command for CommandImpl {
Err(e) => failure!("Get PIV keys failed: {}", e) Err(e) => failure!("Get PIV keys failed: {}", e)
} }
let mut piv_slots = vec![];
for slot in yubikey::piv::SLOTS { 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) 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 slot_id: u8 = slot.into();
let cert = match Certificate::read(yubikey, slot) { let cert = match Certificate::read(yubikey, slot) {
Ok(c) => c, Ok(c) => c,
Err(e) => { 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); return simple_error!("error reading certificate in slot {:?}: {}", slot, e);
} }
}; };
let buf_vec = cert.cert.to_der()?; let buf_vec = cert.cert.to_der()?;
let buf: &[u8] = buf_vec.as_ref(); let algorithm_id = get_algorithm_id(&cert.cert.tbs_certificate.subject_public_key_info)
if buf.is_empty() { .map(|aid| format!("{:?}", aid))
warning!("Slot: {:?}, id: {:x}, certificate buffer empty", slot, slot_id); .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 { } 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); success!("Slot: {:?}, id: {:x}, algorithm: {}, subject: {}", slot, slot_id, algorithm_id, cert_subject);
} }