vapored: Log in with code

This commit is contained in:
Artemis Tosini 2024-09-04 23:17:26 +00:00
parent 9e960d98e4
commit fca43d6220
Signed by: artemist
GPG key ID: ADFFE553DCBB831E
3 changed files with 284 additions and 17 deletions

188
Cargo.lock generated
View file

@ -131,6 +131,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.6.0"
@ -224,6 +230,25 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
[[package]]
name = "console"
version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys 0.52.0",
]
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@ -284,6 +309,30 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "der"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
dependencies = [
"const-oid",
"pem-rfc7468",
"zeroize",
]
[[package]]
name = "dialoguer"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de"
dependencies = [
"console",
"shell-words",
"tempfile",
"thiserror",
"zeroize",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@ -291,6 +340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"const-oid",
"crypto-common", "crypto-common",
] ]
@ -300,6 +350,12 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]] [[package]]
name = "env_filter" name = "env_filter"
version = "0.1.2" version = "0.1.2"
@ -717,6 +773,9 @@ name = "lazy_static"
version = "1.5.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
dependencies = [
"spin",
]
[[package]] [[package]]
name = "libc" name = "libc"
@ -724,6 +783,12 @@ version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.14" version = "0.4.14"
@ -778,6 +843,43 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
dependencies = [
"byteorder",
"lazy_static",
"libm",
"num-integer",
"num-iter",
"num-traits",
"rand",
"smallvec",
"zeroize",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.19"
@ -785,6 +887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"libm",
] ]
[[package]] [[package]]
@ -814,6 +917,15 @@ version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "pem-rfc7468"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
dependencies = [
"base64ct",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.1" version = "2.3.1"
@ -897,6 +1009,27 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkcs1"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [
"der",
"pkcs8",
"spki",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -1143,6 +1276,26 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rsa"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
dependencies = [
"const-oid",
"digest",
"num-bigint-dig",
"num-integer",
"num-traits",
"pkcs1",
"pkcs8",
"rand_core",
"signature",
"spki",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -1335,12 +1488,28 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]] [[package]]
name = "shlex" name = "shlex"
version = "1.3.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
"rand_core",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1372,6 +1541,16 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
]
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.6.1" version = "2.6.1"
@ -1633,6 +1812,12 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unicode-width"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@ -1690,7 +1875,9 @@ name = "vapored"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-tungstenite", "async-tungstenite",
"base64",
"color-eyre", "color-eyre",
"dialoguer",
"env_logger", "env_logger",
"flate2", "flate2",
"futures", "futures",
@ -1701,6 +1888,7 @@ dependencies = [
"qrcode", "qrcode",
"rand", "rand",
"reqwest", "reqwest",
"rsa",
"serde", "serde",
"tokio", "tokio",
"vapore-proto", "vapore-proto",

View file

@ -5,7 +5,9 @@ version.workspace = true
[dependencies] [dependencies]
async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs"] } async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs"] }
base64 = "0.22.1"
color-eyre.workspace = true color-eyre.workspace = true
dialoguer = "0.11.0"
env_logger.workspace = true env_logger.workspace = true
flate2 = "1.0.33" flate2 = "1.0.33"
futures = "0.3.30" futures = "0.3.30"
@ -16,6 +18,7 @@ protobuf.workspace = true
qrcode = "0.14.1" qrcode = "0.14.1"
rand = "0.8.5" rand = "0.8.5"
reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false} reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false}
rsa = "0.9.6"
serde = { version = "1.0.209", features = ["derive"] } serde = { version = "1.0.209", features = ["derive"] }
tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros", "time"]} tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros", "time"]}
vapore-proto.path = "../proto" vapore-proto.path = "../proto"

View file

@ -1,14 +1,21 @@
use color_eyre::eyre; use base64::Engine;
use color_eyre::eyre::{self, Context, OptionExt};
use connection::CMSession; use connection::CMSession;
use message::CMProtoBufMessage; use message::CMProtoBufMessage;
use rand::RngCore; use rand::RngCore;
use vapore_proto::{ use vapore_proto::{
enums::ESessionPersistence,
enums_clientserver::EMsg, enums_clientserver::EMsg,
steammessages_auth_steamclient::{ steammessages_auth_steamclient::{
CAuthentication_BeginAuthSessionViaQR_Request, CAuthentication_BeginAuthSessionViaCredentials_Request,
CAuthentication_BeginAuthSessionViaQR_Response, CAuthentication_DeviceDetails, CAuthentication_BeginAuthSessionViaCredentials_Response, CAuthentication_DeviceDetails,
CAuthentication_GetPasswordRSAPublicKey_Request,
CAuthentication_GetPasswordRSAPublicKey_Response,
CAuthentication_PollAuthSessionStatus_Request, CAuthentication_PollAuthSessionStatus_Request,
CAuthentication_PollAuthSessionStatus_Response, EAuthTokenPlatformType, CAuthentication_PollAuthSessionStatus_Response,
CAuthentication_UpdateAuthSessionWithSteamGuardCode_Request,
CAuthentication_UpdateAuthSessionWithSteamGuardCode_Response, EAuthSessionGuardType,
EAuthTokenPlatformType,
}, },
steammessages_base::{cmsg_ipaddress, CMsgIPAddress}, steammessages_base::{cmsg_ipaddress, CMsgIPAddress},
steammessages_clientserver::CMsgClientLicenseList, steammessages_clientserver::CMsgClientLicenseList,
@ -64,10 +71,52 @@ pub async fn main() -> eyre::Result<()> {
// suitable end bytes // suitable end bytes
machine_id.extend_from_slice(b"\x08\x08"); machine_id.extend_from_slice(b"\x08\x08");
let response = session let username = dialoguer::Input::<String>::new()
.call_service_method::<_, CAuthentication_BeginAuthSessionViaQR_Response>( .with_prompt("Username")
"Authentication.BeginAuthSessionViaQR#1".to_string(), .interact_text()?;
CAuthentication_BeginAuthSessionViaQR_Request { let password = dialoguer::Password::new()
.with_prompt("Password")
.interact()?;
let password_key_response: CMProtoBufMessage<CAuthentication_GetPasswordRSAPublicKey_Response> =
session
.call_service_method(
"Authentication.GetPasswordRSAPublicKey#1".to_string(),
CAuthentication_GetPasswordRSAPublicKey_Request {
account_name: Some(username.clone()),
..Default::default()
},
)
.await?;
let password_key = rsa::RsaPublicKey::new(
rsa::BigUint::parse_bytes(password_key_response.body.publickey_mod().as_bytes(), 16)
.ok_or_eyre("Invalid RSA public modulus")?,
rsa::BigUint::parse_bytes(password_key_response.body.publickey_exp().as_bytes(), 16)
.ok_or_eyre("Invalid RSA public exponent")?,
)
.wrap_err("Invalid RSA public key")?;
let encrypted_password = password_key
.encrypt(
&mut rand::thread_rng(),
rsa::Pkcs1v15Encrypt,
&password.as_bytes(),
)
.wrap_err("Unable to encrypt password")?;
let auth_session_response = session
.call_service_method::<_, CAuthentication_BeginAuthSessionViaCredentials_Response>(
"Authentication.BeginAuthSessionViaCredentials#1".to_string(),
CAuthentication_BeginAuthSessionViaCredentials_Request {
account_name: Some(username.clone()),
encrypted_password: Some(
base64::engine::general_purpose::STANDARD.encode(&encrypted_password),
),
encryption_timestamp: password_key_response.body.timestamp,
persistence: Some(protobuf::EnumOrUnknown::new(
ESessionPersistence::k_ESessionPersistence_Ephemeral,
)),
device_details: protobuf::MessageField::some(CAuthentication_DeviceDetails { device_details: protobuf::MessageField::some(CAuthentication_DeviceDetails {
device_friendly_name: Some("vapore".to_string()), device_friendly_name: Some("vapore".to_string()),
platform_type: Some(protobuf::EnumOrUnknown::new( platform_type: Some(protobuf::EnumOrUnknown::new(
@ -83,16 +132,16 @@ pub async fn main() -> eyre::Result<()> {
) )
.await?; .await?;
log::debug!("Got response {:#x?}", response); log::debug!("Got response {:#x?}", auth_session_response);
let code = qrcode::QrCode::new(response.body.challenge_url()).unwrap(); if auth_session_response.header.eresult != Some(1) {
log::info!( eyre::bail!("Got bad resonse from BeginAuthSessionViaCredentials");
"Got new QR code:\n{}", };
code.render::<qrcode::render::unicode::Dense1x2>().build()
); // TODO: check allowed_confirmations
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs_f32( let mut interval = tokio::time::interval(tokio::time::Duration::from_secs_f32(
response.body.interval(), auth_session_response.body.interval(),
)); ));
let session_cloned = session.clone(); let session_cloned = session.clone();
@ -100,8 +149,8 @@ pub async fn main() -> eyre::Result<()> {
loop { loop {
interval.tick().await; interval.tick().await;
let request = CAuthentication_PollAuthSessionStatus_Request { let request = CAuthentication_PollAuthSessionStatus_Request {
client_id: response.body.client_id, client_id: auth_session_response.body.client_id,
request_id: response.body.request_id.clone(), request_id: auth_session_response.body.request_id.clone(),
..Default::default() ..Default::default()
}; };
let response: CMProtoBufMessage<CAuthentication_PollAuthSessionStatus_Response> = let response: CMProtoBufMessage<CAuthentication_PollAuthSessionStatus_Response> =
@ -130,6 +179,33 @@ pub async fn main() -> eyre::Result<()> {
} }
}); });
loop {
let guard_code = dialoguer::Input::<String>::new()
.with_prompt("Steam Guard Code")
.interact_text()?;
let update_response: CMProtoBufMessage<
CAuthentication_UpdateAuthSessionWithSteamGuardCode_Response,
> = session
.call_service_method(
"Authentication.UpdateAuthSessionWithSteamGuardCode#1".to_string(),
CAuthentication_UpdateAuthSessionWithSteamGuardCode_Request {
client_id: auth_session_response.body.client_id,
steamid: auth_session_response.body.steamid,
code: Some(guard_code),
code_type: Some(protobuf::EnumOrUnknown::new(
EAuthSessionGuardType::k_EAuthSessionGuardType_DeviceCode,
)),
..Default::default()
},
)
.await?;
if update_response.header.eresult == Some(1) {
break;
}
}
let (refresh_token, account_name) = poll_handle.await?; let (refresh_token, account_name) = poll_handle.await?;
log::debug!( log::debug!(