Skip to content

Commit

Permalink
Deprecate env-var-writing functions
Browse files Browse the repository at this point in the history
Replace them with `unsafe` equivalents with documentation indicating
that you probably shouldn't rely on them. Not the best solution but
given the age of this crate there's not really a whole lot else that can
be done.

Closes #30
  • Loading branch information
alexcrichton committed Jan 23, 2025
1 parent a9a9f3e commit 3ea7c1a
Showing 1 changed file with 71 additions and 12 deletions.
83 changes: 71 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,41 @@ fn cert_dirs_iter() -> impl Iterator<Item = &'static Path> {
#[cfg(target_os = "haiku")]
"/boot/system/data/ssl",
]
.iter().map(Path::new).filter(|p| p.exists())
.iter()
.map(Path::new)
.filter(|p| p.exists())
}

/// Probe for SSL certificates on the system, then configure the SSL certificate `SSL_CERT_FILE`
/// and `SSL_CERT_DIR` environment variables in this process for OpenSSL to use.
///
/// Preconfigured values in the environment variables will not be overwritten if the paths they
/// point to exist and are accessible.
#[deprecated(note = "this function is not safe, use `init_openssl_env_vars` instead")]
pub fn init_ssl_cert_env_vars() {
try_init_ssl_cert_env_vars();
unsafe {
init_openssl_env_vars();
}
}

/// Probe for SSL certificates on the system, then configure the SSL certificate `SSL_CERT_FILE`
/// and `SSL_CERT_DIR` environment variables in this process for OpenSSL to use.
///
/// Preconfigured values in the environment variables will not be overwritten if the paths they
/// point to exist and are accessible.
///
/// # Safety
///
/// This function is not safe because it mutates the process's environment
/// variables which is generally not safe. See the [documentation in libstd][doc]
/// for information about why setting environment variables is not safe.
///
/// If possible use the [`probe`] function and directly configure OpenSSL
/// methods instead of relying on environment variables.
///
/// [doc]: https://doc.rust-lang.org/stable/std/env/fn.set_var.html#safety
pub unsafe fn init_openssl_env_vars() {
try_init_openssl_env_vars();
}

/// Probe for SSL certificates on the system, then configure the SSL certificate `SSL_CERT_FILE`
Expand All @@ -64,23 +89,57 @@ pub fn init_ssl_cert_env_vars() {
/// Returns `true` if any certificate file or directory was found while probing.
/// Combine this with `has_ssl_cert_env_vars()` to check whether previously configured environment
/// variables are valid.
#[deprecated(note = "use try_init_openssl_env_vars instead, this function is not safe")]
pub fn try_init_ssl_cert_env_vars() -> bool {
let ProbeResult { cert_file, cert_dir } = probe();
unsafe { try_init_openssl_env_vars() }
}

/// Probe for SSL certificates on the system, then configure the SSL certificate `SSL_CERT_FILE`
/// and `SSL_CERT_DIR` environment variables in this process for OpenSSL to use.
///
/// Preconfigured values in the environment variables will not be overwritten if the paths they
/// point to exist and are accessible.
///
/// Returns `true` if any certificate file or directory was found while probing.
/// Combine this with `has_ssl_cert_env_vars()` to check whether previously configured environment
/// variables are valid.
///
/// # Safety
///
/// This function is not safe because it mutates the process's environment
/// variables which is generally not safe. See the [documentation in libstd][doc]
/// for information about why setting environment variables is not safe.
///
/// If possible use the [`probe`] function and directly configure OpenSSL
/// methods instead of relying on environment variables.
///
/// [doc]: https://doc.rust-lang.org/stable/std/env/fn.set_var.html#safety
pub unsafe fn try_init_openssl_env_vars() -> bool {
let ProbeResult {
cert_file,
cert_dir,
} = probe();
// we won't be overwriting existing env variables because if they're valid probe() will have
// returned them unchanged
if let Some(path) = &cert_file {
put(ENV_CERT_FILE, path);
unsafe {
put(ENV_CERT_FILE, path);
}
}
if let Some(path) = &cert_dir {
put(ENV_CERT_DIR, path);
unsafe {
put(ENV_CERT_DIR, path);
}
}

fn put(var: &str, path: &Path) {
unsafe fn put(var: &str, path: &Path) {
// Avoid calling `setenv` if the variable already has the same contents. This avoids a
// crash when called from out of perl <5.38 (Debian Bookworm is at 5.36), as old versions
// of perl tend to manipulate the `environ` pointer directly.
if env::var_os(var).as_deref() != Some(path.as_os_str()) {
env::set_var(var, path);
unsafe {
env::set_var(var, path);
}
}
}

Expand All @@ -99,17 +158,17 @@ pub fn has_ssl_cert_env_vars() -> bool {
}

fn probe_from_env() -> ProbeResult {
let var = |name| {
env::var_os(name)
.map(PathBuf::from)
.filter(|p| p.exists())
};
let var = |name| env::var_os(name).map(PathBuf::from).filter(|p| p.exists());
ProbeResult {
cert_file: var(ENV_CERT_FILE),
cert_dir: var(ENV_CERT_DIR),
}
}

/// Probe the current system for the "cert file" and "cert dir" variables that
/// OpenSSL typically requires.
///
/// The probe result is returned as a [`ProbeResult`] structure here.
pub fn probe() -> ProbeResult {
let mut result = probe_from_env();
for certs_dir in cert_dirs_iter() {
Expand Down

0 comments on commit 3ea7c1a

Please sign in to comment.