From 84e21aad4e96729408937f9fdde20cfd4f087d1a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 9 Dec 2022 20:56:04 -0800 Subject: [PATCH] Add ability to get the SSH host key and its type. --- libgit2-sys/lib.rs | 4 +++ src/cert.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/libgit2-sys/lib.rs b/libgit2-sys/lib.rs index a113a29526..51e8d7968c 100644 --- a/libgit2-sys/lib.rs +++ b/libgit2-sys/lib.rs @@ -489,6 +489,10 @@ git_enum! { GIT_CERT_SSH_RAW_TYPE_UNKNOWN = 0, GIT_CERT_SSH_RAW_TYPE_RSA = 1, GIT_CERT_SSH_RAW_TYPE_DSS = 2, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 = 3, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 = 4, + GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 = 5, + GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 = 6, } } diff --git a/src/cert.rs b/src/cert.rs index d62b8304ce..b232cc3ce8 100644 --- a/src/cert.rs +++ b/src/cert.rs @@ -27,6 +27,54 @@ pub struct CertX509<'a> { _marker: marker::PhantomData<&'a raw::git_cert>, } +/// The SSH host key type. +#[derive(Copy, Clone, Debug)] +#[non_exhaustive] +pub enum SshHostKeyType { + /// Unknown key type + Unknown = raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN as isize, + /// RSA key type + Rsa = raw::GIT_CERT_SSH_RAW_TYPE_RSA as isize, + /// DSS key type + Dss = raw::GIT_CERT_SSH_RAW_TYPE_DSS as isize, + /// ECDSA 256 key type + Ecdsa256 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 as isize, + /// ECDSA 384 key type + Ecdsa384 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 as isize, + /// ECDSA 521 key type + Ecdsa521 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 as isize, + /// ED25519 key type + Ed255219 = raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 as isize, +} + +impl SshHostKeyType { + /// The name of the key type as encoded in the known_hosts file. + pub fn name(&self) -> &'static str { + match self { + SshHostKeyType::Unknown => "unknown", + SshHostKeyType::Rsa => "ssh-rsa", + SshHostKeyType::Dss => "ssh-dss", + SshHostKeyType::Ecdsa256 => "ecdsa-sha2-nistp256", + SshHostKeyType::Ecdsa384 => "ecdsa-sha2-nistp384", + SshHostKeyType::Ecdsa521 => "ecdsa-sha2-nistp521", + SshHostKeyType::Ed255219 => "ssh-ed25519", + } + } + + /// A short name of the key type, the colloquial form used as a human-readable description. + pub fn short_name(&self) -> &'static str { + match self { + SshHostKeyType::Unknown => "Unknown", + SshHostKeyType::Rsa => "RSA", + SshHostKeyType::Dss => "DSA", + SshHostKeyType::Ecdsa256 => "ECDSA", + SshHostKeyType::Ecdsa384 => "ECDSA", + SshHostKeyType::Ecdsa521 => "ECDSA", + SshHostKeyType::Ed255219 => "ED25519", + } + } +} + impl<'a> Cert<'a> { /// Attempt to view this certificate as an SSH hostkey. /// @@ -87,6 +135,39 @@ impl<'a> CertHostkey<'a> { } } } + + /// Returns the raw host key. + pub fn hostkey(&self) -> Option<&[u8]> { + unsafe { + if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { + return None; + } + Some(slice::from_raw_parts( + (*self.raw).hostkey as *const u8, + (*self.raw).hostkey_len as usize, + )) + } + } + + /// Returns the type of the host key. + pub fn hostkey_type(&self) -> Option { + unsafe { + if (*self.raw).kind & raw::GIT_CERT_SSH_RAW == 0 { + return None; + } + let t = match (*self.raw).raw_type { + raw::GIT_CERT_SSH_RAW_TYPE_UNKNOWN => SshHostKeyType::Unknown, + raw::GIT_CERT_SSH_RAW_TYPE_RSA => SshHostKeyType::Rsa, + raw::GIT_CERT_SSH_RAW_TYPE_DSS => SshHostKeyType::Dss, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256 => SshHostKeyType::Ecdsa256, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_384 => SshHostKeyType::Ecdsa384, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521 => SshHostKeyType::Ecdsa521, + raw::GIT_CERT_SSH_RAW_TYPE_KEY_ED25519 => SshHostKeyType::Ed255219, + t => panic!("unexpected host key type {:?}", t), + }; + Some(t) + } + } } impl<'a> CertX509<'a> {