1 | use crate::crypto::CryptoProvider; |
2 | use crate::error::Error; |
3 | use crate::versions; |
4 | |
5 | use alloc::format; |
6 | use core::fmt; |
7 | use core::marker::PhantomData; |
8 | use std::sync::Arc; |
9 | |
10 | #[cfg (doc)] |
11 | use crate::{ClientConfig, ServerConfig}; |
12 | |
13 | /// A [builder] for [`ServerConfig`] or [`ClientConfig`] values. |
14 | /// |
15 | /// To get one of these, call [`ServerConfig::builder()`] or [`ClientConfig::builder()`]. |
16 | /// |
17 | /// To build a config, you must make at least two decisions (in order): |
18 | /// |
19 | /// - How should this client or server verify certificates provided by its peer? |
20 | /// - What certificates should this client or server present to its peer? |
21 | /// |
22 | /// For settings besides these, see the fields of [`ServerConfig`] and [`ClientConfig`]. |
23 | /// |
24 | /// The usual choice for protocol primitives is to call |
25 | /// [`ClientConfig::builder`]/[`ServerConfig::builder`] |
26 | /// which will use rustls' default cryptographic provider and safe defaults for ciphersuites and |
27 | /// supported protocol versions. |
28 | /// |
29 | /// ``` |
30 | /// # #[cfg (feature = "ring" )] { |
31 | /// use rustls::{ClientConfig, ServerConfig}; |
32 | /// ClientConfig::builder() |
33 | /// // ... |
34 | /// # ; |
35 | /// |
36 | /// ServerConfig::builder() |
37 | /// // ... |
38 | /// # ; |
39 | /// # } |
40 | /// ``` |
41 | /// |
42 | /// You may also override the choice of protocol versions: |
43 | /// |
44 | /// ```no_run |
45 | /// # #[cfg (feature = "ring" )] { |
46 | /// # use rustls::ServerConfig; |
47 | /// ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13]) |
48 | /// // ... |
49 | /// # ; |
50 | /// # } |
51 | /// ``` |
52 | /// |
53 | /// Overriding the default cryptographic provider introduces a `Result` that must be unwrapped, |
54 | /// because the config builder checks for consistency of the choices made. For instance, it's an error to |
55 | /// configure only TLS 1.2 cipher suites while specifying that TLS 1.3 should be the only supported protocol |
56 | /// version. |
57 | /// |
58 | /// If you configure a smaller set of protocol primitives than the default, you may get a smaller binary, |
59 | /// since the code for the unused ones can be optimized away at link time. |
60 | /// |
61 | /// After choosing protocol primitives, you must choose (a) how to verify certificates and (b) what certificates |
62 | /// (if any) to send to the peer. The methods to do this are specific to whether you're building a ClientConfig |
63 | /// or a ServerConfig, as tracked by the [`ConfigSide`] type parameter on the various impls of ConfigBuilder. |
64 | /// |
65 | /// # ClientConfig certificate configuration |
66 | /// |
67 | /// For a client, _certificate verification_ must be configured either by calling one of: |
68 | /// - [`ConfigBuilder::with_root_certificates`] or |
69 | /// - [`ConfigBuilder::dangerous()`] and [`DangerousClientConfigBuilder::with_custom_certificate_verifier`] |
70 | /// |
71 | /// Next, _certificate sending_ (also known as "client authentication", "mutual TLS", or "mTLS") must be configured |
72 | /// or disabled using one of: |
73 | /// - [`ConfigBuilder::with_no_client_auth`] - to not send client authentication (most common) |
74 | /// - [`ConfigBuilder::with_client_auth_cert`] - to always send a specific certificate |
75 | /// - [`ConfigBuilder::with_client_cert_resolver`] - to send a certificate chosen dynamically |
76 | /// |
77 | /// For example: |
78 | /// |
79 | /// ``` |
80 | /// # #[cfg (feature = "ring" )] { |
81 | /// # use rustls::ClientConfig; |
82 | /// # let root_certs = rustls::RootCertStore::empty(); |
83 | /// ClientConfig::builder() |
84 | /// .with_root_certificates(root_certs) |
85 | /// .with_no_client_auth(); |
86 | /// # } |
87 | /// ``` |
88 | /// |
89 | /// # ServerConfig certificate configuration |
90 | /// |
91 | /// For a server, _certificate verification_ must be configured by calling one of: |
92 | /// - [`ConfigBuilder::with_no_client_auth`] - to not require client authentication (most common) |
93 | /// - [`ConfigBuilder::with_client_cert_verifier`] - to use a custom verifier |
94 | /// |
95 | /// Next, _certificate sending_ must be configured by calling one of: |
96 | /// - [`ConfigBuilder::with_single_cert`] - to send a specific certificate |
97 | /// - [`ConfigBuilder::with_single_cert_with_ocsp`] - to send a specific certificate, plus stapled OCSP |
98 | /// - [`ConfigBuilder::with_cert_resolver`] - to send a certificate chosen dynamically |
99 | /// |
100 | /// For example: |
101 | /// |
102 | /// ```no_run |
103 | /// # #[cfg (feature = "ring" )] { |
104 | /// # use rustls::ServerConfig; |
105 | /// # let certs = vec![]; |
106 | /// # let private_key = pki_types::PrivateKeyDer::from( |
107 | /// # pki_types::PrivatePkcs8KeyDer::from(vec![]) |
108 | /// # ); |
109 | /// ServerConfig::builder() |
110 | /// .with_no_client_auth() |
111 | /// .with_single_cert(certs, private_key) |
112 | /// .expect("bad certificate/key" ); |
113 | /// # } |
114 | /// ``` |
115 | /// |
116 | /// # Types |
117 | /// |
118 | /// ConfigBuilder uses the [typestate] pattern to ensure at compile time that each required |
119 | /// configuration item is provided exactly once. This is tracked in the `State` type parameter, |
120 | /// which can have these values: |
121 | /// |
122 | /// - [`WantsVersions`] |
123 | /// - [`WantsVerifier`] |
124 | /// - [`WantsClientCert`] |
125 | /// - [`WantsServerCert`] |
126 | /// |
127 | /// The other type parameter is `Side`, which is either `ServerConfig` or `ClientConfig` |
128 | /// depending on whether the ConfigBuilder was built with [`ServerConfig::builder()`] or |
129 | /// [`ClientConfig::builder()`]. |
130 | /// |
131 | /// You won't need to write out either of these type parameters explicitly. If you write a |
132 | /// correct chain of configuration calls they will be used automatically. If you write an |
133 | /// incorrect chain of configuration calls you will get an error message from the compiler |
134 | /// mentioning some of these types. |
135 | /// |
136 | /// Additionally, ServerConfig and ClientConfig carry a private field containing a |
137 | /// [`CryptoProvider`], from [`ClientConfig::builder_with_provider()`] or |
138 | /// [`ServerConfig::builder_with_provider()`]. This determines which cryptographic backend |
139 | /// is used. The default is [`ring::provider`]. |
140 | /// |
141 | /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html |
142 | /// [typestate]: http://cliffle.com/blog/rust-typestate/ |
143 | /// [`ServerConfig`]: crate::ServerConfig |
144 | /// [`ServerConfig::builder`]: crate::ServerConfig::builder |
145 | /// [`ClientConfig`]: crate::ClientConfig |
146 | /// [`ClientConfig::builder()`]: crate::ClientConfig::builder() |
147 | /// [`ServerConfig::builder()`]: crate::ServerConfig::builder() |
148 | /// [`ClientConfig::builder_with_provider()`]: crate::ClientConfig::builder_with_provider() |
149 | /// [`ServerConfig::builder_with_provider()`]: crate::ServerConfig::builder_with_provider() |
150 | /// [`ConfigBuilder<ClientConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-3 |
151 | /// [`ConfigBuilder<ServerConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-6 |
152 | /// [`WantsClientCert`]: crate::client::WantsClientCert |
153 | /// [`WantsServerCert`]: crate::server::WantsServerCert |
154 | /// [`ring::provider`]: crate::crypto::ring::default_provider |
155 | /// [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]: crate::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier |
156 | #[derive (Clone)] |
157 | pub struct ConfigBuilder<Side: ConfigSide, State> { |
158 | pub(crate) state: State, |
159 | pub(crate) side: PhantomData<Side>, |
160 | } |
161 | |
162 | impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> { |
163 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
164 | let side_name: &str = core::any::type_name::<Side>(); |
165 | let (ty: &str, _) = side_name |
166 | .split_once('<' ) |
167 | .unwrap_or((side_name, "" )); |
168 | let (_, name: &str) = ty.rsplit_once("::" ).unwrap_or(("" , ty)); |
169 | |
170 | f&mut DebugStruct<'_, '_>.debug_struct(&format!("ConfigBuilder< {}, _>" , name,)) |
171 | .field(name:"state" , &self.state) |
172 | .finish() |
173 | } |
174 | } |
175 | |
176 | /// Config builder state where the caller must supply TLS protocol versions. |
177 | /// |
178 | /// For more information, see the [`ConfigBuilder`] documentation. |
179 | #[derive (Clone, Debug)] |
180 | pub struct WantsVersions { |
181 | pub(crate) provider: Arc<CryptoProvider>, |
182 | } |
183 | |
184 | impl<S: ConfigSide> ConfigBuilder<S, WantsVersions> { |
185 | /// Accept the default protocol versions: both TLS1.2 and TLS1.3 are enabled. |
186 | pub fn with_safe_default_protocol_versions( |
187 | self, |
188 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
189 | self.with_protocol_versions(versions::DEFAULT_VERSIONS) |
190 | } |
191 | |
192 | /// Use a specific set of protocol versions. |
193 | pub fn with_protocol_versions( |
194 | self, |
195 | versions: &[&'static versions::SupportedProtocolVersion], |
196 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
197 | let mut any_usable_suite = false; |
198 | for suite in &self.state.provider.cipher_suites { |
199 | if versions.contains(&suite.version()) { |
200 | any_usable_suite = true; |
201 | break; |
202 | } |
203 | } |
204 | |
205 | if !any_usable_suite { |
206 | return Err(Error::General("no usable cipher suites configured" .into())); |
207 | } |
208 | |
209 | if self.state.provider.kx_groups.is_empty() { |
210 | return Err(Error::General("no kx groups configured" .into())); |
211 | } |
212 | |
213 | Ok(ConfigBuilder { |
214 | state: WantsVerifier { |
215 | provider: self.state.provider, |
216 | versions: versions::EnabledVersions::new(versions), |
217 | }, |
218 | side: self.side, |
219 | }) |
220 | } |
221 | } |
222 | |
223 | /// Config builder state where the caller must supply a verifier. |
224 | /// |
225 | /// For more information, see the [`ConfigBuilder`] documentation. |
226 | #[derive (Clone, Debug)] |
227 | pub struct WantsVerifier { |
228 | pub(crate) provider: Arc<CryptoProvider>, |
229 | pub(crate) versions: versions::EnabledVersions, |
230 | } |
231 | |
232 | /// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`]. |
233 | /// |
234 | /// [`ClientConfig`]: crate::ClientConfig |
235 | /// [`ServerConfig`]: crate::ServerConfig |
236 | pub trait ConfigSide: sealed::Sealed {} |
237 | |
238 | impl ConfigSide for crate::ClientConfig {} |
239 | impl ConfigSide for crate::ServerConfig {} |
240 | |
241 | mod sealed { |
242 | pub trait Sealed {} |
243 | impl Sealed for crate::ClientConfig {} |
244 | impl Sealed for crate::ServerConfig {} |
245 | } |
246 | |