203 lines
5.2 KiB
Rust
203 lines
5.2 KiB
Rust
// mod leb128;
|
|
mod num;
|
|
mod object;
|
|
mod proto;
|
|
|
|
use std::{
|
|
io::{Read, Write},
|
|
net::TcpStream,
|
|
sync::Arc,
|
|
};
|
|
|
|
use anyhow::{ensure, Context, Result};
|
|
// use native_tls::TlsConnector;
|
|
// use native_tls::TlsConnector;
|
|
use rustls::{
|
|
client::{ServerCertVerified, ServerCertVerifier},
|
|
ClientConfig, ClientConnection, KeyLogFile, OwnedTrustAnchor, RootCertStore, StreamOwned,
|
|
};
|
|
use trust_dns_resolver::{
|
|
config::{ResolverConfig, ResolverOpts},
|
|
Resolver,
|
|
};
|
|
use uuid::Uuid;
|
|
|
|
use num::Vu64;
|
|
|
|
use crate::num::Vu32;
|
|
|
|
fn main() -> Result<()> {
|
|
// let (port, host) = resolve_dns("daeken.dev")?;
|
|
let port = 12345;
|
|
let host = "localhost";
|
|
|
|
dbg!(&port);
|
|
dbg!(&host);
|
|
|
|
let tls_conf = Arc::new(make_tls_config());
|
|
let mut tls_conn = make_tls_connection(tls_conf, &host, port)
|
|
.with_context(|| format!("Can't connect to {}:{}", host, port))?;
|
|
|
|
let mut uuid = Uuid::new_v4().as_u128().to_le_bytes();
|
|
uuid[0] = 0;
|
|
uuid[1] = 0;
|
|
uuid[2] = 0;
|
|
uuid[3] = 0;
|
|
|
|
tls_conn.write_all(&uuid).context("Can't write UUID")?;
|
|
|
|
let uuid = Uuid::from_bytes(uuid);
|
|
dbg!(uuid);
|
|
|
|
let mut serv_uuid = [0; 16];
|
|
tls_conn.read_exact(&mut serv_uuid)?;
|
|
let serv_uuid = Uuid::from_bytes(serv_uuid);
|
|
|
|
ensure!(serv_uuid != uuid);
|
|
|
|
dbg!(serv_uuid);
|
|
|
|
let mut command_no = 0;
|
|
let mut recv_buff = Vec::new();
|
|
|
|
loop {
|
|
// Recieve step
|
|
let mut compression = [0];
|
|
let l = tls_conn.read(&mut compression)?;
|
|
match l {
|
|
0 => {}
|
|
1 => {
|
|
assert_eq!(compression, [0]);
|
|
|
|
// Handle recieve
|
|
let len = Vu64::read(&mut tls_conn)?;
|
|
dbg!(len);
|
|
recv_buff.resize(len.0 as usize, 0);
|
|
tls_conn.read_exact(&mut recv_buff)?;
|
|
dbg!(&recv_buff);
|
|
|
|
let mut recv_buff = &recv_buff[..];
|
|
let seq_num = Vu64::read(&mut recv_buff)?;
|
|
|
|
if (seq_num & 1) == 0 {
|
|
// LSB = 0: This is a call, we need to respond
|
|
dbg!(seq_num);
|
|
let command_no = Vu32::read(&mut recv_buff)?;
|
|
let obj_id = Vu64::read(&mut recv_buff)?;
|
|
let serialised = recv_buff;
|
|
dbg!(command_no, obj_id, serialised);
|
|
} else {
|
|
// This is a reponce to something we've asked for
|
|
}
|
|
}
|
|
_ => unreachable!("Should only have read one byte"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: How to cache this?
|
|
fn resolve_dns(server: &str) -> Result<(u16, String)> {
|
|
let name = format!("_hypercosm._tls.{}", server);
|
|
|
|
let resp = make_dns_client()?
|
|
.srv_lookup(name)?
|
|
.into_iter()
|
|
.collect::<Vec<_>>();
|
|
|
|
// TODO: Ensure exactly 1 result: I think.
|
|
let srv = &resp[0];
|
|
|
|
// TODO: Handle priority and weight.
|
|
let port = srv.port();
|
|
// TODO: Should this be ascii or utf8
|
|
let name = srv.target().to_ascii();
|
|
|
|
Ok((port, name))
|
|
}
|
|
|
|
fn make_dns_client() -> Result<Resolver> {
|
|
Ok(Resolver::new(
|
|
ResolverConfig::cloudflare_tls(),
|
|
ResolverOpts::default(),
|
|
)?)
|
|
}
|
|
|
|
fn make_tls_config() -> ClientConfig {
|
|
let mut root_store = RootCertStore::empty();
|
|
root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
|
|
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
|
ta.subject,
|
|
ta.spki,
|
|
ta.name_constraints,
|
|
)
|
|
}));
|
|
|
|
// let cert_dir = include_bytes!("../cert.der");
|
|
|
|
// assert_eq!(
|
|
// root_store.add_parsable_certificates(&[cert_dir.to_vec()]),
|
|
// (1, 0)
|
|
// );
|
|
|
|
let mut config = rustls::ClientConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_root_certificates(root_store)
|
|
.with_no_client_auth();
|
|
|
|
struct DontValidate;
|
|
|
|
impl ServerCertVerifier for DontValidate {
|
|
fn verify_server_cert(
|
|
&self,
|
|
_: &rustls::Certificate,
|
|
_: &[rustls::Certificate],
|
|
_: &rustls::ServerName,
|
|
_: &mut dyn Iterator<Item = &[u8]>,
|
|
_: &[u8],
|
|
_: std::time::SystemTime,
|
|
) -> Result<rustls::client::ServerCertVerified, rustls::Error> {
|
|
Ok(ServerCertVerified::assertion())
|
|
}
|
|
}
|
|
|
|
config
|
|
.dangerous()
|
|
.set_certificate_verifier(Arc::new(DontValidate));
|
|
|
|
config.key_log = Arc::new(KeyLogFile::new());
|
|
|
|
config
|
|
}
|
|
|
|
fn make_tls_connection(
|
|
config: Arc<ClientConfig>,
|
|
server: &str,
|
|
port: u16,
|
|
) -> Result<impl Read + Write> {
|
|
let server_name = server
|
|
.try_into()
|
|
.with_context(|| format!("Invalid server name: `{}`", server))?;
|
|
|
|
let conn = ClientConnection::new(config, server_name)?;
|
|
let sock = TcpStream::connect((server, port))?;
|
|
|
|
let stream = StreamOwned::new(conn, sock);
|
|
|
|
Ok(stream)
|
|
}
|
|
|
|
// fn make_tls_connection(
|
|
// config: Arc<ClientConfig>,
|
|
// server: &str,
|
|
// port: u16,
|
|
// ) -> Result<impl Read + Write> {
|
|
// let connector = TlsConnector::builder()
|
|
// .danger_accept_invalid_certs(true)
|
|
// .build()?;
|
|
|
|
// let sock = TcpStream::connect((server, port))?;
|
|
// let conn = connector.connect(server, sock)?;
|
|
|
|
// Ok(conn)
|
|
// }
|