diff options
Diffstat (limited to 'src/server/game/Accounts')
-rw-r--r-- | src/server/game/Accounts/AccountMgr.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Accounts/BattlenetAccountMgr.cpp | 76 | ||||
-rw-r--r-- | src/server/game/Accounts/BattlenetAccountMgr.h | 3 |
3 files changed, 67 insertions, 44 deletions
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 0229dd686b4..113e81153ba 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -29,6 +29,8 @@ #include "World.h" #include "WorldSession.h" +using AccountSRP6 = Trinity::Crypto::SRP::GruntSRP6; + AccountMgr::AccountMgr() { } AccountMgr::~AccountMgr() @@ -60,9 +62,9 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT); stmt->setString(0, username); - std::pair<Trinity::Crypto::SRP6::Salt, Trinity::Crypto::SRP6::Verifier> registrationData = Trinity::Crypto::SRP6::MakeRegistrationData(username, password); - stmt->setBinary(1, registrationData.first); - stmt->setBinary(2, registrationData.second); + auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<AccountSRP6>(username, password); + stmt->setBinary(1, salt); + stmt->setBinary(2, verifier); stmt->setString(3, email); stmt->setString(4, email); @@ -184,10 +186,10 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); - std::pair<Trinity::Crypto::SRP6::Salt, Trinity::Crypto::SRP6::Verifier> registrationData = Trinity::Crypto::SRP6::MakeRegistrationData(newUsername, newPassword); + auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<AccountSRP6>(newUsername, newPassword); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->setBinary(0, registrationData.first); - stmt->setBinary(1, registrationData.second); + stmt->setBinary(0, salt); + stmt->setBinary(1, verifier); stmt->setUInt32(2, accountId); LoginDatabase.Execute(stmt); @@ -212,11 +214,11 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(newPassword); - std::pair<Trinity::Crypto::SRP6::Salt, Trinity::Crypto::SRP6::Verifier> registrationData = Trinity::Crypto::SRP6::MakeRegistrationData(username, newPassword); + auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<AccountSRP6>(username, newPassword); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->setBinary(0, registrationData.first); - stmt->setBinary(1, registrationData.second); + stmt->setBinary(0, salt); + stmt->setBinary(1, verifier); stmt->setUInt32(2, accountId); LoginDatabase.Execute(stmt); @@ -354,9 +356,9 @@ bool AccountMgr::CheckPassword(std::string username, std::string password) if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { - Trinity::Crypto::SRP6::Salt salt = (*result)[0].GetBinary<Trinity::Crypto::SRP6::SALT_LENGTH>(); - Trinity::Crypto::SRP6::Verifier verifier = (*result)[1].GetBinary<Trinity::Crypto::SRP6::VERIFIER_LENGTH>(); - if (Trinity::Crypto::SRP6::CheckLogin(username, password, salt, verifier)) + Trinity::Crypto::SRP::Salt salt = (*result)[0].GetBinary<Trinity::Crypto::SRP::SALT_LENGTH>(); + Trinity::Crypto::SRP::Verifier verifier = (*result)[1].GetBinary(); + if (AccountSRP6(username, salt, verifier).CheckCredentials(username, password)) return true; } @@ -378,9 +380,9 @@ bool AccountMgr::CheckPassword(uint32 accountId, std::string password) if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { - Trinity::Crypto::SRP6::Salt salt = (*result)[0].GetBinary<Trinity::Crypto::SRP6::SALT_LENGTH>(); - Trinity::Crypto::SRP6::Verifier verifier = (*result)[1].GetBinary<Trinity::Crypto::SRP6::VERIFIER_LENGTH>(); - if (Trinity::Crypto::SRP6::CheckLogin(username, password, salt, verifier)) + Trinity::Crypto::SRP::Salt salt = (*result)[0].GetBinary<Trinity::Crypto::SRP::SALT_LENGTH>(); + Trinity::Crypto::SRP::Verifier verifier = (*result)[1].GetBinary(); + if (AccountSRP6(username, salt, verifier).CheckCredentials(username, password)) return true; } diff --git a/src/server/game/Accounts/BattlenetAccountMgr.cpp b/src/server/game/Accounts/BattlenetAccountMgr.cpp index 08a807b8db6..8b57ac71093 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.cpp +++ b/src/server/game/Accounts/BattlenetAccountMgr.cpp @@ -17,29 +17,41 @@ #include "BattlenetAccountMgr.h" #include "AccountMgr.h" -#include "CryptoHash.h" #include "DatabaseEnv.h" +#include "SRP6.h" #include "Util.h" using GameAccountMgr = AccountMgr; +using BnetSRP6_OLD = Trinity::Crypto::SRP::BnetSRP6v1<Trinity::Crypto::SHA256>; +using BnetSRP6 = Trinity::Crypto::SRP::BnetSRP6v2<Trinity::Crypto::SHA256>; + +enum class SrpVersion : int8 +{ + v1 = 1, // password length limit 16 characters, case-insensitive, uses SHA256 to generate verifier + v2 = 2 // password length limit 128 characters, case-sensitive, uses PBKDF2 with SHA512 to generate verifier +}; AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, std::string password, bool withGameAccount, std::string* gameAccountName) { if (utf8length(email) > MAX_BNET_EMAIL_STR) return AccountOpResult::AOR_NAME_TOO_LONG; - if (utf8length(password) > MAX_PASS_STR) + if (utf8length(password) > MAX_BNET_PASS_STR) return AccountOpResult::AOR_PASS_TOO_LONG; Utf8ToUpperOnlyLatin(email); - Utf8ToUpperOnlyLatin(password); if (GetId(email)) return AccountOpResult::AOR_NAME_ALREADY_EXIST; + std::string srpUsername = GetSrpUsername(email); + auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<BnetSRP6>(srpUsername, password); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT); stmt->setString(0, email); - stmt->setString(1, CalculateShaPassHash(email, password)); + stmt->setInt8(1, AsUnderlyingType(SrpVersion::v2)); + stmt->setBinary(2, salt); + stmt->setBinary(3, verifier); LoginDatabase.DirectExecute(stmt); uint32 newAccountId = GetId(email); @@ -48,7 +60,9 @@ AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, if (withGameAccount) { *gameAccountName = std::to_string(newAccountId) + "#1"; - GameAccountMgr::instance()->CreateAccount(*gameAccountName, password, email, newAccountId, 1); + std::string gameAccountPassword = password.substr(0, MAX_PASS_STR); + Utf8ToUpperOnlyLatin(gameAccountPassword); + GameAccountMgr::instance()->CreateAccount(*gameAccountName, gameAccountPassword, email, newAccountId, 1); } return AccountOpResult::AOR_OK; @@ -60,14 +74,17 @@ AccountOpResult Battlenet::AccountMgr::ChangePassword(uint32 accountId, std::str if (!GetName(accountId, username)) return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(newPassword); - if (utf8length(newPassword) > MAX_PASS_STR) + if (utf8length(newPassword) > MAX_BNET_PASS_STR) return AccountOpResult::AOR_PASS_TOO_LONG; - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_PASSWORD); - stmt->setString(0, CalculateShaPassHash(username, newPassword)); - stmt->setUInt32(1, accountId); + std::string srpUsername = GetSrpUsername(username); + auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<BnetSRP6>(srpUsername, newPassword); + + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LOGON); + stmt->setInt8(0, AsUnderlyingType(SrpVersion::v2)); + stmt->setBinary(1, salt); + stmt->setBinary(2, verifier); + stmt->setUInt32(3, accountId); LoginDatabase.Execute(stmt); return AccountOpResult::AOR_OK; @@ -80,14 +97,26 @@ bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password if (!GetName(accountId, username)) return false; - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(password); - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD); stmt->setUInt32(0, accountId); - stmt->setString(1, CalculateShaPassHash(username, password)); - return LoginDatabase.Query(stmt) != nullptr; + if (PreparedQueryResult result = LoginDatabase.Query(stmt)) + { + Trinity::Crypto::SRP::Salt salt = (*result)[1].GetBinary<Trinity::Crypto::SRP::SALT_LENGTH>(); + Trinity::Crypto::SRP::Verifier verifier = (*result)[2].GetBinary(); + switch (SrpVersion((*result)[0].GetInt8())) + { + case SrpVersion::v1: + Utf8ToUpperOnlyLatin(password); + return BnetSRP6_OLD(username, salt, verifier).CheckCredentials(username, password); + case SrpVersion::v2: + return BnetSRP6(username, salt, verifier).CheckCredentials(username, password); + default: + break; + } + } + + return false; } AccountOpResult Battlenet::AccountMgr::LinkWithGameAccount(std::string_view email, std::string_view gameAccountName) @@ -179,17 +208,8 @@ uint8 Battlenet::AccountMgr::GetMaxIndex(uint32 accountId) return 0; } -std::string Battlenet::AccountMgr::CalculateShaPassHash(std::string_view name, std::string_view password) +std::string Battlenet::AccountMgr::GetSrpUsername(std::string name) { - Trinity::Crypto::SHA256 email; - email.UpdateData(name); - email.Finalize(); - - Trinity::Crypto::SHA256 sha; - sha.UpdateData(ByteArrayToHexStr(email.GetDigest())); - sha.UpdateData(":"); - sha.UpdateData(password); - sha.Finalize(); - - return ByteArrayToHexStr(sha.GetDigest(), true); + Utf8ToUpperOnlyLatin(name); + return ByteArrayToHexStr(Trinity::Crypto::SHA256::GetDigestOf(name)); } diff --git a/src/server/game/Accounts/BattlenetAccountMgr.h b/src/server/game/Accounts/BattlenetAccountMgr.h index bfeb02302f7..b4fe7626b42 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.h +++ b/src/server/game/Accounts/BattlenetAccountMgr.h @@ -25,6 +25,7 @@ class QueryCallback; enum class AccountOpResult : uint8; #define MAX_BNET_EMAIL_STR 320 +#define MAX_BNET_PASS_STR 128 namespace Battlenet { @@ -42,7 +43,7 @@ namespace Battlenet [[nodiscard]] TC_GAME_API QueryCallback GetIdByGameAccountAsync(uint32 gameAccountId); TC_GAME_API uint8 GetMaxIndex(uint32 accountId); - TC_GAME_API std::string CalculateShaPassHash(std::string_view name, std::string_view password); + TC_GAME_API std::string GetSrpUsername(std::string name); } } |