1use std::env;
2use std::ffi::{OsStr, OsString};
3use std::path::{Path, PathBuf};
4
5pub unsafe fn try_init_openssl_env_vars() -> bool {
26 let ProbeResult {
27 cert_file,
28 cert_dir,
29 } = probe();
30 if let Some(path) = &cert_file {
33 unsafe {
34 put(ENV_CERT_FILE, path.as_os_str());
35 }
36 }
37
38 if !cert_dir.is_empty() {
39 let mut joined = OsString::new();
40 for (i, path) in cert_dir.iter().enumerate() {
41 if i != 0 {
42 joined.push(":");
43 }
44 joined.push(path.as_os_str());
45 }
46
47 unsafe {
48 put(ENV_CERT_DIR, &joined);
49 }
50 }
51
52 unsafe fn put(var: &str, path: &OsStr) {
53 if env::var_os(var).as_deref() != Some(path) {
57 unsafe {
58 env::set_var(var, path);
59 }
60 }
61 }
62
63 cert_file.is_some() || !cert_dir.is_empty()
64}
65
66pub fn probe() -> ProbeResult {
71 let mut result = ProbeResult::from_env();
72 if result.cert_file.is_none() {
73 result.cert_file =
74 CERTIFICATE_FILE_NAMES
75 .iter()
76 .find_map(|p| match Path::new(p).exists() {
77 true => Some(PathBuf::from(p)),
78 false => None,
79 });
80 }
81
82 for certs_dir in candidate_cert_dirs() {
83 let cert_dir = PathBuf::from(certs_dir);
84 if cert_dir.exists() {
85 result.cert_dir.push(cert_dir);
86 }
87 }
88
89 result
90}
91
92pub fn candidate_cert_dirs() -> impl Iterator<Item = &'static Path> {
97 CERTIFICATE_DIRS
98 .iter()
99 .map(Path::new)
100 .filter(|p| p.exists())
101}
102
103pub fn has_ssl_cert_env_vars() -> bool {
110 let probe = ProbeResult::from_env();
111 probe.cert_file.is_some() || !probe.cert_dir.is_empty()
112}
113
114pub struct ProbeResult {
115 pub cert_file: Option<PathBuf>,
116 pub cert_dir: Vec<PathBuf>,
117}
118
119impl ProbeResult {
120 fn from_env() -> ProbeResult {
121 let var = |name| env::var_os(name).map(PathBuf::from).filter(|p| p.exists());
122 ProbeResult {
123 cert_file: var(ENV_CERT_FILE),
124 cert_dir: match var(ENV_CERT_DIR) {
125 Some(p) => vec![p],
126 None => vec![],
127 },
128 }
129 }
130}
131
132#[cfg(target_os = "linux")]
138const CERTIFICATE_DIRS: &[&str] = &[
139 "/etc/ssl/certs", "/etc/pki/tls/certs", "/etc/security/certificates", ];
143
144#[cfg(target_os = "freebsd")]
145const CERTIFICATE_DIRS: &[&str] = &[
146 "/etc/ssl/certs", "/usr/local/share/certs", ];
149
150#[cfg(any(target_os = "illumos", target_os = "solaris"))]
151const CERTIFICATE_DIRS: &[&str] = &["/etc/certs/CA"];
152
153#[cfg(target_os = "netbsd")]
154const CERTIFICATE_DIRS: &[&str] = &["/etc/openssl/certs"];
155
156#[cfg(target_os = "aix")]
157const CERTIFICATE_DIRS: &[&str] = &["/var/ssl/certs"];
158
159#[cfg(not(any(
160 target_os = "linux",
161 target_os = "freebsd",
162 target_os = "illumos",
163 target_os = "solaris",
164 target_os = "netbsd",
165 target_os = "aix"
166)))]
167const CERTIFICATE_DIRS: &[&str] = &["/etc/ssl/certs"];
168
169#[cfg(target_os = "linux")]
170const CERTIFICATE_FILE_NAMES: &[&str] = &[
171 "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", "/etc/pki/tls/certs/ca-bundle.crt", "/etc/ssl/ca-bundle.pem", "/etc/pki/tls/cacert.pem", "/etc/ssl/cert.pem", "/opt/etc/ssl/certs/ca-certificates.crt", "/etc/ssl/certs/cacert.pem", ];
180
181#[cfg(target_os = "freebsd")]
182const CERTIFICATE_FILE_NAMES: &[&str] = &["/usr/local/etc/ssl/cert.pem"];
183
184#[cfg(target_os = "dragonfly")]
185const CERTIFICATE_FILE_NAMES: &[&str] = &["/usr/local/share/certs/ca-root-nss.crt"];
186
187#[cfg(target_os = "netbsd")]
188const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/openssl/certs/ca-certificates.crt"];
189
190#[cfg(target_os = "openbsd")]
191const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/ssl/cert.pem"];
192
193#[cfg(target_os = "solaris")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/certs/ca-certificates.crt"];
195
196#[cfg(target_os = "illumos")]
197const CERTIFICATE_FILE_NAMES: &[&str] = &[
198 "/etc/ssl/cacert.pem", "/etc/certs/ca-certificates.crt", ];
201
202#[cfg(target_os = "android")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/data/data/com.termux/files/usr/etc/tls/cert.pem"];
204
205#[cfg(target_os = "haiku")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/boot/system/data/ssl/CARootCertificates.pem"];
207
208#[cfg(not(any(
209 target_os = "linux",
210 target_os = "freebsd",
211 target_os = "dragonfly",
212 target_os = "netbsd",
213 target_os = "openbsd",
214 target_os = "solaris",
215 target_os = "illumos",
216 target_os = "android",
217 target_os = "haiku",
218)))]
219const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/ssl/certs/ca-certificates.crt"];
220
221pub const ENV_CERT_FILE: &str = "SSL_CERT_FILE";
223
224pub const ENV_CERT_DIR: &str = "SSL_CERT_DIR";