use alloc::sync::Arc;
use alloc::vec::Vec;
use core::marker::PhantomData;
use pki_types::{CertificateDer, PrivateKeyDer};
use super::client_conn::Resumption;
use crate::builder::{ConfigBuilder, WantsVerifier};
use crate::client::{handy, ClientConfig, EchMode, ResolvesClientCert};
use crate::crypto::CryptoProvider;
use crate::error::Error;
use crate::key_log::NoKeyLog;
use crate::msgs::handshake::CertificateChain;
use crate::time_provider::TimeProvider;
use crate::versions::TLS13;
use crate::webpki::{self, WebPkiServerVerifier};
use crate::{compress, verify, versions, WantsVersions};
impl ConfigBuilder<ClientConfig, WantsVersions> {
pub fn with_ech(
self,
mode: EchMode,
) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
let mut res = self.with_protocol_versions(&[&TLS13][..])?;
res.state.client_ech_mode = Some(mode);
Ok(res)
}
}
impl ConfigBuilder<ClientConfig, WantsVerifier> {
pub fn with_root_certificates(
self,
root_store: impl Into<Arc<webpki::RootCertStore>>,
) -> ConfigBuilder<ClientConfig, WantsClientCert> {
let algorithms = self
.state
.provider
.signature_verification_algorithms;
self.with_webpki_verifier(
WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
)
}
pub fn with_webpki_verifier(
self,
verifier: Arc<WebPkiServerVerifier>,
) -> ConfigBuilder<ClientConfig, WantsClientCert> {
ConfigBuilder {
state: WantsClientCert {
provider: self.state.provider,
versions: self.state.versions,
verifier,
time_provider: self.state.time_provider,
client_ech_mode: self.state.client_ech_mode,
},
side: PhantomData,
}
}
pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
danger::DangerousClientConfigBuilder { cfg: self }
}
}
pub(super) mod danger {
use alloc::sync::Arc;
use core::marker::PhantomData;
use crate::client::WantsClientCert;
use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier};
#[derive(Debug)]
pub struct DangerousClientConfigBuilder {
pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
}
impl DangerousClientConfigBuilder {
pub fn with_custom_certificate_verifier(
self,
verifier: Arc<dyn verify::ServerCertVerifier>,
) -> ConfigBuilder<ClientConfig, WantsClientCert> {
ConfigBuilder {
state: WantsClientCert {
provider: self.cfg.state.provider,
versions: self.cfg.state.versions,
verifier,
time_provider: self.cfg.state.time_provider,
client_ech_mode: self.cfg.state.client_ech_mode,
},
side: PhantomData,
}
}
}
}
#[derive(Clone)]
pub struct WantsClientCert {
provider: Arc<CryptoProvider>,
versions: versions::EnabledVersions,
verifier: Arc<dyn verify::ServerCertVerifier>,
time_provider: Arc<dyn TimeProvider>,
client_ech_mode: Option<EchMode>,
}
impl ConfigBuilder<ClientConfig, WantsClientCert> {
pub fn with_client_auth_cert(
self,
cert_chain: Vec<CertificateDer<'static>>,
key_der: PrivateKeyDer<'static>,
) -> Result<ClientConfig, Error> {
let private_key = self
.state
.provider
.key_provider
.load_private_key(key_der)?;
let resolver =
handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?;
Ok(self.with_client_cert_resolver(Arc::new(resolver)))
}
pub fn with_no_client_auth(self) -> ClientConfig {
self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
}
pub fn with_client_cert_resolver(
self,
client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
) -> ClientConfig {
ClientConfig {
provider: self.state.provider,
alpn_protocols: Vec::new(),
resumption: Resumption::default(),
max_fragment_size: None,
client_auth_cert_resolver,
versions: self.state.versions,
enable_sni: true,
verifier: self.state.verifier,
key_log: Arc::new(NoKeyLog {}),
enable_secret_extraction: false,
enable_early_data: false,
#[cfg(feature = "tls12")]
require_ems: cfg!(feature = "fips"),
time_provider: self.state.time_provider,
cert_compressors: compress::default_cert_compressors().to_vec(),
cert_compression_cache: Arc::new(compress::CompressionCache::default()),
cert_decompressors: compress::default_cert_decompressors().to_vec(),
ech_mode: self.state.client_ech_mode,
}
}
}