diff options
| author | Steven Fackler <[email protected]> | 2017-03-25 15:45:40 +0000 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2017-03-25 19:30:01 -0700 |
| commit | c8d1698f275d2901a7fd65f318155acbd2dd02d3 (patch) | |
| tree | b0366bd4db7059a7066cef2014152d1eb54b3666 /openssl/src | |
| parent | Merge pull request #601 from pgerber/double_unlock (diff) | |
| download | rust-openssl-c8d1698f275d2901a7fd65f318155acbd2dd02d3.tar.xz rust-openssl-c8d1698f275d2901a7fd65f318155acbd2dd02d3.zip | |
Logic to support client-side session reuse
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/ssl/connector.rs | 57 | ||||
| -rw-r--r-- | openssl/src/ssl/mod.rs | 55 |
2 files changed, 105 insertions, 7 deletions
diff --git a/openssl/src/ssl/connector.rs b/openssl/src/ssl/connector.rs index 73d7b675..548e3e97 100644 --- a/openssl/src/ssl/connector.rs +++ b/openssl/src/ssl/connector.rs @@ -93,11 +93,7 @@ impl SslConnector { pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>> where S: Read + Write { - let mut ssl = try!(Ssl::new(&self.0)); - try!(ssl.set_hostname(domain)); - try!(setup_verify(&mut ssl, domain)); - - ssl.connect(stream) + try!(self.configure()).connect(domain, stream) } /// Initiates a client-side TLS session on a stream without performing hostname verification. @@ -113,7 +109,56 @@ impl SslConnector { &self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> where S: Read + Write { - try!(Ssl::new(&self.0)).connect(stream) + try!(self.configure()) + .danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream) + } + + /// Returns a structure allowing for configuration of a single TLS session before connection. + pub fn configure(&self) -> Result<ConnectConfiguration, ErrorStack> { + Ssl::new(&self.0).map(ConnectConfiguration) + } +} + +/// A type which allows for configuration of a client-side TLS session before connection. +pub struct ConnectConfiguration(Ssl); + +impl ConnectConfiguration { + /// Returns a shared reference to the inner `Ssl`. + pub fn ssl(&self) -> &Ssl { + &self.0 + } + + /// Returns a mutable reference to the inner `Ssl`. + pub fn ssl_mut(&mut self) -> &mut Ssl { + &mut self.0 + } + + /// Initiates a client-side TLS session on a stream. + /// + /// The domain is used for SNI and hostname verification. + pub fn connect<S>(mut self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>> + where S: Read + Write + { + try!(self.0.set_hostname(domain)); + try!(setup_verify(&mut self.0, domain)); + + self.0.connect(stream) + } + + /// Initiates a client-side TLS session on a stream without performing hostname verification. + /// + /// The verification configuration of the connector's `SslContext` is not overridden. + /// + /// # Warning + /// + /// You should think very carefully before you use this method. If hostname verification is not + /// used, *any* valid certificate for *any* site will be trusted for use from any other. This + /// introduces a significant vulnerability to man-in-the-middle attacks. + pub fn danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication<S>( + self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> + where S: Read + Write + { + self.0.connect(stream) } } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 7fd5a2d0..0f24499d 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -76,6 +76,7 @@ use libc::{c_int, c_void, c_long, c_ulong}; use libc::{c_uchar, c_uint}; use std::any::Any; use std::any::TypeId; +use std::borrow::Borrow; use std::cmp; use std::collections::HashMap; use std::ffi::{CStr, CString}; @@ -1161,6 +1162,32 @@ foreign_type! { pub struct SslSessionRef; } +unsafe impl Sync for SslSession {} +unsafe impl Send for SslSession {} + +impl Clone for SslSession { + fn clone(&self) -> SslSession { + self.to_owned() + } +} + +impl Borrow<SslSessionRef> for SslSession { + fn borrow(&self) -> &SslSessionRef { + &self + } +} + +impl ToOwned for SslSessionRef { + type Owned = SslSession; + + fn to_owned(&self) -> SslSession { + unsafe { + compat::SSL_SESSION_up_ref(self.as_ptr()); + SslSession(self.as_ptr()) + } + } +} + impl SslSessionRef { /// Returns the SSL session ID. pub fn id(&self) -> &[u8] { @@ -1508,6 +1535,23 @@ impl SslRef { } } + /// Sets the session to be used. + /// + /// # Safety + /// + /// The caller of this method is responsible for ensuring that the session is associated + /// with the same `SslContext` as this `Ssl`. + pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { + cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ()) + } + + /// Determines if the session provided to `set_session` was successfully reused. + pub fn session_reused(&self) -> bool { + unsafe { + ffi::SSL_session_reused(self.as_ptr()) != 0 + } + } + /// Sets the status response a client wishes the server to reply with. pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { unsafe { @@ -1918,7 +1962,7 @@ mod compat { use libc::c_int; pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_clear_options, SSL_CTX_up_ref, - SSL_SESSION_get_master_key, SSL_is_server}; + SSL_SESSION_get_master_key, SSL_is_server, SSL_SESSION_up_ref}; pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL_CTX, @@ -2014,4 +2058,13 @@ mod compat { pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int { (*s).server } + + pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { + ffi::CRYPTO_add_lock(&mut (*ses).references, + 1, + ffi::CRYPTO_LOCK_SSL_CTX, + "mod.rs\0".as_ptr() as *const _, + line!() as libc::c_int); + 0 + } } |