From 7b847ea569efad7fdc775ab4518ea502ba4c5e36 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Thu, 28 Apr 2022 23:03:45 +0800 Subject: [PATCH] feat: v1.3.1, add --pgp-auth --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/cmd_sshagent.rs | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d15a36b..ef99f6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,7 +384,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.3.0" +version = "1.3.1" dependencies = [ "authenticator", "base64 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 8878248..a166f65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.3.0" +version = "1.3.1" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_sshagent.rs b/src/cmd_sshagent.rs index bb88575..4018225 100644 --- a/src/cmd_sshagent.rs +++ b/src/cmd_sshagent.rs @@ -23,13 +23,15 @@ lazy_static! { } struct SshAgent { + use_sign: bool, + pin: String, public_key: PublicKey, comment: String, ssh_string: String, } impl SshAgent { - fn new() -> XResult { + fn new(pin: String, use_sign: bool) -> XResult { let mut card = crate::pgpcardutil::get_card()?; let (public_key, comment, ssh_string) = { let mut pgp = OpenPgp::new(&mut card); @@ -38,7 +40,7 @@ impl SshAgent { .map(|d| d.application_id().map(|i| i.serial())) .unwrap_or_else(|_| Ok(0)).unwrap_or_else(|_| 0); let serial = hex::encode(serial.to_be_bytes()); - let public_key = opt_result!(trans.public_key(KeyType::Signing), "Cannot find signing key: {}"); + let public_key = opt_result!(trans.public_key(iff!(use_sign, KeyType::Signing, KeyType::Authentication)), "Cannot find signing key: {}"); let rsa_public_key = match public_key { PublicKeyMaterial::E(_) => return simple_error!("Not supports ec key"), PublicKeyMaterial::R(rsa_public_key) => rsa_public_key, @@ -51,7 +53,7 @@ impl SshAgent { e: with_sign(e.to_vec()), n: with_sign(n.to_vec()), }); - let comment = format!("pgp-card:{}", serial); + let comment = format!("pgp-card:{}:{}", iff!(use_sign, "sign", "auth"), serial); (public_key, comment.clone(), crate::sshutil::generate_ssh_string(e, n, &comment)) }; { @@ -59,6 +61,8 @@ impl SshAgent { *card_mutex = Some(card); } Ok(Self { + use_sign, + pin, public_key, comment, ssh_string, @@ -107,8 +111,15 @@ impl SshAgent { }; let mut pgp = OpenPgp::new(card_mut); let mut trans = opt_result!(pgp.transaction(), "Open card failed: {}"); - opt_result!(trans.verify_pw1_sign("123456".as_bytes()), "User sign pin verify failed: {}"); - let sig = opt_result!(trans.signature_for_hash(hash), "Sign OpenPGP card failed: {}"); + let sig = if self.use_sign { + debugging!("User pin verify for pw1 sign, use sign: {}", self.use_sign); + opt_result!(trans.verify_pw1_sign(self.pin.as_bytes()), "User sign pin verify failed: {}"); + opt_result!(trans.signature_for_hash(hash), "Sign OpenPGP card failed: {}") + } else { + debugging!("User pin verify for pw1 user, use sign: {}", self.use_sign); + opt_result!(trans.verify_pw1_user(self.pin.as_bytes()), "User user pin verify failed: {}"); + opt_result!(trans.authenticate_for_hash(hash), "Auth OpenPGP card failed: {}") + }; debugging!("Signature: {:?}", sig); success!("SSH request sign success"); @@ -144,6 +155,8 @@ impl Command for CommandImpl { SubCommand::with_name(self.name()).about("SSH-Agent subcommand") .arg(Arg::with_name("pin").short("p").long("pin").default_value("123456").help("OpenPGP card user pin")) .arg(Arg::with_name("pgp").long("pgp").help("Use PGP")) + .arg(Arg::with_name("pgp-sign").long("pgp-sign").help("Use PGP sign")) + .arg(Arg::with_name("pgp-auth").long("pgp-auth").help("Use PGP auth")) .arg(Arg::with_name("piv").long("piv").help("Use PIV")) .arg(Arg::with_name("sock-file").long("sock-file").default_value("connect.ssh").help("Sock file, usage SSH_AUTH_SOCK=sock-file ssh ...")) } @@ -154,18 +167,25 @@ impl Command for CommandImpl { if !(use_pgp ^ use_piv) { return simple_error!("Args --pgp or --piv must have one selection"); } + let use_pgp_sign = sub_arg_matches.is_present("pgp-sign"); + let use_pgp_auth = sub_arg_matches.is_present("pgp-auth"); + if use_pgp && !(use_pgp_sign ^ use_pgp_auth) { + return simple_error!("Args --pgp-sign or --pgp-auth must have one selection when use --pgp"); + } + let pin = sub_arg_matches.value_of("pin").unwrap(); let sock_file = sub_arg_matches.value_of("sock-file").unwrap(); information!("Sock file: {}", sock_file); - let sock_file_path = PathBuf::from(sock_file); + let sock_file_path = PathBuf::from("."); match std::fs::canonicalize(sock_file_path) { - Ok(canonicalized_sock_file_path) => information!("SSH_AUTH_SOCK={}", canonicalized_sock_file_path.to_str().unwrap_or_else(|| "-")), + Ok(canonicalized_sock_file_path) => information!("SSH_AUTH_SOCK={}/{}", + canonicalized_sock_file_path.to_str().unwrap_or_else(|| "-"), sock_file), Err(e) => warning!("Get canonicalized sock file path failed: {}", e), } if use_pgp { - let ssh_agent = SshAgent::new()?; + let ssh_agent = SshAgent::new(pin.to_string(), use_pgp_sign)?; information!("{}", &ssh_agent.ssh_string); let _ = remove_file(sock_file);