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", ];
142
143#[cfg(target_os = "freebsd")]
144const CERTIFICATE_DIRS: &[&str] = &[
145 "/etc/ssl/certs", "/usr/local/share/certs", ];
148
149#[cfg(any(target_os = "illumos", target_os = "solaris"))]
150const CERTIFICATE_DIRS: &[&str] = &["/etc/certs/CA"];
151
152#[cfg(target_os = "netbsd")]
153const CERTIFICATE_DIRS: &[&str] = &["/etc/openssl/certs"];
154
155#[cfg(target_os = "aix")]
156const CERTIFICATE_DIRS: &[&str] = &["/var/ssl/certs"];
157
158#[cfg(not(any(
159 target_os = "linux",
160 target_os = "freebsd",
161 target_os = "illumos",
162 target_os = "solaris",
163 target_os = "netbsd",
164 target_os = "aix"
165)))]
166const CERTIFICATE_DIRS: &[&str] = &["/etc/ssl/certs"];
167
168#[cfg(target_os = "linux")]
169const CERTIFICATE_FILE_NAMES: &[&str] = &[
170 "/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", ];
178
179#[cfg(target_os = "freebsd")]
180const CERTIFICATE_FILE_NAMES: &[&str] = &["/usr/local/etc/ssl/cert.pem"];
181
182#[cfg(target_os = "dragonfly")]
183const CERTIFICATE_FILE_NAMES: &[&str] = &["/usr/local/share/certs/ca-root-nss.crt"];
184
185#[cfg(target_os = "netbsd")]
186const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/openssl/certs/ca-certificates.crt"];
187
188#[cfg(target_os = "openbsd")]
189const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/ssl/cert.pem"];
190
191#[cfg(target_os = "solaris")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/certs/ca-certificates.crt"];
193
194#[cfg(target_os = "illumos")]
195const CERTIFICATE_FILE_NAMES: &[&str] = &[
196 "/etc/ssl/cacert.pem", "/etc/certs/ca-certificates.crt", ];
199
200#[cfg(target_os = "android")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/data/data/com.termux/files/usr/etc/tls/cert.pem"];
202
203#[cfg(target_os = "haiku")] const CERTIFICATE_FILE_NAMES: &[&str] = &["/boot/system/data/ssl/CARootCertificates.pem"];
205
206#[cfg(not(any(
207 target_os = "linux",
208 target_os = "freebsd",
209 target_os = "dragonfly",
210 target_os = "netbsd",
211 target_os = "openbsd",
212 target_os = "solaris",
213 target_os = "illumos",
214 target_os = "android",
215 target_os = "haiku",
216)))]
217const CERTIFICATE_FILE_NAMES: &[&str] = &["/etc/ssl/certs/ca-certificates.crt"];
218
219pub const ENV_CERT_FILE: &'static str = "SSL_CERT_FILE";
221
222pub const ENV_CERT_DIR: &'static str = "SSL_CERT_DIR";