| //! Certificate types which are passed to `CertificateCheck` in |
| //! `RemoteCallbacks`. |
| |
| use std::marker; |
| use std::mem; |
| use std::slice; |
| |
| use crate::raw; |
| use crate::util::Binding; |
| |
| /// A certificate for a remote connection, viewable as one of `CertHostkey` or |
| /// `CertX509` currently. |
| pub struct Cert<'a> { |
| raw: *mut raw::git_cert, |
| _marker: marker::PhantomData<&'a raw::git_cert>, |
| } |
| |
| /// Hostkey information taken from libssh2 |
| pub struct CertHostkey<'a> { |
| raw: *mut raw::git_cert_hostkey, |
| _marker: marker::PhantomData<&'a raw::git_cert>, |
| } |
| |
| /// X.509 certificate information |
| pub struct CertX509<'a> { |
| raw: *mut raw::git_cert_x509, |
| _marker: marker::PhantomData<&'a raw::git_cert>, |
| } |
| |
| impl<'a> Cert<'a> { |
| /// Attempt to view this certificate as an SSH hostkey. |
| /// |
| /// Returns `None` if this is not actually an SSH hostkey. |
| pub fn as_hostkey(&self) -> Option<&CertHostkey<'a>> { |
| self.cast(raw::GIT_CERT_HOSTKEY_LIBSSH2) |
| } |
| |
| /// Attempt to view this certificate as an X.509 certificate. |
| /// |
| /// Returns `None` if this is not actually an X.509 certificate. |
| pub fn as_x509(&self) -> Option<&CertX509<'a>> { |
| self.cast(raw::GIT_CERT_X509) |
| } |
| |
| fn cast<T>(&self, kind: raw::git_cert_t) -> Option<&T> { |
| assert_eq!(mem::size_of::<Cert<'a>>(), mem::size_of::<T>()); |
| unsafe { |
| if kind == (*self.raw).cert_type { |
| Some(&*(self as *const Cert<'a> as *const T)) |
| } else { |
| None |
| } |
| } |
| } |
| } |
| |
| impl<'a> CertHostkey<'a> { |
| /// Returns the md5 hash of the hostkey, if available. |
| pub fn hash_md5(&self) -> Option<&[u8; 16]> { |
| unsafe { |
| if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_MD5 as u32 == 0 { |
| None |
| } else { |
| Some(&(*self.raw).hash_md5) |
| } |
| } |
| } |
| |
| /// Returns the SHA-1 hash of the hostkey, if available. |
| pub fn hash_sha1(&self) -> Option<&[u8; 20]> { |
| unsafe { |
| if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA1 as u32 == 0 { |
| None |
| } else { |
| Some(&(*self.raw).hash_sha1) |
| } |
| } |
| } |
| |
| /// Returns the SHA-256 hash of the hostkey, if available. |
| pub fn hash_sha256(&self) -> Option<&[u8; 32]> { |
| unsafe { |
| if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA256 as u32 == 0 { |
| None |
| } else { |
| Some(&(*self.raw).hash_sha256) |
| } |
| } |
| } |
| } |
| |
| impl<'a> CertX509<'a> { |
| /// Return the X.509 certificate data as a byte slice |
| pub fn data(&self) -> &[u8] { |
| unsafe { slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).len as usize) } |
| } |
| } |
| |
| impl<'a> Binding for Cert<'a> { |
| type Raw = *mut raw::git_cert; |
| unsafe fn from_raw(raw: *mut raw::git_cert) -> Cert<'a> { |
| Cert { |
| raw, |
| _marker: marker::PhantomData, |
| } |
| } |
| fn raw(&self) -> *mut raw::git_cert { |
| self.raw |
| } |
| } |