AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword) { // Check if accounts exists PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_ID); stmt->setUInt32(0, accountId); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) return AccountOpResult::AOR_NAME_NOT_EXIST; if (utf8length(newUsername) > MAX_ACCOUNT_STR) return AccountOpResult::AOR_NAME_TOO_LONG; if (utf8length(newPassword) > MAX_PASS_STR) return AccountOpResult::AOR_PASS_TOO_LONG; Utf8ToUpperOnlyLatin(newUsername); Utf8ToUpperOnlyLatin(newPassword); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_USERNAME); stmt->setString(0, newUsername); stmt->setString(1, CalculateShaPassHash(newUsername, newPassword)); stmt->setUInt32(2, accountId); LoginDatabase.Execute(stmt); return AccountOpResult::AOR_OK; }
AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/) { if (utf8length(username) > MAX_ACCOUNT_STR) return AccountOpResult::AOR_NAME_TOO_LONG; // username's too long Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(password); Utf8ToUpperOnlyLatin(email); if (GetId(username)) return AccountOpResult::AOR_NAME_ALREADY_EXIST; // username does already exist PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT); stmt->setString(0, username); stmt->setString(1, CalculateShaPassHash(username, password)); stmt->setString(2, email); stmt->setString(3, email); LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT); LoginDatabase.Execute(stmt); return AccountOpResult::AOR_OK; // everything's fine }
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) return AccountOpResult::AOR_PASS_TOO_LONG; Utf8ToUpperOnlyLatin(email); Utf8ToUpperOnlyLatin(password); if (GetId(email)) return AccountOpResult::AOR_NAME_ALREADY_EXIST; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT); stmt->setString(0, email); stmt->setString(1, CalculateShaPassHash(email, password)); LoginDatabase.DirectExecute(stmt); uint32 newAccountId = GetId(email); ASSERT(newAccountId); if (withGameAccount) { *gameAccountName = std::to_string(newAccountId) + "#1"; GameAccountMgr::instance()->CreateAccount(*gameAccountName, password, email, newAccountId, 1); } return AccountOpResult::AOR_OK; }
AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmail) { std::string username; if (!GetName(accountId, username)) return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist if (utf8length(newEmail) > MAX_EMAIL_STR) { sScriptMgr->OnFailedEmailChange(accountId); return AccountOpResult::AOR_EMAIL_TOO_LONG; } Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(newEmail); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_REG_EMAIL); stmt->setString(0, newEmail); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); sScriptMgr->OnEmailChange(accountId); return AccountOpResult::AOR_OK; }
int RASocket::check_password(const std::string& user, const std::string& pass) { std::string safe_user = user; Utf8ToUpperOnlyLatin(safe_user); std::string safe_pass = pass; Utf8ToUpperOnlyLatin(safe_pass); std::string hash = AccountMgr::CalculateShaPassHash(safe_user, safe_pass); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME); stmt->setString(0, safe_user); stmt->setString(1, hash); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { TC_LOG_INFO("commands.ra", "Wrong password for user: %s", user.c_str()); return -1; } return 0; }
static bool HandleBanInfoAccountCommand(ChatHandler* handler, char const* args) { if (!*args) return false; char* nameStr = strtok((char*)args, ""); if (!nameStr) return false; std::string accountName = nameStr; if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 accountId = AccountMgr::GetId(accountName); if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); return true; } return HandleBanInfoHelper(accountId, accountName.c_str(), handler); }
bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password) { std::string username; if (!GetName(accountId, username)) return false; Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(password); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD); stmt->setUInt32(0, accountId); stmt->setString(1, CalculateShaPassHash(username, password)); return LoginDatabase.Query(stmt) != nullptr; }
void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) { if (_queryCallback) { Authentication::ResumeResponse* logonResponse = new Authentication::ResumeResponse(); logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::ResumeRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str()); return; } std::string login = resumeRequest.Login; _locale = resumeRequest.Locale; _os = resumeRequest.Platform; auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; }); if (baseComponent != resumeRequest.Components.end()) _build = baseComponent->Build; Utf8ToUpperOnlyLatin(login); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); stmt->setString(0, login); stmt->setString(1, resumeRequest.GameAccountName); _queryCallback = std::bind(&Battlenet::Session::HandleResumeRequestCallback, this, std::placeholders::_1); _queryFuture = LoginDatabase.AsyncQuery(stmt); }
int RASocket::check_access_level(const std::string& user) { std::string safeUser = user; Utf8ToUpperOnlyLatin(safeUser); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS); stmt->setString(0, safeUser); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { TC_LOG_INFO("commands.ra", "User %s does not exist in database", user.c_str()); return -1; } Field* fields = result->Fetch(); if (fields[1].GetUInt8() < _minLevel) { TC_LOG_INFO("commands.ra", "User %s has no privilege to login", user.c_str()); return -1; } else if (fields[2].GetInt32() != -1) { TC_LOG_INFO("commands.ra", "User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str()); return -1; } return 0; }
/// Set password for account static bool HandleAccountSetPasswordCommand(ChatHandler* handler, char const* args) { if (!*args) { handler->SendSysMessage(LANG_CMD_SYNTAX); handler->SetSentErrorMessage(true); return false; } ///- Get the command line arguments char* account = strtok((char*)args, " "); char* password = strtok(NULL, " "); char* passwordConfirmation = strtok(NULL, " "); if (!account || !password || !passwordConfirmation) return false; std::string accountName = account; if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 targetAccountId = Battlenet::AccountMgr::GetId(accountName); if (!targetAccountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } if (strcmp(password, passwordConfirmation)) { handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); handler->SetSentErrorMessage(true); return false; } AccountOpResult result = Battlenet::AccountMgr::ChangePassword(targetAccountId, password); switch (result) { case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); break; case AccountOpResult::AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; case AccountOpResult::AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); handler->SetSentErrorMessage(true); return false; default: break; } return true; }
bool AccountMgr::CheckEmail(uint32 accountId, std::string newEmail) { std::string oldEmail; // We simply return false for a non-existing email if (!GetEmail(accountId, oldEmail)) return false; Utf8ToUpperOnlyLatin(oldEmail); Utf8ToUpperOnlyLatin(newEmail); if (strcmp(oldEmail.c_str(), newEmail.c_str()) == 0) return true; return false; }
AccountOpResult Battlenet::AccountMgr::ChangePassword(uint32 accountId, std::string newPassword) { std::string username; if (!GetName(accountId, username)) return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(newPassword); if (utf8length(newPassword) > MAX_PASS_STR) return AccountOpResult::AOR_PASS_TOO_LONG; PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_PASSWORD); stmt->setString(0, CalculateShaPassHash(username, newPassword)); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); return AccountOpResult::AOR_OK; }
AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPassword) { std::string username; if (!GetName(accountId, username)) { sScriptMgr->OnFailedPasswordChange(accountId); return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist } if (utf8length(newPassword) > MAX_ACCOUNT_STR) { sScriptMgr->OnFailedPasswordChange(accountId); return AccountOpResult::AOR_PASS_TOO_LONG; } Utf8ToUpperOnlyLatin(username); Utf8ToUpperOnlyLatin(newPassword); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_PASSWORD); stmt->setString(0, CalculateShaPassHash(username, newPassword)); stmt->setUInt32(1, accountId); LoginDatabase.Execute(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS); stmt->setString(0, ""); stmt->setString(1, ""); stmt->setString(2, username); LoginDatabase.Execute(stmt); sScriptMgr->OnPasswordChange(accountId); return AccountOpResult::AOR_OK; }
void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) { _accountName = resumeRequest.Login; _locale = resumeRequest.Locale; _os = resumeRequest.Platform; auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; }); if (baseComponent != resumeRequest.Components.end()) _build = baseComponent->Build; Utf8ToUpperOnlyLatin(_accountName); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); stmt->setString(0, _accountName); stmt->setString(1, resumeRequest.GameAccountName); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(resumeResponse); return; } Field* fields = result->Fetch(); _accountId = fields[0].GetUInt32(); K.SetHexStr(fields[1].GetString().c_str()); _gameAccountId = fields[2].GetUInt32(); _gameAccountName = resumeRequest.GameAccountName; ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 0; _reconnectProof.SetRand(16 * 8); resumeData.WriteBytes(&state, 1); resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16); resume->DataSize = resumeData.GetSize(); resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); _modulesWaitingForData.push(MODULE_RESUME); Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); proofRequest->Modules.push_back(thumbprint); proofRequest->Modules.push_back(resume); AsyncWrite(proofRequest); }
static bool HandleUnBanHelper(BanMode mode, char const* args, ChatHandler* handler) { if (!*args) return false; char* nameOrIPStr = strtok((char*)args, " "); if (!nameOrIPStr) return false; std::string nameOrIP = nameOrIPStr; switch (mode) { case BAN_ACCOUNT: if (!Utf8ToUpperOnlyLatin(nameOrIP)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str()); handler->SetSentErrorMessage(true); return false; } break; case BAN_CHARACTER: if (!normalizePlayerName(nameOrIP)) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); handler->SetSentErrorMessage(true); return false; } break; case BAN_IP: if (!IsIPAddress(nameOrIP.c_str())) return false; break; } if (sWorld->RemoveBanAccount(mode, nameOrIP)) handler->PSendSysMessage(LANG_UNBAN_UNBANNED, nameOrIP.c_str()); else handler->PSendSysMessage(LANG_UNBAN_ERROR, nameOrIP.c_str()); return true; }
void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest const& logonRequest) { if (_queryCallback) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str()); return; } if (logonRequest.Program != "WoW") { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Program.c_str()); return; } if (!sComponentMgr->HasPlatform(logonRequest.Platform)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_OS); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Platform.c_str()); return; } if (!sComponentMgr->HasPlatform(logonRequest.Locale)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Locale.c_str()); return; } for (Component const& component : logonRequest.Components) { if (!sComponentMgr->HasComponent(&component)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (!sComponentMgr->HasProgram(component.Program)) { logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.Program.c_str()); } else if (!sComponentMgr->HasPlatform(component.Platform)) { logonResponse->SetAuthResult(AUTH_INVALID_OS); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Platform.c_str()); } else { if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION); else logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Build); } AsyncWrite(logonResponse); return; } if (component.Platform == "base") _build = component.Build; } std::string login = logonRequest.Login; _locale = logonRequest.Locale; _os = logonRequest.Platform; Utf8ToUpperOnlyLatin(login); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); stmt->setString(0, login); _queryCallback = std::bind(&Battlenet::Session::HandleLogonRequestCallback, this, std::placeholders::_1); _queryFuture = LoginDatabase.AsyncQuery(stmt); }
static bool HandlePDumpLoadCommand(ChatHandler* handler, char const* args) { if (!*args) return false; char* fileStr = strtok((char*)args, " "); if (!fileStr) return false; char* accountStr = strtok(NULL, " "); if (!accountStr) return false; std::string accountName = accountStr; if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } uint32 accountId = AccountMgr::GetId(accountName); if (!accountId) { accountId = atoi(accountStr); // use original string if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } } if (!AccountMgr::GetName(accountId, accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; } char* guidStr = NULL; char* nameStr = strtok(NULL, " "); std::string name; if (nameStr) { name = nameStr; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME); handler->SetSentErrorMessage(true); return false; } if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME); handler->SetSentErrorMessage(true); return false; } guidStr = strtok(NULL, " "); } ObjectGuid::LowType guid = UI64LIT(0); if (guidStr) { guid = strtoull(guidStr, nullptr, 10); if (!guid) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_GUID); handler->SetSentErrorMessage(true); return false; } if (ObjectMgr::GetPlayerAccountIdByGUID(ObjectGuid::Create<HighGuid::Player>(guid))) { handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, guid); handler->SetSentErrorMessage(true); return false; } } switch (PlayerDumpReader().LoadDump(fileStr, accountId, name, guid)) { case DUMP_SUCCESS: handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS); break; case DUMP_FILE_OPEN_ERROR: handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileStr); handler->SetSentErrorMessage(true); return false; case DUMP_FILE_BROKEN: handler->PSendSysMessage(LANG_DUMP_BROKEN, fileStr); handler->SetSentErrorMessage(true); return false; case DUMP_TOO_MANY_CHARS: handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName.c_str(), accountId); handler->SetSentErrorMessage(true); return false; default: handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED); handler->SetSentErrorMessage(true); return false; } return true; }
static RBACCommandData* ReadParams(ChatHandler* handler, char const* args, bool checkParams = true) { if (!args) return NULL; char* param1 = strtok((char*)args, " "); char* param2 = strtok(NULL, " "); char* param3 = strtok(NULL, " "); int32 realmId = -1; uint32 accountId = 0; std::string accountName; uint32 id = 0; RBACCommandData* data = NULL; rbac::RBACData* rdata = NULL; bool useSelectedPlayer = false; if (checkParams) { if (!param3) { if (param2) realmId = atoi(param2); if (param1) id = atoi(param1); useSelectedPlayer = true; } else { id = atoi(param2); realmId = atoi(param3); } if (!id) { handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, id); handler->SetSentErrorMessage(true); return NULL; } if (realmId < -1 || !realmId) { handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_REALM, realmId); handler->SetSentErrorMessage(true); return NULL; } } else if (!param1) useSelectedPlayer = true; if (useSelectedPlayer) { Player* player = handler->getSelectedPlayer(); if (!player) return NULL; rdata = player->GetSession()->GetRBACData(); accountId = rdata->GetId(); AccountMgr::GetName(accountId, accountName); } else { accountName = param1; if (Utf8ToUpperOnlyLatin(accountName)) accountId = AccountMgr::GetId(accountName); if (!accountId) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return NULL; } } if (checkParams && handler->HasLowerSecurityAccount(NULL, accountId, true)) return NULL; data = new RBACCommandData(); if (!rdata) { data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID)); data->rbac->LoadFromDB(); data->needDelete = true; } else data->rbac = rdata; data->id = id; data->realmId = realmId; return data; }
static bool HandleBanHelper(BanMode mode, char const* args, ChatHandler* handler) { if (!*args) return false; char* cnameOrIP = strtok((char*)args, " "); if (!cnameOrIP) return false; std::string nameOrIP = cnameOrIP; char* durationStr = strtok(NULL, " "); if (!durationStr || !atoi(durationStr)) return false; char* reasonStr = strtok(NULL, ""); if (!reasonStr) return false; switch (mode) { case BAN_ACCOUNT: if (!Utf8ToUpperOnlyLatin(nameOrIP)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str()); handler->SetSentErrorMessage(true); return false; } break; case BAN_CHARACTER: if (!normalizePlayerName(nameOrIP)) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); handler->SetSentErrorMessage(true); return false; } break; case BAN_IP: if (!IsIPAddress(nameOrIP.c_str())) return false; break; } std::string author = handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Server"; switch (sWorld->BanAccount(mode, nameOrIP, durationStr, reasonStr, author)) { case BAN_SUCCESS: if (atoi(durationStr) > 0) { if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) sWorld->SendWorldText(LANG_BAN_ACCOUNT_YOUBANNEDMESSAGE_WORLD, author.c_str(), nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); else handler->PSendSysMessage(LANG_BAN_YOUBANNED, nameOrIP.c_str(), secsToTimeString(TimeStringToSecs(durationStr), true).c_str(), reasonStr); } else { if (sWorld->getBoolConfig(CONFIG_SHOW_BAN_IN_WORLD)) sWorld->SendWorldText(LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD, author.c_str(), nameOrIP.c_str(), reasonStr); else handler->PSendSysMessage(LANG_BAN_YOUPERMBANNED, nameOrIP.c_str(), reasonStr); } break; case BAN_SYNTAX_ERROR: return false; case BAN_NOTFOUND: switch (mode) { default: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "account", nameOrIP.c_str()); break; case BAN_CHARACTER: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "character", nameOrIP.c_str()); break; case BAN_IP: handler->PSendSysMessage(LANG_BAN_NOTFOUND, "ip", nameOrIP.c_str()); break; } handler->SetSentErrorMessage(true); return false; } return true; }
void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& logonRequest) { // Verify that this IP is not in the ip_banned table LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); std::string ip_address = GetRemoteIpAddress().to_string(); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_BANNED); stmt->setString(0, ip_address); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(LOGIN_BANNED); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Banned ip '%s:%d' tries to login!", ip_address.c_str(), GetRemotePort()); return; } if (logonRequest.Program != "WoW") { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Program.c_str()); return; } if (!sComponentMgr->HasPlatform(logonRequest.Platform)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_OS); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Platform.c_str()); return; } if (!sComponentMgr->HasPlatform(logonRequest.Locale)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Locale.c_str()); return; } for (Component const& component : logonRequest.Components) { if (!sComponentMgr->HasComponent(&component)) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (!sComponentMgr->HasProgram(component.Program)) { logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.Program.c_str()); } else if (!sComponentMgr->HasPlatform(component.Platform)) { logonResponse->SetAuthResult(AUTH_INVALID_OS); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Platform.c_str()); } else { if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION); else logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Build); } AsyncWrite(logonResponse); return; } if (component.Platform == "base") _build = component.Build; } _accountName = logonRequest.Login; _locale = logonRequest.Locale; _os = logonRequest.Platform; Utf8ToUpperOnlyLatin(_accountName); stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); stmt->setString(0, _accountName); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is trying to log in from unknown account!", GetClientInfo().c_str()); return; } Field* fields = result->Fetch(); _accountId = fields[1].GetUInt32(); // If the IP is 'locked', check that the player comes indeed from the correct IP address if (fields[2].GetUInt8() == 1) // if ip is locked { TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to IP - '%s' is logging in from '%s'", _accountName.c_str(), fields[4].GetCString(), ip_address.c_str()); if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); AsyncWrite(logonResponse); return; } } else { TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to ip", _accountName.c_str()); std::string accountCountry = fields[3].GetString(); if (accountCountry.empty() || accountCountry == "00") TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is not locked to country", _accountName.c_str()); else if (!accountCountry.empty()) { uint32 ip = inet_addr(ip_address.c_str()); EndianConvertReverse(ip); stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGON_COUNTRY); stmt->setUInt32(0, ip); if (PreparedQueryResult sessionCountryQuery = LoginDatabase.Query(stmt)) { std::string loginCountry = (*sessionCountryQuery)[0].GetString(); TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] Account '%s' is locked to country: '%s' Player country is '%s'", _accountName.c_str(), accountCountry.c_str(), loginCountry.c_str()); if (loginCountry != accountCountry) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_ACCOUNT_LOCKED); AsyncWrite(logonResponse); return; } } } } //set expired bans to inactive LoginDatabase.DirectExecute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_BNET_EXPIRED_BANS)); // If the account is banned, reject the logon attempt stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN); stmt->setUInt32(0, _accountId); PreparedQueryResult banresult = LoginDatabase.Query(stmt); if (banresult) { Field* fields = banresult->Fetch(); if (fields[0].GetUInt32() == fields[1].GetUInt32()) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(LOGIN_BANNED); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); return; } else { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(LOGIN_SUSPENDED); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "'%s:%d' [Battlenet::LogonRequest] Temporarily banned account %s tried to login!", ip_address.c_str(), GetRemotePort(), _accountName.c_str()); return; } } SHA256Hash sha; sha.UpdateData(_accountName); sha.Finalize(); I.SetBinary(sha.GetDigest(), sha.GetLength()); ModuleInfo* password = sModuleMgr->CreateModule(_os, "Password"); ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); std::string pStr = fields[0].GetString(); std::string databaseV = fields[5].GetString(); std::string databaseS = fields[6].GetString(); if (databaseV.size() != size_t(BufferSizes::SRP_6_V) * 2 || databaseS.size() != size_t(BufferSizes::SRP_6_S) * 2) _SetVSFields(pStr); else { s.SetHexStr(databaseS.c_str()); v.SetHexStr(databaseV.c_str()); } b.SetRand(128 * 8); B = ((v * k) + g.ModExp(b, N)) % N; BigNumber unk; unk.SetRand(128 * 8); BitStream passwordData; uint8 state = 0; passwordData.WriteBytes(&state, 1); passwordData.WriteBytes(I.AsByteArray(32).get(), 32); passwordData.WriteBytes(s.AsByteArray(32).get(), 32); passwordData.WriteBytes(B.AsByteArray(128).get(), 128); passwordData.WriteBytes(unk.AsByteArray(128).get(), 128); password->DataSize = passwordData.GetSize(); password->Data = new uint8[password->DataSize]; memcpy(password->Data, passwordData.GetBuffer(), password->DataSize); _modulesWaitingForData.push(MODULE_PASSWORD); Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); proofRequest->Modules.push_back(password); // if has authenticator, send Token module proofRequest->Modules.push_back(thumbprint); AsyncWrite(proofRequest); }
int32 LoginRESTService::HandlePost(soap* soapClient) { boost::asio::ip::address_v4 address(soapClient->ip); std::string ip_address = address.to_string(); TC_LOG_DEBUG("server.rest", "[%s:%d] Handling POST request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path); static std::string const expectedPath = "/bnetserver/login/"; if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0]) return 404; char *buf; size_t len; soap_http_body(soapClient, &buf, &len); Battlenet::JSON::Login::LoginForm loginForm; Battlenet::JSON::Login::LoginResult loginResult; if (!JSON::Deserialize(buf, &loginForm)) { if (soap_register_plugin_arg(soapClient, &ResponseCodePlugin::Init, nullptr) != SOAP_OK) return 500; ResponseCodePlugin* responseCode = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(soapClient, ResponseCodePlugin::PluginId)); ASSERT(responseCode); responseCode->ErrorCode = 400; loginResult.set_authentication_state(Battlenet::JSON::Login::LOGIN); loginResult.set_error_code("UNABLE_TO_DECODE"); loginResult.set_error_message("There was an internal error while connecting to Battle.net. Please try again later."); return SendResponse(soapClient, loginResult); } std::string login; std::string password; for (int32 i = 0; i < loginForm.inputs_size(); ++i) { if (loginForm.inputs(i).input_id() == "account_name") login = loginForm.inputs(i).value(); else if (loginForm.inputs(i).input_id() == "password") password = loginForm.inputs(i).value(); } Utf8ToUpperOnlyLatin(login); Utf8ToUpperOnlyLatin(password); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); stmt->setString(0, login); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { std::string pass_hash = result->Fetch()[13].GetString(); std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = Trinity::make_unique<Battlenet::Session::AccountInfo>(); accountInfo->LoadResult(result); if (CalculateShaPassHash(login, std::move(password)) == pass_hash) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID); stmt->setUInt32(0, accountInfo->Id); if (PreparedQueryResult characterCountsResult = LoginDatabase.Query(stmt)) { do { Field* fields = characterCountsResult->Fetch(); accountInfo->GameAccounts[fields[0].GetUInt32()] .CharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8(); } while (characterCountsResult->NextRow()); } stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS); stmt->setUInt32(0, accountInfo->Id); if (PreparedQueryResult lastPlayerCharactersResult = LoginDatabase.Query(stmt)) { Field* fields = lastPlayerCharactersResult->Fetch(); Battlenet::RealmHandle realmId{ fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt32() }; Battlenet::Session::LastPlayedCharacterInfo& lastPlayedCharacter = accountInfo->GameAccounts[fields[0].GetUInt32()] .LastPlayedCharacters[realmId.GetSubRegionAddress()]; lastPlayedCharacter.RealmId = realmId; lastPlayedCharacter.CharacterName = fields[4].GetString(); lastPlayedCharacter.CharacterGUID = fields[5].GetUInt64(); lastPlayedCharacter.LastPlayedTime = fields[6].GetUInt32(); } BigNumber ticket; ticket.SetRand(20 * 8); loginResult.set_login_ticket("TC-" + ByteArrayToHexStr(ticket.AsByteArray(20).get(), 20)); AddLoginTicket(loginResult.login_ticket(), std::move(accountInfo)); } else if (!accountInfo->IsBanned) { uint32 maxWrongPassword = uint32(sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0)); if (sConfigMgr->GetBoolDefault("WrongPass.Logging", false)) TC_LOG_DEBUG("server.rest", "[%s, Account %s, Id %u] Attempted to connect with wrong password!", ip_address.c_str(), login.c_str(), accountInfo->Id); if (maxWrongPassword) { SQLTransaction trans = LoginDatabase.BeginTransaction(); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS); stmt->setUInt32(0, accountInfo->Id); trans->Append(stmt); ++accountInfo->FailedLogins; TC_LOG_DEBUG("server.rest", "MaxWrongPass : %u, failed_login : %u", maxWrongPassword, accountInfo->Id); if (accountInfo->FailedLogins >= maxWrongPassword) { BanMode banType = BanMode(sConfigMgr->GetIntDefault("WrongPass.BanType", uint16(BanMode::BAN_IP))); int32 banTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600); if (banType == BanMode::BAN_ACCOUNT) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT_AUTO_BANNED); stmt->setUInt32(0, accountInfo->Id); } else { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED); stmt->setString(0, ip_address); } stmt->setUInt32(1, banTime); trans->Append(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_RESET_FAILED_LOGINS); stmt->setUInt32(0, accountInfo->Id); trans->Append(stmt); } LoginDatabase.CommitTransaction(trans); } } } loginResult.set_authentication_state(Battlenet::JSON::Login::DONE); return SendResponse(soapClient, loginResult); }