feat: actual cert verification ignoring UnknownIssuer
This commit is contained in:
parent
0e8d023880
commit
8e8fa85206
3 changed files with 62 additions and 9 deletions
|
@ -1,5 +1,6 @@
|
|||
//! Custom verifier for Rustls accepting any TLS cert
|
||||
//! (usually called "insecure mode")
|
||||
//! Custom verifier for Rustls allowing self-signed certs
|
||||
//! but performing other required checks;
|
||||
//! mostly for internal use
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -9,6 +10,8 @@ use tokio_rustls::rustls::{
|
|||
crypto::CryptoProvider,
|
||||
};
|
||||
|
||||
use webpki::EndEntityCert;
|
||||
|
||||
/// Custom verifier for Rustls accepting any TLS certificate
|
||||
#[derive(Debug)]
|
||||
pub struct InternalCertVerifier(Arc<CryptoProvider>);
|
||||
|
@ -39,15 +42,42 @@ impl From<Arc<CryptoProvider>> for InternalCertVerifier {
|
|||
}
|
||||
|
||||
impl ServerCertVerifier for InternalCertVerifier {
|
||||
#[inline]
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_end_entity: &rustls::pki_types::CertificateDer<'_>,
|
||||
end_entity: &rustls::pki_types::CertificateDer<'_>,
|
||||
_intermediates: &[rustls::pki_types::CertificateDer<'_>],
|
||||
_server_name: &rustls::pki_types::ServerName<'_>,
|
||||
server_name: &rustls::pki_types::ServerName<'_>,
|
||||
_ocsp_response: &[u8],
|
||||
_now: rustls::pki_types::UnixTime,
|
||||
now: rustls::pki_types::UnixTime,
|
||||
) -> Result<ServerCertVerified, rustls::Error> {
|
||||
let cert = EndEntityCert::try_from(end_entity).map_err(pki_error)?;
|
||||
|
||||
match cert.verify_for_usage(
|
||||
self.0.signature_verification_algorithms.all,
|
||||
&[], // no trusted anchors (i.e. CAs)
|
||||
&[], // i think there's no point in passing intermediates without CAs
|
||||
now, // `now` as the time for expiration check
|
||||
webpki::KeyUsage::server_auth(),
|
||||
None, // no CRLs
|
||||
None, // no verify_path callback
|
||||
) {
|
||||
Ok(_) => Ok(()), // unreachable
|
||||
Err(webpki::Error::UnknownIssuer) => {
|
||||
// trust anchors verification is done after
|
||||
// any other issuer-independent checks (including expiration),
|
||||
// so this error can be safely ignored as
|
||||
// we are working with self-signed certificates.
|
||||
// for reference -- fn webpki::verify_cert::build_chain_inner
|
||||
// (NOTE: should be re-checked on every rustls update)
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
.map_err(pki_error)?;
|
||||
|
||||
cert.verify_is_valid_for_subject_name(server_name)
|
||||
.map_err(pki_error)?;
|
||||
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
|
||||
|
@ -86,3 +116,24 @@ impl ServerCertVerifier for InternalCertVerifier {
|
|||
self.0.signature_verification_algorithms.supported_schemes()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pki_error(e: webpki::Error) -> rustls::CertificateError {
|
||||
// partially copied from private fn rustls::webpki::pki_error(e)
|
||||
use rustls::{CertificateError, OtherError};
|
||||
use webpki::Error::*;
|
||||
match e {
|
||||
BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding,
|
||||
CertNotValidYet => CertificateError::NotValidYet,
|
||||
CertExpired | InvalidCertValidity => CertificateError::Expired,
|
||||
UnknownIssuer => CertificateError::UnknownIssuer,
|
||||
CertNotValidForName => CertificateError::NotValidForName,
|
||||
CertRevoked => CertificateError::Revoked,
|
||||
UnknownRevocationStatus => CertificateError::UnknownRevocationStatus,
|
||||
|
||||
InvalidSignatureForPublicKey
|
||||
| UnsupportedSignatureAlgorithm
|
||||
| UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature,
|
||||
|
||||
_ => CertificateError::Other(OtherError(Arc::new(e))),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue