From 760cec9d1eb1ca9ddc61a9e7d56bcf928a49a56a Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 3 Dec 2024 21:37:27 -0800 Subject: [PATCH] don't check auxiliary data on XB accounts; fixes #584 --- src/Account.cc | 44 ++++++++++++++++++++----------------------- src/Account.hh | 11 ++++------- src/CommandFormats.hh | 13 +++++++------ src/ServerShell.cc | 10 ++++++---- 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/Account.cc b/src/Account.cc index 4210c9e4..e6f081af 100644 --- a/src/Account.cc +++ b/src/Account.cc @@ -185,7 +185,7 @@ Account::Account(const phosg::JSON& json) lic->gamertag = xb_gamertag; lic->user_id = xb_user_id; lic->account_id = xb_account_id; - this->xb_licenses.emplace(lic->gamertag, lic); + this->xb_licenses.emplace(lic->user_id, lic); } if (!bb_username.empty() && !bb_password.empty()) { auto lic = make_shared(); @@ -214,7 +214,7 @@ Account::Account(const phosg::JSON& json) } for (const auto& it : json.get_list("XBLicenses")) { auto lic = XBLicense::from_json(*it); - this->xb_licenses.emplace(lic->gamertag, lic); + this->xb_licenses.emplace(lic->user_id, lic); } for (const auto& it : json.get_list("BBLicenses")) { auto lic = BBLicense::from_json(*it); @@ -660,14 +660,10 @@ shared_ptr AccountIndex::from_gc_credentials( } } -shared_ptr AccountIndex::from_xb_credentials_locked(const string& gamertag, uint64_t user_id, uint64_t account_id) { +shared_ptr AccountIndex::from_xb_credentials_locked(uint64_t user_id) { auto login = make_shared(); - login->account = this->by_xb_gamertag.at(gamertag); - login->xb_license = login->account->xb_licenses.at(gamertag); - if ((login->xb_license->user_id && (login->xb_license->user_id != user_id)) || - (login->xb_license->account_id && (login->xb_license->account_id != account_id))) { - throw incorrect_access_key(); - } + login->account = this->by_xb_user_id.at(user_id); + login->xb_license = login->account->xb_licenses.at(user_id); if (login->account->ban_end_time && (login->account->ban_end_time >= phosg::now())) { throw account_banned(); } @@ -682,13 +678,13 @@ shared_ptr AccountIndex::from_xb_credentials( try { shared_lock g(this->lock); - return this->from_xb_credentials_locked(gamertag, user_id, account_id); + return this->from_xb_credentials_locked(user_id); } catch (const out_of_range&) { } unique_lock g(this->lock); try { - return this->from_xb_credentials_locked(gamertag, user_id, account_id); + return this->from_xb_credentials_locked(user_id); } catch (const out_of_range&) { } @@ -701,7 +697,7 @@ shared_ptr AccountIndex::from_xb_credentials( lic->gamertag = gamertag; lic->user_id = user_id; lic->account_id = account_id; - login->account->xb_licenses.emplace(lic->gamertag, lic); + login->account->xb_licenses.emplace(lic->user_id, lic); login->xb_license = lic; this->add_locked(login->account); return login; @@ -798,8 +794,8 @@ void AccountIndex::add_locked(shared_ptr a) { } } for (const auto& it : a->xb_licenses) { - if (this->by_xb_gamertag.count(it.second->gamertag)) { - throw runtime_error("account already exists with this XB gamertag"); + if (this->by_xb_user_id.count(it.second->user_id)) { + throw runtime_error("account already exists with this XB user ID"); } } for (const auto& it : a->bb_licenses) { @@ -826,7 +822,7 @@ void AccountIndex::add_locked(shared_ptr a) { this->by_gc_serial_number[it.second->serial_number] = a; } for (const auto& it : a->xb_licenses) { - this->by_xb_gamertag[it.second->gamertag] = a; + this->by_xb_user_id[it.second->user_id] = a; } for (const auto& it : a->bb_licenses) { this->by_bb_username[it.second->username] = a; @@ -855,7 +851,7 @@ void AccountIndex::remove(uint32_t account_id) { this->by_gc_serial_number.erase(it.second->serial_number); } for (const auto& it : a->xb_licenses) { - this->by_xb_gamertag.erase(it.second->gamertag); + this->by_xb_user_id.erase(it.second->user_id); } for (const auto& it : a->bb_licenses) { this->by_bb_username.erase(it.second->username); @@ -903,12 +899,12 @@ void AccountIndex::add_gc_license(shared_ptr account, shared_ptr account, shared_ptr license) { - if (!this->by_xb_gamertag.emplace(license->gamertag, account).second) { - throw runtime_error("gamertag already registered"); + if (!this->by_xb_user_id.emplace(license->user_id, account).second) { + throw runtime_error("user ID already registered"); } - if (!account->xb_licenses.emplace(license->gamertag, license).second) { - this->by_xb_gamertag.erase(license->gamertag); - throw logic_error("gamertag registered in account but not in account index"); + if (!account->xb_licenses.emplace(license->user_id, license).second) { + this->by_xb_user_id.erase(license->user_id); + throw logic_error("user ID registered in account but not in account index"); } } @@ -966,12 +962,12 @@ void AccountIndex::remove_gc_license(shared_ptr account, uint32_t seria account->gc_licenses.erase(it); } -void AccountIndex::remove_xb_license(shared_ptr account, const string& gamertag) { - auto it = account->xb_licenses.find(gamertag); +void AccountIndex::remove_xb_license(shared_ptr account, uint64_t user_id) { + auto it = account->xb_licenses.find(user_id); if (it == account->xb_licenses.end()) { throw runtime_error("license not registered to account"); } - if (!this->by_xb_gamertag.erase(it->second->gamertag)) { + if (!this->by_xb_user_id.erase(it->second->user_id)) { throw runtime_error("license registered in account but not in account index"); } account->xb_licenses.erase(it); diff --git a/src/Account.hh b/src/Account.hh index 8413f5b0..976781f3 100644 --- a/src/Account.hh +++ b/src/Account.hh @@ -101,7 +101,7 @@ struct Account { std::unordered_map> dc_licenses; std::unordered_map> pc_licenses; std::unordered_map> gc_licenses; - std::unordered_map> xb_licenses; + std::unordered_map> xb_licenses; std::unordered_map> bb_licenses; Account() = default; @@ -202,7 +202,7 @@ public: void remove_dc_license(std::shared_ptr account, uint32_t serial_number); void remove_pc_license(std::shared_ptr account, uint32_t serial_number); void remove_gc_license(std::shared_ptr account, uint32_t serial_number); - void remove_xb_license(std::shared_ptr account, const std::string& gamertag); + void remove_xb_license(std::shared_ptr account, uint64_t user_id); void remove_bb_license(std::shared_ptr account, const std::string& username); std::shared_ptr from_account_id(uint32_t account_id) const; @@ -253,7 +253,7 @@ protected: std::unordered_map> by_dc_serial_number; std::unordered_map> by_pc_serial_number; std::unordered_map> by_gc_serial_number; - std::unordered_map> by_xb_gamertag; + std::unordered_map> by_xb_user_id; std::unordered_map> by_bb_username; void add_locked(std::shared_ptr a); @@ -274,10 +274,7 @@ protected: const std::string& access_key, const std::string* password, const std::string& character_name); - std::shared_ptr from_xb_credentials_locked( - const std::string& gamertag, - uint64_t user_id, - uint64_t account_id); + std::shared_ptr from_xb_credentials_locked(uint64_t user_id); std::shared_ptr from_bb_credentials_locked( const std::string& username, const std::string* password); diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 93a4ed9a..72747113 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -1962,12 +1962,13 @@ struct C_LoginExtended_GC_9E : C_Login_GC_9E { } __packed_ws__(C_LoginExtended_GC_9E, 0x14C); struct C_Login_XB_9E : C_Login_DC_PC_GC_9D { - parray unused; - XBNetworkLocation netloc; - parray unknown_a1a; - le_uint32_t xb_user_id_high = 0; - le_uint32_t xb_user_id_low = 0; - le_uint32_t unknown_a1b = 0; + /* 00C8 */ parray unused; + /* 00E8 */ XBNetworkLocation netloc; + /* 0118 */ parray unknown_a1a; + /* 0124 */ le_uint32_t xb_user_id_high = 0; + /* 0128 */ le_uint32_t xb_user_id_low = 0; + /* 012C */ le_uint32_t unknown_a1b = 0; + /* 0130 */ } __packed_ws__(C_Login_XB_9E, 0x130); struct C_LoginExtended_XB_9E : C_Login_XB_9E { diff --git a/src/ServerShell.cc b/src/ServerShell.cc index 4a92cf71..e2742308 100644 --- a/src/ServerShell.cc +++ b/src/ServerShell.cc @@ -656,14 +656,16 @@ CommandDefinition c_delete_license( meanings as for add-license. PRIMARY-CREDENTIAL is the first credential\n\ for the license type; specifically:\n\ DC-NTE: PRIMARY-CREDENTIAL is the serial number\n\ - DC: PRIMARY-CREDENTIAL is the serial number (hex)\n\ - PC: PRIMARY-CREDENTIAL is the serial number (hex)\n\ + DC: PRIMARY-CREDENTIAL is the serial number (8 hex digits)\n\ + PC: PRIMARY-CREDENTIAL is the serial number (8 hex digits)\n\ GC: PRIMARY-CREDENTIAL is the serial number (decimal)\n\ - XB: PRIMARY-CREDENTIAL is the gamertag\n\ + XB: PRIMARY-CREDENTIAL is the user ID (16 hex digits)\n\ BB: PRIMARY-CREDENTIAL is the username\n\ Examples (deleting licenses from account 385A92C4):\n\ delete-license 385A92C4 DC 107862F9\n\ + delete-license 385A92C4 PC 2F94C303\n\ delete-license 385A92C4 GC 0418572923\n\ + delete-license 385A92C4 XB 7E29A2950019EB20\n\ delete-license 385A92C4 BB user1", true, +[](CommandArgs& args) { @@ -684,7 +686,7 @@ CommandDefinition c_delete_license( } else if (type_str == "GC") { args.s->account_index->remove_gc_license(account, stoul(tokens[2], nullptr, 0)); } else if (type_str == "XB") { - args.s->account_index->remove_xb_license(account, tokens[2]); + args.s->account_index->remove_xb_license(account, stoull(tokens[2], nullptr, 16)); } else if (type_str == "BB") { args.s->account_index->remove_bb_license(account, tokens[2]); } else {