diff --git a/Cargo.lock b/Cargo.lock index ac96aef..7b0df6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bytes" version = "1.5.0" @@ -162,6 +171,35 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "either" version = "1.9.0" @@ -276,6 +314,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -801,6 +849,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "slab" version = "0.4.9" @@ -910,6 +969,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -934,6 +999,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "vex_mqtt_rust" version = "0.1.0" @@ -948,6 +1019,7 @@ dependencies = [ "rumqttc", "serde", "serde_json", + "sha2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1a54496..d7da985 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ prost-types = "0.12.3" rumqttc = "0.23.0" serde = { version = "1.0.195", features = ["derive"]} serde_json = "1.0.111" +sha2 = "0.10.8" diff --git a/src/main.rs b/src/main.rs index 4fdc7b5..8a479c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,9 @@ use std::io::Cursor; use serde::{Serialize, Deserialize}; use std::io::prelude::*; -use std::io::BufReader; -use std::fs::File; + +use sha2::Digest; +use sha2::Sha256; use std::net::TcpStream; use std::sync::Mutex; @@ -217,6 +218,17 @@ struct BackendPacket { } impl BackendPacket { + fn new(header: u32, timestamp: f64, msg_type: u32, seq_num: u64, data: Vec) -> BackendPacket { + return BackendPacket{ + header, + timestamp, + msg_type, + seq_num, + size: data.len().try_into().unwrap(), + data, + }; + } + fn from_bytes(bytes: Vec) -> Option { if bytes.len() < BACKEND_PACKET_HEADER_SIZE { return None; @@ -232,7 +244,7 @@ impl BackendPacket { }); } - fn to_bytes(self: BackendPacket) -> Vec { + fn as_bytes(self: &BackendPacket) -> Vec { let mut bytes = Vec::new(); bytes.extend(self.header.to_le_bytes()); @@ -240,7 +252,7 @@ impl BackendPacket { bytes.extend(self.msg_type.to_le_bytes()); bytes.extend(self.seq_num.to_le_bytes()); bytes.extend(self.size.to_le_bytes()); - bytes.extend(self.data); + bytes.extend(self.data.clone()); return bytes; } @@ -261,6 +273,25 @@ struct ConnectMsg { } impl ConnectMsg { + fn from_welcome(welcome: ConnectMsg, password: &str, uuid: [u8; 16], client_name: [u8; 32]) -> ConnectMsg { + let mut hasher = Sha256::new(); + hasher.update(welcome.pass_hash); + hasher.update(password); + let result = hasher.finalize(); + + return ConnectMsg{ + version: welcome.version, + uuid, + last_notice_id: welcome.last_notice_id, + username: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + pass_hash: result.try_into().unwrap(), + pw_valid: welcome.pw_valid, + state_valid: welcome.state_valid, + client_name, + server_time_zone: welcome.server_time_zone, + }; + } + fn from_bytes(bytes: Vec) -> Option { if bytes.len() < CONNECT_MSG_LEN { return None; @@ -279,7 +310,7 @@ impl ConnectMsg { }); } - fn to_bytes(self: ConnectMsg) -> Vec { + fn as_bytes(self: &ConnectMsg) -> Vec { let mut bytes = Vec::new(); bytes.extend(self.version.to_le_bytes()); @@ -339,18 +370,33 @@ impl TMClient { let data = incoming[0..read].to_vec(); match BackendPacket::from_bytes(data) { Some(packet) => { - println!("Packet: {:?}", packet); match packet.msg_type { 2 => { match ConnectMsg::from_bytes(packet.data) { - Some(welcome_msg) => println!("Welcome msg: {:?}", welcome_msg), - None => println!("Failed to parse wlecome msg"), + Some(welcome_msg) => { + println!("Welcome msg: {:?}", welcome_msg); + if welcome_msg.pw_valid == 0 { + let uuid = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let client_name = [116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + let connect_response = ConnectMsg::from_welcome(welcome_msg, "", uuid, client_name); + let response = BackendPacket::new(packet.header, packet.timestamp, packet.msg_type, packet.seq_num, connect_response.as_bytes()); + match stream.write(&response.as_bytes()) { + Err(error) => println!("Send error: {:?}", error), + Ok(sent) => println!("Sent {} bytes", sent), + } + } else { + println!("Connected to TM backend!"); + } + }, + None => println!("Failed to parse welcome msg"), } }, _ => println!("Unhandled message type: {}", packet.msg_type), } }, - None => println!("Failed to parse BackendPacket"), + None => { + panic!("Failed to parse BackendPacket({}): {}", read, String::from_utf8_lossy(&incoming)); + } } }, Err(error) => println!("Error: {}", error),