commit 4af9a30a1638f7ab527c150a9fe4e3b0ee01d1e8 Author: Alex Crichton Date: Sat Nov 5 22:24:07 2016 -0700 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2eec003 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "openssl-probe" +version = "0.1.0" +authors = ["Alex Crichton "] + +[dependencies] diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e3711b5 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,77 @@ +use std::env; +use std::fs; +use std::path::PathBuf; + +pub struct ProbeResult { + pub cert_file: Option, + pub cert_dir: Option, +} + +/// Probe the system for the directory in which CA certificates should likely be +/// found. +/// +/// This will only search known system locations. +pub fn find_certs_dirs() -> Vec { + // see http://gagravarr.org/writing/openssl-certs/others.shtml + [ + "/var/ssl", + "/usr/share/ssl", + "/usr/local/ssl", + "/usr/local/openssl", + "/usr/local/share", + "/usr/lib/ssl", + "/usr/ssl", + "/etc/openssl", + "/etc/pki/tls", + "/etc/ssl", + ].iter().map(|s| PathBuf::from(*s)).filter(|p| { + fs::metadata(p).is_ok() + }).collect() +} + +pub fn init_ssl_cert_env_vars() { + let ProbeResult { cert_file, cert_dir } = probe(); + match cert_file { + Some(path) => put("SSL_CERT_FILE", path), + None => {} + } + match cert_dir { + Some(path) => put("SSL_CERT_DIR", path), + None => {} + } + + fn put(var: &str, path: PathBuf) { + // Don't stomp over what anyone else has set + match env::var(var) { + Ok(..) => {} + Err(..) => env::set_var(var, &path), + } + } +} + +pub fn probe() -> ProbeResult { + let mut result = ProbeResult { + cert_file: env::var_os("SSL_CERT_FILE").map(PathBuf::from), + cert_dir: env::var_os("SSL_CERT_DIR").map(PathBuf::from), + }; + for certs_dir in find_certs_dirs().iter() { + // cert.pem looks to be an openssl 1.0.1 thing, while + // certs/ca-certificates.crt appears to be a 0.9.8 thing + for cert in [ + "cert.pem", + "certs.pem", + "certs/ca-certificates.crt", + "certs/ca-root-nss.crt" + ].iter() { + try(&mut result.cert_file, certs_dir.join(cert)); + } + try(&mut result.cert_dir, certs_dir.join("certs")); + } + result +} + +fn try(dst: &mut Option, val: PathBuf) { + if dst.is_none() && fs::metadata(&val).is_ok() { + *dst = Some(val); + } +}