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