pub mod codec; pub mod proto { include!(concat!(env!("OUT_DIR"), "/mumble_proto.rs")); } pub mod udp { include!(concat!(env!("OUT_DIR"), "/mumble_udp.rs")); } use std::fmt::{Debug, Formatter}; use std::net::SocketAddr; use tokio::net::TcpStream; use tokio::io::AsyncWriteExt; use tokio_stream::StreamExt; use prost::Message; use tokio_rustls::rustls::{ClientConfig, DigitallySignedStruct, Error, RootCertStore, SignatureScheme}; use tokio_rustls::client::TlsStream; use tokio_rustls::{TlsConnector}; use std::sync::Arc; use rustls_pki_types::{CertificateDer, ServerName, UnixTime}; use tokio_util::codec::FramedRead; use crate::codec::MumbleCodec; use bytes::BytesMut; use tokio_rustls::rustls::client::danger::{DangerousClientConfig, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}; pub struct MumbleClient { host: SocketAddr, } pub(crate) struct NoVerifier; impl Debug for NoVerifier { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { todo!() } } impl ServerCertVerifier for NoVerifier { fn verify_server_cert(&self, end_entity: &CertificateDer<'_>, intermediates: &[CertificateDer<'_>], server_name: &ServerName<'_>, ocsp_response: &[u8], now: UnixTime) -> Result { Ok(ServerCertVerified::assertion()) } fn verify_tls12_signature(&self, message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn verify_tls13_signature(&self, message: &[u8], cert: &CertificateDer<'_>, dss: &DigitallySignedStruct) -> Result { Ok(HandshakeSignatureValid::assertion()) } fn supported_verify_schemes(&self) -> Vec { vec![ SignatureScheme::RSA_PKCS1_SHA1, SignatureScheme::ECDSA_SHA1_Legacy, SignatureScheme::RSA_PKCS1_SHA256, SignatureScheme::ECDSA_NISTP256_SHA256, SignatureScheme::RSA_PKCS1_SHA384, SignatureScheme::ECDSA_NISTP384_SHA384, SignatureScheme::RSA_PKCS1_SHA512, SignatureScheme::ECDSA_NISTP521_SHA512, SignatureScheme::RSA_PSS_SHA256, SignatureScheme::RSA_PSS_SHA384, SignatureScheme::RSA_PSS_SHA512, SignatureScheme::ED25519, SignatureScheme::ED448, ] } } impl MumbleClient { pub fn new(host: SocketAddr) -> Self { Self { host } } async fn create_tcp_connection(&mut self) -> anyhow::Result> { let mut root_cert_store = RootCertStore::empty(); root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); let mut config = ClientConfig::builder() .with_root_certificates(root_cert_store) .with_no_client_auth(); config .dangerous() .set_certificate_verifier(Arc::new(NoVerifier)); let connector = TlsConnector::from(Arc::new(config)); let dnsname = ServerName::try_from("127.0.0.1")?; let stream = TcpStream::connect(&self.host).await?; Ok(connector.connect(dnsname, stream).await?) } pub async fn connect(&mut self) -> anyhow::Result<()> { let tcp_stream = self.create_tcp_connection().await?; let mut framed_reader = FramedRead::new(tcp_stream, MumbleCodec::new()); let mut message_buffer: BytesMut = BytesMut::new(); let version = (proto::Version { os: Some(String::from("Linux")), os_version: None, release: None, version_v1: None, version_v2: None }).encode(&mut message_buffer)?; // let mut complete_buffer = BytesMut::new(); // complete_buffer.extend((0u16).to_be_bytes()); // complete_buffer.extend(((2+4+message_buffer.len()) as u32).to_be_bytes()); // complete_buffer.extend(&message_buffer); // println!("{complete_buffer:?}"); // tcp_stream.write_all(&complete_buffer).await?; while let Some(frame_result) = framed_reader.next().await { if let Ok(data) = frame_result { println!("{data:?}"); } } Ok(()) } }