From 5e9f8ac95e5fa1c4732b0e85f9f08753c3d3cf7f Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Thu, 16 Feb 2023 23:08:17 +0100 Subject: Initial commit --- src/main.rs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5b8817e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,124 @@ +use mt_net::{MtReceiver, MtSender, RemoteSrv, ToCltPkt, ToSrvPkt}; +use rand::RngCore; +use sha2::Sha256; +use srp::{client::SrpClient, groups::G_2048}; +use std::time::Duration; +use tokio::sync::oneshot; + +async fn handle(tx: MtSender, rx: &mut MtReceiver) { + let mut username = "hydra".to_string(); + let password = "password"; + + let (init_tx, mut init_rx) = oneshot::channel(); + + { + let tx = tx.clone(); + let pkt = ToSrvPkt::Init { + serialize_version: 29, + min_proto_version: 40, + max_proto_version: 40, + player_name: username.clone(), + send_full_item_meta: false, + }; + + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_millis(100)); + while tokio::select! { + _ = &mut init_rx => false, + _ = interval.tick() => true, + } { + tx.send(&pkt).await.unwrap() + } + }); + } + + let mut init_tx = Some(init_tx); + let mut auth = None; + + while let Some(res) = rx.recv().await { + match res { + Ok(pkt) => { + use ToCltPkt::*; + + match pkt { + Hello { + auth_methods, + username: name, + .. + } => { + use mt_net::AuthMethod; + + if let Some(chan) = init_tx.take() { + chan.send(()).unwrap(); + + let client = SrpClient::::new(&G_2048); + + let mut rand_bytes = vec![0; 32]; + rand::thread_rng().fill_bytes(&mut rand_bytes); + + username = name; + + if auth_methods.contains(AuthMethod::FirstSrp) { + let verifier = client.compute_verifier( + username.to_lowercase().as_bytes(), + password.as_bytes(), + &rand_bytes, + ); + + tx.send(&ToSrvPkt::FirstSrp { + salt: rand_bytes, + verifier, + empty_passwd: password.is_empty(), + }) + .await + .unwrap(); + } else if auth_methods.contains(AuthMethod::Srp) { + let a = client.compute_public_ephemeral(&rand_bytes); + auth = Some((rand_bytes, client)); + + tx.send(&ToSrvPkt::SrpBytesA { a, no_sha1: true }) + .await + .unwrap(); + } else { + panic!("unsupported auth methods: {auth_methods:?}"); + } + } + } + SrpBytesSaltB { salt, b } => { + if let Some((a, client)) = auth.take() { + let m = client + .process_reply( + &a, + username.to_lowercase().as_bytes(), + password.as_bytes(), + &salt, + &b, + ) + .unwrap() + .proof() + .into(); + + tx.send(&ToSrvPkt::SrpBytesM { m }).await.unwrap(); + } + } + x => println!("{x:?}"), + } + } + Err(err) => eprintln!("{err}"), + } + } +} + +#[tokio::main] +async fn main() { + let (tx, mut rx) = mt_net::connect("localhost:30000").await.unwrap(); + + tokio::select! { + _ = tokio::signal::ctrl_c() => println!("canceled"), + _ = handle(tx, &mut rx) => { + println!("disconnected"); + } + } + + rx.close().await; +} -- cgit v1.2.3