From bbb1cb61f6fe7ec697f0667807dbc175ac623d07 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Mon, 26 Mar 2018 18:49:03 -0700 Subject: Update to OpenSSL 1.1.1-pre3 --- openssl/src/ssl/mod.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index f3c4ed3a..024e4ca5 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1437,8 +1437,9 @@ impl SslContextBuilder { /// The callback will be called with the SSL context and a slice into which the cookie /// should be written. The callback should return the number of bytes written. /// - /// This corresponds to `SSL_CTX_set_cookie_generate_cb`. - pub fn set_cookie_generate_cb(&mut self, callback: F) + /// This corresponds to `SSL_CTX_set_stateless_cookie_generate_cb`. + #[cfg(ossl111)] + pub fn set_stateless_cookie_generate_cb(&mut self, callback: F) where F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, { @@ -1447,9 +1448,9 @@ impl SslContextBuilder { ffi::SSL_CTX_set_ex_data( self.as_ptr(), get_callback_idx::(), - mem::transmute(callback), + Box::into_raw(callback) as *mut _, ); - ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::)) + ffi::SSL_CTX_set_stateless_cookie_generate_cb(self.as_ptr(), Some(raw_stateless_cookie_generate::)) } } @@ -1461,6 +1462,49 @@ impl SslContextBuilder { /// Note that the OpenSSL implementation independently verifies the integrity of /// application cookies using an HMAC before invoking the supplied callback. /// + /// This corresponds to `SSL_CTX_set_stateless_cookie_verify_cb`. + #[cfg(ossl111)] + pub fn set_stateless_cookie_verify_cb(&mut self, callback: F) + where + 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::(), + Box::into_raw(callback) as *mut _, + ); + ffi::SSL_CTX_set_stateless_cookie_verify_cb(self.as_ptr(), Some(raw_stateless_cookie_verify::)) + } + } + + /// Sets the callback for generating a DTLSv1 cookie + /// + /// The callback will be called with the SSL context and a slice into which the cookie + /// should be written. The callback should return the number of bytes written. + /// + /// This corresponds to `SSL_CTX_set_cookie_generate_cb`. + pub fn set_cookie_generate_cb(&mut self, callback: F) + where + F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, + { + unsafe { + let callback = Box::new(callback); + ffi::SSL_CTX_set_ex_data( + self.as_ptr(), + get_callback_idx::(), + Box::into_raw(callback) as *mut _, + ); + ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::)) + } + } + + /// Sets the callback for verifying a DTLSv1 cookie + /// + /// The callback will be called with the SSL context and the cookie supplied by the + /// client. It should return true if and only if the cookie is valid. + /// /// This corresponds to `SSL_CTX_set_cookie_verify_cb`. pub fn set_cookie_verify_cb(&mut self, callback: F) where @@ -1471,7 +1515,7 @@ impl SslContextBuilder { ffi::SSL_CTX_set_ex_data( self.as_ptr(), get_callback_idx::(), - mem::transmute(callback), + Box::into_raw(callback) as *mut _, ); ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::)) } -- cgit v1.2.3 From 99fdb2bd0b72d4d68536242f7ed5fbb2c50cd9e5 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Sun, 4 Mar 2018 11:28:52 -0800 Subject: Introduce SslStreamBuilder --- openssl/src/ssl/mod.rs | 148 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 114 insertions(+), 34 deletions(-) (limited to 'openssl/src/ssl/mod.rs') diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 024e4ca5..5a600053 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1432,7 +1432,8 @@ impl SslContextBuilder { } } - /// Sets the callback for generating an application cookie for stateless handshakes. + /// Sets the callback for generating an application cookie for TLS1.3 + /// stateless handshakes. /// /// The callback will be called with the SSL context and a slice into which the cookie /// should be written. The callback should return the number of bytes written. @@ -1454,7 +1455,8 @@ impl SslContextBuilder { } } - /// Sets the callback for verifying an application cookie for stateless handshakes. + /// Sets the callback for verifying an application cookie for TLS1.3 + /// stateless handshakes. /// /// The callback will be called with the SSL context and the cookie supplied by the /// client. It should return true if and only if the cookie is valid. @@ -2632,22 +2634,7 @@ impl Ssl { where S: Read + Write, { - let mut stream = SslStream::new_base(self, stream); - let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) }; - if ret > 0 { - Ok(stream) - } else { - let error = stream.make_error(ret); - match error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( - MidHandshakeSslStream { stream, error }, - )), - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream, - error, - })), - } - } + SslStreamBuilder::new(self, stream).connect() } /// Initiates a server-side TLS handshake. @@ -2664,22 +2651,7 @@ impl Ssl { where S: Read + Write, { - let mut stream = SslStream::new_base(self, stream); - let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) }; - if ret > 0 { - Ok(stream) - } else { - let error = stream.make_error(ret); - match error.code() { - ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( - MidHandshakeSslStream { stream, error }, - )), - _ => Err(HandshakeError::Failure(MidHandshakeSslStream { - stream, - error, - })), - } - } + SslStreamBuilder::new(self, stream).accept() } } @@ -2951,6 +2923,114 @@ impl Write for SslStream { } } +/// A partially constructed `SslStream`, useful for unusual handshakes. +pub struct SslStreamBuilder { + inner: SslStream +} + +impl SslStreamBuilder + where S: Read + Write +{ + /// Begin creating an `SslStream` atop `stream` + pub fn new(ssl: Ssl, stream: S) -> Self { + Self { + inner: SslStream::new_base(ssl, stream), + } + } + + /// Perform a stateless server-side handshake + /// + /// Requires that cookie generation and verification callbacks were + /// set on the SSL context. + /// + /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie + /// was read, in which case the handshake should be continued via + /// `accept`. If a HelloRetryRequest containing a fresh cookie was + /// transmitted, `Ok(false)` is returned instead. If the handshake cannot + /// proceed at all, `Err` is returned. + /// + /// This corresponds to [`SSL_stateless`] + /// + /// [`SSL_stateless`]: https://www.openssl.org/docs/manmaster/man3/SSL_stateless.html + #[cfg(ossl111)] + pub fn stateless(&mut self) -> Result { + match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } { + 1 => Ok(true), + 0 => Ok(false), + -1 => Err(ErrorStack::get()), + _ => unreachable!(), + } + } + + /// See `Ssl::connect` + pub fn connect(self) -> Result, HandshakeError> { + let mut stream = self.inner; + let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) }; + if ret > 0 { + Ok(stream) + } else { + let error = stream.make_error(ret); + match error.code() { + ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( + MidHandshakeSslStream { stream, error }, + )), + _ => Err(HandshakeError::Failure(MidHandshakeSslStream { + stream, + error, + })), + } + } + } + + /// See `Ssl::accept` + pub fn accept(self) -> Result, HandshakeError> { + let mut stream = self.inner; + let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) }; + if ret > 0 { + Ok(stream) + } else { + let error = stream.make_error(ret); + match error.code() { + ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock( + MidHandshakeSslStream { stream, error }, + )), + _ => Err(HandshakeError::Failure(MidHandshakeSslStream { + stream, + error, + })), + } + } + } + + // Future work: early IO methods +} + +impl SslStreamBuilder { + /// Returns a shared reference to the underlying stream. + pub fn get_ref(&self) -> &S { + unsafe { + let bio = self.inner.ssl.get_raw_rbio(); + bio::get_ref(bio) + } + } + + /// 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 { + unsafe { + let bio = self.inner.ssl.get_raw_rbio(); + bio::get_mut(bio) + } + } + + /// Returns a shared reference to the `Ssl` object associated with this builder. + pub fn ssl(&self) -> &SslRef { &self.inner.ssl } +} + /// The result of a shutdown request. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ShutdownResult { -- cgit v1.2.3