From 43c951f743e68fac5f45119eda7c994882a1d489 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 30 Sep 2016 00:43:05 -0700 Subject: Add support for OpenSSL 1.1.0 This commit is relatively major refactoring of the `openssl-sys` crate as well as the `openssl` crate itself. The end goal here was to support OpenSSL 1.1.0, and lots of other various tweaks happened along the way. The major new features are: * OpenSSL 1.1.0 is supported * OpenSSL 0.9.8 is no longer supported (aka all OSX users by default) * All FFI bindings are verified with the `ctest` crate (same way as the `libc` crate) * CI matrixes are vastly expanded to include 32/64 of all platforms, more OpenSSL version coverage, as well as ARM coverage on Linux * The `c_helpers` module is completely removed along with the `gcc` dependency. * The `openssl-sys` build script was completely rewritten * Now uses `OPENSSL_DIR` to find the installation, not include/lib env vars. * Better error messages for mismatched versions. * Better error messages for failing to find OpenSSL on a platform (more can be done here) * Probing of OpenSSL build-time configuration to inform the API of the `*-sys` crate. * Many Cargo features have been removed as they're now enabled by default. As this is a breaking change to both the `openssl` and `openssl-sys` crates this will necessitate a major version bump of both. There's still a few more API questions remaining but let's hash that out on a PR! Closes #452 --- openssl/src/ssl/bio.rs | 176 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 130 insertions(+), 46 deletions(-) (limited to 'openssl/src/ssl/bio.rs') diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index c5663eb1..ccf3a472 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -1,5 +1,5 @@ use libc::{c_char, c_int, c_long, c_void, strlen}; -use ffi::{self, BIO, BIO_CTRL_FLUSH, BIO_TYPE_NONE, BIO_new, BIO_clear_retry_flags, +use ffi::{BIO, BIO_CTRL_FLUSH, BIO_new, BIO_clear_retry_flags, BIO_set_retry_read, BIO_set_retry_write}; use std::any::Any; use std::io; @@ -18,22 +18,11 @@ pub struct StreamState { } /// Safe wrapper for BIO_METHOD -pub struct BioMethod(ffi::BIO_METHOD); +pub struct BioMethod(compat::BIO_METHOD); impl BioMethod { pub fn new() -> BioMethod { - BioMethod(ffi::BIO_METHOD { - type_: BIO_TYPE_NONE, - name: b"rust\0".as_ptr() as *const _, - bwrite: Some(bwrite::), - bread: Some(bread::), - bputs: Some(bputs::), - bgets: None, - ctrl: Some(ctrl::), - create: Some(create), - destroy: Some(destroy::), - callback_ctrl: None, - }) + BioMethod(compat::BIO_METHOD::new::()) } } @@ -49,9 +38,9 @@ pub fn new(stream: S) -> Result<(*mut BIO, Arc), Err }); unsafe { - let bio = try_ssl_null!(BIO_new(&method.0)); - (*bio).ptr = Box::into_raw(state) as *mut _; - (*bio).init = 1; + let bio = try_ssl_null!(BIO_new(method.0.get())); + compat::BIO_set_data(bio, Box::into_raw(state) as *mut _); + compat::BIO_set_init(bio, 1); return Ok((bio, method)); } @@ -62,14 +51,13 @@ pub unsafe fn take_error(bio: *mut BIO) -> Option { state.error.take() } -#[cfg_attr(not(feature = "nightly"), allow(dead_code))] pub unsafe fn take_panic(bio: *mut BIO) -> Option> { let state = state::(bio); state.panic.take() } pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S { - let state: &'a StreamState = mem::transmute((*bio).ptr); + let state: &'a StreamState = mem::transmute(compat::BIO_get_data(bio)); &state.stream } @@ -78,24 +66,16 @@ pub unsafe fn get_mut<'a, S: 'a>(bio: *mut BIO) -> &'a mut S { } unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState { - mem::transmute((*bio).ptr) + mem::transmute(compat::BIO_get_data(bio)) } -#[cfg(feature = "nightly")] fn catch_unwind(f: F) -> Result> where F: FnOnce() -> T { ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f)) } -#[cfg(not(feature = "nightly"))] -fn catch_unwind(f: F) -> Result> - where F: FnOnce() -> T -{ - Ok(f()) -} - -unsafe extern "C" fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { +unsafe extern fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { BIO_clear_retry_flags(bio); let state = state::(bio); @@ -117,7 +97,7 @@ unsafe extern "C" fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_ } } -unsafe extern "C" fn bread(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int { +unsafe extern fn bread(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int { BIO_clear_retry_flags(bio); let state = state::(bio); @@ -147,15 +127,15 @@ fn retriable_error(err: &io::Error) -> bool { } } -unsafe extern "C" fn bputs(bio: *mut BIO, s: *const c_char) -> c_int { +unsafe extern fn bputs(bio: *mut BIO, s: *const c_char) -> c_int { bwrite::(bio, s, strlen(s) as c_int) } -unsafe extern "C" fn ctrl(bio: *mut BIO, - cmd: c_int, - _num: c_long, - _ptr: *mut c_void) - -> c_long { +unsafe extern fn ctrl(bio: *mut BIO, + cmd: c_int, + _num: c_long, + _ptr: *mut c_void) + -> c_long { if cmd == BIO_CTRL_FLUSH { let state = state::(bio); @@ -175,22 +155,126 @@ unsafe extern "C" fn ctrl(bio: *mut BIO, } } -unsafe extern "C" fn create(bio: *mut BIO) -> c_int { - (*bio).init = 0; - (*bio).num = 0; - (*bio).ptr = ptr::null_mut(); - (*bio).flags = 0; +unsafe extern fn create(bio: *mut BIO) -> c_int { + compat::BIO_set_init(bio, 0); + compat::BIO_set_num(bio, 0); + compat::BIO_set_data(bio, ptr::null_mut()); + compat::BIO_set_flags(bio, 0); 1 } -unsafe extern "C" fn destroy(bio: *mut BIO) -> c_int { +unsafe extern fn destroy(bio: *mut BIO) -> c_int { if bio.is_null() { return 0; } - assert!(!(*bio).ptr.is_null()); - Box::>::from_raw((*bio).ptr as *mut _); - (*bio).ptr = ptr::null_mut(); - (*bio).init = 0; + let data = compat::BIO_get_data(bio); + assert!(!data.is_null()); + Box::>::from_raw(data as *mut _); + compat::BIO_set_data(bio, ptr::null_mut()); + compat::BIO_set_init(bio, 0); 1 } + +#[cfg(ossl110)] +#[allow(bad_style)] +mod compat { + use std::io::{Read, Write}; + + use libc::c_int; + use ffi; + pub use ffi::{BIO_set_init, BIO_set_flags, BIO_set_data, BIO_get_data}; + + pub unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {} + + pub struct BIO_METHOD { + inner: *mut ffi::BIO_METHOD, + } + + impl BIO_METHOD { + pub fn new() -> BIO_METHOD { + unsafe { + let ptr = ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, + b"rust\0".as_ptr() as *const _); + assert!(!ptr.is_null()); + let ret = BIO_METHOD { inner: ptr }; + assert!(ffi::BIO_meth_set_write(ptr, super::bwrite::) != 0); + assert!(ffi::BIO_meth_set_read(ptr, super::bread::) != 0); + assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::) != 0); + assert!(ffi::BIO_meth_set_ctrl(ptr, super::ctrl::) != 0); + assert!(ffi::BIO_meth_set_create(ptr, super::create) != 0); + assert!(ffi::BIO_meth_set_destroy(ptr, super::destroy::) != 0); + return ret + } + } + + pub fn get(&self) -> *mut ffi::BIO_METHOD { + self.inner + } + } + + impl Drop for BIO_METHOD { + fn drop(&mut self) { + unsafe { + ffi::BIO_meth_free(self.inner); + } + } + } +} + +#[cfg(ossl10x)] +#[allow(bad_style)] +mod compat { + use std::io::{Read, Write}; + use std::cell::UnsafeCell; + + use ffi; + use libc::{c_int, c_void}; + + pub struct BIO_METHOD { + inner: UnsafeCell, + } + + impl BIO_METHOD { + pub fn new() -> BIO_METHOD { + BIO_METHOD { + inner: UnsafeCell::new(ffi::BIO_METHOD { + type_: ffi::BIO_TYPE_NONE, + name: b"rust\0".as_ptr() as *const _, + bwrite: Some(super::bwrite::), + bread: Some(super::bread::), + bputs: Some(super::bputs::), + bgets: None, + ctrl: Some(super::ctrl::), + create: Some(super::create), + destroy: Some(super::destroy::), + callback_ctrl: None, + }), + } + } + + pub fn get(&self) -> *mut ffi::BIO_METHOD { + self.inner.get() + } + } + + pub unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) { + (*bio).init = init; + } + + pub unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) { + (*bio).flags = flags; + } + + pub unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void { + (*bio).ptr + } + + pub unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) { + (*bio).ptr = data; + } + + pub unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) { + (*bio).num = num; + } +} -- cgit v1.2.3