diff --git a/src/fingerprint/error.rs b/src/fingerprint/error.rs index 2b08cd9..8149a75 100644 --- a/src/fingerprint/error.rs +++ b/src/fingerprint/error.rs @@ -4,6 +4,7 @@ use {std::fmt, x509_parser::prelude::X509Error}; /// Errors which can occur when fingerprinting a certificate pub enum Error { Fmt, + InvalidForDate, X509(X509Error), } @@ -11,6 +12,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Fmt => write!(f, "FingerPrint: format error"), + Self::InvalidForDate => write!(f, "FingerPrint: invalid for date"), Self::X509(e) => write!(f, "FingerPrint: {e}"), } } @@ -19,8 +21,8 @@ impl fmt::Display for Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Self::Fmt => None, Self::X509(e) => Some(e), + _ => None, } } } diff --git a/src/fingerprint/mod.rs b/src/fingerprint/mod.rs index d25c7c8..7fc4fe4 100644 --- a/src/fingerprint/mod.rs +++ b/src/fingerprint/mod.rs @@ -1,21 +1,37 @@ -use {digest::Digest, rustls::Certificate, sha2::Sha256, std::fmt::Write, x509_parser::prelude::*}; +use {digest::Digest, rustls::Certificate, sha2::Sha256, std::{io::Read, fmt::Write}, x509_parser::prelude::*}; mod error; pub use error::Error; /// Creates an sha256 fingerprint for a certificate -pub trait Fingerprint { +pub trait GetFingerprint { type Error; - fn fingerprint(&self) -> Result<(String, String), Self::Error>; + fn fingerprint(&self) -> Result; } -impl Fingerprint for Certificate { +pub struct Fingerprint { + pub names: Vec, + pub fingerprint: String, +} + +impl GetFingerprint for Certificate { type Error = Error; - fn fingerprint(&self) -> Result<(String, String), Self::Error> { + fn fingerprint(&self) -> Result { let (_, pk) = X509Certificate::from_der(self.as_ref())?; - let subject = pk.subject().to_string(); + let subject = pk.subject(); + let mut names = vec![]; + subject.iter_common_name().for_each(|n| { + let mut val = n.attr_value().data; + let mut name = String::new(); + if let Ok(_) = val.read_to_string(&mut name) { + names.push(name); + } + }); + if !pk.validity().is_valid() { + return Err(Error::InvalidForDate); + } let key = pk.public_key().subject_public_key.as_ref(); let mut hasher = Sha256::new(); hasher.update(key); @@ -24,6 +40,6 @@ impl Fingerprint for Certificate { for c in res { write!(s, "{c:02x}")?; } - Ok((subject[3..].to_string(), s)) + Ok(Fingerprint { names, fingerprint: s }) } } diff --git a/src/prelude.rs b/src/prelude.rs index 3b93bf8..8f57e98 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,6 +1,6 @@ pub use super::{ certificate_store::CertificateStore, - fingerprint::{Error as FingerprintError, Fingerprint}, + fingerprint::{Error as FingerprintError, Fingerprint, GetFingerprint}, host::{Error as ParseHostError, Host}, //receiver, request::{Error as ParseRequestError, Request}, diff --git a/src/sender/verifier.rs b/src/sender/verifier.rs index f1893b4..a0bda39 100644 --- a/src/sender/verifier.rs +++ b/src/sender/verifier.rs @@ -1,5 +1,5 @@ use { - crate::prelude::{CertificateStore, Fingerprint}, + crate::prelude::{CertificateStore, Fingerprint, GetFingerprint}, rustls::{ client::{ServerCertVerified, ServerCertVerifier}, Certificate, @@ -40,17 +40,22 @@ impl ServerCertVerifier for Verifier { let mut store = self.store.lock().unwrap(); if let Some(fingerprint) = store.get_certificate(&name) { // TODO: needs a lot more checking for certificate validity - if fingerprint == fp.1 && name == fp.0 { - return Ok(ServerCertVerified::assertion()); + if fingerprint == fp.fingerprint { + for n in fp.names { + if n == name { + return Ok(ServerCertVerified::assertion()); + } + } + Err(rustls::Error::InvalidCertificate(rustls::CertificateError::NotValidForName)) + } else { + Err(rustls::Error::InvalidCertificate(rustls::CertificateError::NotValidForName)) } } else { if !store.contains_certificate(&name) { - let _key = store.borrow_mut().insert_certificate(&name, &fp.1); + let _key = store.borrow_mut().insert_certificate(&name, &fp.fingerprint); } + return Ok(ServerCertVerified::assertion()); } - Err(rustls::Error::General( - "Unrecognized certificate".to_string(), - )) } }