From 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:41:41 +0200 Subject: Merging upstream version 1.70.0+dfsg2. Signed-off-by: Daniel Baumann --- vendor/openssl-sys/build/cfgs.rs | 97 +++++++ vendor/openssl-sys/build/expando.c | 124 +++++++++ vendor/openssl-sys/build/find_normal.rs | 275 ++++++++++++++++++++ vendor/openssl-sys/build/find_vendored.rs | 16 ++ vendor/openssl-sys/build/main.rs | 415 ++++++++++++++++++++++++++++++ vendor/openssl-sys/build/run_bindgen.rs | 236 +++++++++++++++++ 6 files changed, 1163 insertions(+) create mode 100644 vendor/openssl-sys/build/cfgs.rs create mode 100644 vendor/openssl-sys/build/expando.c create mode 100644 vendor/openssl-sys/build/find_normal.rs create mode 100644 vendor/openssl-sys/build/find_vendored.rs create mode 100644 vendor/openssl-sys/build/main.rs create mode 100644 vendor/openssl-sys/build/run_bindgen.rs (limited to 'vendor/openssl-sys/build') diff --git a/vendor/openssl-sys/build/cfgs.rs b/vendor/openssl-sys/build/cfgs.rs new file mode 100644 index 000000000..960515f00 --- /dev/null +++ b/vendor/openssl-sys/build/cfgs.rs @@ -0,0 +1,97 @@ +pub fn get(openssl_version: Option, libressl_version: Option) -> Vec<&'static str> { + let mut cfgs = vec![]; + + if let Some(libressl_version) = libressl_version { + cfgs.push("libressl"); + + if libressl_version >= 0x2_05_01_00_0 { + cfgs.push("libressl251"); + } + if libressl_version >= 0x2_05_02_00_0 { + cfgs.push("libressl252"); + } + if libressl_version >= 0x2_06_01_00_0 { + cfgs.push("libressl261"); + } + if libressl_version >= 0x2_07_00_00_0 { + cfgs.push("libressl270"); + } + if libressl_version >= 0x2_07_01_00_0 { + cfgs.push("libressl271"); + } + if libressl_version >= 0x2_07_03_00_0 { + cfgs.push("libressl273"); + } + if libressl_version >= 0x2_08_00_00_0 { + cfgs.push("libressl280"); + } + if libressl_version >= 0x2_08_01_00_0 { + cfgs.push("libressl281"); + } + if libressl_version >= 0x2_09_01_00_0 { + cfgs.push("libressl291"); + } + if libressl_version >= 0x3_01_00_00_0 { + cfgs.push("libressl310"); + } + if libressl_version >= 0x3_02_01_00_0 { + cfgs.push("libressl321"); + } + if libressl_version >= 0x3_03_02_00_0 { + cfgs.push("libressl332"); + } + if libressl_version >= 0x3_04_00_00_0 { + cfgs.push("libressl340"); + } + if libressl_version >= 0x3_05_00_00_0 { + cfgs.push("libressl350"); + } + if libressl_version >= 0x3_06_00_00_0 { + cfgs.push("libressl360"); + } + if libressl_version >= 0x3_07_00_00_0 { + cfgs.push("libressl370"); + } + } else { + let openssl_version = openssl_version.unwrap(); + + if openssl_version >= 0x3_00_00_00_0 { + cfgs.push("ossl300"); + } + if openssl_version >= 0x1_00_01_00_0 { + cfgs.push("ossl101"); + } + if openssl_version >= 0x1_00_02_00_0 { + cfgs.push("ossl102"); + } + if openssl_version >= 0x1_00_02_06_0 { + cfgs.push("ossl102f"); + } + if openssl_version >= 0x1_00_02_08_0 { + cfgs.push("ossl102h"); + } + if openssl_version >= 0x1_01_00_00_0 { + cfgs.push("ossl110"); + } + if openssl_version >= 0x1_01_00_06_0 { + cfgs.push("ossl110f"); + } + if openssl_version >= 0x1_01_00_07_0 { + cfgs.push("ossl110g"); + } + if openssl_version >= 0x1_01_00_08_0 { + cfgs.push("ossl110h"); + } + if openssl_version >= 0x1_01_01_00_0 { + cfgs.push("ossl111"); + } + if openssl_version >= 0x1_01_01_02_0 { + cfgs.push("ossl111b"); + } + if openssl_version >= 0x1_01_01_03_0 { + cfgs.push("ossl111c"); + } + } + + cfgs +} diff --git a/vendor/openssl-sys/build/expando.c b/vendor/openssl-sys/build/expando.c new file mode 100644 index 000000000..11fb04db0 --- /dev/null +++ b/vendor/openssl-sys/build/expando.c @@ -0,0 +1,124 @@ +#include +#include + +#define VERSION2(n, v) RUST_VERSION_##n##_##v +#define VERSION(n, v) VERSION2(n, v) + +#define NEW_VERSION2(a, b, c) RUST_VERSION_NEW_OPENSSL_##a##_##b##_##c +#define NEW_VERSION(a, b, c) NEW_VERSION2(a, b, c) + +#ifdef LIBRESSL_VERSION_NUMBER +VERSION(LIBRESSL, LIBRESSL_VERSION_NUMBER) +#elif defined OPENSSL_VERSION_MAJOR +NEW_VERSION(OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH) +#else +VERSION(OPENSSL, OPENSSL_VERSION_NUMBER) +#endif + +#ifdef OPENSSL_IS_BORINGSSL +RUST_OPENSSL_IS_BORINGSSL +#endif + +#ifdef OPENSSL_NO_BF +RUST_CONF_OPENSSL_NO_BF +#endif + +#ifdef OPENSSL_NO_BUF_FREELISTS +RUST_CONF_OPENSSL_NO_BUF_FREELISTS +#endif + +#ifdef OPENSSL_NO_CHACHA +RUST_CONF_OPENSSL_NO_CHACHA +#endif + +#ifdef OPENSSL_NO_IDEA +RUST_CONF_OPENSSL_NO_IDEA +#endif + +#ifdef OPENSSL_NO_CAMELLIA +RUST_CONF_OPENSSL_NO_CAMELLIA +#endif + +#ifdef OPENSSL_NO_CAST +RUST_CONF_OPENSSL_NO_CAST +#endif + +#ifdef OPENSSL_NO_CMS +RUST_CONF_OPENSSL_NO_CMS +#endif + +#ifdef OPENSSL_NO_COMP +RUST_CONF_OPENSSL_NO_COMP +#endif + +#ifdef OPENSSL_NO_EC +RUST_CONF_OPENSSL_NO_EC +#endif + +#ifdef OPENSSL_NO_EC2M +RUST_CONF_OPENSSL_NO_EC2M +#endif + +#ifdef OPENSSL_NO_ENGINE +RUST_CONF_OPENSSL_NO_ENGINE +#endif + +#ifdef OPENSSL_NO_KRB5 +RUST_CONF_OPENSSL_NO_KRB5 +#endif + +#ifdef OPENSSL_NO_NEXTPROTONEG +RUST_CONF_OPENSSL_NO_NEXTPROTONEG +#endif + +#ifdef OPENSSL_NO_OCSP +RUST_CONF_OPENSSL_NO_OCSP +#endif + +#ifdef OPENSSL_NO_PSK +RUST_CONF_OPENSSL_NO_PSK +#endif + +#ifdef OPENSSL_NO_RFC3779 +RUST_CONF_OPENSSL_NO_RFC3779 +#endif + +#ifdef OPENSSL_NO_RMD160 +RUST_CONF_OPENSSL_NO_RMD160 +#endif + +#ifdef OPENSSL_NO_SHA +RUST_CONF_OPENSSL_NO_SHA +#endif + +#ifdef OPENSSL_NO_SRP +RUST_CONF_OPENSSL_NO_SRP +#endif + +#ifdef OPENSSL_NO_SSL3_METHOD +RUST_CONF_OPENSSL_NO_SSL3_METHOD +#endif + +#ifdef OPENSSL_NO_TLSEXT +RUST_CONF_OPENSSL_NO_TLSEXT +#endif + +#ifdef OPENSSL_NO_STDIO +RUST_CONF_OPENSSL_NO_STDIO +#endif + +#ifdef OPENSSL_NO_SM3 +RUST_CONF_OPENSSL_NO_SM3 +#endif + +#ifdef OPENSSL_NO_SM4 +RUST_CONF_OPENSSL_NO_SM4 +#endif + +#ifdef OPENSSL_NO_DEPRECATED_3_0 +RUST_CONF_OPENSSL_NO_DEPRECATED_3_0 +#endif + +#ifdef OPENSSL_NO_SEED +RUST_CONF_OPENSSL_NO_SEED +#endif diff --git a/vendor/openssl-sys/build/find_normal.rs b/vendor/openssl-sys/build/find_normal.rs new file mode 100644 index 000000000..791fc3398 --- /dev/null +++ b/vendor/openssl-sys/build/find_normal.rs @@ -0,0 +1,275 @@ +use std::ffi::OsString; +use std::path::{Path, PathBuf}; +use std::process::{self, Command}; + +use super::env; + +pub fn get_openssl(target: &str) -> (Vec, PathBuf) { + let lib_dir = env("OPENSSL_LIB_DIR").map(PathBuf::from); + let include_dir = env("OPENSSL_INCLUDE_DIR").map(PathBuf::from); + + match (lib_dir, include_dir) { + (Some(lib_dir), Some(include_dir)) => (vec![lib_dir], include_dir), + (lib_dir, include_dir) => { + let openssl_dir = env("OPENSSL_DIR").unwrap_or_else(|| find_openssl_dir(target)); + let openssl_dir = Path::new(&openssl_dir); + let lib_dir = lib_dir.map(|d| vec![d]).unwrap_or_else(|| { + let mut lib_dirs = vec![]; + // OpenSSL 3.0 now puts it's libraries in lib64/ by default, + // check for both it and lib/. + if openssl_dir.join("lib64").exists() { + lib_dirs.push(openssl_dir.join("lib64")); + } + if openssl_dir.join("lib").exists() { + lib_dirs.push(openssl_dir.join("lib")); + } + lib_dirs + }); + let include_dir = include_dir.unwrap_or_else(|| openssl_dir.join("include")); + (lib_dir, include_dir) + } + } +} + +fn resolve_with_wellknown_homebrew_location(dir: &str) -> Option { + let versions = ["openssl@3", "openssl@1.1"]; + + // Check up default aarch 64 Homebrew installation location first + // for quick resolution if possible. + // `pkg-config` on brew doesn't necessarily contain settings for openssl apparently. + for version in &versions { + let homebrew = Path::new(dir).join(format!("opt/{}", version)); + if homebrew.exists() { + return Some(homebrew); + } + } + + for version in &versions { + // Calling `brew --prefix ` command usually slow and + // takes seconds, and will be used only as a last resort. + let output = execute_command_and_get_output("brew", &["--prefix", version]); + if let Some(ref output) = output { + let homebrew = Path::new(&output); + if homebrew.exists() { + return Some(homebrew.to_path_buf()); + } + } + } + + None +} + +fn resolve_with_wellknown_location(dir: &str) -> Option { + let root_dir = Path::new(dir); + let include_openssl = root_dir.join("include/openssl"); + if include_openssl.exists() { + Some(root_dir.to_path_buf()) + } else { + None + } +} + +fn find_openssl_dir(target: &str) -> OsString { + let host = env::var("HOST").unwrap(); + + if host == target && target.ends_with("-apple-darwin") { + let homebrew_dir = match target { + "aarch64-apple-darwin" => "/opt/homebrew", + _ => "/usr/local", + }; + + if let Some(dir) = resolve_with_wellknown_homebrew_location(homebrew_dir) { + return dir.into(); + } else if let Some(dir) = resolve_with_wellknown_location("/opt/pkg") { + // pkgsrc + return dir.into(); + } else if let Some(dir) = resolve_with_wellknown_location("/opt/local") { + // MacPorts + return dir.into(); + } + } + + try_pkg_config(); + try_vcpkg(); + + // FreeBSD ships with OpenSSL but doesn't include a pkg-config file :( + if host == target && target.contains("freebsd") { + return OsString::from("/usr"); + } + + // DragonFly has libressl (or openssl) in ports, but this doesn't include a pkg-config file + if host == target && target.contains("dragonfly") { + return OsString::from("/usr/local"); + } + + let mut msg = format!( + " + +Could not find directory of OpenSSL installation, and this `-sys` crate cannot +proceed without this knowledge. If OpenSSL is installed and this crate had +trouble finding it, you can set the `OPENSSL_DIR` environment variable for the +compilation process. + +Make sure you also have the development packages of openssl installed. +For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora. + +If you're in a situation where you think the directory *should* be found +automatically, please open a bug at https://github.com/sfackler/rust-openssl +and include information about your system as well as this message. + +$HOST = {} +$TARGET = {} +openssl-sys = {} + +", + host, + target, + env!("CARGO_PKG_VERSION") + ); + + if host.contains("apple-darwin") && target.contains("apple-darwin") { + let system = Path::new("/usr/lib/libssl.0.9.8.dylib"); + if system.exists() { + msg.push_str( + " + +openssl-sys crate build failed: no supported version of OpenSSL found. + +Ways to fix it: +- Use the `vendored` feature of openssl-sys crate to build OpenSSL from source. +- Use Homebrew to install the `openssl` package. + +", + ); + } + } + + if host.contains("unknown-linux") + && target.contains("unknown-linux-gnu") + && Command::new("pkg-config").output().is_err() + { + msg.push_str( + " +It looks like you're compiling on Linux and also targeting Linux. Currently this +requires the `pkg-config` utility to find OpenSSL but unfortunately `pkg-config` +could not be found. If you have OpenSSL installed you can likely fix this by +installing `pkg-config`. + +", + ); + } + + if host.contains("windows") && target.contains("windows-gnu") { + msg.push_str( + " +It looks like you're compiling for MinGW but you may not have either OpenSSL or +pkg-config installed. You can install these two dependencies with: + +pacman -S openssl-devel pkg-config + +and try building this crate again. + +", + ); + } + + if host.contains("windows") && target.contains("windows-msvc") { + msg.push_str( + " +It looks like you're compiling for MSVC but we couldn't detect an OpenSSL +installation. If there isn't one installed then you can try the rust-openssl +README for more information about how to download precompiled binaries of +OpenSSL: + +https://github.com/sfackler/rust-openssl#windows + +", + ); + } + + panic!("{}", msg); +} + +/// Attempt to find OpenSSL through pkg-config. +/// +/// Note that if this succeeds then the function does not return as pkg-config +/// typically tells us all the information that we need. +fn try_pkg_config() { + let target = env::var("TARGET").unwrap(); + let host = env::var("HOST").unwrap(); + + // If we're going to windows-gnu we can use pkg-config, but only so long as + // we're coming from a windows host. + // + // Otherwise if we're going to windows we probably can't use pkg-config. + if target.contains("windows-gnu") && host.contains("windows") { + env::set_var("PKG_CONFIG_ALLOW_CROSS", "1"); + } else if target.contains("windows") { + return; + } + + let lib = match pkg_config::Config::new() + .print_system_libs(false) + .probe("openssl") + { + Ok(lib) => lib, + Err(e) => { + println!("run pkg_config fail: {:?}", e); + return; + } + }; + + super::postprocess(&lib.include_paths); + + for include in lib.include_paths.iter() { + println!("cargo:include={}", include.display()); + } + + process::exit(0); +} + +/// Attempt to find OpenSSL through vcpkg. +/// +/// Note that if this succeeds then the function does not return as vcpkg +/// should emit all of the cargo metadata that we need. +#[cfg(target_env = "msvc")] +fn try_vcpkg() { + // vcpkg will not emit any metadata if it can not find libraries + // appropriate for the target triple with the desired linkage. + + let lib = match vcpkg::Config::new() + .emit_includes(true) + .find_package("openssl") + { + Ok(lib) => lib, + Err(e) => { + println!("note: vcpkg did not find openssl: {}", e); + return; + } + }; + + super::postprocess(&lib.include_paths); + + println!("cargo:rustc-link-lib=user32"); + println!("cargo:rustc-link-lib=gdi32"); + println!("cargo:rustc-link-lib=crypt32"); + + process::exit(0); +} + +#[cfg(not(target_env = "msvc"))] +fn try_vcpkg() {} + +fn execute_command_and_get_output(cmd: &str, args: &[&str]) -> Option { + let out = Command::new(cmd).args(args).output(); + if let Ok(ref r1) = out { + if r1.status.success() { + let r2 = String::from_utf8(r1.stdout.clone()); + if let Ok(r3) = r2 { + return Some(r3.trim().to_string()); + } + } + } + + None +} diff --git a/vendor/openssl-sys/build/find_vendored.rs b/vendor/openssl-sys/build/find_vendored.rs new file mode 100644 index 000000000..c92b2bd39 --- /dev/null +++ b/vendor/openssl-sys/build/find_vendored.rs @@ -0,0 +1,16 @@ +use openssl_src; +use std::path::PathBuf; + +pub fn get_openssl(_target: &str) -> (Vec, PathBuf) { + let artifacts = openssl_src::Build::new().build(); + println!("cargo:vendored=1"); + println!( + "cargo:root={}", + artifacts.lib_dir().parent().unwrap().display() + ); + + ( + vec![artifacts.lib_dir().to_path_buf()], + artifacts.include_dir().to_path_buf(), + ) +} diff --git a/vendor/openssl-sys/build/main.rs b/vendor/openssl-sys/build/main.rs new file mode 100644 index 000000000..5c1f668fb --- /dev/null +++ b/vendor/openssl-sys/build/main.rs @@ -0,0 +1,415 @@ +#![allow( + clippy::inconsistent_digit_grouping, + clippy::uninlined_format_args, + clippy::unusual_byte_groupings +)] + +#[cfg(feature = "bindgen")] +extern crate bindgen; +extern crate cc; +#[cfg(feature = "vendored")] +extern crate openssl_src; +extern crate pkg_config; +#[cfg(target_env = "msvc")] +extern crate vcpkg; + +use std::collections::HashSet; +use std::env; +use std::ffi::OsString; +use std::path::{Path, PathBuf}; +mod cfgs; + +mod find_normal; +#[cfg(feature = "vendored")] +mod find_vendored; +mod run_bindgen; + +#[derive(PartialEq)] +enum Version { + Openssl3xx, + Openssl11x, + Openssl10x, + Libressl, + Boringssl, +} + +fn env_inner(name: &str) -> Option { + let var = env::var_os(name); + println!("cargo:rerun-if-env-changed={}", name); + + match var { + Some(ref v) => println!("{} = {}", name, v.to_string_lossy()), + None => println!("{} unset", name), + } + + var +} + +fn env(name: &str) -> Option { + let prefix = env::var("TARGET").unwrap().to_uppercase().replace('-', "_"); + let prefixed = format!("{}_{}", prefix, name); + env_inner(&prefixed).or_else(|| env_inner(name)) +} + +fn find_openssl(target: &str) -> (Vec, PathBuf) { + #[cfg(feature = "vendored")] + { + // vendor if the feature is present, unless + // OPENSSL_NO_VENDOR exists and isn't `0` + if env("OPENSSL_NO_VENDOR").map_or(true, |s| s == "0") { + return find_vendored::get_openssl(target); + } + } + find_normal::get_openssl(target) +} + +fn check_ssl_kind() { + if cfg!(feature = "unstable_boringssl") { + println!("cargo:rustc-cfg=boringssl"); + println!("cargo:boringssl=true"); + // BoringSSL does not have any build logic, exit early + std::process::exit(0); + } +} + +fn main() { + check_ssl_kind(); + + let target = env::var("TARGET").unwrap(); + + let (lib_dirs, include_dir) = find_openssl(&target); + + if !lib_dirs.iter().all(|p| Path::new(p).exists()) { + panic!("OpenSSL library directory does not exist: {:?}", lib_dirs); + } + if !Path::new(&include_dir).exists() { + panic!( + "OpenSSL include directory does not exist: {}", + include_dir.to_string_lossy() + ); + } + + for lib_dir in lib_dirs.iter() { + println!( + "cargo:rustc-link-search=native={}", + lib_dir.to_string_lossy() + ); + } + println!("cargo:include={}", include_dir.to_string_lossy()); + + let version = postprocess(&[include_dir]); + + let libs_env = env("OPENSSL_LIBS"); + let libs = match libs_env.as_ref().and_then(|s| s.to_str()) { + Some(v) => { + if v.is_empty() { + vec![] + } else { + v.split(':').collect() + } + } + None => match version { + Version::Openssl10x if target.contains("windows") => vec!["ssleay32", "libeay32"], + Version::Openssl3xx | Version::Openssl11x if target.contains("windows-msvc") => { + vec!["libssl", "libcrypto"] + } + _ => vec!["ssl", "crypto"], + }, + }; + + let kind = determine_mode(&lib_dirs, &libs); + for lib in libs.into_iter() { + println!("cargo:rustc-link-lib={}={}", kind, lib); + } + + if kind == "static" && target.contains("windows") { + println!("cargo:rustc-link-lib=dylib=gdi32"); + println!("cargo:rustc-link-lib=dylib=user32"); + println!("cargo:rustc-link-lib=dylib=crypt32"); + println!("cargo:rustc-link-lib=dylib=ws2_32"); + println!("cargo:rustc-link-lib=dylib=advapi32"); + } +} + +#[allow(clippy::let_and_return)] +fn postprocess(include_dirs: &[PathBuf]) -> Version { + let version = validate_headers(include_dirs); + + // Never run bindgen for BoringSSL, if it was needed we already ran it. + if version != Version::Boringssl { + #[cfg(feature = "bindgen")] + run_bindgen::run(&include_dirs); + } + + version +} + +/// Validates the header files found in `include_dir` and then returns the +/// version string of OpenSSL. +#[allow(clippy::manual_strip)] // we need to support pre-1.45.0 +fn validate_headers(include_dirs: &[PathBuf]) -> Version { + // This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0.0. + // To correctly expose the right API from this crate, take a look at + // `opensslv.h` to see what version OpenSSL claims to be. + // + // OpenSSL has a number of build-time configuration options which affect + // various structs and such. Since OpenSSL 1.1.0 this isn't really a problem + // as the library is much more FFI-friendly, but 1.0.{1,2} suffer this problem. + // + // To handle all this conditional compilation we slurp up the configuration + // file of OpenSSL, `opensslconf.h`, and then dump out everything it defines + // as our own #[cfg] directives. That way the `ossl10x.rs` bindings can + // account for compile differences and such. + println!("cargo:rerun-if-changed=build/expando.c"); + let mut gcc = cc::Build::new(); + for include_dir in include_dirs { + gcc.include(include_dir); + } + let expanded = match gcc.file("build/expando.c").try_expand() { + Ok(expanded) => expanded, + Err(e) => { + panic!( + " +Header expansion error: +{:?} + +Failed to find OpenSSL development headers. + +You can try fixing this setting the `OPENSSL_DIR` environment variable +pointing to your OpenSSL installation or installing OpenSSL headers package +specific to your distribution: + + # On Ubuntu + sudo apt-get install libssl-dev + # On Arch Linux + sudo pacman -S openssl + # On Fedora + sudo dnf install openssl-devel + # On Alpine Linux + apk add openssl-dev + +See rust-openssl documentation for more information: + + https://docs.rs/openssl +", + e + ); + } + }; + let expanded = String::from_utf8(expanded).unwrap(); + + let mut enabled = vec![]; + let mut openssl_version = None; + let mut libressl_version = None; + let mut is_boringssl = false; + for line in expanded.lines() { + let line = line.trim(); + + let openssl_prefix = "RUST_VERSION_OPENSSL_"; + let new_openssl_prefix = "RUST_VERSION_NEW_OPENSSL_"; + let libressl_prefix = "RUST_VERSION_LIBRESSL_"; + let boringsl_prefix = "RUST_OPENSSL_IS_BORINGSSL"; + let conf_prefix = "RUST_CONF_"; + if line.starts_with(openssl_prefix) { + let version = &line[openssl_prefix.len()..]; + openssl_version = Some(parse_version(version)); + } else if line.starts_with(new_openssl_prefix) { + let version = &line[new_openssl_prefix.len()..]; + openssl_version = Some(parse_new_version(version)); + } else if line.starts_with(libressl_prefix) { + let version = &line[libressl_prefix.len()..]; + libressl_version = Some(parse_version(version)); + } else if line.starts_with(conf_prefix) { + enabled.push(&line[conf_prefix.len()..]); + } else if line.starts_with(boringsl_prefix) { + is_boringssl = true; + } + } + + if is_boringssl { + println!("cargo:rustc-cfg=boringssl"); + println!("cargo:boringssl=true"); + run_bindgen::run_boringssl(include_dirs); + return Version::Boringssl; + } + + // We set this for any non-BoringSSL lib. + println!("cargo:rustc-cfg=openssl"); + + for enabled in &enabled { + println!("cargo:rustc-cfg=osslconf=\"{}\"", enabled); + } + println!("cargo:conf={}", enabled.join(",")); + + for cfg in cfgs::get(openssl_version, libressl_version) { + println!("cargo:rustc-cfg={}", cfg); + } + + if let Some(libressl_version) = libressl_version { + println!("cargo:libressl_version_number={:x}", libressl_version); + + let major = (libressl_version >> 28) as u8; + let minor = (libressl_version >> 20) as u8; + let fix = (libressl_version >> 12) as u8; + let (major, minor, fix) = match (major, minor, fix) { + (2, 5, 0) => ('2', '5', '0'), + (2, 5, 1) => ('2', '5', '1'), + (2, 5, 2) => ('2', '5', '2'), + (2, 5, _) => ('2', '5', 'x'), + (2, 6, 0) => ('2', '6', '0'), + (2, 6, 1) => ('2', '6', '1'), + (2, 6, 2) => ('2', '6', '2'), + (2, 6, _) => ('2', '6', 'x'), + (2, 7, _) => ('2', '7', 'x'), + (2, 8, 0) => ('2', '8', '0'), + (2, 8, 1) => ('2', '8', '1'), + (2, 8, _) => ('2', '8', 'x'), + (2, 9, 0) => ('2', '9', '0'), + (2, 9, _) => ('2', '9', 'x'), + (3, 0, 0) => ('3', '0', '0'), + (3, 0, 1) => ('3', '0', '1'), + (3, 0, _) => ('3', '0', 'x'), + (3, 1, 0) => ('3', '1', '0'), + (3, 1, _) => ('3', '1', 'x'), + (3, 2, 0) => ('3', '2', '0'), + (3, 2, 1) => ('3', '2', '1'), + (3, 2, _) => ('3', '2', 'x'), + (3, 3, 0) => ('3', '3', '0'), + (3, 3, 1) => ('3', '3', '1'), + (3, 3, _) => ('3', '3', 'x'), + (3, 4, 0) => ('3', '4', '0'), + (3, 4, _) => ('3', '4', 'x'), + (3, 5, _) => ('3', '5', 'x'), + (3, 6, 0) => ('3', '6', '0'), + (3, 6, _) => ('3', '6', 'x'), + (3, 7, 0) => ('3', '7', '0'), + (3, 7, 1) => ('3', '7', '1'), + _ => version_error(), + }; + + println!("cargo:libressl=true"); + println!("cargo:libressl_version={}{}{}", major, minor, fix); + println!("cargo:version=101"); + Version::Libressl + } else { + let openssl_version = openssl_version.unwrap(); + println!("cargo:version_number={:x}", openssl_version); + + if openssl_version >= 0x4_00_00_00_0 { + version_error() + } else if openssl_version >= 0x3_00_00_00_0 { + Version::Openssl3xx + } else if openssl_version >= 0x1_01_01_00_0 { + println!("cargo:version=111"); + Version::Openssl11x + } else if openssl_version >= 0x1_01_00_06_0 { + println!("cargo:version=110"); + println!("cargo:patch=f"); + Version::Openssl11x + } else if openssl_version >= 0x1_01_00_00_0 { + println!("cargo:version=110"); + Version::Openssl11x + } else if openssl_version >= 0x1_00_02_00_0 { + println!("cargo:version=102"); + Version::Openssl10x + } else if openssl_version >= 0x1_00_01_00_0 { + println!("cargo:version=101"); + Version::Openssl10x + } else { + version_error() + } + } +} + +fn version_error() -> ! { + panic!( + " + +This crate is only compatible with OpenSSL (version 1.0.1 through 1.1.1, or 3.0.0), or LibreSSL 2.5 +through 3.7.1, but a different version of OpenSSL was found. The build is now aborting +due to this version mismatch. + +" + ); +} + +// parses a string that looks like "0x100020cfL" +#[allow(deprecated)] // trim_right_matches is now trim_end_matches +#[allow(clippy::match_like_matches_macro)] // matches macro requires rust 1.42.0 +fn parse_version(version: &str) -> u64 { + // cut off the 0x prefix + assert!(version.starts_with("0x")); + let version = &version[2..]; + + // and the type specifier suffix + let version = version.trim_right_matches(|c: char| match c { + '0'..='9' | 'a'..='f' | 'A'..='F' => false, + _ => true, + }); + + u64::from_str_radix(version, 16).unwrap() +} + +// parses a string that looks like 3_0_0 +fn parse_new_version(version: &str) -> u64 { + println!("version: {}", version); + let mut it = version.split('_'); + let major = it.next().unwrap().parse::().unwrap(); + let minor = it.next().unwrap().parse::().unwrap(); + let patch = it.next().unwrap().parse::().unwrap(); + + (major << 28) | (minor << 20) | (patch << 4) +} + +/// Given a libdir for OpenSSL (where artifacts are located) as well as the name +/// of the libraries we're linking to, figure out whether we should link them +/// statically or dynamically. +fn determine_mode(libdirs: &[PathBuf], libs: &[&str]) -> &'static str { + // First see if a mode was explicitly requested + let kind = env("OPENSSL_STATIC"); + match kind.as_ref().and_then(|s| s.to_str()) { + Some("0") => return "dylib", + Some(_) => return "static", + None => {} + } + + // Next, see what files we actually have to link against, and see what our + // possibilities even are. + let mut files = HashSet::new(); + for dir in libdirs { + for path in dir + .read_dir() + .unwrap() + .map(|e| e.unwrap()) + .map(|e| e.file_name()) + .filter_map(|e| e.into_string().ok()) + { + files.insert(path); + } + } + let can_static = libs + .iter() + .all(|l| files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l))); + let can_dylib = libs.iter().all(|l| { + files.contains(&format!("lib{}.so", l)) + || files.contains(&format!("{}.dll", l)) + || files.contains(&format!("lib{}.dylib", l)) + }); + match (can_static, can_dylib) { + (true, false) => return "static", + (false, true) => return "dylib", + (false, false) => { + panic!( + "OpenSSL libdir at `{:?}` does not contain the required files \ + to either statically or dynamically link OpenSSL", + libdirs + ); + } + (true, true) => {} + } + + // Ok, we've got not explicit preference and can *either* link statically or + // link dynamically. In the interest of "security upgrades" and/or "best + // practices with security libs", let's link dynamically. + "dylib" +} diff --git a/vendor/openssl-sys/build/run_bindgen.rs b/vendor/openssl-sys/build/run_bindgen.rs new file mode 100644 index 000000000..0c127ae5c --- /dev/null +++ b/vendor/openssl-sys/build/run_bindgen.rs @@ -0,0 +1,236 @@ +#[cfg(feature = "bindgen")] +use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; +#[cfg(feature = "bindgen")] +use bindgen::{MacroTypeVariation, RustTarget}; +use std::io::Write; +use std::path::PathBuf; +#[cfg(not(feature = "bindgen"))] +use std::process; +use std::{env, fs}; + +const INCLUDES: &str = " +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// this must be included after ssl.h for libressl! +#include + +#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) +#include +#endif + +#if !defined(OPENSSL_IS_BORINGSSL) +#include +#include +#endif + +#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000 +#include +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x30000000 +#include +#endif +"; + +#[cfg(feature = "bindgen")] +pub fn run(include_dirs: &[PathBuf]) { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + let mut builder = bindgen::builder() + .parse_callbacks(Box::new(OpensslCallbacks)) + .rust_target(RustTarget::Stable_1_47) + .ctypes_prefix("::libc") + .raw_line("use libc::*;") + .raw_line("type evp_pkey_st = EVP_PKEY;") + .allowlist_file(".*/openssl/[^/]+\\.h") + .allowlist_recursively(false) + // libc is missing pthread_once_t on macOS + .blocklist_type("CRYPTO_ONCE") + .blocklist_function("CRYPTO_THREAD_run_once") + // we don't want to mess with va_list + .blocklist_function("BIO_vprintf") + .blocklist_function("BIO_vsnprintf") + .blocklist_function("ERR_vset_error") + .blocklist_function("ERR_add_error_vdata") + .blocklist_function("EVP_KDF_vctrl") + .blocklist_type("OSSL_FUNC_core_vset_error_fn") + .blocklist_type("OSSL_FUNC_BIO_vprintf_fn") + .blocklist_type("OSSL_FUNC_BIO_vsnprintf_fn") + // Maintain compatibility for existing enum definitions + .rustified_enum("point_conversion_form_t") + // Maintain compatibility for pre-union definitions + .blocklist_type("GENERAL_NAME") + .blocklist_type("GENERAL_NAME_st") + .blocklist_type("EVP_PKEY") + .blocklist_type("evp_pkey_st") + .layout_tests(false) + .header_contents("includes.h", INCLUDES); + + for include_dir in include_dirs { + builder = builder + .clang_arg("-I") + .clang_arg(include_dir.display().to_string()); + } + + builder + .generate() + .unwrap() + .write_to_file(out_dir.join("bindgen.rs")) + .unwrap(); +} + +#[cfg(feature = "bindgen")] +pub fn run_boringssl(include_dirs: &[PathBuf]) { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let mut builder = bindgen::builder() + .rust_target(RustTarget::Stable_1_47) + .ctypes_prefix("::libc") + .derive_default(false) + .enable_function_attribute_detection() + .size_t_is_usize(true) + .default_macro_constant_type(MacroTypeVariation::Signed) + .rustified_enum("point_conversion_form_t") + .allowlist_file(".*/openssl/[^/]+\\.h") + .wrap_static_fns(true) + .wrap_static_fns_path(out_dir.join("boring_static_wrapper").display().to_string()) + .layout_tests(false) + .header_contents("includes.h", INCLUDES); + + for include_dir in include_dirs { + builder = builder + .clang_arg("-I") + .clang_arg(include_dir.display().to_string()); + } + + builder + .generate() + .unwrap() + .write_to_file(out_dir.join("bindgen.rs")) + .unwrap(); + + fs::File::create(out_dir.join("boring_static_wrapper.h")) + .expect("Failed to create boring_static_wrapper.h") + .write_all(INCLUDES.as_bytes()) + .expect("Failed to write contents to boring_static_wrapper.h"); + + cc::Build::new() + .file(out_dir.join("boring_static_wrapper.c")) + .includes(include_dirs) + .flag("-include") + .flag( + &out_dir + .join("boring_static_wrapper.h") + .display() + .to_string(), + ) + .compile("boring_static_wrapper"); +} + +#[cfg(not(feature = "bindgen"))] +pub fn run_boringssl(include_dirs: &[PathBuf]) { + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + fs::File::create(out_dir.join("boring_static_wrapper.h")) + .expect("Failed to create boring_static_wrapper.h") + .write_all(INCLUDES.as_bytes()) + .expect("Failed to write contents to boring_static_wrapper.h"); + + let mut bindgen_cmd = process::Command::new("bindgen"); + bindgen_cmd + .arg("-o") + .arg(out_dir.join("bindgen.rs")) + .arg("--rust-target=1.47") + .arg("--ctypes-prefix=::libc") + .arg("--no-derive-default") + .arg("--enable-function-attribute-detection") + .arg("--size_t-is-usize") + .arg("--default-macro-constant-type=signed") + .arg("--rustified-enum=point_conversion_form_t") + .arg("--allowlist-file=.*/openssl/[^/]+\\.h") + .arg("--experimental") + .arg("--wrap-static-fns") + .arg("--wrap-static-fns-path") + .arg(out_dir.join("boring_static_wrapper").display().to_string()) + .arg("--no-layout-tests") + .arg(out_dir.join("boring_static_wrapper.h")) + .arg("--") + .arg(format!("--target={}", env::var("TARGET").unwrap())); + + for include_dir in include_dirs { + bindgen_cmd.arg("-I").arg(include_dir.display().to_string()); + } + + let result = bindgen_cmd.status().expect("bindgen failed to execute"); + assert!(result.success()); + + cc::Build::new() + .file(out_dir.join("boring_static_wrapper.c")) + .includes(include_dirs) + .flag("-include") + .flag( + &out_dir + .join("boring_static_wrapper.h") + .display() + .to_string(), + ) + .compile("boring_static_wrapper"); +} + +#[derive(Debug)] +struct OpensslCallbacks; + +#[cfg(feature = "bindgen")] +impl ParseCallbacks for OpensslCallbacks { + // for now we'll continue hand-writing constants + fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior { + MacroParsingBehavior::Ignore + } + + fn item_name(&self, original_item_name: &str) -> Option { + match original_item_name { + // Our original definitions of these are wrong, so rename to avoid breakage + "CRYPTO_EX_new" + | "CRYPTO_EX_dup" + | "CRYPTO_EX_free" + | "BIO_meth_set_write" + | "BIO_meth_set_read" + | "BIO_meth_set_puts" + | "BIO_meth_set_ctrl" + | "BIO_meth_set_create" + | "BIO_meth_set_destroy" + | "CRYPTO_set_locking_callback" + | "CRYPTO_set_id_callback" + | "SSL_CTX_set_tmp_dh_callback" + | "SSL_set_tmp_dh_callback" + | "SSL_CTX_set_tmp_ecdh_callback" + | "SSL_set_tmp_ecdh_callback" + | "SSL_CTX_callback_ctrl" + | "SSL_CTX_set_alpn_select_cb" => Some(format!("{}__fixed_rust", original_item_name)), + _ => None, + } + } +} -- cgit v1.2.3