Skip to content

Commit 214a2b4

Browse files
jbrdjc
authored andcommitted
fix: correctly poll alert.write until it finishes
1 parent 48ec73b commit 214a2b4

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

src/common/handshake.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,16 @@ where
5151
mut io,
5252
mut alert,
5353
error,
54-
} => {
55-
return match alert.write(&mut SyncWriteAdapter { io: &mut io, cx }) {
56-
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
54+
} => loop {
55+
match alert.write(&mut SyncWriteAdapter { io: &mut io, cx }) {
56+
Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
5757
*this = MidHandshake::SendAlert { io, error, alert };
58-
Poll::Pending
58+
return Poll::Pending;
5959
}
60-
_ => Poll::Ready(Err((error, io))),
60+
Err(_) | Ok(0) => return Poll::Ready(Err((error, io))),
61+
Ok(_) => {}
6162
};
62-
}
63+
},
6364
// Starting the handshake returned an error; fail the future immediately.
6465
MidHandshake::Error { io, error } => return Poll::Ready(Err((error, io))),
6566
_ => panic!("unexpected polling after handshake"),

tests/test.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,5 +241,54 @@ async fn lazy_config_acceptor_take_io() -> Result<(), rustls::Error> {
241241
Ok(())
242242
}
243243

244+
#[tokio::test]
245+
async fn acceptor_alert() {
246+
let (sconfig, _) = utils::make_configs();
247+
// this is the client hello from https://tls12.xargs.org/#client-hello/annotated with the minor
248+
// version byte changed
249+
let bad_hello = [
250+
0x16, 0x03, 0x01, 0x00, 0xa5, 0x01, 0x00, 0x00, 0xa1, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03,
251+
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
252+
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00,
253+
0x20, 0xcc, 0xa8, 0xcc, 0xa9, 0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x2b, 0xc0, 0x2c, 0xc0, 0x13,
254+
0xc0, 0x09, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0xc0,
255+
0x12, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x18, 0x00, 0x16, 0x00, 0x00,
256+
0x13, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x75, 0x6c, 0x66, 0x68, 0x65, 0x69,
257+
0x6d, 0x2e, 0x6e, 0x65, 0x74, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
258+
0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b,
259+
0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x01, 0x04, 0x03, 0x05,
260+
0x01, 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x02, 0x01, 0x02, 0x03, 0xff, 0x01, 0x00, 0x01,
261+
0x00, 0x00, 0x12, 0x00, 0x00,
262+
];
263+
264+
// Intentionally small so that we have to call alert.write several times
265+
let (mut cstream, sstream) = tokio::io::duplex(2);
266+
267+
let (tx, rx) = oneshot::channel();
268+
269+
tokio::spawn(async move {
270+
cstream.write_all(&bad_hello).await.unwrap();
271+
let mut buf = Vec::new();
272+
cstream.read_to_end(&mut buf).await.unwrap();
273+
tx.send(buf).unwrap();
274+
});
275+
276+
let accept = LazyConfigAcceptor::new(rustls::server::Acceptor::default(), sstream);
277+
278+
let Ok(Ok(start_handshake)) = time::timeout(Duration::from_secs(3), accept).await else {
279+
panic!("timeout");
280+
};
281+
282+
let err = start_handshake.into_stream(sconfig).await.unwrap_err();
283+
284+
assert_eq!(err.to_string(), "peer is incompatible: Tls12NotOffered");
285+
286+
let Ok(Ok(received)) = time::timeout(Duration::from_secs(3), rx).await else {
287+
panic!("failed to receive");
288+
};
289+
290+
assert_eq!(received, [0x15, 0x03, 0x03, 0x00, 0x02, 0x02, 0x46]);
291+
}
292+
244293
// Include `utils` module
245294
include!("utils.rs");

0 commit comments

Comments
 (0)