diff options
| author | mredlek <[email protected]> | 2017-02-07 20:41:27 +0100 |
|---|---|---|
| committer | mredlek <[email protected]> | 2017-02-07 20:41:27 +0100 |
| commit | 30a634c877b831a0e8faf26433a302f8df61d256 (patch) | |
| tree | c6aa3a0edd4ec50e5a7e571d4facc2502a4b4d7f /openssl-sys | |
| parent | Add setters to new getter-functions in X509ReqRef (diff) | |
| parent | Merge pull request #572 from sfackler/foreign-types (diff) | |
| download | rust-openssl-30a634c877b831a0e8faf26433a302f8df61d256.tar.xz rust-openssl-30a634c877b831a0e8faf26433a302f8df61d256.zip | |
Merge branch 'master' into x509_req_version_subject
Diffstat (limited to 'openssl-sys')
| -rw-r--r-- | openssl-sys/Cargo.toml | 3 | ||||
| -rw-r--r-- | openssl-sys/build.rs | 297 | ||||
| -rw-r--r-- | openssl-sys/src/lib.rs | 18 |
3 files changed, 152 insertions, 166 deletions
diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 1f1750dc..76bd9172 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -16,11 +16,12 @@ libc = "0.2" [build-dependencies] pkg-config = "0.3.9" +gcc = "0.3.42" [target.'cfg(windows)'.dependencies] user32-sys = "0.2" gdi32-sys = "0.2" -# We don't actually use metadeps for annoying reasons but this is still hear for tooling +# We don't actually use metadeps for annoying reasons but this is still here for tooling [package.metadata.pkg-config] openssl = "1.0.1" diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 0e1cdc46..fc0f4680 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -1,13 +1,38 @@ extern crate pkg_config; +extern crate gcc; use std::collections::HashSet; use std::env; use std::ffi::OsString; use std::fs::File; -use std::io::Read; +use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; +use std::panic::{self, AssertUnwindSafe}; use std::process::Command; +// The set of `OPENSSL_NO_<FOO>`s that we care about. +const DEFINES: &'static [&'static str] = &[ + "OPENSSL_NO_BUF_FREELISTS", + "OPENSSL_NO_COMP", + "OPENSSL_NO_EC", + "OPENSSL_NO_ENGINE", + "OPENSSL_NO_KRB5", + "OPENSSL_NO_NEXTPROTONEG", + "OPENSSL_NO_PSK", + "OPENSSL_NO_RFC3779", + "OPENSSL_NO_SHA", + "OPENSSL_NO_SRP", + "OPENSSL_NO_SSL3_METHOD", + "OPENSSL_NO_TLSEXT", +]; + +enum Version { + Openssl110, + Openssl102, + Openssl101, + Libressl, +} + fn main() { let target = env::var("TARGET").unwrap(); @@ -38,17 +63,14 @@ fn main() { println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy()); println!("cargo:include={}", include_dir.to_string_lossy()); - let version = validate_headers(&[include_dir.clone().into()], - &[lib_dir.clone().into()]); + let version = validate_headers(&[include_dir.clone().into()]); - let libs = if (version.contains("0x10001") || - version.contains("0x10002")) && - target.contains("windows") { - ["ssleay32", "libeay32"] - } else if target.contains("windows") { - ["libssl", "libcrypto"] - } else { - ["ssl", "crypto"] + let libs = match version { + Version::Openssl101 | Version::Openssl102 if target.contains("windows") => { + ["ssleay32", "libeay32"] + } + Version::Openssl110 if target.contains("windows") => ["libssl", "libcrypto"], + _ => ["ssl", "crypto"], }; let kind = determine_mode(Path::new(&lib_dir), &libs); @@ -168,29 +190,79 @@ fn try_pkg_config() { return } - // We're going to be looking at header files, so show us all the system - // cflags dirs for showing us lots of `-I`. - env::set_var("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", "1"); - - // This is more complex than normal because we need to track down opensslconf.h. - // To do that, we need the inlude paths even if they're on the default search path, but the - // linkage directories emitted from that cause all kinds of issues if other libraries happen to - // live in them. So, we run pkg-config twice, once asking for system dirs but not emitting - // metadata, and a second time emitting metadata but not asking for system dirs. Yay. - let lib = match pkg_config::Config::new() - .cargo_metadata(false) - .print_system_libs(true) - .find("openssl") { - Ok(lib) => lib, - Err(_) => return, - }; + let lib = pkg_config::Config::new() + .print_system_libs(false) + .find("openssl") + .unwrap(); - if lib.include_paths.len() == 0 { - panic!(" + validate_headers(&lib.include_paths); + + for include in lib.include_paths.iter() { + println!("cargo:include={}", include.display()); + } + + std::process::exit(0); +} + +/// Validates the header files found in `include_dir` and then returns the +/// version string of OpenSSL. +fn validate_headers(include_dirs: &[PathBuf]) -> Version { + // This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, and 1.1.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. + let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + path.push("expando.c"); + let mut file = BufWriter::new(File::create(&path).unwrap()); + + write!(file, "\ +#include <openssl/opensslv.h> +#include <openssl/opensslconf.h> + +#ifdef LIBRESSL_VERSION_NUMBER +RUST_LIBRESSL +#elif OPENSSL_VERSION_NUMBER >= 0x10200000 +RUST_OPENSSL_NEW +#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 +#endif +").unwrap(); + + for define in DEFINES { + write!(file, "\ +#ifdef {define} +RUST_{define} +#endif +", define = define).unwrap(); + } + + file.flush().unwrap(); + drop(file); -Used pkg-config to discover the OpenSSL installation, but pkg-config did not -return any include paths for the installation. This crate needs to take a peek -at the header files so it cannot proceed unless they're found. + let mut gcc = gcc::Config::new(); + for include_dir in include_dirs { + gcc.include(include_dir); + } + // https://github.com/alexcrichton/gcc-rs/issues/133 + let expanded = match panic::catch_unwind(AssertUnwindSafe(|| gcc.file(&path).expand())) { + Ok(expanded) => expanded, + Err(_) => { + panic!(" +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 @@ -207,150 +279,45 @@ See rust-openssl README for more information: https://github.com/sfackler/rust-openssl#linux "); - } - - validate_headers(&lib.include_paths, &lib.link_paths); - - for include in lib.include_paths.iter() { - println!("cargo:include={}", include.display()); - } - - pkg_config::Config::new() - .print_system_libs(false) - .find("openssl") - .unwrap(); - - std::process::exit(0); -} - -/// Validates the header files found in `include_dir` and then returns the -/// version string of OpenSSL. -fn validate_headers(include_dirs: &[PathBuf], - libdirs: &[PathBuf]) -> String { - // This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, and 1.1.0. To - // correctly expose the right API from this crate, take a look at - // `opensslv.h` to see what version OpenSSL claims to be. - let mut version_header = String::new(); - let mut include = include_dirs.iter() - .map(|p| p.join("openssl/opensslv.h")) - .filter(|p| p.exists()); - let mut f = match include.next() { - Some(f) => File::open(f).unwrap(), - None => { - panic!("failed to open header file at `openssl/opensslv.h` to learn - about OpenSSL's version number, looked inside:\n\n{:#?}\n\n", - include_dirs); } }; - f.read_to_string(&mut version_header).unwrap(); - - // Do a bit of string parsing to find `#define OPENSSL_VERSION_NUMBER ...` - let version_line = version_header.lines().find(|l| { - l.contains("define ") && l.contains("OPENSSL_VERSION_NUMBER") - }).and_then(|line| { - let start = match line.find("0x") { - Some(start) => start, - None => return None, - }; - Some(line[start..].trim()) - }); - let version_text = match version_line { - Some(text) => text, - None => { - panic!("header file at `{}` did not include `OPENSSL_VERSION_NUMBER` \ - that this crate recognized, failed to learn about the \ - OpenSSL version number"); + let expanded = String::from_utf8(expanded).unwrap(); + + let mut enabled = vec![]; + for &define in DEFINES { + if expanded.contains(&format!("RUST_{}", define)) { + println!("cargo:rustc-cfg=osslconf=\"{}\"", define); + enabled.push(define); } - }; - if version_text.contains("0x10001") { - println!("cargo:rustc-cfg=ossl101"); + } + println!("cargo:conf={}", enabled.join(",")); + + if expanded.contains("RUST_LIBRESSL") { + println!("cargo:rustc-cfg=libressl"); + println!("cargo:libressl=true"); println!("cargo:version=101"); - } else if version_text.contains("0x10002") { - println!("cargo:rustc-cfg=ossl102"); - println!("cargo:version=102"); - } else if version_text.contains("0x10100") { + Version::Libressl + } else if expanded.contains("RUST_OPENSSL_110") { println!("cargo:rustc-cfg=ossl110"); println!("cargo:version=110"); - } else if version_text.contains("0x20000000L") { - // Check if it is really LibreSSL - if version_header.lines().any(|l| { - l.contains("define ") && l.contains("LIBRESSL_VERSION_NUMBER") - }) { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:libressl=true"); - println!("cargo:version=101"); - } + 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!(" -This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, but a -different version of OpenSSL was found: - - {} - -The build is now aborting due to this version mismatch. +This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, or LibreSSL, +but a different version of OpenSSL was found. The build is now aborting due to +this version mismatch. -", version_text); - } - - // 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. - let mut conf_header = String::new(); - let mut include = include_dirs.iter() - .map(|p| p.join("openssl/opensslconf.h")) - .filter(|p| p.exists()); - let mut f = match include.next() { - Some(f) => File::open(f).unwrap(), - None => { - // It's been seen that on linux the include dir printed out by - // `pkg-config` doesn't actually have opensslconf.h. Instead - // it's in an architecture-specific include directory. - // - // Try to detect that case to see if it exists. - let mut libdirs = libdirs.iter().map(|p| { - p.iter() - .map(|p| if p == "lib" {"include".as_ref()} else {p}) - .collect::<PathBuf>() - }).map(|p| { - p.join("openssl/opensslconf.h") - }).filter(|p| p.exists()); - match libdirs.next() { - Some(f) => File::open(f).unwrap(), - None => { - panic!("failed to open header file at - `openssl/opensslconf.h` to learn about \ - OpenSSL's version number, looked \ - inside:\n\n{:#?}\n\n", - include_dirs); - } - } - } - }; - f.read_to_string(&mut conf_header).unwrap(); - - // Look for `#define OPENSSL_FOO`, print out everything as our own - // #[cfg] flag. - let mut vars = vec![]; - for line in conf_header.lines() { - let i = match line.find("define ") { - Some(i) => i, - None => continue, - }; - let var = line[i + "define ".len()..].trim(); - if var.starts_with("OPENSSL") && !var.contains(" ") { - println!("cargo:rustc-cfg=osslconf=\"{}\"", var); - vars.push(var); - } +"); } - println!("cargo:conf={}", vars.join(",")); - - return version_text.to_string() } /// 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 1340a63f..e611fc81 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -150,6 +150,12 @@ pub const EVP_PKEY_DSA: c_int = NID_dsa; pub const EVP_PKEY_DH: c_int = NID_dhKeyAgreement; pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey; +pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000; + +pub const EVP_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1; + +pub const EVP_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6; + pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11; @@ -1303,6 +1309,15 @@ pub unsafe fn BIO_set_retry_write(b: *mut BIO) { BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY) } +// EVP_PKEY_CTX_ctrl macros +pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) +} + +pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) +} + pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) } @@ -1632,6 +1647,9 @@ extern { key: *const c_uchar, keylen: c_int) -> *mut EVP_PKEY; + + pub fn EVP_PKEY_CTX_ctrl(ctx: *mut EVP_PKEY_CTX, keytype: c_int, optype: c_int, cmd: c_int, p1: c_int, p2: *mut c_void) -> c_int; + pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *mut HMAC_CTX) -> c_int; pub fn OCSP_BASICRESP_new() -> *mut OCSP_BASICRESP; |