1#[cfg(feature = "rustls-tls")]
2pub mod rustls_tls {
3 use hyper_rustls::ConfigBuilderExt;
4 use rustls::{
5 self,
6 client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
7 pki_types::{CertificateDer, InvalidDnsNameError, PrivateKeyDer, ServerName},
8 ClientConfig, DigitallySignedStruct,
9 };
10 use thiserror::Error;
11
12 #[derive(Debug, Error)]
14 pub enum Error {
15 #[error("identity PEM is invalid: {0}")]
17 InvalidIdentityPem(#[source] std::io::Error),
18
19 #[error("identity PEM is missing a private key: the key must be PKCS8 or RSA/PKCS1")]
21 MissingPrivateKey,
22
23 #[error("identity PEM is missing certificate")]
25 MissingCertificate,
26
27 #[error("invalid private key: {0}")]
29 InvalidPrivateKey(#[source] rustls::Error),
30
31 #[error("unknown private key format")]
33 UnknownPrivateKeyFormat,
34
35 #[error("failed to add a root certificate: {0}")]
38 AddRootCertificate(#[source] Box<dyn std::error::Error + Send + Sync>),
39
40 #[error("no valid native root CA certificates found")]
42 NoValidNativeRootCA(#[source] std::io::Error),
43
44 #[error("invalid server name: {0}")]
46 InvalidServerName(#[source] InvalidDnsNameError),
47 }
48
49 pub fn rustls_client_config(
51 identity_pem: Option<&[u8]>,
52 root_certs: Option<&[Vec<u8>]>,
53 accept_invalid: bool,
54 ) -> Result<ClientConfig, Error> {
55 let config_builder = if let Some(certs) = root_certs {
56 ClientConfig::builder().with_root_certificates(root_store(certs)?)
57 } else {
58 #[cfg(feature = "webpki-roots")]
59 {
60 ClientConfig::builder().with_webpki_roots()
62 }
63 #[cfg(not(feature = "webpki-roots"))]
64 {
65 ClientConfig::builder()
67 .with_native_roots()
68 .map_err(Error::NoValidNativeRootCA)?
69 }
70 };
71
72 let mut client_config = if let Some((chain, pkey)) = identity_pem.map(client_auth).transpose()? {
73 config_builder
74 .with_client_auth_cert(chain, pkey)
75 .map_err(Error::InvalidPrivateKey)?
76 } else {
77 config_builder.with_no_client_auth()
78 };
79
80 if accept_invalid {
81 client_config
82 .dangerous()
83 .set_certificate_verifier(std::sync::Arc::new(NoCertificateVerification {}));
84 }
85 Ok(client_config)
86 }
87
88 fn root_store(root_certs: &[Vec<u8>]) -> Result<rustls::RootCertStore, Error> {
89 let mut root_store = rustls::RootCertStore::empty();
90 for der in root_certs {
91 root_store
92 .add(CertificateDer::from(der.to_owned()))
93 .map_err(|e| Error::AddRootCertificate(Box::new(e)))?;
94 }
95 Ok(root_store)
96 }
97
98 fn client_auth(data: &[u8]) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>), Error> {
99 use rustls_pemfile::Item;
100
101 let mut cert_chain = Vec::new();
102 let mut pkcs8_key = None;
103 let mut pkcs1_key = None;
104 let mut sec1_key = None;
105 let mut reader = std::io::Cursor::new(data);
106 for item in rustls_pemfile::read_all(&mut reader)
107 .collect::<Result<Vec<_>, _>>()
108 .map_err(Error::InvalidIdentityPem)?
109 {
110 match item {
111 Item::X509Certificate(cert) => cert_chain.push(cert),
112 Item::Pkcs8Key(key) => pkcs8_key = Some(PrivateKeyDer::Pkcs8(key)),
113 Item::Pkcs1Key(key) => pkcs1_key = Some(PrivateKeyDer::from(key)),
114 Item::Sec1Key(key) => sec1_key = Some(PrivateKeyDer::from(key)),
115 _ => return Err(Error::UnknownPrivateKeyFormat),
116 }
117 }
118
119 let private_key = pkcs8_key
120 .or(pkcs1_key)
121 .or(sec1_key)
122 .ok_or(Error::MissingPrivateKey)?;
123 if cert_chain.is_empty() {
124 return Err(Error::MissingCertificate);
125 }
126 Ok((cert_chain, private_key))
127 }
128
129 #[derive(Debug)]
130 struct NoCertificateVerification {}
131
132 impl ServerCertVerifier for NoCertificateVerification {
133 fn verify_server_cert(
134 &self,
135 _end_entity: &CertificateDer,
136 _intermediates: &[CertificateDer],
137 _server_name: &ServerName,
138 _ocsp_response: &[u8],
139 _now: rustls::pki_types::UnixTime,
140 ) -> Result<ServerCertVerified, rustls::Error> {
141 tracing::warn!("Server cert bypassed");
142 Ok(ServerCertVerified::assertion())
143 }
144
145 fn verify_tls13_signature(
146 &self,
147 _message: &[u8],
148 _cert: &CertificateDer,
149 _dss: &DigitallySignedStruct,
150 ) -> Result<HandshakeSignatureValid, rustls::Error> {
151 Ok(HandshakeSignatureValid::assertion())
152 }
153
154 fn verify_tls12_signature(
155 &self,
156 _message: &[u8],
157 _cert: &CertificateDer,
158 _dss: &DigitallySignedStruct,
159 ) -> Result<HandshakeSignatureValid, rustls::Error> {
160 Ok(HandshakeSignatureValid::assertion())
161 }
162
163 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
164 use rustls::SignatureScheme;
165 vec![
166 SignatureScheme::RSA_PKCS1_SHA1,
167 SignatureScheme::ECDSA_SHA1_Legacy,
168 SignatureScheme::RSA_PKCS1_SHA256,
169 SignatureScheme::ECDSA_NISTP256_SHA256,
170 SignatureScheme::RSA_PKCS1_SHA384,
171 SignatureScheme::ECDSA_NISTP384_SHA384,
172 SignatureScheme::RSA_PKCS1_SHA512,
173 SignatureScheme::ECDSA_NISTP521_SHA512,
174 SignatureScheme::RSA_PSS_SHA256,
175 SignatureScheme::RSA_PSS_SHA384,
176 SignatureScheme::RSA_PSS_SHA512,
177 SignatureScheme::ED25519,
178 SignatureScheme::ED448,
179 ]
180 }
181 }
182}
183
184#[cfg(feature = "openssl-tls")]
185pub mod openssl_tls {
186 use openssl::{
187 pkey::PKey,
188 ssl::{SslConnector, SslConnectorBuilder, SslMethod},
189 x509::X509,
190 };
191 use thiserror::Error;
192
193 #[derive(Debug, Error)]
195 pub enum Error {
196 #[error("failed to create OpenSSL HTTPS connector: {0}")]
198 CreateHttpsConnector(#[source] openssl::error::ErrorStack),
199
200 #[error("failed to create OpenSSL SSL connector: {0}")]
202 CreateSslConnector(#[source] SslConnectorError),
203 }
204
205 #[derive(Debug, Error)]
207 pub enum SslConnectorError {
208 #[error("failed to build SslConnectorBuilder: {0}")]
210 CreateBuilder(#[source] openssl::error::ErrorStack),
211
212 #[error("failed to deserialize PEM-encoded chain of certificates: {0}")]
214 DeserializeCertificateChain(#[source] openssl::error::ErrorStack),
215
216 #[error("failed to deserialize PEM-encoded private key: {0}")]
218 DeserializePrivateKey(#[source] openssl::error::ErrorStack),
219
220 #[error("failed to set private key: {0}")]
222 SetPrivateKey(#[source] openssl::error::ErrorStack),
223
224 #[error("failed to get a leaf certificate, the certificate chain is empty")]
226 GetLeafCertificate,
227
228 #[error("failed to set the leaf certificate: {0}")]
230 SetLeafCertificate(#[source] openssl::error::ErrorStack),
231
232 #[error("failed to append a certificate to the chain: {0}")]
234 AppendCertificate(#[source] openssl::error::ErrorStack),
235
236 #[error("failed to deserialize DER-encoded root certificate: {0}")]
238 DeserializeRootCertificate(#[source] openssl::error::ErrorStack),
239
240 #[error("failed to add a root certificate: {0}")]
242 AddRootCertificate(#[source] openssl::error::ErrorStack),
243 }
244
245 pub fn ssl_connector_builder(
247 identity_pem: Option<&Vec<u8>>,
248 root_certs: Option<&Vec<Vec<u8>>>,
249 ) -> Result<SslConnectorBuilder, SslConnectorError> {
250 let mut builder =
251 SslConnector::builder(SslMethod::tls()).map_err(SslConnectorError::CreateBuilder)?;
252 if let Some(pem) = identity_pem {
253 let mut chain = X509::stack_from_pem(pem)
254 .map_err(SslConnectorError::DeserializeCertificateChain)?
255 .into_iter();
256 let leaf_cert = chain.next().ok_or(SslConnectorError::GetLeafCertificate)?;
257 builder
258 .set_certificate(&leaf_cert)
259 .map_err(SslConnectorError::SetLeafCertificate)?;
260 for cert in chain {
261 builder
262 .add_extra_chain_cert(cert)
263 .map_err(SslConnectorError::AppendCertificate)?;
264 }
265
266 let pkey = PKey::private_key_from_pem(pem).map_err(SslConnectorError::DeserializePrivateKey)?;
267 builder
268 .set_private_key(&pkey)
269 .map_err(SslConnectorError::SetPrivateKey)?;
270 }
271
272 if let Some(ders) = root_certs {
273 for der in ders {
274 let cert = X509::from_der(der).map_err(SslConnectorError::DeserializeRootCertificate)?;
275 builder
276 .cert_store_mut()
277 .add_cert(cert)
278 .map_err(SslConnectorError::AddRootCertificate)?;
279 }
280 }
281
282 Ok(builder)
283 }
284}