1use rustls::pki_types::{CertificateDer, PrivateKeyDer};
2use rustls::server::WebPkiClientVerifier;
3use rustls::{ClientConfig, RootCertStore, ServerConfig};
4use rustls_pemfile::{certs, private_key};
5use std::fs::File;
6use std::io::{BufReader, Cursor};
7use std::path::Path;
8use std::sync::Arc;
9
10use crate::TunnelError;
11
12fn load_certs(path: &Path) -> Result<Vec<CertificateDer<'static>>, TunnelError> {
14 let file = File::open(path).map_err(|e| {
15 TunnelError::Certificate(format!("Failed to open cert file {:?}: {}", path, e))
16 })?;
17 let mut reader = BufReader::new(file);
18 certs(&mut reader)
19 .collect::<Result<Vec<_>, _>>()
20 .map_err(|e| TunnelError::Certificate(format!("Failed to parse certificates: {}", e)))
21}
22
23fn load_private_key(path: &Path) -> Result<PrivateKeyDer<'static>, TunnelError> {
25 let file = File::open(path).map_err(|e| {
26 TunnelError::Certificate(format!("Failed to open key file {:?}: {}", path, e))
27 })?;
28 let mut reader = BufReader::new(file);
29 private_key(&mut reader)
30 .map_err(|e| TunnelError::Certificate(format!("Failed to parse private key: {}", e)))?
31 .ok_or_else(|| TunnelError::Certificate("No private key found in file".to_string()))
32}
33
34fn load_root_store(ca_path: &Path) -> Result<RootCertStore, TunnelError> {
36 let ca_certs = load_certs(ca_path)?;
37 let mut root_store = RootCertStore::empty();
38 for cert in ca_certs {
39 root_store.add(cert).map_err(|e| {
40 TunnelError::Certificate(format!("Failed to add CA certificate: {}", e))
41 })?;
42 }
43 Ok(root_store)
44}
45
46pub fn load_certs_from_pem(pem_content: &str) -> Result<Vec<CertificateDer<'static>>, TunnelError> {
52 let mut cursor = Cursor::new(pem_content.as_bytes());
53 certs(&mut cursor)
54 .collect::<Result<Vec<_>, _>>()
55 .map_err(|e| TunnelError::Certificate(format!("Failed to parse certificates: {}", e)))
56}
57
58pub fn load_private_key_from_pem(pem_content: &str) -> Result<PrivateKeyDer<'static>, TunnelError> {
60 let mut cursor = Cursor::new(pem_content.as_bytes());
61 private_key(&mut cursor)
62 .map_err(|e| TunnelError::Certificate(format!("Failed to parse private key: {}", e)))?
63 .ok_or_else(|| TunnelError::Certificate("No private key found in PEM content".to_string()))
64}
65
66fn load_root_store_from_pem(pem_content: &str) -> Result<RootCertStore, TunnelError> {
68 let ca_certs = load_certs_from_pem(pem_content)?;
69 let mut root_store = RootCertStore::empty();
70 for cert in ca_certs {
71 root_store.add(cert).map_err(|e| {
72 TunnelError::Certificate(format!("Failed to add CA certificate: {}", e))
73 })?;
74 }
75 Ok(root_store)
76}
77
78pub fn load_server_config(
85 cert_path: &Path,
86 key_path: &Path,
87 ca_path: &Path,
88) -> Result<ServerConfig, TunnelError> {
89 let certs = load_certs(cert_path)?;
90 let key = load_private_key(key_path)?;
91 let root_store = load_root_store(ca_path)?;
92
93 let client_verifier = WebPkiClientVerifier::builder(Arc::new(root_store))
95 .build()
96 .map_err(|e| TunnelError::Tls(format!("Failed to build client verifier: {}", e)))?;
97
98 let config = ServerConfig::builder()
99 .with_client_cert_verifier(client_verifier)
100 .with_single_cert(certs, key)
101 .map_err(|e| TunnelError::Tls(format!("Failed to build server config: {}", e)))?;
102
103 Ok(config)
104}
105
106pub fn load_client_config(
113 cert_path: &Path,
114 key_path: &Path,
115 ca_path: &Path,
116) -> Result<ClientConfig, TunnelError> {
117 let certs = load_certs(cert_path)?;
118 let key = load_private_key(key_path)?;
119 let root_store = load_root_store(ca_path)?;
120
121 let config = ClientConfig::builder()
122 .with_root_certificates(root_store)
123 .with_client_auth_cert(certs, key)
124 .map_err(|e| TunnelError::Tls(format!("Failed to build client config: {}", e)))?;
125
126 Ok(config)
127}
128
129pub fn load_server_config_from_pem(
136 cert_pem: &str,
137 key_pem: &str,
138 ca_pem: &str,
139) -> Result<ServerConfig, TunnelError> {
140 let certs = load_certs_from_pem(cert_pem)?;
141 let key = load_private_key_from_pem(key_pem)?;
142 let root_store = load_root_store_from_pem(ca_pem)?;
143
144 let client_verifier = WebPkiClientVerifier::builder(Arc::new(root_store))
146 .build()
147 .map_err(|e| TunnelError::Tls(format!("Failed to build client verifier: {}", e)))?;
148
149 let config = ServerConfig::builder()
150 .with_client_cert_verifier(client_verifier)
151 .with_single_cert(certs, key)
152 .map_err(|e| TunnelError::Tls(format!("Failed to build server config: {}", e)))?;
153
154 Ok(config)
155}
156
157pub fn load_server_config_no_client_auth(
165 cert_pem: &str,
166 key_pem: &str,
167) -> Result<ServerConfig, TunnelError> {
168 let certs = load_certs_from_pem(cert_pem)?;
169 let key = load_private_key_from_pem(key_pem)?;
170
171 let config = ServerConfig::builder()
172 .with_no_client_auth()
173 .with_single_cert(certs, key)
174 .map_err(|e| TunnelError::Tls(format!("Failed to build server config: {}", e)))?;
175
176 Ok(config)
177}
178
179pub fn load_client_config_from_pem(
186 cert_pem: &str,
187 key_pem: &str,
188 ca_pem: &str,
189) -> Result<ClientConfig, TunnelError> {
190 let certs = load_certs_from_pem(cert_pem)?;
191 let key = load_private_key_from_pem(key_pem)?;
192 let root_store = load_root_store_from_pem(ca_pem)?;
193
194 let config = ClientConfig::builder()
195 .with_root_certificates(root_store)
196 .with_client_auth_cert(certs, key)
197 .map_err(|e| TunnelError::Tls(format!("Failed to build client config: {}", e)))?;
198
199 Ok(config)
200}
201
202#[allow(dead_code)]
204pub fn extract_cn(cert: &rustls::pki_types::CertificateDer<'_>) -> Option<String> {
205 let _ = cert;
212 None
213}