-
Notifications
You must be signed in to change notification settings - Fork 19
Description
try_init_openssl_env_vars() invokes probe() and then manipulates the process environment with SSL_CERT_DIR/SSL_CERT_FILE. This may happen on any system, but for me at least on FreeBSD, when the following condition is met:
https://github.com/alexcrichton/openssl-probe/blob/4221247cfad3e77b758bf9b6e4c3d91a557c429e/src/lib.rs#L31-L50
None of these directories contain a CAfile, but contain a dir CANDIDATE/certs which is not CApath. That path is being used to set SSL_CERT_DIR, OpenSSL picks up this empty directory and fails all validations.
Here on the example of FreeBSD:
For many years FreeBSD contains certctl(8) to manage the system truststore which is assembled from various sources into a CApath in /etc/ssl/certs. If one relies on OpenSSL's SSL_CTX_set_default_verify_paths() all is good.
certctl(8) includes by default these two paths with CA certificates:
/usr/share/certs/trusted: comes with the base system and contains all NSS CA certificate from Mozilla/usr/local/share/certs: is initially empty and allows an admin to drop off custom/enterprise CAs (which a do at work).
certcrtl rehash scans all of them and puts symlinks into /etc/ssl/certs, but since candidate_cert_dirs[] has ""/usr/local/share" before "/etc/ssl" an invalid value is set and all fails.
A sample main which fails:
use curl::easy::Easy;
fn main() {
openssl_probe::init_ssl_cert_env_vars();
let mut data = Vec::new();
let mut handle = Easy::new();
handle.url("https://www.rust-lang.org/").unwrap();
{
let mut transfer = handle.transfer();
transfer.write_function(|new_data| {
data.extend_from_slice(new_data);
Ok(new_data.len())
}).unwrap();
transfer.perform().unwrap();
}
}
Remove the first line in the main and you are good to go.
This causes problems with downstream consumers like git2-rs and then cargo. I will report the issue also downstream.