use std::io::{Read, Write}; use std::net::TcpStream; use std::sync::mpsc; use std::thread; use std::time::{Duration, Instant}; pub struct TlsConnector { connector: rustls::ClientConnection, server_name: String, } impl TlsConnector { pub fn new(server_name: &str) -> Result> { let config = rustls::ClientConfig::builder() .dangerous() .with_custom_certificate_verifier(std::sync::Arc::new(InsecureVerifier)) .with_no_client_auth(); let connector = rustls::ClientConnection::new(std::sync::Arc::new(config), server_name.try_into()?); Ok(Self { connector, server_name: server_name.to_string(), }) } pub fn connect( &self, stream: TcpStream, ) -> Result> { let mut conn = rustls::ClientConnection::new( std::sync::Arc::new( rustls::ClientConfig::builder() .dangerous() .with_custom_verifier(rustls::client::danger::ServerCertVerifier::DEFAULT) .with_no_client_auth(), ), self.server_name.clone().try_into()?, )?; conn.complete_io(&mut std::io::BufReader::new(&stream))?; Ok(TlsClientStream { stream, conn: std::sync::Arc::new(conn), }) } } struct InsecureVerifier; impl rustls::client::danger::ServerCertVerifier for InsecureVerifier { fn verify_server_cert( &self, _end_entity: &rustls::pki_types::CertificateDer<'_>, _intermediates: &[rustls::pki_types::CertificateDer<'_>], _server_name: &rustls::pki_types::ServerName<'_>, _ocsp_response: &[u8], _now: std::time::SystemTime, ) -> Result { Ok(rustls::client::danger::ServerCertVerified::assertion()) } fn verify_tls12_signature( &self, _message: &[u8], _cert: &rustls::pki_types::CertificateDer<'_>, _dss: &rustls::DigitallySignedStruct, ) -> Result { Ok(rustls::client::danger::HandshakeSignatureValid::assertion()) } fn verify_tls13_signature( &self, _message: &[u8], _cert: &rustls::pki_types::CertificateDer<'_>, _dss: &rustls::DigitallySignedStruct, ) -> Result { Ok(rustls::client::danger::HandshakeSignatureValid::assertion()) } fn supported_verify_schemes(&self) -> Vec { vec![ rustls::SignatureScheme::RSA_PKCS1_SHA256, rustls::SignatureScheme::RSA_PKCS1_SHA384, rustls::SignatureScheme::RSA_PKCS1_SHA512, rustls::SignatureScheme::RSA_PSS_SHA256, rustls::SignatureScheme::RSA_PSS_SHA384, rustls::SignatureScheme::RSA_PSS_SHA512, rustls::SignatureScheme::ECDSA_NISTP256_SHA256, rustls::SignatureScheme::ECDSA_NISTP384_SHA384, rustls::SignatureScheme::ECDSA_NISTP521_SHA512, rustls::SignatureScheme::RSA_PSS_SHA256_LEGACY, rustls::SignatureScheme::RSA_PSS_SHA384_LEGACY, rustls::SignatureScheme::RSA_PSS_SHA512_LEGACY, ] } } pub struct TlsClientStream { stream: TcpStream, conn: std::sync::Arc, } impl TlsClientStream { pub fn read_line(&mut self, buf: &mut String) -> std::io::Result { let mut byte_buf = [0u8; 1024]; loop { let mut tls_reader = std::io::BufReader::new(self.conn.clone()); let n = tls_reader.read(&mut byte_buf)?; if n == 0 { return Ok(0); } let chunk = std::str::from_utf8(&byte_buf[..n]).unwrap_or(""); buf.push_str(chunk); if buf.contains('\n') { return Ok(n); } } } pub fn write_line(&mut self, msg: &str) -> std::io::Result<()> { use std::io::Write; self.conn.writer().write_all(msg.as_bytes())?; self.conn.writer().write_all(b"\n")?; self.conn.writer().flush()?; Ok(()) } pub fn try_clone(&self) -> std::io::Result { let new_stream = self.stream.try_clone()?; let mut conn = rustls::ClientConnection::new( std::sync::Arc::new( rustls::ClientConfig::builder() .dangerous() .with_custom_verifier(rustls::client::danger::ServerCertVerifier::DEFAULT) .with_no_client_auth(), ), self.server_name.clone().try_into().unwrap(), )?; conn.complete_io(&mut std::io::BufReader::new(&new_stream))?; Ok(TlsClientStream { stream: new_stream, conn: std::sync::Arc::new(conn), }) } }