1#![warn(clippy::all)]
19
20use std::fs::File;
21use std::io::BufReader;
22use std::path::Path;
23
24use log::warn;
25pub use no_debug::{Ellipses, NoDebug, WithTypeInfo};
26use pingora_error::{Error, ErrorType, OrErr, Result};
27
28pub use rustls::server::danger::{ClientCertVerified, ClientCertVerifier};
29pub use rustls::server::{
30 ClientCertVerifierBuilder, ClientHello, ResolvesServerCert, WebPkiClientVerifier,
31};
32pub use rustls::sign;
33pub use rustls::{
34 client::WebPkiServerVerifier, crypto::CryptoProvider, version, CertificateError, ClientConfig,
35 DigitallySignedStruct, Error as RusTlsError, KeyLogFile, RootCertStore, ServerConfig,
36 SignatureScheme, Stream,
37};
38
39pub fn install_default_crypto_provider() {
45 let _ = CryptoProvider::install_default(rustls::crypto::ring::default_provider());
46}
47pub use rustls_native_certs::load_native_certs;
48use rustls_pemfile::Item;
49pub use rustls_pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime};
50pub use tokio_rustls::client::TlsStream as ClientTlsStream;
51pub use tokio_rustls::server::TlsStream as ServerTlsStream;
52pub use tokio_rustls::{Accept, Connect, TlsAcceptor, TlsConnector, TlsStream};
53
54pub use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
56
57fn load_file<P>(path: P) -> Result<BufReader<File>>
60where
61 P: AsRef<Path>,
62{
63 File::open(path)
64 .or_err(ErrorType::FileReadError, "Failed to load file")
65 .map(BufReader::new)
66}
67
68fn load_pem_file<P>(path: P) -> Result<Vec<Item>>
70where
71 P: AsRef<Path>,
72{
73 rustls_pemfile::read_all(&mut load_file(path)?)
74 .map(|item_res| {
75 item_res.or_err(
76 ErrorType::InvalidCert,
77 "Certificate in pem file could not be read",
78 )
79 })
80 .collect()
81}
82
83pub fn load_ca_file_into_store<P>(path: P, cert_store: &mut RootCertStore) -> Result<()>
86where
87 P: AsRef<Path>,
88{
89 for pem_item in load_pem_file(path)? {
90 let Item::X509Certificate(content) = pem_item else {
92 return Error::e_explain(
93 ErrorType::InvalidCert,
94 "Pem file contains un-loadable certificate type",
95 );
96 };
97 cert_store.add(content).or_err(
98 ErrorType::InvalidCert,
99 "Failed to load X509 certificate into root store",
100 )?;
101 }
102
103 Ok(())
104}
105
106pub fn load_platform_certs_incl_env_into_store(ca_certs: &mut RootCertStore) -> Result<()> {
108 for cert in load_native_certs()
110 .or_err(ErrorType::InvalidCert, "Failed to load native certificates")?
111 .into_iter()
112 {
113 ca_certs.add(cert).or_err(
114 ErrorType::InvalidCert,
115 "Failed to load native certificate into root store",
116 )?;
117 }
118
119 Ok(())
120}
121
122pub fn load_certs_and_key_files<'a>(
124 cert: &str,
125 key: &str,
126) -> Result<Option<(Vec<CertificateDer<'a>>, PrivateKeyDer<'a>)>> {
127 let certs_file = load_pem_file(cert)?;
128 let key_file = load_pem_file(key)?;
129
130 let certs = certs_file
131 .into_iter()
132 .filter_map(|item| {
133 if let Item::X509Certificate(cert) = item {
134 Some(cert)
135 } else {
136 None
137 }
138 })
139 .collect::<Vec<_>>();
140
141 let private_key_opt = key_file
144 .into_iter()
145 .filter_map(|key_item| match key_item {
146 Item::Pkcs1Key(key) => Some(PrivateKeyDer::from(key)),
147 Item::Pkcs8Key(key) => Some(PrivateKeyDer::from(key)),
148 Item::Sec1Key(key) => Some(PrivateKeyDer::from(key)),
149 _ => None,
150 })
151 .next();
152
153 if let (Some(private_key), false) = (private_key_opt, certs.is_empty()) {
154 Ok(Some((certs, private_key)))
155 } else {
156 Ok(None)
157 }
158}
159
160pub fn load_pem_file_ca(path: &String) -> Result<Vec<u8>> {
162 let mut reader = load_file(path)?;
163 let cas_file_items = rustls_pemfile::certs(&mut reader)
164 .map(|item_res| {
165 item_res.or_err(
166 ErrorType::InvalidCert,
167 "Failed to load certificate from file",
168 )
169 })
170 .collect::<Result<Vec<_>>>()?;
171
172 Ok(cas_file_items
173 .first()
174 .map(|ca| ca.to_vec())
175 .unwrap_or_default())
176}
177
178pub fn load_pem_file_private_key(path: &String) -> Result<Vec<u8>> {
179 Ok(rustls_pemfile::private_key(&mut load_file(path)?)
180 .or_err(
181 ErrorType::InvalidCert,
182 "Failed to load private key from file",
183 )?
184 .map(|key| key.secret_der().to_vec())
185 .unwrap_or_default())
186}
187
188pub fn hash_certificate(cert: &CertificateDer) -> Vec<u8> {
189 let hash = ring::digest::digest(&ring::digest::SHA256, cert.as_ref());
190 hash.as_ref().to_vec()
191}