use super::ResolvesClientCert; #[cfg(feature = "logging")] use crate::log::{debug, trace}; use crate::msgs::enums::ExtensionType; use crate::msgs::handshake::CertificatePayload; use crate::msgs::handshake::SCTList; use crate::msgs::handshake::ServerExtension; use crate::{sign, DistinguishedNames, SignatureScheme}; use std::sync::Arc; #[derive(Debug)] pub(super) struct ServerCertDetails { pub(super) cert_chain: CertificatePayload, pub(super) ocsp_response: Vec, pub(super) scts: Option, } impl ServerCertDetails { pub(super) fn new( cert_chain: CertificatePayload, ocsp_response: Vec, scts: Option, ) -> Self { Self { cert_chain, ocsp_response, scts, } } pub(super) fn scts(&self) -> impl Iterator { self.scts .as_deref() .unwrap_or(&[]) .iter() .map(|payload| payload.0.as_slice()) } } pub(super) struct ClientHelloDetails { pub(super) sent_extensions: Vec, } impl ClientHelloDetails { pub(super) fn new() -> Self { Self { sent_extensions: Vec::new(), } } pub(super) fn server_may_send_sct_list(&self) -> bool { self.sent_extensions .contains(&ExtensionType::SCT) } pub(super) fn server_sent_unsolicited_extensions( &self, received_exts: &[ServerExtension], allowed_unsolicited: &[ExtensionType], ) -> bool { for ext in received_exts { let ext_type = ext.get_type(); if !self.sent_extensions.contains(&ext_type) && !allowed_unsolicited.contains(&ext_type) { trace!("Unsolicited extension {:?}", ext_type); return true; } } false } } pub(super) enum ClientAuthDetails { /// Send an empty `Certificate` and no `CertificateVerify`. Empty { auth_context_tls13: Option> }, /// Send a non-empty `Certificate` and a `CertificateVerify`. Verify { certkey: Arc, signer: Box, auth_context_tls13: Option>, }, } impl ClientAuthDetails { pub(super) fn resolve( resolver: &dyn ResolvesClientCert, canames: Option<&DistinguishedNames>, sigschemes: &[SignatureScheme], auth_context_tls13: Option>, ) -> Self { let acceptable_issuers = canames .map(Vec::as_slice) .unwrap_or_default() .iter() .map(|p| p.0.as_slice()) .collect::>(); if let Some(certkey) = resolver.resolve(&acceptable_issuers, sigschemes) { if let Some(signer) = certkey.key.choose_scheme(sigschemes) { debug!("Attempting client auth"); return Self::Verify { certkey, signer, auth_context_tls13, }; } } debug!("Client auth requested but no cert/sigscheme available"); Self::Empty { auth_context_tls13 } } }