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 ++++++++++++++++------ openssl/src/ssl/mod.rs | 350 ++++++++++++++++++++++++------------------- openssl/src/ssl/tests/mod.rs | 124 +++++++-------- 3 files changed, 388 insertions(+), 262 deletions(-) (limited to 'openssl/src/ssl') 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; + } +} diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6e365af6..51bfc790 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_void, c_long}; +use libc::{c_int, c_void, c_long, c_ulong}; use std::any::Any; use std::any::TypeId; use std::cmp; @@ -38,12 +38,11 @@ use self::bio::BioMethod; pub use ssl::error::Error; bitflags! { - pub flags SslContextOptions: c_long { + pub flags SslContextOptions: c_ulong { const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG, const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi::SSL_OP_NETSCAPE_CHALLENGE_BUG, const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ffi::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, - const SSL_OP_TLSEXT_PADDING = ffi::SSL_OP_TLSEXT_PADDING, const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, const SSL_OP_TLS_D5_BUG = ffi::SSL_OP_TLS_D5_BUG, @@ -73,74 +72,11 @@ bitflags! { #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub enum SslMethod { - #[cfg(feature = "sslv2")] - /// Only support the SSLv2 protocol, requires the `sslv2` feature. - Sslv2, - /// Support the SSLv2, SSLv3, TLSv1, TLSv1.1, and TLSv1.2 protocols depending on what the - /// linked OpenSSL library supports. - Sslv23, - #[cfg(feature = "sslv3")] - /// Only support the SSLv3 protocol. - Sslv3, - /// Only support the TLSv1 protocol. - Tlsv1, - #[cfg(feature = "tlsv1_1")] - /// Support TLSv1.1 protocol, requires the `tlsv1_1` feature. - Tlsv1_1, - #[cfg(feature = "tlsv1_2")] - /// Support TLSv1.2 protocol, requires the `tlsv1_2` feature. - Tlsv1_2, - #[cfg(feature = "dtlsv1")] - /// Support DTLSv1 protocol, requires the `dtlsv1` feature. - Dtlsv1, - #[cfg(feature = "dtlsv1_2")] - /// Support DTLSv1.2 protocol, requires the `dtlsv1_2` feature. - Dtlsv1_2, -} - -impl SslMethod { - fn to_raw(&self) -> *const ffi::SSL_METHOD { - unsafe { - match *self { - #[cfg(feature = "sslv2")] - SslMethod::Sslv2 => ffi::SSLv2_method(), - #[cfg(feature = "sslv3")] - SslMethod::Sslv3 => ffi::SSLv3_method(), - SslMethod::Tlsv1 => ffi::TLSv1_method(), - SslMethod::Sslv23 => ffi::SSLv23_method(), - #[cfg(feature = "tlsv1_1")] - SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(), - #[cfg(feature = "tlsv1_2")] - SslMethod::Tlsv1_2 => ffi::TLSv1_2_method(), - #[cfg(feature = "dtlsv1")] - SslMethod::Dtlsv1 => ffi::DTLSv1_method(), - #[cfg(feature = "dtlsv1_2")] - SslMethod::Dtlsv1_2 => ffi::DTLSv1_2_method(), - } - } - } - - fn from_raw(method: *const ffi::SSL_METHOD) -> Option { - unsafe { - match method { - #[cfg(feature = "sslv2")] - x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2), - #[cfg(feature = "sslv3")] - x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3), - x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1), - x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23), - #[cfg(feature = "tlsv1_1")] - x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1), - #[cfg(feature = "tlsv1_2")] - x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2), - #[cfg(feature = "dtlsv1")] - x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1), - #[cfg(feature = "dtlsv1_2")] - x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2), - _ => None, - } - } - } + // TODO: support more methods + /// Support the TLS protocol + Tls, + /// Support DTLS protocol + Dtls, } /// Determines the type of certificate verification used @@ -172,11 +108,11 @@ fn get_ssl_verify_data_idx() -> c_int { *SSL_INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| get_new_ssl_idx::()) } -#[cfg(feature = "npn")] +#[cfg(all(feature = "npn", not(ossl101)))] lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); } -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] lazy_static! { static ref ALPN_PROTOS_IDX: c_int = get_new_idx::>(); } @@ -184,52 +120,50 @@ lazy_static! { /// Determine a new index to use for SSL CTX ex data. /// Registers a destruct for the data which will be called by openssl when the context is freed. fn get_new_idx() -> c_int { - extern "C" fn free_data_box(_parent: *mut c_void, - ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, - _idx: c_int, - _argl: c_long, - _argp: *mut c_void) { + extern fn free_data_box(_parent: *mut c_void, + ptr: *mut c_void, + _ad: *mut ffi::CRYPTO_EX_DATA, + _idx: c_int, + _argl: c_long, + _argp: *mut c_void) { if !ptr.is_null() { let _: Box = unsafe { mem::transmute(ptr) }; } } unsafe { - let f: ffi::CRYPTO_EX_free = free_data_box::; - let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f)); + let idx = compat::get_new_idx(free_data_box::); assert!(idx >= 0); idx } } fn get_new_ssl_idx() -> c_int { - extern "C" fn free_data_box(_parent: *mut c_void, - ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, - _idx: c_int, - _argl: c_long, - _argp: *mut c_void) { + extern fn free_data_box(_parent: *mut c_void, + ptr: *mut c_void, + _ad: *mut ffi::CRYPTO_EX_DATA, + _idx: c_int, + _argl: c_long, + _argp: *mut c_void) { if !ptr.is_null() { let _: Box = unsafe { mem::transmute(ptr) }; } } unsafe { - let f: ffi::CRYPTO_EX_free = free_data_box::; - let idx = ffi::SSL_get_ex_new_index(0, ptr::null(), None, None, Some(f)); + let idx = compat::get_new_ssl_idx(free_data_box::); assert!(idx >= 0); idx } } -extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int +extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); + let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); let verify: &F = mem::transmute(verify); @@ -239,13 +173,14 @@ extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_ } } -extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int +extern fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); - let verify = ffi::SSL_get_ex_data(ssl, get_ssl_verify_data_idx::()); + let verify = ffi::SSL_get_ex_data(ssl as *const _, + get_ssl_verify_data_idx::()); let verify: &F = mem::transmute(verify); let ctx = X509StoreContext::new(x509_ctx); @@ -254,7 +189,7 @@ extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST } } -extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int +extern fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int where F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { @@ -278,7 +213,7 @@ extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) } } -#[cfg(any(feature = "npn", feature = "alpn"))] +#[cfg(all(any(feature = "npn", feature = "alpn"), not(ossl101)))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, @@ -311,26 +246,26 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, /// supported by the server. It achieves this by delegating to the `SSL_select_next_proto` /// function. The list of protocols supported by the client is found in the extra data of the /// OpenSSL context. -#[cfg(feature = "npn")] -extern "C" fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, - outlen: *mut c_uchar, - inbuf: *const c_uchar, - inlen: c_uint, - _arg: *mut c_void) - -> c_int { +#[cfg(all(feature = "npn", not(ossl101)))] +extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, + out: *mut *mut c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + _arg: *mut c_void) + -> c_int { unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) } } -#[cfg(feature = "alpn")] -extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, - outlen: *mut c_uchar, - inbuf: *const c_uchar, - inlen: c_uint, - _arg: *mut c_void) - -> c_int { - unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) } +#[cfg(all(feature = "alpn", not(ossl101)))] +extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, + out: *mut *const c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + _arg: *mut c_void) + -> c_int { + unsafe { select_proto_using(ssl, out as *mut _, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) } } /// The function is given as the callback to `SSL_CTX_set_next_protos_advertised_cb`. @@ -340,12 +275,12 @@ extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL, /// that it supports. /// The list of supported protocols is found in the extra data of the OpenSSL /// context. -#[cfg(feature = "npn")] -extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, - out: *mut *const c_uchar, - outlen: *mut c_uint, - _arg: *mut c_void) - -> c_int { +#[cfg(all(feature = "npn", not(ossl101)))] +extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, + out: *mut *const c_uchar, + outlen: *mut c_uint, + _arg: *mut c_void) + -> c_int { unsafe { // First, get the list of (supported) protocols saved in the context extra data. let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); @@ -367,7 +302,7 @@ extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, /// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte /// containing the length followed by the string. -#[cfg(any(feature = "npn", feature = "alpn"))] +#[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))] fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { let mut enc = Vec::new(); for string in strings { @@ -442,8 +377,8 @@ impl<'a> SslContextRef<'a> { ffi::SSL_CTX_set_ex_data(self.as_ptr(), get_verify_data_idx::(), mem::transmute(callback)); - let f: extern "C" fn(_, _, _) -> _ = raw_sni::; - let f: extern "C" fn() = mem::transmute(f); + let f: extern fn(_, _, _) -> _ = raw_sni::; + let f: extern fn() = mem::transmute(f); ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f)); } } @@ -515,15 +450,12 @@ impl<'a> SslContextRef<'a> { } /// Specifies the file that contains certificate chain - pub fn set_certificate_chain_file>(&mut self, - file: P, - file_type: X509FileType) + pub fn set_certificate_chain_file>(&mut self, file: P) -> Result<(), ErrorStack> { let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap(); wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate_chain_file(self.as_ptr(), - file.as_ptr() as *const _, - file_type as c_int) + file.as_ptr() as *const _) }) } @@ -575,27 +507,44 @@ impl<'a> SslContextRef<'a> { }) } - /// If `onoff` is set to `true`, enable ECDHE for key exchange with compatible - /// clients, and automatically select an appropriate elliptic curve. + /// If `onoff` is set to `true`, enable ECDHE for key exchange with + /// compatible clients, and automatically select an appropriate elliptic + /// curve. /// - /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. - #[cfg(feature = "ecdh_auto")] + /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` + /// feature. + #[cfg(all(feature = "ecdh_auto", not(ossl101)))] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_long) as c_int }) + self._set_ecdh_auto(onoff) + } + + #[cfg(all(feature = "ecdh_auto", ossl102))] + fn _set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { + wrap_ssl_result(unsafe { + ffi::SSL_CTX_ctrl(self.as_ptr(), + ffi::SSL_CTRL_SET_ECDH_AUTO, + onoff as c_long, + ptr::null_mut()) as c_int + }) + } + + #[cfg(all(feature = "ecdh_auto", ossl110))] + fn _set_ecdh_auto(&mut self, _onoff: bool) -> Result<(), ErrorStack> { + Ok(()) } pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; + let ret = unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } pub fn options(&self) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) }; + let ret = unsafe { compat::SSL_CTX_get_options(self.as_ptr()) }; SslContextOptions::from_bits(ret).unwrap() } pub fn clear_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; + let ret = unsafe { compat::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; SslContextOptions::from_bits(ret).unwrap() } @@ -603,7 +552,7 @@ impl<'a> SslContextRef<'a> { /// supported by the application). /// /// This method needs the `npn` feature. - #[cfg(feature = "npn")] + #[cfg(all(feature = "npn", not(ossl101)))] pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) { // Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL // APIs -- a list of length-prefixed strings. @@ -635,7 +584,7 @@ impl<'a> SslContextRef<'a> { /// Note that ordering of the protocols controls the priority with which they are chosen. /// /// This method needs the `alpn` feature. - #[cfg(feature = "alpn")] + #[cfg(all(feature = "alpn", not(ossl101)))] pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) { let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); unsafe { @@ -662,12 +611,10 @@ pub struct SslContext(SslContextRef<'static>); unsafe impl Send for SslContext {} unsafe impl Sync for SslContext {} -#[cfg(feature = "ssl_context_clone")] impl Clone for SslContext { - /// Requires the `ssl_context_clone` feature. fn clone(&self) -> Self { unsafe { - ::c_helpers::rust_0_8_SSL_CTX_clone(self.as_ptr()); + compat::SSL_CTX_up_ref(self.as_ptr()); SslContext::from_ptr(self.as_ptr()) } } @@ -706,15 +653,13 @@ impl SslContext { init(); let mut ctx = unsafe { - let ctx = try_ssl_null!(ffi::SSL_CTX_new(method.to_raw())); + let method = compat::get_method(method); + let ctx = try_ssl_null!(ffi::SSL_CTX_new(method)); SslContext::from_ptr(ctx) }; match method { - #[cfg(feature = "dtlsv1")] - SslMethod::Dtlsv1 => ctx.set_read_ahead(1), - #[cfg(feature = "dtlsv1_2")] - SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1), + SslMethod::Dtls => ctx.set_read_ahead(1), _ => {} } // this is a bit dubious (?) @@ -982,7 +927,7 @@ impl<'a> SslRef<'a> { /// to interpret it. /// /// This method needs the `alpn` feature. - #[cfg(feature = "alpn")] + #[cfg(all(feature = "alpn", not(ossl101)))] pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { unsafe { let mut data: *const c_uchar = ptr::null(); @@ -1023,13 +968,6 @@ impl<'a> SslRef<'a> { Some(s) } - pub fn ssl_method(&self) -> SslMethod { - unsafe { - let method = ffi::SSL_get_ssl_method(self.as_ptr()); - SslMethod::from_raw(method).unwrap() - } - } - /// Returns the server's name for the current connection pub fn servername(&self) -> Option { let name = unsafe { ffi::SSL_get_servername(self.as_ptr(), ffi::TLSEXT_NAMETYPE_host_name) }; @@ -1319,16 +1257,12 @@ impl SslStream { } } - #[cfg(feature = "nightly")] fn check_panic(&mut self) { if let Some(err) = unsafe { bio::take_panic::(self.ssl.get_raw_rbio()) } { ::std::panic::resume_unwind(err) } } - #[cfg(not(feature = "nightly"))] - fn check_panic(&mut self) {} - fn get_bio_error(&mut self) -> io::Error { let error = unsafe { bio::take_error::(self.ssl.get_raw_rbio()) }; match error { @@ -1412,3 +1346,107 @@ impl<'a> IntoSsl for &'a SslContext { Ssl::new(self) } } + +#[cfg(ossl110)] +mod compat { + use std::ptr; + + use ffi; + use libc::c_int; + + pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options}; + pub use ffi::{SSL_CTX_clear_options, SSL_CTX_up_ref}; + + use super::SslMethod; + + pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { + ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL_CTX, + 0, + ptr::null_mut(), + None, + None, + Some(f)) + } + + pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { + ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL, + 0, + ptr::null_mut(), + None, + None, + Some(f)) + } + + pub unsafe fn get_method(method: SslMethod) -> *const ffi::SSL_METHOD { + match method { + SslMethod::Tls => ffi::TLS_method(), + SslMethod::Dtls => ffi::DTLS_method(), + } + } +} + +#[cfg(ossl10x)] +#[allow(bad_style)] +mod compat { + use std::ptr; + + use ffi; + use libc::{self, c_long, c_ulong, c_int}; + + use super::SslMethod; + + pub unsafe fn SSL_CTX_get_options(ctx: *const ffi::SSL_CTX) -> c_ulong { + ffi::SSL_CTX_ctrl(ctx as *mut _, + ffi::SSL_CTRL_OPTIONS, + 0, + ptr::null_mut()) as c_ulong + } + + pub unsafe fn SSL_CTX_set_options(ctx: *const ffi::SSL_CTX, + op: c_ulong) -> c_ulong { + ffi::SSL_CTX_ctrl(ctx as *mut _, + ffi::SSL_CTRL_OPTIONS, + op as c_long, + ptr::null_mut()) as c_ulong + } + + pub unsafe fn SSL_CTX_clear_options(ctx: *const ffi::SSL_CTX, + op: c_ulong) -> c_ulong { + ffi::SSL_CTX_ctrl(ctx as *mut _, + ffi::SSL_CTRL_CLEAR_OPTIONS, + op as c_long, + ptr::null_mut()) as c_ulong + } + + pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { + ffi::SSL_CTX_get_ex_new_index(0, + ptr::null_mut(), + None, + None, + Some(f)) + } + + pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { + ffi::SSL_get_ex_new_index(0, + ptr::null_mut(), + None, + None, + Some(f)) + } + + pub unsafe fn get_method(method: SslMethod) -> *const ffi::SSL_METHOD { + match method { + SslMethod::Tls => ffi::SSLv23_method(), + SslMethod::Dtls => ffi::DTLSv1_method(), + } + } + + pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> libc::c_int { + ffi::CRYPTO_add_lock(&mut (*ssl).references, + 1, + ffi::CRYPTO_LOCK_SSL_CTX, + "mod.rs\0".as_ptr() as *const _, + line!() as libc::c_int); + 0 + } +} diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 3bbbed03..e5bdc8da 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] +use std::env; use std::fs::File; use std::io::prelude::*; use std::io::{self, BufReader}; @@ -12,11 +13,12 @@ use std::thread; use std::time::Duration; use net2::TcpStreamExt; +use tempdir::TempDir; use crypto::hash::Type::SHA256; use ssl; use ssl::SSL_VERIFY_PEER; -use ssl::SslMethod::Sslv23; +use ssl::SslMethod::Tls; use ssl::{SslMethod, HandshakeError}; use ssl::error::Error; use ssl::{SslContext, SslStream}; @@ -46,10 +48,21 @@ fn next_addr() -> SocketAddr { struct Server { p: Child, + _temp: TempDir, } impl Server { fn spawn(args: &[&str], input: Option>) -> (Server, SocketAddr) { + static CERT: &'static [u8] = include_bytes!("../../../test/cert.pem"); + static KEY: &'static [u8] = include_bytes!("../../../test/key.pem"); + + + let td = TempDir::new("openssl").unwrap(); + let cert = td.path().join("cert.pem"); + let key = td.path().join("key.pem"); + File::create(&cert).unwrap().write_all(CERT).unwrap(); + File::create(&key).unwrap().write_all(KEY).unwrap(); + let addr = next_addr(); let mut child = Command::new("openssl") .arg("s_server") @@ -57,11 +70,10 @@ impl Server { .arg(addr.port().to_string()) .args(args) .arg("-cert") - .arg("cert.pem") + .arg(&cert) .arg("-key") - .arg("key.pem") + .arg(&key) .arg("-no_dhe") - .current_dir("test") .stdout(Stdio::null()) .stderr(Stdio::null()) .stdin(Stdio::piped()) @@ -71,7 +83,7 @@ impl Server { if let Some(mut input) = input { thread::spawn(move || input(stdin)); } - (Server { p: child }, addr) + (Server { p: child, _temp: td }, addr) } fn new_tcp(args: &[&str]) -> (Server, TcpStream) { @@ -92,7 +104,7 @@ impl Server { Server::new_tcp(&["-www"]) } - #[cfg(any(feature = "alpn", feature = "npn"))] + #[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))] fn new_alpn() -> (Server, TcpStream) { Server::new_tcp(&["-www", "-nextprotoneg", @@ -119,7 +131,7 @@ impl Server { // but don't currently have a great way to do that so just wait for a // bit. thread::sleep(Duration::from_millis(100)); - let socket = UdpSocket::bind(next_addr()).unwrap(); + let socket = UdpSocket::bind("127.0.0.1:0").unwrap(); socket.connect(&addr).unwrap(); (s, UdpConnected(socket)) } @@ -205,7 +217,7 @@ macro_rules! run_test( #[test] fn sslv23() { let (_s, stream) = Server::new(); - $blk(SslMethod::Sslv23, stream); + $blk(SslMethod::Tls, stream); } #[test] @@ -226,11 +238,6 @@ run_test!(new_sslstream, |method, stream| { SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); }); -run_test!(get_ssl_method, |method, _| { - let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap(); - assert_eq!(ssl.ssl_method(), method); -}); - run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); @@ -391,11 +398,11 @@ run_test!(ssl_verify_callback, |method, stream| { // Make sure every write call translates to a write call to the underlying socket. #[test] fn test_write_hits_stream() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let guard = thread::spawn(move || { - let ctx = SslContext::new(Sslv23).unwrap(); + let ctx = SslContext::new(Tls).unwrap(); let stream = TcpStream::connect(addr).unwrap(); let mut stream = SslStream::connect(&ctx, stream).unwrap(); @@ -403,7 +410,7 @@ fn test_write_hits_stream() { stream }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap(); ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap(); @@ -423,7 +430,7 @@ fn test_set_certificate_and_private_key() { let cert = include_bytes!("../../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_private_key(&key).unwrap(); ctx.set_certificate(&cert).unwrap(); @@ -451,7 +458,7 @@ run_test!(clear_ctx_options, |method, _| { #[test] fn test_write() { let (_s, stream) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -461,7 +468,7 @@ fn test_write() { #[test] fn test_write_direct() { let (_s, stream) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -492,7 +499,7 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -501,7 +508,7 @@ fn test_read() { #[test] fn test_read_direct() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); @@ -510,7 +517,7 @@ fn test_read_direct() { #[test] fn test_pending() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -533,7 +540,7 @@ fn test_pending() { #[test] fn test_state() { let (_s, tcp) = Server::new(); - let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap(); assert_eq!(stream.ssl().state_string(), "SSLOK "); assert_eq!(stream.ssl().state_string_long(), "SSL negotiation finished successfully"); @@ -542,10 +549,10 @@ fn test_state() { /// Tests that connecting with the client using ALPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] fn test_connect_with_unilateral_alpn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -564,10 +571,10 @@ fn test_connect_with_unilateral_alpn() { /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(feature = "npn")] +#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_unilateral_npn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -586,10 +593,10 @@ fn test_connect_with_unilateral_npn() { /// Tests that when both the client as well as the server use ALPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] fn test_connect_with_alpn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -608,10 +615,10 @@ fn test_connect_with_alpn_successful_multiple_matching() { /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(feature = "npn")] +#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_npn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -631,10 +638,10 @@ fn test_connect_with_npn_successful_multiple_matching() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] fn test_connect_with_alpn_successful_single_match() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -655,10 +662,10 @@ fn test_connect_with_alpn_successful_single_match() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(feature = "npn")] +#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_npn_successful_single_match() { let (_s, stream) = Server::new_alpn(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -677,13 +684,13 @@ fn test_connect_with_npn_successful_single_match() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(feature = "npn")] +#[cfg(all(feature = "npn", not(ossl101)))] fn test_npn_server_advertise_multiple() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) @@ -698,7 +705,7 @@ fn test_npn_server_advertise_multiple() { let _ = SslStream::accept(&listener_ctx, stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_npn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -718,13 +725,13 @@ fn test_npn_server_advertise_multiple() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] fn test_alpn_server_advertise_multiple() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) @@ -739,7 +746,7 @@ fn test_alpn_server_advertise_multiple() { let _ = SslStream::accept(&listener_ctx, stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"spdy/3.1"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -759,13 +766,13 @@ fn test_alpn_server_advertise_multiple() { /// Test that Servers supporting ALPN don't report a protocol when none of their protocols match /// the client's reported protocol. #[test] -#[cfg(feature = "alpn")] +#[cfg(all(feature = "alpn", not(ossl101)))] fn test_alpn_server_select_none() { - let listener = TcpListener::bind(next_addr()).unwrap(); + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); // We create a different context instance for the server... let listener_ctx = { - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]); assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM) @@ -780,7 +787,7 @@ fn test_alpn_server_select_none() { let _ = SslStream::accept(&listener_ctx, stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::new(Tls).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); ctx.set_alpn_protocols(&[b"http/2"]); match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { @@ -875,7 +882,7 @@ fn handshake(res: Result, HandshakeError>) fn test_write_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); + let cx = SslContext::new(Tls).unwrap(); let mut stream = handshake(SslStream::connect(&cx, stream)); let mut iterations = 0; @@ -913,7 +920,7 @@ fn test_write_nonblocking() { fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); + let cx = SslContext::new(Tls).unwrap(); let mut stream = handshake(SslStream::connect(&cx, stream)); let mut iterations = 0; @@ -965,7 +972,6 @@ fn test_read_nonblocking() { #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn write_panic() { struct ExplodingStream(TcpStream); @@ -988,13 +994,12 @@ fn write_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let ctx = SslContext::new(SslMethod::Tls).unwrap(); let _ = SslStream::connect(&ctx, stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn read_panic() { struct ExplodingStream(TcpStream); @@ -1017,13 +1022,12 @@ fn read_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let ctx = SslContext::new(SslMethod::Tls).unwrap(); let _ = SslStream::connect(&ctx, stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn flush_panic() { struct ExplodingStream(TcpStream); @@ -1046,20 +1050,20 @@ fn flush_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let mut stream = SslStream::connect(&ctx, stream).unwrap(); + let ctx = SslContext::new(SslMethod::Tls).unwrap(); + let mut stream = SslStream::connect(&ctx, stream).ok().unwrap(); let _ = stream.flush(); } #[test] fn refcount_ssl_context() { let mut ssl = { - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let ctx = SslContext::new(SslMethod::Tls).unwrap(); ssl::Ssl::new(&ctx).unwrap() }; { - let new_ctx_a = SslContext::new(SslMethod::Sslv23).unwrap(); + let new_ctx_a = SslContext::new(SslMethod::Tls).unwrap(); let _new_ctx_b = ssl.set_ssl_context(&new_ctx_a); } } @@ -1067,7 +1071,7 @@ fn refcount_ssl_context() { #[test] #[cfg_attr(windows, ignore)] // don't have a trusted CA list easily available :( fn default_verify_paths() { - let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let mut ctx = SslContext::new(SslMethod::Tls).unwrap(); ctx.set_default_verify_paths().unwrap(); ctx.set_verify(SSL_VERIFY_PEER); let s = TcpStream::connect("google.com:443").unwrap(); @@ -1086,6 +1090,6 @@ fn default_verify_paths() { fn add_extra_chain_cert() { let cert = include_bytes!("../../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); - let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + let mut ctx = SslContext::new(SslMethod::Tls).unwrap(); ctx.add_extra_chain_cert(&cert).unwrap(); } -- cgit v1.2.3 From af3e06d3e897d0ea5a2a50f0a6b932c3c42bd450 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 12 Oct 2016 22:34:13 -0700 Subject: Add remaining SSL_OP constants --- openssl/src/ssl/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 51bfc790..1c3fe1ae 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -65,6 +65,11 @@ bitflags! { const SSL_OP_NO_SSLV2 = ffi::SSL_OP_NO_SSLv2, const SSL_OP_NO_SSLV3 = ffi::SSL_OP_NO_SSLv3, const SSL_OP_NO_TLSV1 = ffi::SSL_OP_NO_TLSv1, + const SSL_OP_NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2, + const SSL_OP_NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1, + const SSL_OP_NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1, + const SSL_OP_NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2, + const SSL_OP_NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK, } } -- cgit v1.2.3 From 715b700aff6e46c555895618892a46fa53a5d17a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Oct 2016 22:51:47 -0700 Subject: Ignore a test on OpenSSL 1.1.0 --- openssl/src/ssl/tests/mod.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index e5bdc8da..01c836e7 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -767,6 +767,9 @@ fn test_alpn_server_advertise_multiple() { /// the client's reported protocol. #[test] #[cfg(all(feature = "alpn", not(ossl101)))] +// TODO: not sure why this test is failing on OpenSSL 1.1.0, may be related to +// something about SSLv3 though? +#[cfg_attr(ossl110, ignore)] fn test_alpn_server_select_none() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); -- cgit v1.2.3 From b610e01793f31836bb5e56b655a3bbae498649d6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 19:06:53 -0700 Subject: Flag off dtls and mask ssl_ops Also un-feature gate npn as it ships with 1.0.1 --- openssl/src/ssl/mod.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1c3fe1ae..fc1c131c 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -14,9 +14,7 @@ use std::path::Path; use std::ptr; use std::str; use std::sync::{Mutex, Arc}; -#[cfg(any(feature = "npn", feature = "alpn"))] use libc::{c_uchar, c_uint}; -#[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; use std::marker::PhantomData; use ffi; @@ -67,8 +65,11 @@ bitflags! { const SSL_OP_NO_TLSV1 = ffi::SSL_OP_NO_TLSv1, const SSL_OP_NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2, const SSL_OP_NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1, + #[cfg(feature = "openssl-102")] const SSL_OP_NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1, + #[cfg(feature = "openssl-102")] const SSL_OP_NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2, + #[cfg(feature = "openssl-102")] const SSL_OP_NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK, } } @@ -113,7 +114,6 @@ fn get_ssl_verify_data_idx() -> c_int { *SSL_INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| get_new_ssl_idx::()) } -#[cfg(all(feature = "npn", not(ossl101)))] lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); } @@ -218,7 +218,6 @@ extern fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c } } -#[cfg(all(any(feature = "npn", feature = "alpn"), not(ossl101)))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, @@ -251,7 +250,6 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, /// supported by the server. It achieves this by delegating to the `SSL_select_next_proto` /// function. The list of protocols supported by the client is found in the extra data of the /// OpenSSL context. -#[cfg(all(feature = "npn", not(ossl101)))] extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, @@ -280,7 +278,6 @@ extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, /// that it supports. /// The list of supported protocols is found in the extra data of the OpenSSL /// context. -#[cfg(all(feature = "npn", not(ossl101)))] extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, out: *mut *const c_uchar, outlen: *mut c_uint, @@ -307,7 +304,6 @@ extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, /// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte /// containing the length followed by the string. -#[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))] fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { let mut enc = Vec::new(); for string in strings { @@ -555,9 +551,6 @@ impl<'a> SslContextRef<'a> { /// Set the protocols to be used during Next Protocol Negotiation (the protocols /// supported by the application). - /// - /// This method needs the `npn` feature. - #[cfg(all(feature = "npn", not(ossl101)))] pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) { // Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL // APIs -- a list of length-prefixed strings. @@ -907,9 +900,6 @@ impl<'a> SslRef<'a> { /// /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client /// to interpret it. - /// - /// This method needs the `npn` feature. - #[cfg(feature = "npn")] pub fn selected_npn_protocol(&self) -> Option<&[u8]> { unsafe { let mut data: *const c_uchar = ptr::null(); -- cgit v1.2.3 From edfc50f37db8d230eb17480f124b9fd70166a940 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 19:46:13 -0700 Subject: Clean up features --- openssl/src/ssl/mod.rs | 22 ++++++++++++---------- openssl/src/ssl/tests/mod.rs | 15 +++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index fc1c131c..74c924cc 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -117,7 +117,7 @@ fn get_ssl_verify_data_idx() -> c_int { lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); } -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] lazy_static! { static ref ALPN_PROTOS_IDX: c_int = get_new_idx::>(); } @@ -260,7 +260,7 @@ extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL, unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) } } -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL, out: *mut *const c_uchar, outlen: *mut c_uchar, @@ -512,14 +512,16 @@ impl<'a> SslContextRef<'a> { /// compatible clients, and automatically select an appropriate elliptic /// curve. /// - /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` - /// feature. - #[cfg(all(feature = "ecdh_auto", not(ossl101)))] + /// This feature is always enabled on OpenSSL 1.1.0, and calling this + /// method does nothing. + /// + /// This method requires the `openssl-102` feature. + #[cfg(feature = "openssl-102")] pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { self._set_ecdh_auto(onoff) } - #[cfg(all(feature = "ecdh_auto", ossl102))] + #[cfg(all(feature = "openssl-102", ossl102))] fn _set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_ctrl(self.as_ptr(), @@ -529,7 +531,7 @@ impl<'a> SslContextRef<'a> { }) } - #[cfg(all(feature = "ecdh_auto", ossl110))] + #[cfg(all(feature = "openssl-102", ossl110))] fn _set_ecdh_auto(&mut self, _onoff: bool) -> Result<(), ErrorStack> { Ok(()) } @@ -581,8 +583,8 @@ impl<'a> SslContextRef<'a> { /// /// Note that ordering of the protocols controls the priority with which they are chosen. /// - /// This method needs the `alpn` feature. - #[cfg(all(feature = "alpn", not(ossl101)))] + /// This method needs the `openssl-102` feature. + #[cfg(feature = "openssl-102")] pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) { let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); unsafe { @@ -922,7 +924,7 @@ impl<'a> SslRef<'a> { /// to interpret it. /// /// This method needs the `alpn` feature. - #[cfg(all(feature = "alpn", not(ossl101)))] + #[cfg(feature = "openssl-102")] pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { unsafe { let mut data: *const c_uchar = ptr::null(); diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 01c836e7..58520930 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -104,7 +104,6 @@ impl Server { Server::new_tcp(&["-www"]) } - #[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))] fn new_alpn() -> (Server, TcpStream) { Server::new_tcp(&["-www", "-nextprotoneg", @@ -549,7 +548,7 @@ fn test_state() { /// Tests that connecting with the client using ALPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] fn test_connect_with_unilateral_alpn() { let (_s, stream) = Server::new(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -571,7 +570,6 @@ fn test_connect_with_unilateral_alpn() { /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior. #[test] -#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_unilateral_npn() { let (_s, stream) = Server::new(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -593,7 +591,7 @@ fn test_connect_with_unilateral_npn() { /// Tests that when both the client as well as the server use ALPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] fn test_connect_with_alpn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -615,7 +613,6 @@ fn test_connect_with_alpn_successful_multiple_matching() { /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] -#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_npn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -638,7 +635,7 @@ fn test_connect_with_npn_successful_multiple_matching() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] fn test_connect_with_alpn_successful_single_match() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -662,7 +659,6 @@ fn test_connect_with_alpn_successful_single_match() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] -#[cfg(all(feature = "npn", not(ossl101)))] fn test_connect_with_npn_successful_single_match() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -684,7 +680,6 @@ fn test_connect_with_npn_successful_single_match() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(all(feature = "npn", not(ossl101)))] fn test_npn_server_advertise_multiple() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); @@ -725,7 +720,7 @@ fn test_npn_server_advertise_multiple() { /// Tests that when the `SslStream` is created as a server stream, the protocols /// are correctly advertised to the client. #[test] -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] fn test_alpn_server_advertise_multiple() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let localhost = listener.local_addr().unwrap(); @@ -766,7 +761,7 @@ fn test_alpn_server_advertise_multiple() { /// Test that Servers supporting ALPN don't report a protocol when none of their protocols match /// the client's reported protocol. #[test] -#[cfg(all(feature = "alpn", not(ossl101)))] +#[cfg(feature = "openssl-102")] // TODO: not sure why this test is failing on OpenSSL 1.1.0, may be related to // something about SSLv3 though? #[cfg_attr(ossl110, ignore)] -- cgit v1.2.3 From 143556078b70c3794c95da740a21d7d7917bea68 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 19:48:30 -0700 Subject: Reenable dtls tests --- openssl/src/ssl/tests/mod.rs | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 58520930..e8f5da54 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -27,13 +27,10 @@ use x509::X509FileType; use x509::X509; use crypto::pkey::PKey; -#[cfg(feature="dtlsv1")] use std::net::UdpSocket; -#[cfg(feature="dtlsv1")] -use ssl::SslMethod::Dtlsv1; +use ssl::SslMethod::Dtls; #[cfg(feature="sslv2")] use ssl::SslMethod::Sslv2; -#[cfg(feature="dtlsv1")] use net2::UdpSocketExt; mod select; @@ -112,7 +109,6 @@ impl Server { "http/1.1,spdy/3.1"]) } - #[cfg(feature = "dtlsv1")] fn new_dtlsv1(input: I) -> (Server, UdpConnected) where I: IntoIterator, I::IntoIter: Send + 'static @@ -143,18 +139,15 @@ impl Drop for Server { } } -#[cfg(feature = "dtlsv1")] #[derive(Debug)] struct UdpConnected(UdpSocket); -#[cfg(feature = "dtlsv1")] impl Read for UdpConnected { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.recv_from(buf).map(|(s, _)| s) } } -#[cfg(feature = "dtlsv1")] impl Write for UdpConnected { #[cfg(unix)] fn write(&mut self, buf: &[u8]) -> io::Result { @@ -220,10 +213,9 @@ macro_rules! run_test( } #[test] - #[cfg(feature="dtlsv1")] fn dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - $blk(SslMethod::Dtlsv1, stream); + $blk(SslMethod::Dtls, stream); } } ); @@ -484,11 +476,10 @@ run_test!(get_peer_certificate, |method, stream| { }); #[test] -#[cfg(feature = "dtlsv1")] fn test_write_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtls).unwrap(), stream).unwrap(); stream.write_all(b"hello").unwrap(); stream.flush().unwrap(); stream.write_all(b" there").unwrap(); @@ -804,7 +795,6 @@ fn test_alpn_server_select_none() { } -#[cfg(feature="dtlsv1")] #[cfg(test)] mod dtlsv1 { use serialize::hex::FromHex; @@ -813,12 +803,12 @@ mod dtlsv1 { use crypto::hash::Type::SHA256; use ssl::SslMethod; - use ssl::SslMethod::Dtlsv1; + use ssl::SslMethod::Dtls; use ssl::{SslContext, SslStream}; use ssl::SSL_VERIFY_PEER; use x509::X509StoreContext; - const PROTOCOL: SslMethod = Dtlsv1; + const PROTOCOL: SslMethod = Dtls; #[test] fn test_new_ctx() { @@ -827,24 +817,14 @@ mod dtlsv1 { } #[test] -#[cfg(feature = "dtlsv1")] fn test_read_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let mut stream = SslStream::connect(&SslContext::new(Dtls).unwrap(), stream).unwrap(); let mut buf = [0u8; 100]; assert!(stream.read(&mut buf).is_ok()); } -#[test] -#[cfg(feature = "sslv2")] -fn test_sslv2_connect_failure() { - let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]); - SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp) - .err() - .unwrap(); -} - fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { unsafe { let mut set: select::fd_set = mem::zeroed(); -- cgit v1.2.3 From 140ef1b98845594fea6b8d5a5409453320b0def9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 20:01:31 -0700 Subject: Fix tests on windows --- openssl/src/ssl/tests/mod.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index e8f5da54..2cd4e05e 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -169,12 +169,13 @@ impl Write for UdpConnected { #[cfg(windows)] fn write(&mut self, buf: &[u8]) -> io::Result { use std::os::windows::prelude::*; - use libc; + use ws2_32; + let n = unsafe { - libc::send(self.0.as_raw_socket(), - buf.as_ptr() as *const _, - buf.len() as libc::c_int, - 0) + ws2_32::send(self.0.as_raw_socket(), + buf.as_ptr() as *const _, + buf.len() as libc::c_int, + 0) }; if n < 0 { Err(io::Error::last_os_error()) -- cgit v1.2.3 From 5b29fc9d6954e32cc20482e5e3d1d65f8d7cf252 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 20:03:02 -0700 Subject: Disable npn tests on < 1.0.2 s_client doesn't seem to support the required flag before then. --- openssl/src/ssl/tests/mod.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 2cd4e05e..f5078648 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -605,6 +605,7 @@ fn test_connect_with_alpn_successful_multiple_matching() { /// Tests that when both the client as well as the server use NPN and their /// lists of supported protocols have an overlap, the correct protocol is chosen. #[test] +#[cfg(feature = "openssl-102")] fn test_connect_with_npn_successful_multiple_matching() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); @@ -651,6 +652,7 @@ fn test_connect_with_alpn_successful_single_match() { /// lists of supported protocols have an overlap -- with only ONE protocol /// being valid for both. #[test] +#[cfg(feature = "openssl-102")] fn test_connect_with_npn_successful_single_match() { let (_s, stream) = Server::new_alpn(); let mut ctx = SslContext::new(Tls).unwrap(); -- cgit v1.2.3 From a09f46266d7f2f42a019a13e31ffaa7067577130 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 20:06:01 -0700 Subject: Fix windows for real --- openssl/src/ssl/tests/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index f5078648..0140e283 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -168,8 +168,9 @@ impl Write for UdpConnected { #[cfg(windows)] fn write(&mut self, buf: &[u8]) -> io::Result { + extern crate ws2_32; use std::os::windows::prelude::*; - use ws2_32; + use libc; let n = unsafe { ws2_32::send(self.0.as_raw_socket(), -- cgit v1.2.3 From 3d535f661f8ae2b402abf212f3d89404eedab498 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 20:15:26 -0700 Subject: Use stdlib logic for udp --- openssl/src/ssl/tests/mod.rs | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 0140e283..2e362b5e 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -12,7 +12,6 @@ use std::process::{Command, Child, Stdio, ChildStdin}; use std::thread; use std::time::Duration; -use net2::TcpStreamExt; use tempdir::TempDir; use crypto::hash::Type::SHA256; @@ -29,9 +28,6 @@ use crypto::pkey::PKey; use std::net::UdpSocket; use ssl::SslMethod::Dtls; -#[cfg(feature="sslv2")] -use ssl::SslMethod::Sslv2; -use net2::UdpSocketExt; mod select; @@ -144,45 +140,13 @@ struct UdpConnected(UdpSocket); impl Read for UdpConnected { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.recv_from(buf).map(|(s, _)| s) + self.0.recv(buf) } } impl Write for UdpConnected { - #[cfg(unix)] fn write(&mut self, buf: &[u8]) -> io::Result { - use std::os::unix::prelude::*; - use libc; - let n = unsafe { - libc::send(self.0.as_raw_fd(), - buf.as_ptr() as *const _, - buf.len() as libc::size_t, - 0) - }; - if n < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(n as usize) - } - } - - #[cfg(windows)] - fn write(&mut self, buf: &[u8]) -> io::Result { - extern crate ws2_32; - use std::os::windows::prelude::*; - use libc; - - let n = unsafe { - ws2_32::send(self.0.as_raw_socket(), - buf.as_ptr() as *const _, - buf.len() as libc::c_int, - 0) - }; - if n < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(n as usize) - } + self.0.send(buf) } fn flush(&mut self) -> io::Result<()> { -- cgit v1.2.3 From f44cff29e658987b980a6927958d9bed334232ad Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 13 Oct 2016 22:34:39 -0700 Subject: Cleanup --- openssl/src/ssl/mod.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 74c924cc..0bd3272b 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -75,10 +75,8 @@ bitflags! { } /// Determines the SSL method supported -#[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub enum SslMethod { - // TODO: support more methods /// Support the TLS protocol Tls, /// Support DTLS protocol -- cgit v1.2.3 From 0908fddc7460529f4536b22516da20d3b89c993a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 14 Oct 2016 11:15:22 -0700 Subject: Ignore DTLS tests on Windows/ARM for now cc #467 --- openssl/src/ssl/tests/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'openssl/src/ssl') diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 2e362b5e..f86895e5 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -179,6 +179,7 @@ macro_rules! run_test( } #[test] + #[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); $blk(SslMethod::Dtls, stream); @@ -442,6 +443,7 @@ run_test!(get_peer_certificate, |method, stream| { }); #[test] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_write_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); @@ -785,6 +787,7 @@ mod dtlsv1 { } #[test] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); @@ -862,7 +865,7 @@ fn test_write_nonblocking() { } #[test] -#[cfg_attr(windows, ignore)] // FIXME flickers on appveyor +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); -- cgit v1.2.3