From 2331c7ecf11110718305c4aef9149d30545c7209 Mon Sep 17 00:00:00 2001 From: Artemis Tosini Date: Tue, 27 Aug 2024 22:59:24 +0000 Subject: [PATCH] well, steam gives me an auth token now --- Cargo.lock | 79 +++++++++++++++++++++++++++++++++++++++- daemon/Cargo.toml | 4 +- daemon/src/connection.rs | 28 ++++++++++++-- daemon/src/main.rs | 57 ++++++++++++++++++++++++++++- daemon/src/message.rs | 27 ++++++++++++-- 5 files changed, 184 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 288b432..d9e3ac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -114,7 +120,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -146,12 +152,24 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.7.1" @@ -231,6 +249,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -328,6 +355,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fnv" version = "1.0.7" @@ -599,6 +636,17 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +dependencies = [ + "bytemuck", + "byteorder-lite", + "num-traits", +] + [[package]] name = "indenter" version = "0.3.3" @@ -709,6 +757,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.2" @@ -721,6 +778,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "object" version = "0.32.2" @@ -897,6 +963,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "qrcode" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68782463e408eb1e668cf6152704bd856c78c5b6417adaee3203d8f4c1fc9ec" +dependencies = [ + "image", +] + [[package]] name = "quinn" version = "0.11.2" @@ -1617,11 +1692,13 @@ dependencies = [ "async-tungstenite", "color-eyre", "env_logger", + "flate2", "futures", "hex", "keyvalues-serde", "log", "protobuf", + "qrcode", "rand", "reqwest", "serde", diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index 0f01284..d3b547c 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -7,13 +7,15 @@ version.workspace = true async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs"] } color-eyre.workspace = true env_logger.workspace = true +flate2 = "1.0.33" futures = "0.3.30" hex = "0.4.3" keyvalues-serde.workspace = true log.workspace = true protobuf.workspace = true +qrcode = "0.14.1" rand = "0.8.5" reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false} serde = { version = "1.0.209", features = ["derive"] } -tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros"]} +tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros", "time"]} vapore-proto.path = "../proto" diff --git a/daemon/src/connection.rs b/daemon/src/connection.rs index 21bfa7f..f86fe8a 100644 --- a/daemon/src/connection.rs +++ b/daemon/src/connection.rs @@ -1,3 +1,4 @@ +use core::time; use std::{ collections::{BTreeMap, HashMap, VecDeque}, future::Future, @@ -16,7 +17,10 @@ use color_eyre::eyre::{self, bail, OptionExt}; use futures::{SinkExt as _, StreamExt}; use serde::Deserialize; use tokio::sync::broadcast; -use vapore_proto::{enums_clientserver::EMsg, steammessages_base::CMsgProtoBufHeader}; +use vapore_proto::{ + enums_clientserver::EMsg, steammessages_base::CMsgProtoBufHeader, + steammessages_clientserver_login::CMsgClientHeartBeat, +}; use crate::message::{CMProtoBufMessage, CMRawProtoBufMessage}; @@ -235,9 +239,27 @@ impl CMSession { tokio::spawn(context); - Ok(Self { + let session = Self { inner: inner_wrapped, - }) + }; + + let session_cloned = session.clone(); + tokio::spawn(async move { session_cloned.send_heartbeat_task().await }); + + Ok(session) + } + + async fn send_heartbeat_task(mut self) -> eyre::Result<()> { + let mut interval = tokio::time::interval(time::Duration::from_secs(5)); + loop { + interval.tick().await; + self.send_notification(EMsg::k_EMsgClientHeartBeat, CMsgClientHeartBeat::default())? + } + } + + pub fn set_client_session_id(&mut self, new_client_session_id: i32) { + let mut inner = self.inner.lock().expect("Lock was poisoned"); + inner.client_session_id = new_client_session_id; } pub fn call_service_method( diff --git a/daemon/src/main.rs b/daemon/src/main.rs index e4f7a43..ac29cd6 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -1,13 +1,15 @@ use color_eyre::eyre; +use message::CMProtoBufMessage; use rand::RngCore; use vapore_proto::{ enums_clientserver::EMsg, steammessages_auth_steamclient::{ CAuthentication_BeginAuthSessionViaQR_Request, CAuthentication_BeginAuthSessionViaQR_Response, CAuthentication_DeviceDetails, - EAuthTokenPlatformType, + CAuthentication_PollAuthSessionStatus_Request, + CAuthentication_PollAuthSessionStatus_Response, EAuthTokenPlatformType, }, - steammessages_clientserver_login::CMsgClientHello, + steammessages_clientserver_login::{CMsgClientHello, CMsgClientLogonResponse}, }; mod connection; @@ -82,5 +84,56 @@ pub async fn main() -> eyre::Result<()> { log::debug!("Got response {:#x?}", response); + let code = qrcode::QrCode::new(response.body.challenge_url()).unwrap(); + log::info!( + "Got new QR code:\n{}", + code.render::().build() + ); + + let cloned_session = session.clone(); + let poll_task = tokio::spawn(async move { + let mut session = cloned_session; + let mut interval = tokio::time::interval(tokio::time::Duration::from_secs_f32( + response.body.interval(), + )); + + loop { + interval.tick().await; + let request = CAuthentication_PollAuthSessionStatus_Request { + client_id: response.body.client_id.clone(), + request_id: response.body.request_id.clone(), + ..Default::default() + }; + let response: CMProtoBufMessage = + session + .call_service_method( + "Authentication.PollAuthSessionStatus#1".to_string(), + request, + ) + .await + .unwrap(); + + log::debug!("Got auth poll status {:#?}", response.body); + + if let Some(new_url) = response.body.new_challenge_url { + let code = qrcode::QrCode::new(new_url).unwrap(); + log::info!( + "Got new QR code:\n{}", + code.render::().build() + ) + }; + } + }); + + let mut finish_receiver = session.subscribe_message_type(EMsg::k_EMsgClientLogOnResponse); + + let raw_response = finish_receiver.recv().await?; + let response: CMProtoBufMessage = + CMProtoBufMessage::deserialize(raw_response)?; + + poll_task.abort(); + + log::debug!("Got logon response: {:#x?}", response); + Ok(()) } diff --git a/daemon/src/message.rs b/daemon/src/message.rs index ddc37eb..17213e5 100644 --- a/daemon/src/message.rs +++ b/daemon/src/message.rs @@ -1,4 +1,7 @@ +use std::io::Read; + use color_eyre::eyre; +use flate2::read::GzDecoder; use protobuf::{Enum as _, Message as _}; use vapore_proto::{ enums_clientserver::EMsg, @@ -82,12 +85,28 @@ impl CMRawProtoBufMessage { // possibly gzipped bytes inside a protobuf. // why, valve let root = CMProtoBufMessage::::deserialize(root_raw)?; - if root.body.size_unzipped.is_some() { - todo!("gzip support in CMsgMulti") - } + let mut gzip_decompressed = Vec::new(); + + let mut body = if let Some(size_unzipped) = root.body.size_unzipped { + gzip_decompressed.reserve(size_unzipped as usize); + + let mut gz = GzDecoder::new(root.body.message_body()); + gz.read_to_end(&mut gzip_decompressed)?; + + if gzip_decompressed.len() != size_unzipped as usize { + eyre::bail!( + "Expected decompressed len {}, got {}", + size_unzipped, + gzip_decompressed.len() + ); + } + + &gzip_decompressed + } else { + root.body.message_body() + }; let mut items = Vec::new(); - let mut body = root.body.message_body(); while body.len() >= 4 { let full_length = u32::from_le_bytes(body[0..4].try_into().unwrap()); let message_end = 4 + full_length as usize;