Skip to content

Commit b27a6e7

Browse files
committed
Introduce setup_accept and setup_connect
These two new kinds of methods immediately return a MidHandshakeSslStream instead of actually initiating a handshake. This greatly simplifies loops around MidHandshakeSslStream::WouldBlock.
1 parent 4b16781 commit b27a6e7

3 files changed

Lines changed: 180 additions & 119 deletions

File tree

boring/src/ssl/connector.rs

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::ssl::{
99
};
1010
use crate::version;
1111

12+
use super::MidHandshakeSslStream;
13+
1214
const FFDHE_2048: &str = "
1315
-----BEGIN DH PARAMETERS-----
1416
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
@@ -98,11 +100,30 @@ impl SslConnector {
98100
/// Initiates a client-side TLS session on a stream.
99101
///
100102
/// The domain is used for SNI and hostname verification.
103+
pub fn setup_connect<S>(
104+
&self,
105+
domain: &str,
106+
stream: S,
107+
) -> Result<MidHandshakeSslStream<S>, ErrorStack>
108+
where
109+
S: Read + Write,
110+
{
111+
self.configure()?.setup_connect(domain, stream)
112+
}
113+
114+
/// Attempts a client-side TLS session on a stream.
115+
///
116+
/// The domain is used for SNI and hostname verification.
117+
///
118+
/// This is a convenience method which combines [`Self::setup_connect`] and
119+
/// [`MidHandshakeSslStream::handshake`].
101120
pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
102121
where
103122
S: Read + Write,
104123
{
105-
self.configure()?.connect(domain, stream)
124+
self.setup_connect(domain, stream)
125+
.map_err(HandshakeError::SetupFailure)?
126+
.handshake()
106127
}
107128

108129
/// Returns a structure allowing for configuration of a single TLS session before connection.
@@ -192,7 +213,13 @@ impl ConnectConfiguration {
192213
/// Initiates a client-side TLS session on a stream.
193214
///
194215
/// The domain is used for SNI and hostname verification if enabled.
195-
pub fn connect<S>(mut self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
216+
///
217+
/// See [`Ssl::setup_connect`] for more details.
218+
pub fn setup_connect<S>(
219+
mut self,
220+
domain: &str,
221+
stream: S,
222+
) -> Result<MidHandshakeSslStream<S>, ErrorStack>
196223
where
197224
S: Read + Write,
198225
{
@@ -210,7 +237,22 @@ impl ConnectConfiguration {
210237
setup_verify_hostname(&mut self.ssl, domain)?;
211238
}
212239

213-
self.ssl.connect(stream)
240+
Ok(self.ssl.setup_connect(stream))
241+
}
242+
243+
/// Attempts a client-side TLS session on a stream.
244+
///
245+
/// The domain is used for SNI and hostname verification if enabled.
246+
///
247+
/// This is a convenience method which combines [`Self::setup_connect`] and
248+
/// [`MidHandshakeSslStream::handshake`].
249+
pub fn connect<S>(self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
250+
where
251+
S: Read + Write,
252+
{
253+
self.setup_connect(domain, stream)
254+
.map_err(HandshakeError::SetupFailure)?
255+
.handshake()
214256
}
215257
}
216258

@@ -319,13 +361,29 @@ impl SslAcceptor {
319361
Ok(SslAcceptorBuilder(ctx))
320362
}
321363

322-
/// Initiates a server-side TLS session on a stream.
323-
pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
364+
/// Initiates a server-side TLS handshake on a stream.
365+
///
366+
/// See [`Ssl::setup_accept`] for more details.
367+
pub fn setup_accept<S>(&self, stream: S) -> Result<MidHandshakeSslStream<S>, ErrorStack>
324368
where
325369
S: Read + Write,
326370
{
327371
let ssl = Ssl::new(&self.0)?;
328-
ssl.accept(stream)
372+
373+
Ok(ssl.setup_accept(stream))
374+
}
375+
376+
/// Attempts a server-side TLS handshake on a stream.
377+
///
378+
/// This is a convenience method which combines [`Self::setup_accept`] and
379+
/// [`MidHandshakeSslStream::handshake`].
380+
pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
381+
where
382+
S: Read + Write,
383+
{
384+
self.setup_accept(stream)
385+
.map_err(HandshakeError::SetupFailure)?
386+
.handshake()
329387
}
330388

331389
/// Consumes the `SslAcceptor`, returning the inner raw `SslContext`.

boring/src/ssl/mod.rs

Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,34 +2306,52 @@ impl Ssl {
23062306
}
23072307
}
23082308

2309-
/// Initiates a client-side TLS handshake.
2309+
/// Initiates a client-side TLS handshake, returning a [`MidHandshakeSslStream`].
23102310
///
2311-
/// This corresponds to [`SSL_connect`].
2311+
/// This method is guaranteed to return without calling any callback defined
2312+
/// in the internal [`Ssl`] or [`SslContext`].
2313+
///
2314+
/// See [`SslStreamBuilder::setup_connect`] for more details.
23122315
///
23132316
/// # Warning
23142317
///
2315-
/// OpenSSL's default configuration is insecure. It is highly recommended to use
2316-
/// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
2318+
/// BoringSSL's default configuration is insecure. It is highly recommended to use
2319+
/// [`SslConnector`] rather than [`Ssl`] directly, as it manages that configuration.
2320+
pub fn setup_connect<S>(self, stream: S) -> MidHandshakeSslStream<S>
2321+
where
2322+
S: Read + Write,
2323+
{
2324+
SslStreamBuilder::new(self, stream).setup_connect()
2325+
}
2326+
2327+
/// Attempts a client-side TLS handshake.
2328+
///
2329+
/// This is a convenience method which combines [`Self::setup_connect`] and
2330+
/// [`MidHandshakeSslStream::handshake`].
2331+
///
2332+
/// # Warning
23172333
///
2318-
/// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html
2334+
/// OpenSSL's default configuration is insecure. It is highly recommended to use
2335+
/// [`SslConnector`] rather than `Ssl` directly, as it manages that configuration.
23192336
pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
23202337
where
23212338
S: Read + Write,
23222339
{
2323-
SslStreamBuilder::new(self, stream).connect()
2340+
self.setup_connect(stream).handshake()
23242341
}
23252342

23262343
/// Initiates a server-side TLS handshake.
23272344
///
2328-
/// This corresponds to [`SSL_accept`].
2345+
/// This method is guaranteed to return without calling any callback defined
2346+
/// in the internal [`Ssl`] or [`SslContext`].
23292347
///
2330-
/// # Warning
2348+
/// See [`SslStreamBuilder::setup_accept`] for more details.
23312349
///
2332-
/// OpenSSL's default configuration is insecure. It is highly recommended to use
2333-
/// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
2350+
/// # Warning
23342351
///
2335-
/// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html
2336-
pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2352+
/// BoringSSL's default configuration is insecure. It is highly recommended to use
2353+
/// [`SslAcceptor`] rather than [`Ssl`] directly, as it manages that configuration.
2354+
pub fn setup_accept<S>(self, stream: S) -> MidHandshakeSslStream<S>
23372355
where
23382356
S: Read + Write,
23392357
{
@@ -2352,7 +2370,25 @@ impl Ssl {
23522370
}
23532371
}
23542372

2355-
SslStreamBuilder::new(self, stream).accept()
2373+
SslStreamBuilder::new(self, stream).setup_accept()
2374+
}
2375+
2376+
/// Attempts a server-side TLS handshake.
2377+
///
2378+
/// This is a convenience method which combines [`Self::setup_accept`] and
2379+
/// [`MidHandshakeSslStream::handshake`].
2380+
///
2381+
/// # Warning
2382+
///
2383+
/// OpenSSL's default configuration is insecure. It is highly recommended to use
2384+
/// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
2385+
///
2386+
/// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html
2387+
pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2388+
where
2389+
S: Read + Write,
2390+
{
2391+
self.setup_accept(stream).handshake()
23562392
}
23572393
}
23582394

@@ -3461,46 +3497,60 @@ where
34613497
unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
34623498
}
34633499

3464-
/// See `Ssl::connect`
3500+
/// Initiates a client-side TLS handshake, returning a [`MidHandshakeSslStream`].
3501+
///
3502+
/// This method calls [`Self::set_connect_state`] and returns without actually
3503+
/// initiating the handshake. The caller is then free to call
3504+
/// [`MidHandshakeSslStream`] and loop on [`HandshakeError::WouldBlock`].
3505+
pub fn setup_connect(mut self) -> MidHandshakeSslStream<S> {
3506+
self.set_connect_state();
3507+
3508+
MidHandshakeSslStream {
3509+
stream: self.inner,
3510+
error: Error {
3511+
code: ErrorCode::WANT_WRITE,
3512+
cause: Some(InnerError::Io(io::Error::new(
3513+
io::ErrorKind::WouldBlock,
3514+
"connect handshake has not started yet",
3515+
))),
3516+
},
3517+
}
3518+
}
3519+
3520+
/// Attempts a client-side TLS handshake.
3521+
///
3522+
/// This is a convenience method which combines [`Self::setup_connect`] and
3523+
/// [`MidHandshakeSslStream::handshake`].
34653524
pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
3466-
let mut stream = self.inner;
3467-
let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) };
3468-
if ret > 0 {
3469-
Ok(stream)
3470-
} else {
3471-
let error = stream.make_error(ret);
3472-
match error.would_block() {
3473-
true => Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
3474-
stream,
3475-
error,
3476-
})),
3477-
false => Err(HandshakeError::Failure(MidHandshakeSslStream {
3478-
stream,
3479-
error,
3480-
})),
3481-
}
3525+
self.setup_connect().handshake()
3526+
}
3527+
3528+
/// Initiates a server-side TLS handshake, returning a [`MidHandshakeSslStream`].
3529+
///
3530+
/// This method calls [`Self::set_accept_state`] and returns without actually
3531+
/// initiating the handshake. The caller is then free to call
3532+
/// [`MidHandshakeSslStream`] and loop on [`HandshakeError::WouldBlock`].
3533+
pub fn setup_accept(mut self) -> MidHandshakeSslStream<S> {
3534+
self.set_accept_state();
3535+
3536+
MidHandshakeSslStream {
3537+
stream: self.inner,
3538+
error: Error {
3539+
code: ErrorCode::WANT_READ,
3540+
cause: Some(InnerError::Io(io::Error::new(
3541+
io::ErrorKind::WouldBlock,
3542+
"accept handshake has not started yet",
3543+
))),
3544+
},
34823545
}
34833546
}
34843547

3485-
/// See `Ssl::accept`
3548+
/// Attempts a server-side TLS handshake.
3549+
///
3550+
/// This is a convenience method which combines [`Self::setup_accept`] and
3551+
/// [`MidHandshakeSslStream::handshake`].
34863552
pub fn accept(self) -> Result<SslStream<S>, HandshakeError<S>> {
3487-
let mut stream = self.inner;
3488-
let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) };
3489-
if ret > 0 {
3490-
Ok(stream)
3491-
} else {
3492-
let error = stream.make_error(ret);
3493-
match error.would_block() {
3494-
true => Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
3495-
stream,
3496-
error,
3497-
})),
3498-
false => Err(HandshakeError::Failure(MidHandshakeSslStream {
3499-
stream,
3500-
error,
3501-
})),
3502-
}
3503-
}
3553+
self.setup_accept().handshake()
35043554
}
35053555

35063556
/// Initiates the handshake.

0 commit comments

Comments
 (0)