From de47d158c20768b8526e939e7eb3ae9175e282f2 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 10:41:47 -0800 Subject: Remove NonblockingSslStream --- openssl/src/ssl/mod.rs | 133 +------------------------------------------------ 1 file changed, 1 insertion(+), 132 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index aa785142..4404eb55 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -26,7 +26,7 @@ use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; use dh::DH; -use ssl::error::{NonblockingSslError, SslError, OpenSslError, OpensslError}; +use ssl::error::{SslError, OpenSslError}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; @@ -1572,134 +1572,3 @@ impl MaybeSslStream { } } } - -/// # Deprecated -/// -/// Use `SslStream` with `ssl_read` and `ssl_write`. -pub struct NonblockingSslStream(SslStream); - -impl Clone for NonblockingSslStream { - fn clone(&self) -> Self { - NonblockingSslStream(self.0.clone()) - } -} - -#[cfg(unix)] -impl AsRawFd for NonblockingSslStream { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} - -#[cfg(windows)] -impl AsRawSocket for NonblockingSslStream { - fn as_raw_socket(&self) -> RawSocket { - self.0.as_raw_socket() - } -} - -impl NonblockingSslStream { - pub fn try_clone(&self) -> io::Result> { - self.0.try_clone().map(NonblockingSslStream) - } -} - -impl NonblockingSslStream { - /// Returns a reference to the underlying stream. - pub fn get_ref(&self) -> &S { - self.0.get_ref() - } - - /// Returns a mutable reference to the underlying stream. - /// - /// ## Warning - /// - /// It is inadvisable to read from or write to the underlying stream as it - /// will most likely corrupt the SSL session. - pub fn get_mut(&mut self) -> &mut S { - self.0.get_mut() - } - - /// Returns a reference to the Ssl. - pub fn ssl(&self) -> &Ssl { - self.0.ssl() - } -} - -impl NonblockingSslStream { - /// Create a new nonblocking client ssl connection on wrapped `stream`. - /// - /// Note that this method will most likely not actually complete the SSL - /// handshake because doing so requires several round trips; the handshake will - /// be completed in subsequent read/write calls managed by your event loop. - pub fn connect(ssl: T, stream: S) -> Result, SslError> { - SslStream::connect(ssl, stream).map(NonblockingSslStream) - } - - /// Create a new nonblocking server ssl connection on wrapped `stream`. - /// - /// Note that this method will most likely not actually complete the SSL - /// handshake because doing so requires several round trips; the handshake will - /// be completed in subsequent read/write calls managed by your event loop. - pub fn accept(ssl: T, stream: S) -> Result, SslError> { - SslStream::accept(ssl, stream).map(NonblockingSslStream) - } - - fn convert_err(&self, err: Error) -> NonblockingSslError { - match err { - Error::ZeroReturn => SslError::SslSessionClosed.into(), - Error::WantRead(_) => NonblockingSslError::WantRead, - Error::WantWrite(_) => NonblockingSslError::WantWrite, - Error::WantX509Lookup => unreachable!(), - Error::Stream(e) => SslError::StreamError(e).into(), - Error::Ssl(e) => { - SslError::OpenSslErrors(e.iter() - .map(|e| OpensslError::from_error_code(e.error_code())) - .collect()) - .into() - } - } - } - - /// Read bytes from the SSL stream into `buf`. - /// - /// Given the SSL state machine, this method may return either `WantWrite` - /// or `WantRead` to indicate that your event loop should respectively wait - /// for write or read readiness on the underlying stream. Upon readiness, - /// repeat your `read()` call with the same arguments each time until you - /// receive an `Ok(count)`. - /// - /// An `SslError` return value, is terminal; do not re-attempt your read. - /// - /// As expected of a nonblocking API, this method will never block your - /// thread on I/O. - /// - /// On a return value of `Ok(count)`, count is the number of decrypted - /// plaintext bytes copied into the `buf` slice. - pub fn read(&mut self, buf: &mut [u8]) -> Result { - match self.0.ssl_read(buf) { - Ok(n) => Ok(n), - Err(Error::ZeroReturn) => Ok(0), - Err(e) => Err(self.convert_err(e)), - } - } - - /// Write bytes from `buf` to the SSL stream. - /// - /// Given the SSL state machine, this method may return either `WantWrite` - /// or `WantRead` to indicate that your event loop should respectively wait - /// for write or read readiness on the underlying stream. Upon readiness, - /// repeat your `write()` call with the same arguments each time until you - /// receive an `Ok(count)`. - /// - /// An `SslError` return value, is terminal; do not re-attempt your write. - /// - /// As expected of a nonblocking API, this method will never block your - /// thread on I/O. - /// - /// Given a return value of `Ok(count)`, count is the number of plaintext bytes - /// from the `buf` slice that were encrypted and written onto the stream. - pub fn write(&mut self, buf: &[u8]) -> Result { - self.0.ssl_write(buf).map_err(|e| self.convert_err(e)) - } -} -- cgit v1.2.3 From 58654bc49140d37f28837ba1982ed4aa9fc5c466 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 10:44:01 -0800 Subject: Remove deprecated methods --- openssl/src/ssl/mod.rs | 62 +------------------------------------------------- 1 file changed, 1 insertion(+), 61 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 4404eb55..c713aeb2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -7,7 +7,6 @@ use std::io; use std::io::prelude::*; use std::mem; use std::str; -use std::net; use std::path::Path; use std::ptr; use std::sync::{Once, ONCE_INIT, Mutex, Arc}; @@ -922,15 +921,6 @@ impl Drop for Ssl { } } -impl Clone for Ssl { - /// # Deprecated - fn clone(&self) -> Ssl { - unsafe { rust_SSL_clone(self.ssl) }; - Ssl { ssl: self.ssl } - - } -} - impl Ssl { pub fn new(ctx: &SslContext) -> Result { let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); @@ -1210,19 +1200,7 @@ pub struct SslStream { _p: PhantomData, } -/// # Deprecated -/// -/// This method does not behave as expected and will be removed in a future -/// release. -impl Clone for SslStream { - fn clone(&self) -> SslStream { - SslStream { - ssl: self.ssl.clone(), - _method: self._method.clone(), - _p: PhantomData, - } - } -} +unsafe impl Send for SslStream {} impl fmt::Debug for SslStream where S: fmt::Debug { @@ -1292,20 +1270,6 @@ impl SslStream { } } - /// ### Deprecated - /// - /// Use `connect`. - pub fn connect_generic(ssl: T, stream: S) -> Result, SslError> { - Self::connect(ssl, stream) - } - - /// ### Deprecated - /// - /// Use `accept`. - pub fn accept_generic(ssl: T, stream: S) -> Result, SslError> { - Self::accept(ssl, stream) - } - /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. /// /// This is particularly useful with a nonblocking socket, where the error @@ -1442,20 +1406,6 @@ impl SslStream { } } -impl SslStream<::std::net::TcpStream> { - /// # Deprecated - /// - /// This method does not behave as expected and will be removed in a future - /// release. - pub fn try_clone(&self) -> io::Result> { - Ok(SslStream { - ssl: self.ssl.clone(), - _method: self._method.clone(), - _p: PhantomData, - }) - } -} - impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.ssl_read(buf) { @@ -1562,13 +1512,3 @@ impl MaybeSslStream where S: Read + Write } } } - -impl MaybeSslStream { - /// Like `TcpStream::try_clone`. - pub fn try_clone(&self) -> io::Result> { - match *self { - MaybeSslStream::Ssl(ref s) => s.try_clone().map(MaybeSslStream::Ssl), - MaybeSslStream::Normal(ref s) => s.try_clone().map(MaybeSslStream::Normal), - } - } -} -- cgit v1.2.3 From fa622326490e1dd27df4d42b4097ca574deedb3f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 30 Jan 2016 12:55:22 -0800 Subject: Error reform --- openssl/src/ssl/mod.rs | 123 ++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 77 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index c713aeb2..f9534bc2 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -25,9 +25,9 @@ use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; use dh::DH; -use ssl::error::{SslError, OpenSslError}; use x509::{X509StoreContext, X509FileType, X509}; use crypto::pkey::PKey; +use error::ErrorStack; pub mod error; mod bio; @@ -513,9 +513,9 @@ pub type ServerNameCallbackData = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) - // FIXME: macro may be instead of inlining? #[inline] -fn wrap_ssl_result(res: c_int) -> Result<(), SslError> { +fn wrap_ssl_result(res: c_int) -> Result<(), ErrorStack> { if res == 0 { - Err(SslError::get()) + Err(ErrorStack::get()) } else { Ok(()) } @@ -558,7 +558,7 @@ impl SslContext { } /// Creates a new SSL context. - pub fn new(method: SslMethod) -> Result { + pub fn new(method: SslMethod) -> Result { init(); let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); @@ -647,7 +647,7 @@ impl SslContext { } } - pub fn set_tmp_dh(&self, dh: DH) -> Result<(), SslError> { + pub fn set_tmp_dh(&self, dh: DH) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } @@ -656,13 +656,13 @@ impl SslContext { /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` /// environment variables if present, or defaults specified at OpenSSL /// build time otherwise. - pub fn set_default_verify_paths(&mut self) -> Result<(), SslError> { + pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.ctx) }) } #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. - pub fn set_CA_file>(&mut self, file: P) -> Result<(), SslError> { + pub fn set_CA_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_load_verify_locations(self.ctx, file.as_ptr() as *const _, ptr::null()) @@ -677,7 +677,7 @@ impl SslContext { /// /// This value should be set when using client certificates, or each request will fail /// handshake and need to be restarted. - pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), SslError> { + pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_set_session_id_context(self.ctx, sid_ctx.as_ptr(), sid_ctx.len() as u32) }) @@ -687,7 +687,7 @@ impl SslContext { pub fn set_certificate_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> 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_file(self.ctx, @@ -700,7 +700,7 @@ impl SslContext { pub fn set_certificate_chain_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> 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.ctx, @@ -710,13 +710,13 @@ impl SslContext { } /// Specifies the certificate - pub fn set_certificate(&mut self, cert: &X509) -> Result<(), SslError> { + pub fn set_certificate(&mut self, cert: &X509) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.ctx, cert.get_handle()) }) } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() - pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), SslError> { + pub fn add_extra_chain_cert(&mut self, cert: &X509) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_add_extra_chain_cert(self.ctx, cert.get_handle()) as c_int }) @@ -726,7 +726,7 @@ impl SslContext { pub fn set_private_key_file>(&mut self, file: P, file_type: X509FileType) - -> Result<(), SslError> { + -> 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_PrivateKey_file(self.ctx, @@ -736,16 +736,16 @@ impl SslContext { } /// Specifies the private key - pub fn set_private_key(&mut self, key: &PKey) -> Result<(), SslError> { + pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.ctx, key.get_handle()) }) } /// Check consistency of private key and certificate - pub fn check_private_key(&mut self) -> Result<(), SslError> { + pub fn check_private_key(&mut self) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.ctx) }) } - pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), SslError> { + pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { let cipher_list = CString::new(cipher_list).unwrap(); ffi::SSL_CTX_set_cipher_list(self.ctx, cipher_list.as_ptr() as *const _) @@ -757,7 +757,7 @@ impl SslContext { /// /// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature. #[cfg(feature = "ecdh_auto")] - pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), SslError> { + pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_ecdh_auto(self.ctx, onoff as c_int) }) } @@ -922,7 +922,7 @@ impl Drop for Ssl { } impl Ssl { - pub fn new(ctx: &SslContext) -> Result { + pub fn new(ctx: &SslContext) -> Result { let ssl = try_ssl_null!(unsafe { ffi::SSL_new(ctx.ctx) }); let ssl = Ssl { ssl: ssl }; Ok(ssl) @@ -950,9 +950,9 @@ impl Ssl { unsafe { ffi::SSL_write(self.ssl, buf.as_ptr() as *const c_void, len) } } - fn get_error(&self, ret: c_int) -> LibSslError { + fn get_error(&self, ret: c_int) -> LibErrorStack { let err = unsafe { ffi::SSL_get_error(self.ssl, ret) }; - match LibSslError::from_i32(err as i32) { + match LibErrorStack::from_i32(err as i32) { Some(err) => err, None => unreachable!(), } @@ -1013,7 +1013,7 @@ impl Ssl { } /// Sets the host name to be used with SNI (Server Name Indication). - pub fn set_hostname(&self, hostname: &str) -> Result<(), SslError> { + pub fn set_hostname(&self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); let ret = unsafe { ffi_extras::SSL_set_tlsext_host_name(self.ssl, cstr.as_ptr() as *const _) @@ -1021,7 +1021,7 @@ impl Ssl { // For this case, 0 indicates failure. if ret == 0 { - Err(SslError::get()) + Err(ErrorStack::get()) } else { Ok(()) } @@ -1162,18 +1162,18 @@ impl Ssl { } } -macro_rules! make_LibSslError { +macro_rules! make_LibErrorStack { ($($variant:ident = $value:ident),+) => { #[derive(Debug)] #[repr(i32)] - enum LibSslError { + enum LibErrorStack { $($variant = ffi::$value),+ } - impl LibSslError { - fn from_i32(val: i32) -> Option { + impl LibErrorStack { + fn from_i32(val: i32) -> Option { match val { - $(ffi::$value => Some(LibSslError::$variant),)+ + $(ffi::$value => Some(LibErrorStack::$variant),)+ _ => None } } @@ -1181,7 +1181,7 @@ macro_rules! make_LibSslError { } } -make_LibSslError! { +make_LibErrorStack! { ErrorNone = SSL_ERROR_NONE, ErrorSsl = SSL_ERROR_SSL, ErrorWantRead = SSL_ERROR_WANT_READ, @@ -1241,31 +1241,31 @@ impl SslStream { } /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) -> Result { + pub fn connect(ssl: T, stream: S) -> Result { let ssl = try!(ssl.into_ssl()); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.connect(); if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - Some(err) => Err(err), - None => Ok(stream), + match stream.make_error(ret) { + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + err => Err(err) } } } /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) -> Result { + pub fn accept(ssl: T, stream: S) -> Result { let ssl = try!(ssl.into_ssl()); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.accept(); if ret > 0 { Ok(stream) } else { - match stream.make_old_error(ret) { - Some(err) => Err(err), - None => Ok(stream), + match stream.make_error(ret) { + Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), + err => Err(err) } } } @@ -1302,10 +1302,10 @@ impl SslStream { self.check_panic(); match self.ssl.get_error(ret) { - LibSslError::ErrorSsl => Error::Ssl(OpenSslError::get_stack()), - LibSslError::ErrorSyscall => { - let errs = OpenSslError::get_stack(); - if errs.is_empty() { + LibErrorStack::ErrorSsl => Error::Ssl(ErrorStack::get()), + LibErrorStack::ErrorSyscall => { + let errs = ErrorStack::get(); + if errs.errors().is_empty() { if ret == 0 { Error::Stream(io::Error::new(io::ErrorKind::ConnectionAborted, "unexpected EOF observed")) @@ -1316,9 +1316,9 @@ impl SslStream { Error::Ssl(errs) } } - LibSslError::ErrorZeroReturn => Error::ZeroReturn, - LibSslError::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), - LibSslError::ErrorWantRead => Error::WantRead(self.get_bio_error()), + LibErrorStack::ErrorZeroReturn => Error::ZeroReturn, + LibErrorStack::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), + LibErrorStack::ErrorWantRead => Error::WantRead(self.get_bio_error()), err => { Error::Stream(io::Error::new(io::ErrorKind::Other, format!("unexpected error {:?}", err))) @@ -1326,37 +1326,6 @@ impl SslStream { } } - fn make_old_error(&mut self, ret: c_int) -> Option { - self.check_panic(); - - match self.ssl.get_error(ret) { - LibSslError::ErrorSsl => Some(SslError::get()), - LibSslError::ErrorSyscall => { - let err = SslError::get(); - let count = match err { - SslError::OpenSslErrors(ref v) => v.len(), - _ => unreachable!(), - }; - if count == 0 { - if ret == 0 { - Some(SslError::StreamError(io::Error::new(io::ErrorKind::ConnectionAborted, - "unexpected EOF observed"))) - } else { - Some(SslError::StreamError(self.get_bio_error())) - } - } else { - Some(err) - } - } - LibSslError::ErrorZeroReturn => Some(SslError::SslSessionClosed), - LibSslError::ErrorWantWrite | LibSslError::ErrorWantRead => None, - err => { - Some(SslError::StreamError(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err)))) - } - } - } - #[cfg(feature = "nightly")] fn check_panic(&mut self) { if let Some(err) = unsafe { bio::take_panic::(self.ssl.get_raw_rbio()) } { @@ -1437,17 +1406,17 @@ impl Write for SslStream { } pub trait IntoSsl { - fn into_ssl(self) -> Result; + fn into_ssl(self) -> Result; } impl IntoSsl for Ssl { - fn into_ssl(self) -> Result { + fn into_ssl(self) -> Result { Ok(self) } } impl<'a> IntoSsl for &'a SslContext { - fn into_ssl(self) -> Result { + fn into_ssl(self) -> Result { Ssl::new(self) } } -- cgit v1.2.3 From a0549c160675c69935a71049143cabff4ec9aeee Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 8 Feb 2016 23:03:25 -0800 Subject: Adjust set_ssl_context API --- openssl/src/ssl/mod.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f9534bc2..55a97c94 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1139,18 +1139,11 @@ impl Ssl { /// change the context corresponding to the current connection /// /// Returns a clone of the SslContext @ctx (ie: the new context). The old context is freed. - pub fn set_ssl_context(&self, ctx: &SslContext) -> SslContext { - // If duplication of @ctx's cert fails, this returns NULL. This _appears_ to only occur on - // allocation failures (meaning panicing is probably appropriate), but it might be nice to - // propogate the error. - assert!(unsafe { ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx) } != ptr::null_mut()); - - // FIXME: we return this reference here for compatibility, but it isn't actually required. - // This should be removed when a api-incompatabile version is to be released. - // - // ffi:SSL_set_SSL_CTX() returns copy of the ctx pointer passed to it, so it's easier for - // us to do the clone directly. - ctx.clone() + pub fn set_ssl_context(&self, ctx: &SslContext) -> Result<(), ErrorStack> { + unsafe { + try_ssl_null!(ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx)); + } + Ok(()) } /// obtain the context corresponding to the current connection -- cgit v1.2.3 From 696b1961ce31e77aebf5fcf13398c8c54ed22d87 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 21:02:29 -0700 Subject: Rename getters in line with conventions --- openssl/src/ssl/mod.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 55a97c94..1bb4a2d8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -767,7 +767,7 @@ impl SslContext { SslContextOptions::from_bits(ret).unwrap() } - pub fn get_options(&mut self) -> SslContextOptions { + pub fn options(&mut self) -> SslContextOptions { let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } @@ -982,7 +982,7 @@ impl Ssl { } } - pub fn get_current_cipher<'a>(&'a self) -> Option> { + pub fn current_cipher<'a>(&'a self) -> Option> { unsafe { let ptr = ffi::SSL_get_current_cipher(self.ssl); @@ -1119,7 +1119,7 @@ impl Ssl { Some(s) } - pub fn get_ssl_method(&self) -> Option { + pub fn ssl_method(&self) -> Option { unsafe { let method = ffi::SSL_get_ssl_method(self.ssl); SslMethod::from_raw(method) @@ -1127,7 +1127,7 @@ impl Ssl { } /// Returns the server's name for the current connection - pub fn get_servername(&self) -> Option { + pub fn servername(&self) -> Option { let name = unsafe { ffi::SSL_get_servername(self.ssl, ffi::TLSEXT_NAMETYPE_host_name) }; if name == ptr::null() { return None; @@ -1136,9 +1136,7 @@ impl Ssl { unsafe { String::from_utf8(CStr::from_ptr(name as *const _).to_bytes().to_vec()).ok() } } - /// change the context corresponding to the current connection - /// - /// Returns a clone of the SslContext @ctx (ie: the new context). The old context is freed. + /// Changes the context corresponding to the current connection. pub fn set_ssl_context(&self, ctx: &SslContext) -> Result<(), ErrorStack> { unsafe { try_ssl_null!(ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx)); @@ -1146,8 +1144,8 @@ impl Ssl { Ok(()) } - /// obtain the context corresponding to the current connection - pub fn get_ssl_context(&self) -> SslContext { + /// Returns the context corresponding to the current connection + pub fn ssl_context(&self) -> SslContext { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(self.ssl); SslContext::new_ref(ssl_ctx) -- cgit v1.2.3 From 61f65cd8d636dc0c7f08876f404819b20cc56ca0 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 21:30:24 -0700 Subject: Move SslContext::set_verify to a closure based API --- openssl/src/ssl/mod.rs | 81 +++++++++----------------------------------------- 1 file changed, 14 insertions(+), 67 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1bb4a2d8..9ef27238 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -44,7 +44,6 @@ extern "C" { fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } -static mut VERIFY_IDX: c_int = -1; static mut SNI_IDX: c_int = -1; /// Manually initialize SSL. @@ -56,10 +55,6 @@ pub fn init() { INIT.call_once(|| { ffi::init(); - let verify_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); - assert!(verify_idx >= 0); - VERIFY_IDX = verify_idx; - let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(sni_idx >= 0); SNI_IDX = sni_idx; @@ -291,47 +286,19 @@ fn get_new_ssl_idx() -> c_int { } } -extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { - 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 verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, VERIFY_IDX); - let verify: Option = mem::transmute(verify); - - let ctx = X509StoreContext::new(x509_ctx); - - match verify { - None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx) as c_int, - } - } -} - -extern "C" fn raw_verify_with_data(preverify_ok: c_int, - x509_ctx: *mut ffi::X509_STORE_CTX) - -> c_int - where T: Any + 'static +extern "C" 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 verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, VERIFY_IDX); - let verify: Option> = mem::transmute(verify); - - let data = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); - let data: &T = mem::transmute(data); + let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); + let verify: &F = mem::transmute(verify); let ctx = X509StoreContext::new(x509_ctx); - let res = match verify { - None => preverify_ok, - Some(verify) => verify(preverify_ok != 0, &ctx, data) as c_int, - }; - - res + verify(preverify_ok != 0, &ctx) as c_int } } @@ -498,14 +465,6 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { enc } -/// The signature of functions that can be used to manually verify certificates -pub type VerifyCallback = fn(preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool; - -/// The signature of functions that can be used to manually verify certificates -/// when user-data should be carried for all verification process -pub type VerifyCallbackData = fn(preverify_ok: bool, x509_ctx: &X509StoreContext, data: &T) - -> bool; - /// The signature of functions that can be used to choose the context depending on the server name pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; @@ -573,33 +532,21 @@ impl SslContext { } /// Configures the certificate verification method for new connections. - pub fn set_verify(&mut self, mode: SslVerifyMode, verify: Option) { + pub fn set_verify(&mut self, mode: SslVerifyMode) { unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(verify)); - let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = raw_verify; - - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); + ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, None); } } - /// Configures the certificate verification method for new connections also - /// carrying supplied data. - // Note: no option because there is no point to set data without providing - // a function handling it - pub fn set_verify_with_data(&mut self, - mode: SslVerifyMode, - verify: VerifyCallbackData, - data: T) - where T: Any + 'static + /// Configures the certificate verification method for new connections and + /// registers a verification callback. + pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send { - let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, VERIFY_IDX, mem::transmute(Some(verify))); - ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(data)); - let f: extern "C" fn(c_int, *mut ffi::X509_STORE_CTX) -> c_int = - raw_verify_with_data::; - - ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(f)); + let verify = Box::new(verify); + ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(verify)); + ffi::SSL_CTX_set_verify(self.ctx, mode.bits as c_int, Some(raw_verify::)); } } -- cgit v1.2.3 From f09ca6fee26dc04e7f5d8d879ccfde311257db61 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 1 May 2016 22:28:09 -0700 Subject: Clean up SNI APIs --- openssl/src/ssl/mod.rs | 103 ++++++++++++++----------------------------------- 1 file changed, 30 insertions(+), 73 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 9ef27238..0b7d8b27 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -44,22 +44,11 @@ extern "C" { fn rust_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX); } -static mut SNI_IDX: c_int = -1; - /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. pub fn init() { static mut INIT: Once = ONCE_INIT; - - unsafe { - INIT.call_once(|| { - ffi::init(); - - let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); - assert!(sni_idx >= 0); - SNI_IDX = sni_idx; - }); - } + unsafe { INIT.call_once(|| ffi::init()); } } bitflags! { @@ -317,50 +306,31 @@ 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, ad: &mut c_int, _arg: *mut c_void) -> c_int { - unsafe { - let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); - let callback: Option = mem::transmute(callback); - rust_SSL_clone(ssl); - let mut s = Ssl { ssl: ssl }; - - let res = match callback { - None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad), - }; - - res - } -} - -extern "C" fn raw_sni_with_data(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int - where T: Any + 'static +extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int + where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); - - let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); - let callback: Option> = mem::transmute(callback); + let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); + let callback: &F = mem::transmute(callback); rust_SSL_clone(ssl); - let mut s = Ssl { ssl: ssl }; - - let data: &T = mem::transmute(arg); + let mut ssl = Ssl { ssl: ssl }; - let res = match callback { - None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, - Some(callback) => callback(&mut s, ad, &*data), - }; - - // Since data might be required on the next verification - // it is time to forget about it and avoid dropping - // data will be freed once OpenSSL considers it is time - // to free all context data - res + match callback(&mut ssl) { + Ok(()) => ffi::SSL_TLSEXT_ERR_OK, + Err(SniError::Fatal(e)) => { + *al = e; + ffi::SSL_TLSEXT_ERR_ALERT_FATAL + } + Err(SniError::Warning(e)) => { + *al = e; + ffi::SSL_TLSEXT_ERR_ALERT_WARNING + } + Err(SniError::NoAck) => ffi::SSL_TLSEXT_ERR_NOACK, + } } } - #[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, @@ -465,10 +435,12 @@ fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { enc } -/// The signature of functions that can be used to choose the context depending on the server name -pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; - -pub type ServerNameCallbackData = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) -> i32; +/// An error returned from an SNI callback. +pub enum SniError { + Fatal(c_int), + Warning(c_int), + NoAck, +} // FIXME: macro may be instead of inlining? #[inline] @@ -552,30 +524,15 @@ impl SslContext { /// Configures the server name indication (SNI) callback for new connections /// - /// obtain the server name with `get_servername` then set the corresponding context + /// Obtain the server name with `servername` then set the corresponding context /// with `set_ssl_context` - pub fn set_servername_callback(&mut self, callback: Option) { - unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback)); - let f: extern "C" fn(_, _, _) -> _ = raw_sni; - let f: extern "C" fn() = mem::transmute(f); - ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); - } - } - - /// Configures the server name indication (SNI) callback for new connections - /// carrying supplied data - pub fn set_servername_callback_with_data(&mut self, - callback: ServerNameCallbackData, - data: T) - where T: Any + 'static + pub fn set_servername_callback(&mut self, callback: F) + where F: Fn(&mut Ssl) -> Result<(), SniError> + Any + 'static + Sync + Send { - let data = Box::new(data); unsafe { - ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback))); - - ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data)); - let f: extern "C" fn(_, _, _) -> _ = raw_sni_with_data::; + let callback = Box::new(callback); + ffi::SSL_CTX_set_ex_data(self.ctx, get_verify_data_idx::(), mem::transmute(callback)); + let f: extern "C" fn(_, _, _) -> _ = raw_sni::; let f: extern "C" fn() = mem::transmute(f); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } -- cgit v1.2.3 From 085b2e6f035b74a51bd648b36fb8be98fa3e5405 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 20:10:12 -0700 Subject: Drop is_dtls methods on SslMethod --- openssl/src/ssl/mod.rs | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0b7d8b27..f9ba99ca 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -169,30 +169,6 @@ impl SslMethod { _ => None, } } - - #[cfg(feature = "dtlsv1")] - pub fn is_dtlsv1(&self) -> bool { - *self == SslMethod::Dtlsv1 - } - - #[cfg(feature = "dtlsv1_2")] - pub fn is_dtlsv1_2(&self) -> bool { - *self == SslMethod::Dtlsv1_2 - } - - pub fn is_dtls(&self) -> bool { - self.is_dtlsv1() || self.is_dtlsv1_2() - } - - #[cfg(not(feature = "dtlsv1"))] - pub fn is_dtlsv1(&self) -> bool { - false - } - - #[cfg(not(feature = "dtlsv1_2"))] - pub fn is_dtlsv1_2(&self) -> bool { - false - } } /// Determines the type of certificate verification used @@ -496,8 +472,12 @@ impl SslContext { let ctx = SslContext { ctx: ctx }; - if method.is_dtls() { - ctx.set_read_ahead(1); + match method { + #[cfg(feature = "dtlsv1")] + SslMethod::Dtlsv1 => ctx.set_read_ahead(1), + #[cfg(feature = "dtlsv1_2")] + SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1), + _ => {} } Ok(ctx) -- cgit v1.2.3 From 00f517d2cdb10dfe113caa1476c85a3b57722eae Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 20:22:00 -0700 Subject: Drop MaybeSslStream It should be inlined into crates that depend on it. --- openssl/src/ssl/mod.rs | 61 -------------------------------------------------- 1 file changed, 61 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f9ba99ca..08f85dfb 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1295,64 +1295,3 @@ impl<'a> IntoSsl for &'a SslContext { Ssl::new(self) } } - -/// A utility type to help in cases where the use of SSL is decided at runtime. -#[derive(Debug)] -pub enum MaybeSslStream - where S: Read + Write -{ - /// A connection using SSL - Ssl(SslStream), - /// A connection not using SSL - Normal(S), -} - -impl Read for MaybeSslStream where S: Read + Write -{ - fn read(&mut self, buf: &mut [u8]) -> io::Result { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.read(buf), - MaybeSslStream::Normal(ref mut s) => s.read(buf), - } - } -} - -impl Write for MaybeSslStream where S: Read + Write -{ - fn write(&mut self, buf: &[u8]) -> io::Result { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.write(buf), - MaybeSslStream::Normal(ref mut s) => s.write(buf), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.flush(), - MaybeSslStream::Normal(ref mut s) => s.flush(), - } - } -} - -impl MaybeSslStream where S: Read + Write -{ - /// Returns a reference to the underlying stream. - pub fn get_ref(&self) -> &S { - match *self { - MaybeSslStream::Ssl(ref s) => s.get_ref(), - MaybeSslStream::Normal(ref s) => s, - } - } - - /// Returns a mutable reference to the underlying stream. - /// - /// ## Warning - /// - /// It is inadvisable to read from or write to the underlying stream. - pub fn get_mut(&mut self) -> &mut S { - match *self { - MaybeSslStream::Ssl(ref mut s) => s.get_mut(), - MaybeSslStream::Normal(ref mut s) => s, - } - } -} -- cgit v1.2.3 From f1846bce7840b16cdcf079d2d96d6ed24d2cc269 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 21:20:13 -0700 Subject: Remove silly internal error enum --- openssl/src/ssl/mod.rs | 53 +++++++++----------------------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 08f85dfb..c6ebb397 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -834,12 +834,8 @@ impl Ssl { unsafe { ffi::SSL_write(self.ssl, buf.as_ptr() as *const c_void, len) } } - fn get_error(&self, ret: c_int) -> LibErrorStack { - let err = unsafe { ffi::SSL_get_error(self.ssl, ret) }; - match LibErrorStack::from_i32(err as i32) { - Some(err) => err, - None => unreachable!(), - } + fn get_error(&self, ret: c_int) -> c_int { + unsafe { ffi::SSL_get_error(self.ssl, ret) } } /// Sets the verification mode to be used during the handshake process. @@ -1037,37 +1033,6 @@ impl Ssl { } } -macro_rules! make_LibErrorStack { - ($($variant:ident = $value:ident),+) => { - #[derive(Debug)] - #[repr(i32)] - enum LibErrorStack { - $($variant = ffi::$value),+ - } - - impl LibErrorStack { - fn from_i32(val: i32) -> Option { - match val { - $(ffi::$value => Some(LibErrorStack::$variant),)+ - _ => None - } - } - } - } -} - -make_LibErrorStack! { - ErrorNone = SSL_ERROR_NONE, - ErrorSsl = SSL_ERROR_SSL, - ErrorWantRead = SSL_ERROR_WANT_READ, - ErrorWantWrite = SSL_ERROR_WANT_WRITE, - ErrorWantX509Lookup = SSL_ERROR_WANT_X509_LOOKUP, - ErrorSyscall = SSL_ERROR_SYSCALL, - ErrorZeroReturn = SSL_ERROR_ZERO_RETURN, - ErrorWantConnect = SSL_ERROR_WANT_CONNECT, - ErrorWantAccept = SSL_ERROR_WANT_ACCEPT -} - /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { ssl: Ssl, @@ -1177,8 +1142,8 @@ impl SslStream { self.check_panic(); match self.ssl.get_error(ret) { - LibErrorStack::ErrorSsl => Error::Ssl(ErrorStack::get()), - LibErrorStack::ErrorSyscall => { + ffi::SSL_ERROR_SSL => Error::Ssl(ErrorStack::get()), + ffi::SSL_ERROR_SYSCALL => { let errs = ErrorStack::get(); if errs.errors().is_empty() { if ret == 0 { @@ -1191,12 +1156,12 @@ impl SslStream { Error::Ssl(errs) } } - LibErrorStack::ErrorZeroReturn => Error::ZeroReturn, - LibErrorStack::ErrorWantWrite => Error::WantWrite(self.get_bio_error()), - LibErrorStack::ErrorWantRead => Error::WantRead(self.get_bio_error()), + ffi::SSL_ERROR_ZERO_RETURN => Error::ZeroReturn, + ffi::SSL_ERROR_WANT_WRITE => Error::WantWrite(self.get_bio_error()), + ffi::SSL_ERROR_WANT_READ => Error::WantRead(self.get_bio_error()), err => { - Error::Stream(io::Error::new(io::ErrorKind::Other, - format!("unexpected error {:?}", err))) + Error::Stream(io::Error::new(io::ErrorKind::InvalidData, + format!("unexpected error {}", err))) } } } -- cgit v1.2.3 From 356d4a0420e73dc55491322a21ad5872d2a08415 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 2 May 2016 21:29:25 -0700 Subject: Remove AsRaw{Fd, Socket} impls An SslStream can't really act as a raw socket since you'd skip the whole TLS layer --- openssl/src/ssl/mod.rs | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index c6ebb397..5536a99e 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -17,10 +17,6 @@ use libc::{c_uchar, c_uint}; #[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; use std::marker::PhantomData; -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, RawFd}; -#[cfg(windows)] -use std::os::windows::io::{AsRawSocket, RawSocket}; use ffi; use ffi_extras; @@ -1052,20 +1048,6 @@ impl fmt::Debug for SslStream where S: fmt::Debug } } -#[cfg(unix)] -impl AsRawFd for SslStream { - fn as_raw_fd(&self) -> RawFd { - self.get_ref().as_raw_fd() - } -} - -#[cfg(windows)] -impl AsRawSocket for SslStream { - fn as_raw_socket(&self) -> RawSocket { - self.get_ref().as_raw_socket() - } -} - impl SslStream { fn new_base(ssl: Ssl, stream: S) -> Self { unsafe { -- cgit v1.2.3 From f4f6412fcb54f54df8667587de39fcb3c3781204 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Thu, 2 Jun 2016 00:05:57 -0400 Subject: Fix a few mutable types for `self` parameters. --- openssl/src/ssl/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 5536a99e..89a7f7d4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -521,13 +521,13 @@ impl SslContext { } } - pub fn set_read_ahead(&self, m: u32) { + pub fn set_read_ahead(&mut self, m: u32) { unsafe { ffi_extras::SSL_CTX_set_read_ahead(self.ctx, m as c_long); } } - pub fn set_tmp_dh(&self, dh: DH) -> Result<(), ErrorStack> { + pub fn set_tmp_dh(&mut self, dh: DH) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_tmp_dh(self.ctx, dh.raw()) as i32 }) } @@ -647,7 +647,7 @@ impl SslContext { SslContextOptions::from_bits(ret).unwrap() } - pub fn options(&mut self) -> SslContextOptions { + pub fn options(&self) -> SslContextOptions { let ret = unsafe { ffi_extras::SSL_CTX_get_options(self.ctx) }; SslContextOptions::from_bits(ret).unwrap() } -- cgit v1.2.3 From 5cb04db787baefc7f6368bd40cc1d4378760cf68 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 31 Jul 2016 15:35:45 -0700 Subject: Fix build with dtls --- openssl/src/ssl/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index b18df7b3..aba809fd 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -466,7 +466,7 @@ impl SslContext { let ctx = try_ssl_null!(unsafe { ffi::SSL_CTX_new(method.to_raw()) }); - let ctx = SslContext { ctx: ctx }; + let mut ctx = SslContext { ctx: ctx }; match method { #[cfg(feature = "dtlsv1")] @@ -529,7 +529,7 @@ impl SslContext { } } - fn set_mode(&self, mode: c_long) -> Result<(), ErrorStack> { + fn set_mode(&mut self, mode: c_long) -> Result<(), ErrorStack> { wrap_ssl_result(unsafe { ffi_extras::SSL_CTX_set_mode(self.ctx, mode) as c_int }) } -- cgit v1.2.3 From 3539be33660dc136e0b585400f70447e31ccb62a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 27 Jul 2016 14:18:02 -0700 Subject: Add MidHandshakeSslStream Allows recognizing when a stream is still in handshake mode and can gracefully transition when ready. The blocking usage of the API should still be the same, just helps nonblocking implementations! --- openssl/src/ssl/mod.rs | 120 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 112 insertions(+), 8 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index b18df7b3..9215a928 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -5,6 +5,7 @@ use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; +use std::error as stderror; use std::mem; use std::str; use std::path::Path; @@ -832,6 +833,10 @@ impl Ssl { unsafe { ffi::SSL_accept(self.ssl) } } + fn handshake(&self) -> c_int { + unsafe { ffi::SSL_do_handshake(self.ssl) } + } + fn read(&self, buf: &mut [u8]) -> c_int { let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; unsafe { ffi::SSL_read(self.ssl, buf.as_ptr() as *mut c_void, len) } @@ -1081,31 +1086,49 @@ impl SslStream { } /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) -> Result { - let ssl = try!(ssl.into_ssl()); + pub fn connect(ssl: T, stream: S) + -> Result>{ + let ssl = try!(ssl.into_ssl().map_err(|e| { + HandshakeError::Failure(Error::Ssl(e)) + })); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.connect(); if ret > 0 { Ok(stream) } else { match stream.make_error(ret) { - Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), - err => Err(err) + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => Err(HandshakeError::Failure(err)), } } } /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) -> Result { - let ssl = try!(ssl.into_ssl()); + pub fn accept(ssl: T, stream: S) + -> Result> { + let ssl = try!(ssl.into_ssl().map_err(|e| { + HandshakeError::Failure(Error::Ssl(e)) + })); let mut stream = Self::new_base(ssl, stream); let ret = stream.ssl.accept(); if ret > 0 { Ok(stream) } else { match stream.make_error(ret) { - Error::WantRead(..) | Error::WantWrite(..) => Ok(stream), - err => Err(err) + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => Err(HandshakeError::Failure(err)), } } } @@ -1137,6 +1160,87 @@ impl SslStream { } } +/// An error or intermediate state after a TLS handshake attempt. +#[derive(Debug)] +pub enum HandshakeError { + /// The handshake failed. + Failure(Error), + /// The handshake was interrupted midway through. + Interrupted(MidHandshakeSslStream), +} + +impl stderror::Error for HandshakeError { + fn description(&self) -> &str { + match *self { + HandshakeError::Failure(ref e) => e.description(), + HandshakeError::Interrupted(ref e) => e.error.description(), + } + } + + fn cause(&self) -> Option<&stderror::Error> { + match *self { + HandshakeError::Failure(ref e) => Some(e), + HandshakeError::Interrupted(ref e) => Some(&e.error), + } + } +} + +impl fmt::Display for HandshakeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str(stderror::Error::description(self))); + if let Some(e) = stderror::Error::cause(self) { + try!(write!(f, ": {}", e)); + } + Ok(()) + } +} + +/// An SSL stream midway through the handshake process. +#[derive(Debug)] +pub struct MidHandshakeSslStream { + stream: SslStream, + error: Error, +} + +impl MidHandshakeSslStream { + /// Returns a shared reference to the inner stream. + pub fn get_ref(&self) -> &S { + self.stream.get_ref() + } + + /// Returns a mutable reference to the inner stream. + pub fn get_mut(&mut self) -> &mut S { + self.stream.get_mut() + } + + /// Returns a shared reference to the `SslContext` of the stream. + pub fn ssl(&self) -> &Ssl { + self.stream.ssl() + } + + /// Returns the underlying error which interrupted this handshake. + pub fn error(&self) -> &Error { + &self.error + } + + /// Restarts the handshake process. + pub fn handshake(mut self) -> Result, HandshakeError> { + let ret = self.stream.ssl.handshake(); + if ret > 0 { + Ok(self.stream) + } else { + match self.stream.make_error(ret) { + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + self.error = e; + Err(HandshakeError::Interrupted(self)) + } + err => Err(HandshakeError::Failure(err)), + } + } + } +} + impl SslStream { fn make_error(&mut self, ret: c_int) -> Error { self.check_panic(); -- cgit v1.2.3