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