rustls/client/
builder.rs

1use crate::builder::{ConfigBuilder, WantsVerifier};
2use crate::client::{handy, ClientConfig, ResolvesClientCert};
3use crate::error::Error;
4use crate::key_log::NoKeyLog;
5use crate::kx::SupportedKxGroup;
6use crate::suites::SupportedCipherSuite;
7use crate::verify::{self, CertificateTransparencyPolicy};
8use crate::{anchors, key, versions};
9
10use super::client_conn::Resumption;
11
12use std::marker::PhantomData;
13use std::sync::Arc;
14use std::time::SystemTime;
15
16impl ConfigBuilder<ClientConfig, WantsVerifier> {
17    /// Choose how to verify server certificates.
18    pub fn with_root_certificates(
19        self,
20        root_store: impl Into<Arc<anchors::RootCertStore>>,
21    ) -> ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert> {
22        ConfigBuilder {
23            state: WantsTransparencyPolicyOrClientCert {
24                cipher_suites: self.state.cipher_suites,
25                kx_groups: self.state.kx_groups,
26                versions: self.state.versions,
27                root_store: root_store.into(),
28            },
29            side: PhantomData,
30        }
31    }
32
33    #[cfg(feature = "dangerous_configuration")]
34    /// Set a custom certificate verifier.
35    pub fn with_custom_certificate_verifier(
36        self,
37        verifier: Arc<dyn verify::ServerCertVerifier>,
38    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
39        ConfigBuilder {
40            state: WantsClientCert {
41                cipher_suites: self.state.cipher_suites,
42                kx_groups: self.state.kx_groups,
43                versions: self.state.versions,
44                verifier,
45            },
46            side: PhantomData,
47        }
48    }
49}
50
51/// A config builder state where the caller needs to supply a certificate transparency policy or
52/// client certificate resolver.
53///
54/// In this state, the caller can optionally enable certificate transparency, or ignore CT and
55/// invoke one of the methods related to client certificates (as in the [`WantsClientCert`] state).
56///
57/// For more information, see the [`ConfigBuilder`] documentation.
58#[derive(Clone, Debug)]
59pub struct WantsTransparencyPolicyOrClientCert {
60    cipher_suites: Vec<SupportedCipherSuite>,
61    kx_groups: Vec<&'static SupportedKxGroup>,
62    versions: versions::EnabledVersions,
63    root_store: Arc<anchors::RootCertStore>,
64}
65
66impl ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert> {
67    /// Set Certificate Transparency logs to use for server certificate validation.
68    ///
69    /// Because Certificate Transparency logs are sharded on a per-year basis and can be trusted or
70    /// distrusted relatively quickly, rustls stores a validation deadline. Server certificates will
71    /// be validated against the configured CT logs until the deadline expires. After the deadline,
72    /// certificates will no longer be validated, and a warning message will be logged. The deadline
73    /// may vary depending on how often you deploy builds with updated dependencies.
74    pub fn with_certificate_transparency_logs(
75        self,
76        logs: &'static [&'static sct::Log],
77        validation_deadline: SystemTime,
78    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
79        self.with_logs(Some(CertificateTransparencyPolicy::new(
80            logs,
81            validation_deadline,
82        )))
83    }
84
85    /// Sets a single certificate chain and matching private key for use
86    /// in client authentication.
87    ///
88    /// `cert_chain` is a vector of DER-encoded certificates.
89    /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key.
90    ///
91    /// This function fails if `key_der` is invalid.
92    pub fn with_client_auth_cert(
93        self,
94        cert_chain: Vec<key::Certificate>,
95        key_der: key::PrivateKey,
96    ) -> Result<ClientConfig, Error> {
97        self.with_logs(None)
98            .with_client_auth_cert(cert_chain, key_der)
99    }
100
101    /// Sets a single certificate chain and matching private key for use
102    /// in client authentication.
103    ///
104    /// `cert_chain` is a vector of DER-encoded certificates.
105    /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key.
106    ///
107    /// This function fails if `key_der` is invalid.
108    #[deprecated(since = "0.21.4", note = "Use `with_client_auth_cert` instead")]
109    pub fn with_single_cert(
110        self,
111        cert_chain: Vec<key::Certificate>,
112        key_der: key::PrivateKey,
113    ) -> Result<ClientConfig, Error> {
114        self.with_client_auth_cert(cert_chain, key_der)
115    }
116
117    /// Do not support client auth.
118    pub fn with_no_client_auth(self) -> ClientConfig {
119        self.with_logs(None)
120            .with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
121    }
122
123    /// Sets a custom [`ResolvesClientCert`].
124    pub fn with_client_cert_resolver(
125        self,
126        client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
127    ) -> ClientConfig {
128        self.with_logs(None)
129            .with_client_cert_resolver(client_auth_cert_resolver)
130    }
131
132    fn with_logs(
133        self,
134        ct_policy: Option<CertificateTransparencyPolicy>,
135    ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
136        ConfigBuilder {
137            state: WantsClientCert {
138                cipher_suites: self.state.cipher_suites,
139                kx_groups: self.state.kx_groups,
140                versions: self.state.versions,
141                verifier: Arc::new(verify::WebPkiVerifier::new(
142                    self.state.root_store,
143                    ct_policy,
144                )),
145            },
146            side: PhantomData,
147        }
148    }
149}
150
151/// A config builder state where the caller needs to supply whether and how to provide a client
152/// certificate.
153///
154/// For more information, see the [`ConfigBuilder`] documentation.
155#[derive(Clone, Debug)]
156pub struct WantsClientCert {
157    cipher_suites: Vec<SupportedCipherSuite>,
158    kx_groups: Vec<&'static SupportedKxGroup>,
159    versions: versions::EnabledVersions,
160    verifier: Arc<dyn verify::ServerCertVerifier>,
161}
162
163impl ConfigBuilder<ClientConfig, WantsClientCert> {
164    /// Sets a single certificate chain and matching private key for use
165    /// in client authentication.
166    ///
167    /// `cert_chain` is a vector of DER-encoded certificates.
168    /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key.
169    ///
170    /// This function fails if `key_der` is invalid.
171    pub fn with_client_auth_cert(
172        self,
173        cert_chain: Vec<key::Certificate>,
174        key_der: key::PrivateKey,
175    ) -> Result<ClientConfig, Error> {
176        let resolver = handy::AlwaysResolvesClientCert::new(cert_chain, &key_der)?;
177        Ok(self.with_client_cert_resolver(Arc::new(resolver)))
178    }
179
180    /// Sets a single certificate chain and matching private key for use
181    /// in client authentication.
182    ///
183    /// `cert_chain` is a vector of DER-encoded certificates.
184    /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key.
185    ///
186    /// This function fails if `key_der` is invalid.
187    #[deprecated(since = "0.21.4", note = "Use `with_client_auth_cert` instead")]
188    pub fn with_single_cert(
189        self,
190        cert_chain: Vec<key::Certificate>,
191        key_der: key::PrivateKey,
192    ) -> Result<ClientConfig, Error> {
193        self.with_client_auth_cert(cert_chain, key_der)
194    }
195
196    /// Do not support client auth.
197    pub fn with_no_client_auth(self) -> ClientConfig {
198        self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
199    }
200
201    /// Sets a custom [`ResolvesClientCert`].
202    pub fn with_client_cert_resolver(
203        self,
204        client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
205    ) -> ClientConfig {
206        ClientConfig {
207            cipher_suites: self.state.cipher_suites,
208            kx_groups: self.state.kx_groups,
209            alpn_protocols: Vec::new(),
210            resumption: Resumption::default(),
211            max_fragment_size: None,
212            client_auth_cert_resolver,
213            versions: self.state.versions,
214            enable_sni: true,
215            verifier: self.state.verifier,
216            key_log: Arc::new(NoKeyLog {}),
217            #[cfg(feature = "secret_extraction")]
218            enable_secret_extraction: false,
219            enable_early_data: false,
220        }
221    }
222}