1 //! Certificate types which are passed to `CertificateCheck` in 2 //! `RemoteCallbacks`. 3 4 use std::marker; 5 use std::mem; 6 use std::slice; 7 8 use crate::raw; 9 use crate::util::Binding; 10 11 /// A certificate for a remote connection, viewable as one of `CertHostkey` or 12 /// `CertX509` currently. 13 pub struct Cert<'a> { 14 raw: *mut raw::git_cert, 15 _marker: marker::PhantomData<&'a raw::git_cert>, 16 } 17 18 /// Hostkey information taken from libssh2 19 pub struct CertHostkey<'a> { 20 raw: *mut raw::git_cert_hostkey, 21 _marker: marker::PhantomData<&'a raw::git_cert>, 22 } 23 24 /// X.509 certificate information 25 pub struct CertX509<'a> { 26 raw: *mut raw::git_cert_x509, 27 _marker: marker::PhantomData<&'a raw::git_cert>, 28 } 29 30 impl<'a> Cert<'a> { 31 /// Attempt to view this certificate as an SSH hostkey. 32 /// 33 /// Returns `None` if this is not actually an SSH hostkey. as_hostkey(&self) -> Option<&CertHostkey<'a>>34 pub fn as_hostkey(&self) -> Option<&CertHostkey<'a>> { 35 self.cast(raw::GIT_CERT_HOSTKEY_LIBSSH2) 36 } 37 38 /// Attempt to view this certificate as an X.509 certificate. 39 /// 40 /// Returns `None` if this is not actually an X.509 certificate. as_x509(&self) -> Option<&CertX509<'a>>41 pub fn as_x509(&self) -> Option<&CertX509<'a>> { 42 self.cast(raw::GIT_CERT_X509) 43 } 44 cast<T>(&self, kind: raw::git_cert_t) -> Option<&T>45 fn cast<T>(&self, kind: raw::git_cert_t) -> Option<&T> { 46 assert_eq!(mem::size_of::<Cert<'a>>(), mem::size_of::<T>()); 47 unsafe { 48 if kind == (*self.raw).cert_type { 49 Some(&*(self as *const Cert<'a> as *const T)) 50 } else { 51 None 52 } 53 } 54 } 55 } 56 57 impl<'a> CertHostkey<'a> { 58 /// Returns the md5 hash of the hostkey, if available. hash_md5(&self) -> Option<&[u8; 16]>59 pub fn hash_md5(&self) -> Option<&[u8; 16]> { 60 unsafe { 61 if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_MD5 as u32 == 0 { 62 None 63 } else { 64 Some(&(*self.raw).hash_md5) 65 } 66 } 67 } 68 69 /// Returns the SHA-1 hash of the hostkey, if available. hash_sha1(&self) -> Option<&[u8; 20]>70 pub fn hash_sha1(&self) -> Option<&[u8; 20]> { 71 unsafe { 72 if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA1 as u32 == 0 { 73 None 74 } else { 75 Some(&(*self.raw).hash_sha1) 76 } 77 } 78 } 79 80 /// Returns the SHA-256 hash of the hostkey, if available. hash_sha256(&self) -> Option<&[u8; 32]>81 pub fn hash_sha256(&self) -> Option<&[u8; 32]> { 82 unsafe { 83 if (*self.raw).kind as u32 & raw::GIT_CERT_SSH_SHA256 as u32 == 0 { 84 None 85 } else { 86 Some(&(*self.raw).hash_sha256) 87 } 88 } 89 } 90 } 91 92 impl<'a> CertX509<'a> { 93 /// Return the X.509 certificate data as a byte slice data(&self) -> &[u8]94 pub fn data(&self) -> &[u8] { 95 unsafe { slice::from_raw_parts((*self.raw).data as *const u8, (*self.raw).len as usize) } 96 } 97 } 98 99 impl<'a> Binding for Cert<'a> { 100 type Raw = *mut raw::git_cert; from_raw(raw: *mut raw::git_cert) -> Cert<'a>101 unsafe fn from_raw(raw: *mut raw::git_cert) -> Cert<'a> { 102 Cert { 103 raw, 104 _marker: marker::PhantomData, 105 } 106 } raw(&self) -> *mut raw::git_cert107 fn raw(&self) -> *mut raw::git_cert { 108 self.raw 109 } 110 } 111