Introduce SslStreamBuilder
This commit is contained in:
parent
bbb1cb61f6
commit
99fdb2bd0b
|
|
@ -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
|
/// 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.
|
/// 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
|
/// 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.
|
/// client. It should return true if and only if the cookie is valid.
|
||||||
|
|
@ -2632,22 +2634,7 @@ impl Ssl {
|
||||||
where
|
where
|
||||||
S: Read + Write,
|
S: Read + Write,
|
||||||
{
|
{
|
||||||
let mut stream = SslStream::new_base(self, stream);
|
SslStreamBuilder::new(self, stream).connect()
|
||||||
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,
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initiates a server-side TLS handshake.
|
/// Initiates a server-side TLS handshake.
|
||||||
|
|
@ -2664,22 +2651,7 @@ impl Ssl {
|
||||||
where
|
where
|
||||||
S: Read + Write,
|
S: Read + Write,
|
||||||
{
|
{
|
||||||
let mut stream = SslStream::new_base(self, stream);
|
SslStreamBuilder::new(self, stream).accept()
|
||||||
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,
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2951,6 +2923,114 @@ impl<S: Read + Write> Write for SslStream<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A partially constructed `SslStream`, useful for unusual handshakes.
|
||||||
|
pub struct SslStreamBuilder<S> {
|
||||||
|
inner: SslStream<S>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> SslStreamBuilder<S>
|
||||||
|
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<bool, ErrorStack> {
|
||||||
|
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<SslStream<S>, HandshakeError<S>> {
|
||||||
|
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<SslStream<S>, HandshakeError<S>> {
|
||||||
|
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<S> SslStreamBuilder<S> {
|
||||||
|
/// 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.
|
/// The result of a shutdown request.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum ShutdownResult {
|
pub enum ShutdownResult {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue