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] rustls::pki_types::pem::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::pki_types::pem::{self, SectionKind};
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 while let Some((kind, der)) = pem::from_buf(&mut reader).map_err(Error::InvalidIdentityPem)? {
107 match kind {
108 SectionKind::Certificate => cert_chain.push(der.into()),
109 SectionKind::PrivateKey => pkcs8_key = Some(PrivateKeyDer::Pkcs8(der.into())),
110 SectionKind::RsaPrivateKey => pkcs1_key = Some(PrivateKeyDer::Pkcs1(der.into())),
111 SectionKind::EcPrivateKey => sec1_key = Some(PrivateKeyDer::Sec1(der.into())),
112 _ => return Err(Error::UnknownPrivateKeyFormat),
113 }
114 }
115
116 let private_key = pkcs8_key
117 .or(pkcs1_key)
118 .or(sec1_key)
119 .ok_or(Error::MissingPrivateKey)?;
120 if cert_chain.is_empty() {
121 return Err(Error::MissingCertificate);
122 }
123 Ok((cert_chain, private_key))
124 }
125
126 #[derive(Debug)]
127 struct NoCertificateVerification {}
128
129 impl ServerCertVerifier for NoCertificateVerification {
130 fn verify_server_cert(
131 &self,
132 _end_entity: &CertificateDer,
133 _intermediates: &[CertificateDer],
134 _server_name: &ServerName,
135 _ocsp_response: &[u8],
136 _now: rustls::pki_types::UnixTime,
137 ) -> Result<ServerCertVerified, rustls::Error> {
138 tracing::warn!("Server cert bypassed");
139 Ok(ServerCertVerified::assertion())
140 }
141
142 fn verify_tls13_signature(
143 &self,
144 _message: &[u8],
145 _cert: &CertificateDer,
146 _dss: &DigitallySignedStruct,
147 ) -> Result<HandshakeSignatureValid, rustls::Error> {
148 Ok(HandshakeSignatureValid::assertion())
149 }
150
151 fn verify_tls12_signature(
152 &self,
153 _message: &[u8],
154 _cert: &CertificateDer,
155 _dss: &DigitallySignedStruct,
156 ) -> Result<HandshakeSignatureValid, rustls::Error> {
157 Ok(HandshakeSignatureValid::assertion())
158 }
159
160 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
161 use rustls::SignatureScheme;
162 vec![
163 SignatureScheme::RSA_PKCS1_SHA1,
164 SignatureScheme::ECDSA_SHA1_Legacy,
165 SignatureScheme::RSA_PKCS1_SHA256,
166 SignatureScheme::ECDSA_NISTP256_SHA256,
167 SignatureScheme::RSA_PKCS1_SHA384,
168 SignatureScheme::ECDSA_NISTP384_SHA384,
169 SignatureScheme::RSA_PKCS1_SHA512,
170 SignatureScheme::ECDSA_NISTP521_SHA512,
171 SignatureScheme::RSA_PSS_SHA256,
172 SignatureScheme::RSA_PSS_SHA384,
173 SignatureScheme::RSA_PSS_SHA512,
174 SignatureScheme::ED25519,
175 SignatureScheme::ED448,
176 ]
177 }
178 }
179}
180
181#[cfg(feature = "openssl-tls")]
182pub mod openssl_tls {
183 use openssl::{
184 pkey::PKey,
185 ssl::{SslConnector, SslConnectorBuilder, SslMethod},
186 x509::X509,
187 };
188 use thiserror::Error;
189
190 #[derive(Debug, Error)]
192 pub enum Error {
193 #[error("failed to create OpenSSL HTTPS connector: {0}")]
195 CreateHttpsConnector(#[source] openssl::error::ErrorStack),
196
197 #[error("failed to create OpenSSL SSL connector: {0}")]
199 CreateSslConnector(#[source] SslConnectorError),
200 }
201
202 #[derive(Debug, Error)]
204 pub enum SslConnectorError {
205 #[error("failed to build SslConnectorBuilder: {0}")]
207 CreateBuilder(#[source] openssl::error::ErrorStack),
208
209 #[error("failed to deserialize PEM-encoded chain of certificates: {0}")]
211 DeserializeCertificateChain(#[source] openssl::error::ErrorStack),
212
213 #[error("failed to deserialize PEM-encoded private key: {0}")]
215 DeserializePrivateKey(#[source] openssl::error::ErrorStack),
216
217 #[error("failed to set private key: {0}")]
219 SetPrivateKey(#[source] openssl::error::ErrorStack),
220
221 #[error("failed to get a leaf certificate, the certificate chain is empty")]
223 GetLeafCertificate,
224
225 #[error("failed to set the leaf certificate: {0}")]
227 SetLeafCertificate(#[source] openssl::error::ErrorStack),
228
229 #[error("failed to append a certificate to the chain: {0}")]
231 AppendCertificate(#[source] openssl::error::ErrorStack),
232
233 #[error("failed to deserialize DER-encoded root certificate: {0}")]
235 DeserializeRootCertificate(#[source] openssl::error::ErrorStack),
236
237 #[error("failed to add a root certificate: {0}")]
239 AddRootCertificate(#[source] openssl::error::ErrorStack),
240 }
241
242 pub fn ssl_connector_builder(
244 identity_pem: Option<&Vec<u8>>,
245 root_certs: Option<&Vec<Vec<u8>>>,
246 ) -> Result<SslConnectorBuilder, SslConnectorError> {
247 let mut builder =
248 SslConnector::builder(SslMethod::tls()).map_err(SslConnectorError::CreateBuilder)?;
249 if let Some(pem) = identity_pem {
250 let mut chain = X509::stack_from_pem(pem)
251 .map_err(SslConnectorError::DeserializeCertificateChain)?
252 .into_iter();
253 let leaf_cert = chain.next().ok_or(SslConnectorError::GetLeafCertificate)?;
254 builder
255 .set_certificate(&leaf_cert)
256 .map_err(SslConnectorError::SetLeafCertificate)?;
257 for cert in chain {
258 builder
259 .add_extra_chain_cert(cert)
260 .map_err(SslConnectorError::AppendCertificate)?;
261 }
262
263 let pkey = PKey::private_key_from_pem(pem).map_err(SslConnectorError::DeserializePrivateKey)?;
264 builder
265 .set_private_key(&pkey)
266 .map_err(SslConnectorError::SetPrivateKey)?;
267 }
268
269 if let Some(ders) = root_certs {
270 for der in ders {
271 let cert = X509::from_der(der).map_err(SslConnectorError::DeserializeRootCertificate)?;
272 builder
273 .cert_store_mut()
274 .add_cert(cert)
275 .map_err(SslConnectorError::AddRootCertificate)?;
276 }
277 }
278
279 Ok(builder)
280 }
281}