feat: v1.3.1, add --pgp-auth

This commit is contained in:
2022-04-28 23:03:45 +08:00
parent 74482ae918
commit 7b847ea569
3 changed files with 30 additions and 10 deletions

View File

@@ -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<Self> {
fn new(pin: String, use_sign: bool) -> XResult<Self> {
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);