aboutsummaryrefslogtreecommitdiff
path: root/openssl/src
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2017-03-25 15:45:40 +0000
committerSteven Fackler <[email protected]>2017-03-25 19:30:01 -0700
commitc8d1698f275d2901a7fd65f318155acbd2dd02d3 (patch)
treeb0366bd4db7059a7066cef2014152d1eb54b3666 /openssl/src
parentMerge pull request #601 from pgerber/double_unlock (diff)
downloadrust-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.rs57
-rw-r--r--openssl/src/ssl/mod.rs55
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
+ }
}