diff options
Diffstat (limited to 'openssl/src/ssl')
| -rw-r--r-- | openssl/src/ssl/callbacks.rs | 274 | ||||
| -rw-r--r-- | openssl/src/ssl/mod.rs | 440 | ||||
| -rw-r--r-- | openssl/src/ssl/test.rs | 150 |
3 files changed, 423 insertions, 441 deletions
diff --git a/openssl/src/ssl/callbacks.rs b/openssl/src/ssl/callbacks.rs index bff71022..fd5b7ef5 100644 --- a/openssl/src/ssl/callbacks.rs +++ b/openssl/src/ssl/callbacks.rs @@ -1,45 +1,49 @@ use ffi; -use libc::{c_char, c_int, c_uchar, c_uint, c_void}; +use foreign_types::ForeignType; +use foreign_types::ForeignTypeRef; #[cfg(ossl111)] use libc::size_t; +use libc::{c_char, c_int, c_uchar, c_uint, c_void}; use std::ffi::CStr; +use std::mem; use std::ptr; use std::slice; -use std::mem; #[cfg(ossl111)] use std::str; -use foreign_types::ForeignTypeRef; -use foreign_types::ForeignType; +use std::sync::Arc; -use error::ErrorStack; use dh::Dh; #[cfg(any(ossl101, ossl102))] use ec::EcKey; +use error::ErrorStack; use pkey::Params; -use ssl::{get_callback_idx, get_ssl_callback_idx, SniError, SslAlert, SslContextRef, SslRef, - SslSession, SslSessionRef}; #[cfg(any(ossl102, ossl110))] use ssl::AlpnError; -use x509::X509StoreContextRef; #[cfg(ossl111)] use ssl::ExtensionContext; +use ssl::{SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef, SslSession, SslSessionRef}; #[cfg(ossl111)] use x509::X509Ref; +use x509::{X509StoreContext, X509StoreContextRef}; pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int where F: Fn(bool, &mut X509StoreContextRef) -> bool + '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 as *const _); - let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx); - - verify(preverify_ok != 0, ctx) as c_int + let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing"); + let verify_idx = SslContext::cached_ex_index::<F>(); + + // raw pointer shenanigans to break the borrow of ctx + // the callback can't mess with its own ex_data slot so this is safe + let verify = ctx.ex_data(ssl_idx) + .expect("BUG: store context missing ssl") + .ssl_context() + .ex_data(verify_idx) + .expect("BUG: verify callback missing") as *const F; + + (*verify)(preverify_ok != 0, ctx) as c_int } } @@ -59,10 +63,12 @@ where + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); let ssl = SslRef::from_ptr_mut(ssl); - let callback = &*(callback as *mut F); + let callback_idx = SslContext::cached_ex_index::<F>(); + + let callback = ssl.ssl_context() + .ex_data(callback_idx) + .expect("BUG: psk callback missing") as *const F; let hint = if hint != ptr::null() { Some(CStr::from_ptr(hint).to_bytes()) } else { @@ -71,7 +77,7 @@ where // Give the callback mutable slices into which it can write the identity and psk. let identity_sl = slice::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize); let psk_sl = slice::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize); - match callback(ssl, hint, identity_sl, psk_sl) { + match (*callback)(ssl, hint, identity_sl, psk_sl) { Ok(psk_len) => psk_len as u32, _ => 0, } @@ -86,14 +92,17 @@ where F: Fn(bool, &mut X509StoreContextRef) -> bool + '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 as *const _, get_ssl_callback_idx::<F>()); - let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx); + let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing"); + let callback_idx = Ssl::cached_ex_index::<Arc<F>>(); + + let callback = ctx.ex_data(ssl_idx) + .expect("BUG: store context missing ssl") + .ex_data(callback_idx) + .expect("BUG: ssl verify callback missing") + .clone(); - verify(preverify_ok != 0, ctx) as c_int + callback(preverify_ok != 0, ctx) as c_int } } @@ -102,13 +111,13 @@ where F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let callback: &F = &*(callback as *mut F); let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: sni callback missing") as *const F; let mut alert = SslAlert(*al); - let r = callback(ssl, &mut alert); + let r = (*callback)(ssl, &mut alert); *al = alert.0; match r { Ok(()) => ffi::SSL_TLSEXT_ERR_OK, @@ -130,13 +139,13 @@ where F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let callback: &F = &*(callback as *mut F); let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: alpn callback missing") as *const F; let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize); - match callback(ssl, protos) { + match (*callback)(ssl, protos) { Ok(proto) => { *out = proto.as_ptr() as *const c_uchar; *outlen = proto.len() as c_uchar; @@ -155,12 +164,12 @@ pub unsafe extern "C" fn raw_tmp_dh<F>( where F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { - let ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); - match callback(ssl, is_export != 0, keylength as u32) { + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: tmp dh callback missing") as *const F; + + match (*callback)(ssl, is_export != 0, keylength as u32) { Ok(dh) => { let ptr = dh.as_ptr(); mem::forget(dh); @@ -182,12 +191,12 @@ pub unsafe extern "C" fn raw_tmp_ecdh<F>( where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { - let ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); - match callback(ssl, is_export != 0, keylength as u32) { + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: tmp ecdh callback missing") as *const F; + + match (*callback)(ssl, is_export != 0, keylength as u32) { Ok(ec_key) => { let ptr = ec_key.as_ptr(); mem::forget(ec_key); @@ -208,10 +217,11 @@ pub unsafe extern "C" fn raw_tmp_dh_ssl<F>( where F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { - let callback = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ex_data(Ssl::cached_ex_index::<Arc<F>>()) + .expect("BUG: ssl tmp dh callback missing") + .clone(); + match callback(ssl, is_export != 0, keylength as u32) { Ok(dh) => { let ptr = dh.as_ptr(); @@ -234,10 +244,11 @@ pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>( where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { - let callback = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ex_data(Ssl::cached_ex_index::<Arc<F>>()) + .expect("BUG: ssl tmp ecdh callback missing") + .clone(); + match callback(ssl, is_export != 0, keylength as u32) { Ok(ec_key) => { let ptr = ec_key.as_ptr(); @@ -255,12 +266,11 @@ pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void where F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); - let ret = callback(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: ocsp callback missing") as *const F; + let ret = (*callback)(ssl); if ssl.is_server() { match ret { @@ -290,14 +300,13 @@ pub unsafe extern "C" fn raw_new_session<F>( where F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: new session callback missing") as *const F; let session = SslSession::from_ptr(session); - callback(ssl, session); + (*callback)(ssl, session); // the return code doesn't indicate error vs success, but whether or not we consumed the session 1 @@ -309,18 +318,17 @@ pub unsafe extern "C" fn raw_remove_session<F>( ) where F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, { - let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ctx = SslContextRef::from_ptr(ctx); + let callback = ctx.ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: remove session callback missing"); let session = SslSessionRef::from_ptr(session); callback(ctx, session) } -#[cfg(any(ossl110))] +#[cfg(ossl110)] type DataPtr = *const c_uchar; -#[cfg(not(any(ossl110)))] +#[cfg(not(ossl110))] type DataPtr = *mut c_uchar; pub unsafe extern "C" fn raw_get_session<F>( @@ -332,14 +340,13 @@ pub unsafe extern "C" fn raw_get_session<F>( where F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, { - let ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: get session callback missing") as *const F; let data = slice::from_raw_parts(data as *const u8, len as usize); - match callback(ssl, data) { + match (*callback)(ssl, data) { Some(session) => { let p = session.as_ptr(); mem::forget(p); @@ -355,11 +362,10 @@ pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char where F: Fn(&SslRef, &str) + 'static + Sync + Send, { - let ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); - let ssl = SslRef::from_ptr(ssl as *mut _); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: get session callback missing"); let line = CStr::from_ptr(line).to_bytes(); let line = str::from_utf8_unchecked(line); @@ -367,7 +373,7 @@ where } #[cfg(ossl111)] -pub extern "C" fn raw_stateless_cookie_generate<F>( +pub unsafe extern "C" fn raw_stateless_cookie_generate<F>( ssl: *mut ffi::SSL, cookie: *mut c_uchar, cookie_len: *mut size_t, @@ -375,28 +381,25 @@ pub extern "C" fn raw_stateless_cookie_generate<F>( where F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, { - unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let ssl = SslRef::from_ptr_mut(ssl); - let callback = &*(callback as *mut F); - let slice = - slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); - match callback(ssl, slice) { - Ok(len) => { - *cookie_len = len as size_t; - 1 - } - Err(e) => { - e.put(); - 0 - } + let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: stateless cookie generate callback missing") as *const F; + let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); + match (*callback)(ssl, slice) { + Ok(len) => { + *cookie_len = len as size_t; + 1 + } + Err(e) => { + e.put(); + 0 } } } #[cfg(ossl111)] -pub extern "C" fn raw_stateless_cookie_verify<F>( +pub unsafe extern "C" fn raw_stateless_cookie_verify<F>( ssl: *mut ffi::SSL, cookie: *const c_uchar, cookie_len: size_t, @@ -404,15 +407,12 @@ pub extern "C" fn raw_stateless_cookie_verify<F>( where F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, { - unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let ssl = SslRef::from_ptr_mut(ssl); - let callback = &*(callback as *mut F); - let slice = - slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); - callback(ssl, slice) as c_int - } + let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: stateless cookie verify callback missing") as *const F; + let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); + (*callback)(ssl, slice) as c_int } pub extern "C" fn raw_cookie_generate<F>( @@ -424,15 +424,15 @@ where F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); let ssl = SslRef::from_ptr_mut(ssl); - let callback = &*(callback as *mut F); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: cookie generate callback missing") as *const F; // We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for // compatibility. See comments in dtls1.h. let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1); - match callback(ssl, slice) { + match (*callback)(ssl, slice) { Ok(len) => { *cookie_len = len as c_uint; 1 @@ -460,13 +460,13 @@ where F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); let ssl = SslRef::from_ptr_mut(ssl); - let callback = &*(callback as *mut F); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: cookie verify callback missing") as *const F; let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); - callback(ssl, slice) as c_int + (*callback)(ssl, slice) as c_int } } @@ -487,35 +487,39 @@ pub extern "C" fn raw_custom_ext_add<F, T>( ) -> c_int where F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert> - + 'static, + + 'static + + Sync + + Send, T: AsRef<[u8]> + 'static + Sync + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); - let callback = &*(callback as *mut F); let ssl = SslRef::from_ptr_mut(ssl); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: custom ext add callback missing") as *const F; let ectx = ExtensionContext::from_bits_truncate(context); let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) { Some((chainidx, X509Ref::from_ptr(x))) } else { None }; - match (callback)(ssl, ectx, cert) { + match (*callback)(ssl, ectx, cert) { Ok(None) => 0, Ok(Some(buf)) => { - *outlen = buf.as_ref().len() as size_t; + *outlen = buf.as_ref().len(); *out = buf.as_ref().as_ptr(); - let idx = get_ssl_callback_idx::<CustomExtAddState<T>>(); - let ptr = ffi::SSL_get_ex_data(ssl.as_ptr(), idx); - if ptr.is_null() { - let x = Box::into_raw(Box::<CustomExtAddState<T>>::new(CustomExtAddState( - Some(buf), - ))) as *mut c_void; - ffi::SSL_set_ex_data(ssl.as_ptr(), idx, x); - } else { - *(ptr as *mut _) = CustomExtAddState(Some(buf)) + let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>(); + let mut buf = Some(buf); + let new = match ssl.ex_data_mut(idx) { + Some(state) => { + state.0 = buf.take(); + false + } + None => true, + }; + if new { + ssl.set_ex_data(idx, CustomExtAddState(buf)); } 1 } @@ -538,9 +542,11 @@ pub extern "C" fn raw_custom_ext_free<T>( T: 'static + Sync + Send, { unsafe { - let state = ffi::SSL_get_ex_data(ssl, get_ssl_callback_idx::<CustomExtAddState<T>>()); - let state = &mut (*(state as *mut CustomExtAddState<T>)).0; - state.take(); + let ssl = SslRef::from_ptr_mut(ssl); + let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>(); + if let Some(state) = ssl.ex_data_mut(idx) { + state.0 = None; + } } } @@ -557,14 +563,16 @@ pub extern "C" fn raw_custom_ext_parse<F>( _: *mut c_void, ) -> c_int where - F: FnMut(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> - + 'static, + F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert> + + 'static + + Sync + + Send, { unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_callback_idx::<F>()); let ssl = SslRef::from_ptr_mut(ssl); - let callback = &mut *(callback as *mut F); + let callback = ssl.ssl_context() + .ex_data(SslContext::cached_ex_index::<F>()) + .expect("BUG: custom ext parse callback missing") as *const F; let ectx = ExtensionContext::from_bits_truncate(context); let slice = slice::from_raw_parts(input as *const u8, inlen as usize); let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) { @@ -572,7 +580,7 @@ where } else { None }; - match callback(ssl, ectx, slice, cert) { + match (*callback)(ssl, ectx, slice, cert) { Ok(()) => 1, Err(alert) => { *al = alert.0; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0f9e8935..8dc605ed 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -7,7 +7,7 @@ //! //! To connect as a client to a remote server: //! -//! ``` +//! ```no_run //! use openssl::ssl::{SslMethod, SslConnector}; //! use std::io::{Read, Write}; //! use std::net::TcpStream; @@ -75,38 +75,39 @@ use std::path::Path; use std::ptr; use std::slice; use std::str; -use std::sync::Mutex; +use std::sync::{Arc, Mutex}; -use {cvt, cvt_n, cvt_p, init}; use dh::{Dh, DhRef}; -use ec::EcKeyRef; #[cfg(any(ossl101, ossl102))] use ec::EcKey; -use x509::{X509, X509Name, X509Ref, X509StoreContextRef, X509VerifyResult}; -use x509::store::{X509StoreBuilderRef, X509StoreRef}; -#[cfg(any(ossl102, ossl110))] -use x509::store::X509Store; -#[cfg(any(ossl102, ossl110))] -use x509::verify::X509VerifyParamRef; -use pkey::{HasPrivate, PKeyRef, Params, Private}; +use ec::EcKeyRef; use error::ErrorStack; use ex_data::Index; -use stack::{Stack, StackRef}; -use ssl::bio::BioMethod; -use ssl::error::InnerError; -use ssl::callbacks::*; -use nid::Nid; #[cfg(ossl111)] use hash::MessageDigest; +use nid::Nid; +use pkey::{HasPrivate, PKeyRef, Params, Private}; +use ssl::bio::BioMethod; +use ssl::callbacks::*; +use ssl::error::InnerError; +use stack::{Stack, StackRef}; +#[cfg(any(ossl102, ossl110))] +use x509::store::X509Store; +use x509::store::{X509StoreBuilderRef, X509StoreRef}; +#[cfg(any(ossl102, ossl110))] +use x509::verify::X509VerifyParamRef; +use x509::{X509, X509Name, X509Ref, X509StoreContextRef, X509VerifyResult}; +use {cvt, cvt_n, cvt_p, init}; -pub use ssl::connector::{ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, - SslConnectorBuilder}; +pub use ssl::connector::{ + ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder, +}; pub use ssl::error::{Error, ErrorCode, HandshakeError}; -mod error; +mod bio; mod callbacks; mod connector; -mod bio; +mod error; #[cfg(test)] mod test; @@ -465,25 +466,6 @@ lazy_static! { static ref SSL_INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new()); } -// Creates a static index for user data of type T -// Registers a destructor for the data which will be called -// when context is freed -fn get_callback_idx<T: 'static>() -> c_int { - *INDEXES - .lock() - .unwrap() - .entry(TypeId::of::<T>()) - .or_insert_with(|| get_new_idx::<T>()) -} - -fn get_ssl_callback_idx<T: 'static>() -> c_int { - *SSL_INDEXES - .lock() - .unwrap() - .entry(TypeId::of::<T>()) - .or_insert_with(|| get_new_ssl_idx::<T>()) -} - unsafe extern "C" fn free_data_box<T>( _parent: *mut c_void, ptr: *mut c_void, @@ -497,22 +479,6 @@ unsafe extern "C" fn free_data_box<T>( } } -fn get_new_idx<T>() -> c_int { - unsafe { - let idx = compat::get_new_idx(free_data_box::<T>); - assert!(idx >= 0); - idx - } -} - -fn get_new_ssl_idx<T>() -> c_int { - unsafe { - let idx = compat::get_new_ssl_idx(free_data_box::<T>); - assert!(idx >= 0); - idx - } -} - /// An error returned from the SNI callback. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct SniError(c_int); @@ -668,12 +634,7 @@ impl SslContextBuilder { F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, { unsafe { - let verify = Box::new(verify); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - mem::transmute(verify), - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), verify); ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>)); } } @@ -694,12 +655,7 @@ impl SslContextBuilder { F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - mem::transmute(callback), - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); let f: extern "C" fn(_, _, _) -> _ = raw_sni::<F>; let f: extern "C" fn() = mem::transmute(f); ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f)); @@ -789,14 +745,8 @@ impl SslContextBuilder { F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); - let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh::<F>; - ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), f); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), raw_tmp_dh::<F>); } } @@ -823,14 +773,8 @@ impl SslContextBuilder { F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); - let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh::<F>; - ffi::SSL_CTX_set_tmp_ecdh_callback(self.as_ptr(), f); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_tmp_ecdh_callback(self.as_ptr(), raw_tmp_ecdh::<F>); } } @@ -1119,10 +1063,10 @@ impl SslContextBuilder { /// /// This corresponds to [`SSL_CTX_get_min_proto_version`]. /// - /// Requires OpenSSL 1.1.0 or newer. + /// Requires OpenSSL 1.1.0g or newer. /// /// [`SSL_CTX_get_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html - #[cfg(any(ossl110))] + #[cfg(any(ossl110g))] pub fn min_proto_version(&mut self) -> Option<SslVersion> { unsafe { let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); @@ -1141,10 +1085,10 @@ impl SslContextBuilder { /// /// This corresponds to [`SSL_CTX_get_max_proto_version`]. /// - /// Requires OpenSSL 1.1.0 or newer. + /// Requires OpenSSL 1.1.0g or newer. /// /// [`SSL_CTX_get_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html - #[cfg(any(ossl110))] + #[cfg(any(ossl110g))] pub fn max_proto_version(&mut self) -> Option<SslVersion> { unsafe { let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); @@ -1207,12 +1151,7 @@ impl SslContextBuilder { F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); ffi::SSL_CTX_set_alpn_select_cb( self.as_ptr(), callbacks::raw_alpn_select::<F>, @@ -1269,14 +1208,11 @@ impl SslContextBuilder { F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); - let f: unsafe extern "C" fn(_, _) -> _ = raw_tlsext_status::<F>; - cvt(ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(f)) as c_int).map(|_| ()) + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + cvt( + ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>)) + as c_int, + ).map(|_| ()) } } @@ -1298,13 +1234,8 @@ impl SslContextBuilder { + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - mem::transmute(callback), - ); - ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_psk::<F>)) + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_psk::<F>)); } } @@ -1329,12 +1260,7 @@ impl SslContextBuilder { F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>)); } } @@ -1351,12 +1277,7 @@ impl SslContextBuilder { F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); ffi::SSL_CTX_sess_set_remove_cb( self.as_ptr(), Some(callbacks::raw_remove_session::<F>), @@ -1382,12 +1303,7 @@ impl SslContextBuilder { where F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>)); } @@ -1408,12 +1324,7 @@ impl SslContextBuilder { F: Fn(&SslRef, &str) + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>)); } } @@ -1445,13 +1356,11 @@ impl SslContextBuilder { F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_stateless_cookie_generate_cb( self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, + Some(raw_stateless_cookie_generate::<F>), ); - ffi::SSL_CTX_set_stateless_cookie_generate_cb(self.as_ptr(), Some(raw_stateless_cookie_generate::<F>)) } } @@ -1471,13 +1380,11 @@ impl SslContextBuilder { F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_stateless_cookie_verify_cb( self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); - ffi::SSL_CTX_set_stateless_cookie_verify_cb(self.as_ptr(), Some(raw_stateless_cookie_verify::<F>)) + Some(raw_stateless_cookie_verify::<F>), + ) } } @@ -1492,13 +1399,8 @@ impl SslContextBuilder { F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); - ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>)) + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>)); } } @@ -1513,13 +1415,8 @@ impl SslContextBuilder { F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<F>(), - Box::into_raw(callback) as *mut _, - ); - ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>)) + self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); + ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>)); } } @@ -1571,19 +1468,8 @@ impl SslContextBuilder { + Send, { let ret = unsafe { - let add_cb = Box::new(add_cb); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<AddFn>(), - Box::into_raw(add_cb) as *mut _, - ); - - let parse_cb = Box::new(parse_cb); - ffi::SSL_CTX_set_ex_data( - self.as_ptr(), - get_callback_idx::<ParseFn>(), - Box::into_raw(parse_cb) as *mut _, - ); + self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb); + self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb); ffi::SSL_CTX_add_custom_ext( self.as_ptr(), @@ -1665,6 +1551,21 @@ impl SslContext { Ok(Index::from_raw(idx)) } } + + // FIXME should return a result? + fn cached_ex_index<T>() -> Index<SslContext, T> + where + T: 'static + Sync + Send, + { + unsafe { + let idx = *INDEXES + .lock() + .unwrap_or_else(|e| e.into_inner()) + .entry(TypeId::of::<T>()) + .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw()); + Index::from_raw(idx) + } + } } impl SslContextRef { @@ -1914,6 +1815,19 @@ impl Clone for SslSession { } } +impl SslSession { + from_der! { + /// Deserializes a DER-encoded session structure. + /// + /// This corresponds to [`d2i_SSL_SESSION`]. + /// + /// [`d2i_SSL_SESSION`]: https://www.openssl.org/docs/man1.0.2/ssl/d2i_SSL_SESSION.html + from_der, + SslSession, + ffi::d2i_SSL_SESSION + } +} + impl ToOwned for SslSessionRef { type Owned = SslSession; @@ -1958,6 +1872,16 @@ impl SslSessionRef { pub fn master_key(&self, buf: &mut [u8]) -> usize { unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } } + + to_der! { + /// Serializes the session into a DER-encoded structure. + /// + /// This corresponds to [`i2d_SSL_SESSION`]. + /// + /// [`i2d_SSL_SESSION`]: https://www.openssl.org/docs/man1.0.2/ssl/i2d_SSL_SESSION.html + to_der, + ffi::i2d_SSL_SESSION + } } foreign_type! { @@ -1978,6 +1902,15 @@ foreign_type! { pub struct SslRef; } +unsafe impl Sync for Ssl {} +unsafe impl Send for Ssl {} + +impl fmt::Debug for Ssl { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, fmt) + } +} + impl Ssl { /// Returns a new extra data index. /// @@ -1997,6 +1930,67 @@ impl Ssl { Ok(Index::from_raw(idx)) } } + + // FIXME should return a result? + fn cached_ex_index<T>() -> Index<Ssl, T> + where + T: 'static + Sync + Send, + { + unsafe { + let idx = *SSL_INDEXES + .lock() + .unwrap_or_else(|e| e.into_inner()) + .entry(TypeId::of::<T>()) + .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw()); + Index::from_raw(idx) + } + } + + /// Creates a new `Ssl`. + /// + /// This corresponds to [`SSL_new`]. + /// + /// [`SSL_new`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_new.html + pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> { + unsafe { + let ssl = cvt_p(ffi::SSL_new(ctx.as_ptr()))?; + Ok(Ssl::from_ptr(ssl)) + } + } + + /// Initiates a client-side TLS handshake. + /// + /// This corresponds to [`SSL_connect`]. + /// + /// # Warning + /// + /// OpenSSL's default configuration is insecure. It is highly recommended to use + /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. + /// + /// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html + pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> + where + S: Read + Write, + { + SslStreamBuilder::new(self, stream).connect() + } + + /// Initiates a server-side TLS handshake. + /// + /// This corresponds to [`SSL_accept`]. + /// + /// # Warning + /// + /// OpenSSL's default configuration is insecure. It is highly recommended to use + /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. + /// + /// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html + pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> + where + S: Read + Write, + { + SslStreamBuilder::new(self, stream).accept() + } } impl fmt::Debug for SslRef { @@ -2048,12 +2042,8 @@ impl SslRef { F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, { unsafe { - let verify = Box::new(verify); - ffi::SSL_set_ex_data( - self.as_ptr(), - get_ssl_callback_idx::<F>(), - mem::transmute(verify), - ); + // this needs to be in an Arc since the callback can register a new callback! + self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify)); ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>)); } } @@ -2079,14 +2069,9 @@ impl SslRef { F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_set_ex_data( - self.as_ptr(), - get_ssl_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); - let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh_ssl::<F>; - ffi::SSL_set_tmp_dh_callback(self.as_ptr(), f); + // this needs to be in an Arc since the callback can register a new callback! + self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); + ffi::SSL_set_tmp_dh_callback(self.as_ptr(), raw_tmp_dh_ssl::<F>); } } @@ -2112,14 +2097,9 @@ impl SslRef { F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, { unsafe { - let callback = Box::new(callback); - ffi::SSL_set_ex_data( - self.as_ptr(), - get_ssl_callback_idx::<F>(), - Box::into_raw(callback) as *mut c_void, - ); - let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh_ssl::<F>; - ffi::SSL_set_tmp_ecdh_callback(self.as_ptr(), f); + // this needs to be in an Arc since the callback can register a new callback! + self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); + ffi::SSL_set_tmp_ecdh_callback(self.as_ptr(), raw_tmp_ecdh_ssl::<F>); } } @@ -2598,63 +2578,22 @@ impl SslRef { } } } -} - -unsafe impl Sync for Ssl {} -unsafe impl Send for Ssl {} - -impl fmt::Debug for Ssl { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, fmt) - } -} -impl Ssl { - /// Creates a new `Ssl`. + /// Returns a mutable reference to the extra data at the specified index. /// - /// This corresponds to [`SSL_new`]. + /// This corresponds to [`SSL_get_ex_data`]. /// - /// [`SSL_new`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_new.html - pub fn new(ctx: &SslContext) -> Result<Ssl, ErrorStack> { + /// [`SSL_get_ex_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_ex_data.html + pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> { unsafe { - let ssl = cvt_p(ffi::SSL_new(ctx.as_ptr()))?; - Ok(Ssl::from_ptr(ssl)) + let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); + if data.is_null() { + None + } else { + Some(&mut *(data as *mut T)) + } } } - - /// Initiates a client-side TLS handshake. - /// - /// This corresponds to [`SSL_connect`]. - /// - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. - /// - /// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html - pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> - where - S: Read + Write, - { - SslStreamBuilder::new(self, stream).connect() - } - - /// Initiates a server-side TLS handshake. - /// - /// This corresponds to [`SSL_accept`]. - /// - /// # Warning - /// - /// OpenSSL's default configuration is insecure. It is highly recommended to use - /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. - /// - /// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html - pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> - where - S: Read + Write, - { - SslStreamBuilder::new(self, stream).accept() - } } /// An SSL stream midway through the handshake process. @@ -2927,11 +2866,12 @@ impl<S: Read + Write> Write for SslStream<S> { /// A partially constructed `SslStream`, useful for unusual handshakes. pub struct SslStreamBuilder<S> { - inner: SslStream<S> + inner: SslStream<S>, } impl<S> SslStreamBuilder<S> - where S: Read + Write +where + S: Read + Write, { /// Begin creating an `SslStream` atop `stream` pub fn new(ssl: Ssl, stream: S) -> Self { @@ -3030,7 +2970,9 @@ impl<S> SslStreamBuilder<S> { } /// Returns a shared reference to the `Ssl` object associated with this builder. - pub fn ssl(&self) -> &SslRef { &self.inner.ssl } + pub fn ssl(&self) -> &SslRef { + &self.inner.ssl + } } /// The result of a shutdown request. @@ -3050,8 +2992,10 @@ mod compat { use ffi; use libc::c_int; - pub use ffi::{SSL_CTX_clear_options, SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_up_ref, - SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; + pub use ffi::{ + SSL_CTX_clear_options, SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_up_ref, + SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server, + }; pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { ffi::CRYPTO_get_ex_new_index( diff --git a/openssl/src/ssl/test.rs b/openssl/src/ssl/test.rs index ddcb49ff..2e906728 100644 --- a/openssl/src/ssl/test.rs +++ b/openssl/src/ssl/test.rs @@ -17,16 +17,17 @@ use tempdir::TempDir; use dh::Dh; use hash::MessageDigest; use ocsp::{OcspResponse, OcspResponseStatus}; +use pkey::PKey; use ssl; -use ssl::{Error, HandshakeError, ShutdownResult, Ssl, SslAcceptor, SslConnector, SslContext, - SslFiletype, SslMethod, SslSessionCacheMode, SslStream, MidHandshakeSslStream, - SslVerifyMode, StatusType}; #[cfg(any(ossl110, ossl111))] use ssl::SslVersion; -use x509::{X509, X509Name, X509StoreContext, X509VerifyResult}; +use ssl::{ + Error, HandshakeError, MidHandshakeSslStream, ShutdownResult, Ssl, SslAcceptor, SslConnector, + SslContext, SslFiletype, SslMethod, SslSessionCacheMode, SslStream, SslVerifyMode, StatusType, +}; #[cfg(any(ossl102, ossl110))] use x509::verify::X509CheckFlags; -use pkey::PKey; +use x509::{X509, X509Name, X509StoreContext, X509VerifyResult}; use std::net::UdpSocket; @@ -762,6 +763,7 @@ fn refcount_ssl_context() { } #[test] +#[cfg_attr(libressl250, ignore)] fn default_verify_paths() { let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_default_verify_paths().unwrap(); @@ -831,6 +833,7 @@ fn verify_invalid_hostname() { } #[test] +#[cfg_attr(libressl250, ignore)] fn connector_valid_hostname() { let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); @@ -855,6 +858,7 @@ fn connector_invalid_hostname() { } #[test] +#[cfg_attr(libressl250, ignore)] fn connector_invalid_no_hostname_verification() { let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); @@ -1175,6 +1179,7 @@ fn idle_session() { } #[test] +#[cfg_attr(libressl250, ignore)] fn active_session() { let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); @@ -1323,7 +1328,9 @@ fn no_version_overlap() { ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) .unwrap(); ctx.set_max_proto_version(Some(SslVersion::TLS1_1)).unwrap(); + #[cfg(ossl110g)] assert_eq!(ctx.min_proto_version(), None); + #[cfg(ossl110g)] assert_eq!(ctx.max_proto_version(), Some(SslVersion::TLS1_1)); let ssl = Ssl::new(&ctx.build()).unwrap(); ssl.accept(stream).unwrap_err(); @@ -1332,7 +1339,9 @@ fn no_version_overlap() { let stream = TcpStream::connect(addr).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_min_proto_version(Some(SslVersion::TLS1_2)).unwrap(); + #[cfg(ossl110g)] assert_eq!(ctx.min_proto_version(), Some(SslVersion::TLS1_2)); + #[cfg(ossl110g)] assert_eq!(ctx.max_proto_version(), None); let ssl = Ssl::new(&ctx.build()).unwrap(); ssl.connect(stream).unwrap_err(); @@ -1391,74 +1400,89 @@ fn _check_kinds() { is_sync::<SslStream<TcpStream>>(); } -#[derive(Debug)] -struct MemoryStream { - incoming: io::Cursor<Vec<u8>>, - outgoing: Vec<u8>, -} - -impl MemoryStream { - pub fn new() -> Self { Self { - incoming: io::Cursor::new(Vec::new()), - outgoing: Vec::new(), - }} +#[test] +#[cfg(ossl111)] +fn stateless() { + use super::SslOptions; - pub fn extend_incoming(&mut self, data: &[u8]) { - self.incoming.get_mut().extend_from_slice(data); + #[derive(Debug)] + struct MemoryStream { + incoming: io::Cursor<Vec<u8>>, + outgoing: Vec<u8>, } - pub fn take_outgoing(&mut self) -> Outgoing { Outgoing(&mut self.outgoing) } -} + impl MemoryStream { + pub fn new() -> Self { + Self { + incoming: io::Cursor::new(Vec::new()), + outgoing: Vec::new(), + } + } -impl Read for MemoryStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - let n = self.incoming.read(buf)?; - if self.incoming.position() == self.incoming.get_ref().len() as u64 { - self.incoming.set_position(0); - self.incoming.get_mut().clear(); + pub fn extend_incoming(&mut self, data: &[u8]) { + self.incoming.get_mut().extend_from_slice(data); } - if n == 0 { - return Err(io::Error::new(io::ErrorKind::WouldBlock, "no data available")); + + pub fn take_outgoing(&mut self) -> Outgoing { + Outgoing(&mut self.outgoing) } - Ok(n) } -} -impl Write for MemoryStream { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.outgoing.write(buf) + impl Read for MemoryStream { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let n = self.incoming.read(buf)?; + if self.incoming.position() == self.incoming.get_ref().len() as u64 { + self.incoming.set_position(0); + self.incoming.get_mut().clear(); + } + if n == 0 { + return Err(io::Error::new( + io::ErrorKind::WouldBlock, + "no data available", + )); + } + Ok(n) + } } - fn flush(&mut self) -> io::Result<()> { Ok(()) } -} - -pub struct Outgoing<'a>(&'a mut Vec<u8>); + impl Write for MemoryStream { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.outgoing.write(buf) + } -impl<'a> Drop for Outgoing<'a> { - fn drop(&mut self) { - self.0.clear(); + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } } -} -impl<'a> ::std::ops::Deref for Outgoing<'a> { - type Target = [u8]; - fn deref(&self) -> &[u8] { &self.0 } -} + pub struct Outgoing<'a>(&'a mut Vec<u8>); -impl<'a> AsRef<[u8]> for Outgoing<'a> { - fn as_ref(&self) -> &[u8] { &self.0 } -} + impl<'a> Drop for Outgoing<'a> { + fn drop(&mut self) { + self.0.clear(); + } + } -fn send(from: &mut MemoryStream, to: &mut MemoryStream) { - to.extend_incoming(&from.take_outgoing()); -} + impl<'a> ::std::ops::Deref for Outgoing<'a> { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.0 + } + } -#[test] -#[cfg(ossl111)] -fn stateless() { - use super::SslOptions; + impl<'a> AsRef<[u8]> for Outgoing<'a> { + fn as_ref(&self) -> &[u8] { + &self.0 + } + } - fn hs<S: ::std::fmt::Debug>(stream: Result<SslStream<S>, HandshakeError<S>>) -> Result<SslStream<S>, MidHandshakeSslStream<S>> { + fn send(from: &mut MemoryStream, to: &mut MemoryStream) { + to.extend_incoming(&from.take_outgoing()); + } + + fn hs<S: ::std::fmt::Debug>( + stream: Result<SslStream<S>, HandshakeError<S>>, + ) -> Result<SslStream<S>, MidHandshakeSslStream<S>> { match stream { Ok(stream) => Ok(stream), Err(HandshakeError::WouldBlock(stream)) => Err(stream), @@ -1475,14 +1499,20 @@ fn stateless() { let client_stream = Ssl::new(&client_ctx.build()).unwrap(); let mut server_ctx = SslContext::builder(SslMethod::tls()).unwrap(); - server_ctx.set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) + server_ctx + .set_certificate_file(&Path::new("test/cert.pem"), SslFiletype::PEM) .unwrap(); - server_ctx.set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) + server_ctx + .set_private_key_file(&Path::new("test/key.pem"), SslFiletype::PEM) .unwrap(); const COOKIE: &[u8] = b"chocolate chip"; - server_ctx.set_stateless_cookie_generate_cb(|_tls, buf| { buf[0..COOKIE.len()].copy_from_slice(COOKIE); Ok(COOKIE.len()) }); + server_ctx.set_stateless_cookie_generate_cb(|_tls, buf| { + buf[0..COOKIE.len()].copy_from_slice(COOKIE); + Ok(COOKIE.len()) + }); server_ctx.set_stateless_cookie_verify_cb(|_tls, buf| buf == COOKIE); - let mut server_stream = ssl::SslStreamBuilder::new(Ssl::new(&server_ctx.build()).unwrap(), MemoryStream::new()); + let mut server_stream = + ssl::SslStreamBuilder::new(Ssl::new(&server_ctx.build()).unwrap(), MemoryStream::new()); // // Handshake |