use super::*; use http_body_util::{BodyExt, Full}; use hyper_util::rt::{TokioExecutor, TokioIo}; pub(super) const ROOT: &[u8] = include_bytes!("../../../dever-tests/fixtures/tls/root.pem"); pub(super) const CERTIFICATE: &[u8] = include_bytes!("../../../dever-tests/fixtures/tls/server.pem"); pub(super) const KEY: &[u8] = include_bytes!("../../../dever-tests/fixtures/tls/server-key.pem"); #[test] fn tls_verifies_ca_hostname_alpn_and_keeps_bad_handshakes_isolated() { runtime() .run(async |scope| { for http2 in [false, true] { let listener = net::listen("127.0.0.1", 0, scope).await.unwrap(); let port = listener.port().unwrap(); let incoming = listener.clone(); let server = scope .spawn(move |child| async move { let tls = dever_runtime::tls::server(CERTIFICATE, KEY).unwrap(); let limits = Limits { http2: http2.then(http::Http2Limits::default), timeout_ms: 1000, ..Limits::default() }; http::serve_tls::<_, _, false>(&incoming, &limits, &child, &tls, route) .await }) .unwrap(); let custom = dever_runtime::tls::client(ROOT).unwrap(); for (tls, host, protocol) in [ (dever_runtime::tls::system(), "localhost", http2), (custom.clone(), "wrong.test", http2), (custom.clone(), "localhost", !http2), ] { let stream = tokio::net::TcpStream::connect(("127.0.0.1", port as u16)) .await .unwrap(); assert!(tls.connect(host, stream, protocol).await.is_err()); } let stream = tokio::net::TcpStream::connect(("127.0.0.1", port as u16)) .await .unwrap(); let stream = custom.connect("localhost", stream, http2).await.unwrap(); let message = hyper::Request::builder() .method("POST") .uri(if http2 { "https://localhost/echo" } else { "/echo" }) .header("Host", "localhost") .body(Full::new(bytes::Bytes::from_static(b"verified TLS"))) .unwrap(); let response = if http2 { let (mut sender, connection) = hyper::client::conn::http2::Builder::new(TokioExecutor::new()) .handshake(TokioIo::new(stream)) .await .unwrap(); let driver = scope.spawn_leaf(move || connection).unwrap(); let response = sender.send_request(message).await.unwrap(); let body = response.into_body().collect().await.unwrap().to_bytes(); drop(sender); driver.stop().await.unwrap(); body } else { let (mut sender, connection) = hyper::client::conn::http1::handshake(TokioIo::new(stream)) .await .unwrap(); let driver = scope.spawn_leaf(move || connection).unwrap(); let response = sender.send_request(message).await.unwrap(); let body = response.into_body().collect().await.unwrap().to_bytes(); drop(sender); driver.stop().await.unwrap(); body }; assert_eq!(response, b"verified TLS"[..]); listener.close().unwrap(); server.wait().await.unwrap().unwrap(); } }) .unwrap(); } #[test] fn tls_configuration_rejects_invalid_inputs_without_exposing_them() { assert!( dever_runtime::tls::client(b"private-input") .unwrap_err() .contains("empty") ); let error = dever_runtime::tls::server(CERTIFICATE, b"private-key-input").unwrap_err(); assert!(!error.contains("private-key-input")); assert!(dever_runtime::tls::server(ROOT, KEY).is_err()); let mut keys = KEY.to_vec(); keys.extend_from_slice(KEY); assert!( dever_runtime::tls::server(CERTIFICATE, &keys) .unwrap_err() .contains("one private key") ); }