From 03a4c6bd26f70f37c79e594a86a0388b880ca998 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 26 Apr 2018 22:45:09 -0700 Subject: [PATCH] Reform version checking logic Rather than having an infinitely growing set of things to look for, just grab the literal version out. We also provide that to downstream crates, and it should be used rather than the random assortment of other stuff that's also passed down. --- openssl-sys/build.rs | 241 +++++++++++++++----------------- openssl-sys/src/lib.rs | 10 +- openssl-sys/src/libressl/mod.rs | 12 +- 3 files changed, 120 insertions(+), 143 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 0af3f8ed..a5a6c744 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -9,7 +9,6 @@ use std::ffi::OsString; use std::fs::File; use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; -use std::panic::{self, AssertUnwindSafe}; use std::process::Command; // The set of `OPENSSL_NO_`s that we care about. @@ -133,7 +132,7 @@ 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. @@ -326,42 +325,13 @@ fn validate_headers(include_dirs: &[PathBuf]) -> Version { #include #include -#if LIBRESSL_VERSION_NUMBER >= 0x20800000 -RUST_LIBRESSL_NEW -#elif LIBRESSL_VERSION_NUMBER >= 0x20700000 -RUST_LIBRESSL_27X -#elif LIBRESSL_VERSION_NUMBER >= 0x20603000 -RUST_LIBRESSL_26X -#elif LIBRESSL_VERSION_NUMBER >= 0x20602000 -RUST_LIBRESSL_262 -#elif LIBRESSL_VERSION_NUMBER >= 0x20601000 -RUST_LIBRESSL_261 -#elif LIBRESSL_VERSION_NUMBER >= 0x20600000 -RUST_LIBRESSL_260 -#elif LIBRESSL_VERSION_NUMBER >= 0x20503000 -RUST_LIBRESSL_25X -#elif LIBRESSL_VERSION_NUMBER >= 0x20502000 -RUST_LIBRESSL_252 -#elif LIBRESSL_VERSION_NUMBER >= 0x20501000 -RUST_LIBRESSL_251 -#elif LIBRESSL_VERSION_NUMBER >= 0x20500000 -RUST_LIBRESSL_250 -#elif defined (LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20500000 -RUST_LIBRESSL_OLD -#elif OPENSSL_VERSION_NUMBER >= 0x10102000 -RUST_OPENSSL_NEW -#elif OPENSSL_VERSION_NUMBER >= 0x10101000 -RUST_OPENSSL_111 -#elif OPENSSL_VERSION_NUMBER >= 0x10100060 -RUST_OPENSSL_110F -#elif OPENSSL_VERSION_NUMBER >= 0x10100000 -RUST_OPENSSL_110 -#elif OPENSSL_VERSION_NUMBER >= 0x10002000 -RUST_OPENSSL_102 -#elif OPENSSL_VERSION_NUMBER >= 0x10001000 -RUST_OPENSSL_101 -#else -RUST_OPENSSL_OLD +#define VERSION2(n, v) RUST_VERSION_ ## n ## _ ## v +#define VERSION(n, v) VERSION2(n, v) + +VERSION(OPENSSL, OPENSSL_VERSION_NUMBER) + +#ifdef LIBRESSL_VERSION_NUMBER +VERSION(LIBRESSL, LIBRESSL_VERSION_NUMBER) #endif " ).unwrap(); @@ -371,7 +341,7 @@ RUST_OPENSSL_OLD file, "\ #ifdef {define} -RUST_{define}_RUST +RUST_CONF_{define} #endif ", define = define @@ -386,11 +356,14 @@ RUST_{define}_RUST gcc.include(include_dir); } // https://github.com/alexcrichton/gcc-rs/issues/133 - let expanded = match panic::catch_unwind(AssertUnwindSafe(|| gcc.file(&path).expand())) { + let expanded = match gcc.file(&path).try_expand() { Ok(expanded) => expanded, - Err(_) => { + Err(e) => { panic!( " +Header expansion error: +{:?} + Failed to find OpenSSL development headers. You can try fixing this setting the `OPENSSL_DIR` environment variable @@ -407,118 +380,122 @@ specific to your distribution: See rust-openssl README for more information: https://github.com/sfackler/rust-openssl#linux -" +", + e ); } }; let expanded = String::from_utf8(expanded).unwrap(); let mut enabled = vec![]; - for &define in DEFINES { - if expanded.contains(&format!("RUST_{}_RUST", define)) { - println!("cargo:rustc-cfg=osslconf=\"{}\"", define); - enabled.push(define); + let mut openssl_version = None; + let mut libressl_version = None; + for line in expanded.lines() { + let line = line.trim(); + + let openssl_prefix = "RUST_VERSION_OPENSSL_"; + let libressl_prefix = "RUST_VERSION_LIBRESSL_"; + 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(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()..]); } } + + for enabled in &enabled { + println!("cargo:rustc-cfg=osslconf=\"{}\"", enabled); + } println!("cargo:conf={}", enabled.join(",")); - if expanded.contains("RUST_LIBRESSL_250") { + if let Some(libressl_version) = libressl_version { + println!("cargo:libressl_version_number={:x}", libressl_version); + + let minor = (libressl_version >> 20) as u8; + let fix = (libressl_version >> 12) as u8; + let (minor, fix) = match (minor, fix) { + (5, 0) => ('5', '0'), + (5, 1) => ('5', '1'), + (5, 2) => ('5', '2'), + (5, _) => ('5', 'x'), + (6, 0) => ('6', '0'), + (6, 1) => ('6', '1'), + (6, 2) => ('6', '2'), + (6, _) => ('6', 'x'), + (7, _) => ('7', 'x'), + _ => version_error(), + }; + println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl250"); + println!("cargo:rustc-cfg=libressl2{}{}", minor, fix); println!("cargo:libressl=true"); - println!("cargo:libressl_version=250"); + println!("cargo:libressl_version=2{}{}", minor, fix); println!("cargo:version=101"); Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_251") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl251"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=251"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_252") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl252"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=252"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_25X") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl25x"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=25x"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_260") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl260"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=260"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_261") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl261"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=261"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_262") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl262"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=262"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_26X") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl26x"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=26x"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_LIBRESSL_27X") { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:rustc-cfg=libressl27"); - println!("cargo:libressl=true"); - println!("cargo:libressl_version=27x"); - println!("cargo:version=101"); - Version::Libressl - } else if expanded.contains("RUST_OPENSSL_111") { - println!("cargo:rustc-cfg=ossl111"); - println!("cargo:rustc-cfg=ossl110"); - println!("cargo:version=111"); - Version::Openssl110 - } else if expanded.contains("RUST_OPENSSL_110F") { - println!("cargo:rustc-cfg=ossl110"); - println!("cargo:rustc-cfg=ossl110f"); - println!("cargo:version=110"); - println!("cargo:patch=f"); - Version::Openssl110 - } else if expanded.contains("RUST_OPENSSL_110") { - println!("cargo:rustc-cfg=ossl110"); - println!("cargo:version=110"); - Version::Openssl110 - } else if expanded.contains("RUST_OPENSSL_102") { - println!("cargo:rustc-cfg=ossl102"); - println!("cargo:version=102"); - Version::Openssl102 - } else if expanded.contains("RUST_OPENSSL_101") { - println!("cargo:rustc-cfg=ossl101"); - println!("cargo:version=101"); - Version::Openssl101 } else { - panic!( - " + let openssl_version = openssl_version.unwrap(); + println!("cargo:version_number={:x}", openssl_version); + + if openssl_version >= 0x1_01_02_00_0 { + version_error() + } else if openssl_version >= 0x1_01_01_00_0 { + println!("cargo:rustc-cfg=ossl111"); + println!("cargo:rustc-cfg=ossl110"); + println!("cargo:version=111"); + Version::Openssl110 + } else if openssl_version >= 0x1_01_00_06_0 { + println!("cargo:rustc-cfg=ossl110"); + println!("cargo:rustc-cfg=ossl110f"); + println!("cargo:version=110"); + println!("cargo:patch=f"); + Version::Openssl110 + } else if openssl_version >= 0x1_01_00_00_0 { + println!("cargo:rustc-cfg=ossl110"); + println!("cargo:version=110"); + Version::Openssl110 + } else if openssl_version >= 0x1_00_02_00_0 { + println!("cargo:rustc-cfg=ossl102"); + println!("cargo:version=102"); + Version::Openssl102 + } else if openssl_version >= 0x1_00_01_00_0 { + println!("cargo:rustc-cfg=ossl101"); + println!("cargo:version=101"); + Version::Openssl101 + } else { + version_error() + } + } +} + +fn version_error() -> ! { + panic!( + " This crate is only compatible with OpenSSL 1.0.1 through 1.1.1, or LibreSSL 2.5 through 2.7, 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" +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() } /// Given a libdir for OpenSSL (where artifacts are located) as well as the name diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 03ab60f4..8ebcb187 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -5,8 +5,8 @@ extern crate libc; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t, FILE}; -use std::ptr; use std::mem; +use std::ptr; #[cfg(any(ossl101, ossl102))] mod ossl10x; @@ -1277,14 +1277,14 @@ pub const SSL_VERIFY_NONE: c_int = 0; pub const SSL_VERIFY_PEER: c_int = 1; pub const SSL_VERIFY_FAIL_IF_NO_PEER_CERT: c_int = 2; -#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27, ossl101)))] +#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x, ossl101)))] pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x00000010; -#[cfg(any(libressl261, libressl262, libressl26x, libressl27))] +#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x0; pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_ulong = 0x00000800; -#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27)))] +#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x80000000; -#[cfg(any(libressl261, libressl262, libressl26x, libressl27))] +#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x0; pub const SSL_OP_LEGACY_SERVER_CONNECT: c_ulong = 0x00000004; #[cfg(not(libressl))] diff --git a/openssl-sys/src/libressl/mod.rs b/openssl-sys/src/libressl/mod.rs index 0bcf83e1..366d9502 100644 --- a/openssl-sys/src/libressl/mod.rs +++ b/openssl-sys/src/libressl/mod.rs @@ -1,7 +1,7 @@ -use std::sync::{Mutex, MutexGuard}; -use std::sync::{Once, ONCE_INIT}; use std::mem; use std::ptr; +use std::sync::{Mutex, MutexGuard}; +use std::sync::{Once, ONCE_INIT}; #[cfg(libressl250)] pub use libressl::v250::*; @@ -337,9 +337,9 @@ pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; -#[cfg(any(libressl261, libressl262, libressl26x, libressl27))] +#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] pub const SSL_OP_ALL: c_ulong = 0x4; -#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27)))] +#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] pub const SSL_OP_ALL: c_ulong = 0x80000014; pub const SSL_OP_CISCO_ANYCONNECT: c_ulong = 0x0; pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x0; @@ -352,9 +352,9 @@ pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_ulong = 0x0; pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_ulong = 0x0; pub const SSL_OP_TLS_D5_BUG: c_ulong = 0x0; pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_ulong = 0x0; -#[cfg(any(libressl261, libressl262, libressl26x, libressl27))] +#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x0; -#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27)))] +#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000; pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000; pub const SSL_OP_NO_SSLv2: c_ulong = 0x0;