#![cfg(feature = "wss")]
use std::net::TcpListener;
use std::sync::Arc;
use std::thread;
use liminal_sdk::{RemoteConfig, SdkError};
use rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
type TestResult = Result<(), Box<dyn std::error::Error>>;
type Listener = (u16, thread::JoinHandle<Result<(), String>>);
fn untrusted_tls_listener() -> Result<Listener, Box<dyn std::error::Error>> {
let certified = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()])?;
let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(certified.key_pair.serialize_der()));
let config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(vec![certified.cert.der().clone()], key)?;
let listener = TcpListener::bind("127.0.0.1:0")?;
let port = listener.local_addr()?.port();
let handle = thread::spawn(move || {
let (mut tcp, _) = listener.accept().map_err(|error| error.to_string())?;
let mut server =
rustls::ServerConnection::new(Arc::new(config)).map_err(|error| error.to_string())?;
while server.is_handshaking() {
if server.complete_io(&mut tcp).is_err() {
break;
}
}
Ok(())
});
Ok((port, handle))
}
#[test]
fn a_wss_server_whose_certificate_no_root_vouches_for_is_refused_by_name() -> TestResult {
let (port, server) = untrusted_tls_listener()?;
let config = RemoteConfig::new(
format!("wss://localhost:{port}/ws"),
"c".to_owned(),
"s".to_owned(),
liminal_sdk::ConnectionPoolConfig::new(1, 10, 16),
)?;
let refused = config.connect_websocket();
let Err(SdkError::Connection { description }) = refused else {
return Err("an untrusted certificate was not refused".into());
};
assert!(
description.contains("invalid peer certificate") && description.contains("UnknownIssuer"),
"{description}"
);
server.join().map_err(|_| "the TLS listener panicked")??;
Ok(())
}