From 2fc2a0ac1ef954675ba6f42e40fa431dbaba582a Mon Sep 17 00:00:00 2001 From: Maple Date: Sun, 12 Apr 2026 18:56:08 +0200 Subject: [PATCH] implement nintendo_create_account --- rnex-core/src/grpc/account.rs | 36 +++++++++++++++++++ rnex-core/src/nex/friends_handler.rs | 30 ++++++++++++++++ .../src/rmc/protocols/account_management.rs | 13 ++++++- rnex-core/src/rmc/protocols/friends.rs | 6 ++-- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/rnex-core/src/grpc/account.rs b/rnex-core/src/grpc/account.rs index 64be4e9..d6ad140 100644 --- a/rnex-core/src/grpc/account.rs +++ b/rnex-core/src/grpc/account.rs @@ -103,6 +103,42 @@ impl Client { Ok(val.as_bytes().try_into().map_err(|_| SomethingHappened)?) } + pub async fn get_pid_from_token(&mut self, token: String) -> Result { + let req = self + .do_request(object! { + "query": + r"query($token: String!){ + token(tokenData: $token){ + pid + } + }", + "variables": { + "token": token + } + }) + .await?; + // this breaks switch nex servers and should be fixed eventually + let Some(val) = req + .entries() + .find(|v| v.0 == "data") + .ok_or(SomethingHappened)? + .1 + .entries() + .find(|v| v.0 == "token") + .ok_or(SomethingHappened)? + .1 + .entries() + .find(|v| v.0 == "pid") + .ok_or(SomethingHappened)? + .1 + .as_u32() + else { + return Err(SomethingHappened); + }; + + Ok(val) + } + /*pub async fn get_user_data(&mut self , pid: u32) -> Result{ let req = Request::new(GetUserDataRequest{ pid diff --git a/rnex-core/src/nex/friends_handler.rs b/rnex-core/src/nex/friends_handler.rs index 36d08dc..42e5c71 100644 --- a/rnex-core/src/nex/friends_handler.rs +++ b/rnex-core/src/nex/friends_handler.rs @@ -1,5 +1,8 @@ +use std::io::{Cursor, Write}; use std::sync::{Arc, atomic::AtomicU32}; +use bytemuck::bytes_of; +use hmac::Mac; use log::info; use macros::rmc_struct; use rnex_core::rmc::protocols::account_management::{ @@ -27,6 +30,9 @@ use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo}; use rnex_core::PID; +use crate::rmc::protocols::account_management::NintendoCreateAccountData; +use rnex_core::rmc::structures::RmcSerialize; + define_rmc_proto!( proto FriendsUser{ Secure, @@ -153,6 +159,8 @@ impl Friends for FriendsUser { } } +type HMacMd5 = hmac::Hmac; + impl Secure for FriendsUser { async fn register( &self, @@ -213,6 +221,28 @@ impl AccountManagement for FriendsGuest { auth_data: Any, ) -> Result<(PID, String), ErrorCode> { println!("{}, {}, {}, {}", principal_name, key, groups, email); + if auth_data.name == "NintendoCreateAccountData" { + let Ok(data) = + NintendoCreateAccountData::deserialize(&mut Cursor::new(&auth_data.data)) + else { + return Err(ErrorCode::Authentication_InvalidParam); + }; + + let pid = data.nna_info.principal_basic_info.pid; + info!("create account: {}", pid); + + let Ok(mut mac) = HMacMd5::new_from_slice(key.as_bytes()) else { + return Err(ErrorCode::Authentication_InvalidParam); + }; + + mac.write_all(bytes_of(&pid)) + .expect("failed to write to hmac???"); + let mac = mac.finalize().into_bytes(); + + let hex_str = hex::encode(mac); + + return Ok((pid, hex_str)); + } Err(ErrorCode::Core_NotImplemented) } } diff --git a/rnex-core/src/rmc/protocols/account_management.rs b/rnex-core/src/rmc/protocols/account_management.rs index 64bd3bc..8ef2d9e 100644 --- a/rnex-core/src/rmc/protocols/account_management.rs +++ b/rnex-core/src/rmc/protocols/account_management.rs @@ -1,10 +1,21 @@ -use macros::{method_id, rmc_proto}; +use macros::{RmcSerialize, method_id, rmc_proto}; use rnex_core::{ PID, rmc::{response::ErrorCode, structures::any::Any}, }; +use crate::{kerberos::KerberosDateTime, rmc::protocols::friends::NNAInfo}; + +#[derive(RmcSerialize, Debug, Clone)] +#[rmc_struct(0)] +pub struct NintendoCreateAccountData { + pub nna_info: NNAInfo, + pub nex_token: String, + pub birthday: KerberosDateTime, + pub unk: u64, +} + #[rmc_proto(25)] pub trait AccountManagement { #[method_id(27)] diff --git a/rnex-core/src/rmc/protocols/friends.rs b/rnex-core/src/rmc/protocols/friends.rs index 07dcd1a..3f6138f 100644 --- a/rnex-core/src/rmc/protocols/friends.rs +++ b/rnex-core/src/rmc/protocols/friends.rs @@ -2,7 +2,7 @@ use macros::{RmcSerialize, method_id, rmc_proto}; use rnex_core::{kerberos::KerberosDateTime, rmc::response::ErrorCode}; -#[derive(RmcSerialize)] +#[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(0)] pub struct MiiV2 { pub name: String, @@ -12,7 +12,7 @@ pub struct MiiV2 { pub date_time: KerberosDateTime, } -#[derive(RmcSerialize)] +#[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(0)] pub struct PrincipalBasicInfo { pub pid: u32, @@ -21,7 +21,7 @@ pub struct PrincipalBasicInfo { pub unk: u8, } -#[derive(RmcSerialize)] +#[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(0)] pub struct NNAInfo { pub principal_basic_info: PrincipalBasicInfo,