TrinityCore
BattlenetAccountMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "BattlenetAccountMgr.h"
19#include "AccountMgr.h"
20#include "DatabaseEnv.h"
21#include "SRP6.h"
22#include "Util.h"
23
27
28enum class SrpVersion : int8
29{
30 v1 = 1, // password length limit 16 characters, case-insensitive, uses SHA256 to generate verifier
31 v2 = 2 // password length limit 128 characters, case-sensitive, uses PBKDF2 with SHA512 to generate verifier
32};
33
34AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, std::string password, bool withGameAccount, std::string* gameAccountName)
35{
36 if (utf8length(email) > MAX_BNET_EMAIL_STR)
38
39 if (utf8length(password) > MAX_BNET_PASS_STR)
41
43
44 if (GetId(email))
46
47 std::string srpUsername = GetSrpUsername(email);
48 auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<BnetSRP6>(srpUsername, password);
49
51 stmt->setString(0, email);
53 stmt->setBinary(2, salt);
54 stmt->setBinary(3, verifier);
55 LoginDatabase.DirectExecute(stmt);
56
57 uint32 newAccountId = GetId(email);
58 ASSERT(newAccountId);
59
60 if (withGameAccount)
61 {
62 *gameAccountName = std::to_string(newAccountId) + "#1";
63 std::string gameAccountPassword = password.substr(0, MAX_PASS_STR);
64 Utf8ToUpperOnlyLatin(gameAccountPassword);
65 GameAccountMgr::instance()->CreateAccount(*gameAccountName, gameAccountPassword, email, newAccountId, 1);
66 }
67
69}
70
72{
73 std::string username;
74 if (!GetName(accountId, username))
75 return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist
76
77 if (utf8length(newPassword) > MAX_BNET_PASS_STR)
79
80 std::string srpUsername = GetSrpUsername(username);
81 auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationData<BnetSRP6>(srpUsername, newPassword);
82
85 stmt->setBinary(1, salt);
86 stmt->setBinary(2, verifier);
87 stmt->setUInt32(3, accountId);
88 LoginDatabase.Execute(stmt);
89
91}
92
93bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password)
94{
95 std::string username;
96
97 if (!GetName(accountId, username))
98 return false;
99
101 stmt->setUInt32(0, accountId);
102
103 if (PreparedQueryResult result = LoginDatabase.Query(stmt))
104 {
105 Trinity::Crypto::SRP::Salt salt = (*result)[1].GetBinary<Trinity::Crypto::SRP::SALT_LENGTH>();
106 Trinity::Crypto::SRP::Verifier verifier = (*result)[2].GetBinary();
107 switch (SrpVersion((*result)[0].GetInt8()))
108 {
109 case SrpVersion::v1:
110 Utf8ToUpperOnlyLatin(password);
111 return BnetSRP6_OLD(username, salt, verifier).CheckCredentials(username, password);
112 case SrpVersion::v2:
113 return BnetSRP6(username, salt, verifier).CheckCredentials(username, password);
114 default:
115 break;
116 }
117 }
118
119 return false;
120}
121
122AccountOpResult Battlenet::AccountMgr::LinkWithGameAccount(std::string_view email, std::string_view gameAccountName)
123{
124 uint32 bnetAccountId = GetId(email);
125 if (!bnetAccountId)
127
128 uint32 gameAccountId = GameAccountMgr::GetId(gameAccountName);
129 if (!gameAccountId)
131
132 if (GetIdByGameAccount(gameAccountId))
134
136 stmt->setUInt32(0, bnetAccountId);
137 stmt->setUInt8(1, GetMaxIndex(bnetAccountId) + 1);
138 stmt->setUInt32(2, gameAccountId);
139 LoginDatabase.Execute(stmt);
141}
142
144{
145 uint32 gameAccountId = GameAccountMgr::GetId(gameAccountName);
146 if (!gameAccountId)
148
149 if (!GetIdByGameAccount(gameAccountId))
151
153 stmt->setNull(0);
154 stmt->setNull(1);
155 stmt->setUInt32(2, gameAccountId);
156 LoginDatabase.Execute(stmt);
158}
159
160uint32 Battlenet::AccountMgr::GetId(std::string_view username)
161{
163 stmt->setStringView(0, username);
164 if (PreparedQueryResult result = LoginDatabase.Query(stmt))
165 return (*result)[0].GetUInt32();
166
167 return 0;
168}
169
170bool Battlenet::AccountMgr::GetName(uint32 accountId, std::string& name)
171{
173 stmt->setUInt32(0, accountId);
174 if (PreparedQueryResult result = LoginDatabase.Query(stmt))
175 {
176 name = (*result)[0].GetString();
177 return true;
178 }
179
180 return false;
181}
182
184{
186 stmt->setUInt32(0, gameAccountId);
187 if (PreparedQueryResult result = LoginDatabase.Query(stmt))
188 return (*result)[0].GetUInt32();
189
190 return 0;
191}
192
194{
196 stmt->setUInt32(0, gameAccountId);
197 return LoginDatabase.AsyncQuery(stmt);
198}
199
201{
203 stmt->setUInt32(0, accountId);
204 PreparedQueryResult result = LoginDatabase.Query(stmt);
205 if (result)
206 return (*result)[0].GetUInt8();
207
208 return 0;
209}
210
211std::string Battlenet::AccountMgr::GetSrpUsername(std::string name)
212{
215}
#define MAX_PASS_STR
Definition: AccountMgr.h:42
AccountOpResult
Definition: AccountMgr.h:24
Trinity::Crypto::SRP::BnetSRP6v2< Trinity::Crypto::SHA256 > BnetSRP6
Trinity::Crypto::SRP::BnetSRP6v1< Trinity::Crypto::SHA256 > BnetSRP6_OLD
#define MAX_BNET_EMAIL_STR
#define MAX_BNET_PASS_STR
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
Definition: DatabaseEnv.cpp:22
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
@ LOGIN_UPD_BNET_GAME_ACCOUNT_LINK
@ LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL
@ LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT
@ LOGIN_UPD_BNET_LOGON
@ LOGIN_INS_BNET_ACCOUNT
@ LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX
@ LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID
@ LOGIN_SEL_BNET_CHECK_PASSWORD
bool Utf8ToUpperOnlyLatin(std::string &utf8String)
Definition: Util.cpp:795
size_t utf8length(std::string &utf8str)
Definition: Util.cpp:349
std::string ByteArrayToHexStr(Container const &c, bool reverse=false)
Definition: Util.h:368
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
AccountOpResult CreateAccount(std::string username, std::string password, std::string email="", uint32 bnetAccountId=0, uint8 bnetIndex=0)
Definition: AccountMgr.cpp:47
static AccountMgr * instance()
Definition: AccountMgr.cpp:41
static uint32 GetId(std::string_view username)
Definition: AccountMgr.cpp:289
void setStringView(const uint8 index, const std::string_view value)
void setUInt8(const uint8 index, const uint8 value)
void setBinary(const uint8 index, const std::vector< uint8 > &value)
void setUInt32(const uint8 index, const uint32 value)
void setNull(const uint8 index)
void setString(const uint8 index, const std::string &value)
void setInt8(const uint8 index, const int8 value)
static Digest GetDigestOf(uint8 const *data, size_t len)
Definition: CryptoHash.h:49
TC_GAME_API AccountOpResult LinkWithGameAccount(std::string_view email, std::string_view gameAccountName)
TC_GAME_API AccountOpResult ChangePassword(uint32 accountId, std::string newPassword)
TC_GAME_API uint8 GetMaxIndex(uint32 accountId)
TC_GAME_API QueryCallback GetIdByGameAccountAsync(uint32 gameAccountId)
TC_GAME_API AccountOpResult CreateBattlenetAccount(std::string email, std::string password, bool withGameAccount, std::string *gameAccountName)
TC_GAME_API uint32 GetId(std::string_view username)
TC_GAME_API uint32 GetIdByGameAccount(uint32 gameAccountId)
TC_GAME_API bool CheckPassword(uint32 accountId, std::string password)
TC_GAME_API AccountOpResult UnlinkGameAccount(std::string_view gameAccountName)
TC_GAME_API bool GetName(uint32 accountId, std::string &name)
TC_GAME_API std::string GetSrpUsername(std::string name)
std::array< uint8, SALT_LENGTH > Salt
Definition: SRP6.h:33
std::vector< uint8 > Verifier
Definition: SRP6.h:35
static constexpr size_t SALT_LENGTH
Definition: SRP6.h:32