diff options
-rw-r--r-- | sql/base/auth_database.sql | 12 | ||||
-rw-r--r-- | sql/updates/auth/3.3.5/2020_09_06_00_auth.sql | 8 | ||||
-rw-r--r-- | src/common/Cryptography/Authentication/SRP6.cpp | 21 | ||||
-rw-r--r-- | src/common/Cryptography/Authentication/SRP6.h | 6 | ||||
-rw-r--r-- | src/server/authserver/Main.cpp | 2 | ||||
-rw-r--r-- | src/server/authserver/Server/AuthSession.cpp | 124 | ||||
-rw-r--r-- | src/server/authserver/Server/AuthSession.h | 1 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/LoginDatabase.cpp | 9 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/LoginDatabase.h | 1 | ||||
-rw-r--r-- | src/server/game/Accounts/AccountMgr.cpp | 23 |
10 files changed, 30 insertions, 177 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 62dd06db112..06ae7646c24 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -25,13 +25,10 @@ DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Identifier', `username` varchar(32) NOT NULL DEFAULT '', - `salt` binary(32) DEFAULT NULL, - `verifier` binary(32) DEFAULT NULL, + `salt` binary(32) NOT NULL, + `verifier` binary(32) NOT NULL, `session_key_auth` binary(40) DEFAULT NULL, `session_key_bnet` varbinary(64) DEFAULT NULL, - `sha_pass_hash` varchar(40) NOT NULL DEFAULT '', - `v` varchar(64) NOT NULL DEFAULT 'dummy value, use `verifier` instead', - `s` varchar(64) NOT NULL DEFAULT 'dummy value, use `salt` instead', `totp_secret` varbinary(128) DEFAULT NULL, `email` varchar(255) NOT NULL DEFAULT '', `reg_mail` varchar(255) NOT NULL DEFAULT '', @@ -1972,8 +1969,9 @@ INSERT INTO `updates` VALUES ('2020_08_03_00_auth.sql','492CA77C0FAEEEF3E0492121B3A92689373ECFA3','ARCHIVED','2020-08-03 00:00:00',0), ('2020_08_03_01_auth.sql','EC1063396CA20A2303D83238470D41EF4439EC72','ARCHIVED','2020-08-03 00:00:01',0), ('2020_08_11_00_auth.sql','14C99177E43003D83A4D6F2227722F15FC15A1D0','ARCHIVED','2020-08-11 00:00:00',0), -('2020_08_15_00_auth.sql','A49F4A776E1583B1FF63DFE99BC0E0DD97A74674','ARCHIVED','2020-08-15 09:34:44',0), -('2020_08_22_00_auth.sql','060A87FCC8F836A96D9D55BEDC32CBAD05008B4C','ARCHIVED','2020-08-22 16:27:26',0); +('2020_08_15_00_auth.sql','A49F4A776E1583B1FF63DFE99BC0E0DD97A74674','ARCHIVED','2020-08-15 00:00:00',0), +('2020_08_22_00_auth.sql','060A87FCC8F836A96D9D55BEDC32CBAD05008B4C','RELEASED','2020-08-22 00:00:00',0), +('2020_09_06_00_auth.sql','DC4B5D4C65EB138D5609F137799C3289B9CC2493','RELEASED','2020-09-06 00:00:00',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/3.3.5/2020_09_06_00_auth.sql b/sql/updates/auth/3.3.5/2020_09_06_00_auth.sql new file mode 100644 index 00000000000..d04bdf6f4fe --- /dev/null +++ b/sql/updates/auth/3.3.5/2020_09_06_00_auth.sql @@ -0,0 +1,8 @@ +-- +UPDATE `account` SET `salt`=UNHEX(CONCAT(MD5(RAND()),MD5(RAND()))), `verifier`=UNHEX(CONCAT(MD5(RAND()),MD5(RAND()))) WHERE `salt` IS NULL OR `verifier` IS NULL; +ALTER TABLE `account` + DROP COLUMN `s`, + DROP COLUMN `v`, + DROP COLUMN `sha_pass_hash`, + MODIFY COLUMN `salt` BINARY(32) NOT NULL, + MODIFY COLUMN `verifier` BINARY(32) NOT NULL; diff --git a/src/common/Cryptography/Authentication/SRP6.cpp b/src/common/Cryptography/Authentication/SRP6.cpp index 11125a3211b..daaa1155869 100644 --- a/src/common/Cryptography/Authentication/SRP6.cpp +++ b/src/common/Cryptography/Authentication/SRP6.cpp @@ -37,24 +37,15 @@ using SRP6 = Trinity::Crypto::SRP6; return res; } -/*static*/ std::pair<SRP6::Salt, SRP6::Verifier> SRP6::MakeRegistrationDataFromHash_DEPRECATED_DONOTUSE(SHA1::Digest const& hash) -{ - std::pair<SRP6::Salt, SRP6::Verifier> res; - Crypto::GetRandomBytes(res.first); - res.second = CalculateVerifierFromHash(hash, res.first); - return res; -} - /*static*/ SRP6::Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, SRP6::Salt const& salt) { // v = g ^ H(s || H(u || ':' || p)) mod N - return CalculateVerifierFromHash(SHA1::GetDigestOf(username, ":", password), salt); -} - -// merge this into CalculateVerifier once the sha_pass hack finally gets nuked from orbit -/*static*/ SRP6::Verifier SRP6::CalculateVerifierFromHash(SHA1::Digest const& hash, SRP6::Salt const& salt) -{ - return _g.ModExp(SHA1::GetDigestOf(salt, hash), _N).ToByteArray<32>(); + return _g.ModExp( + SHA1::GetDigestOf( + salt, + SHA1::GetDigestOf(username, ":", password) + ) + ,_N).ToByteArray<32>(); } /*static*/ SessionKey SRP6::SHA1Interleave(SRP6::EphemeralKey const& S) diff --git a/src/common/Cryptography/Authentication/SRP6.h b/src/common/Cryptography/Authentication/SRP6.h index ab4dfc56889..7014c26607e 100644 --- a/src/common/Cryptography/Authentication/SRP6.h +++ b/src/common/Cryptography/Authentication/SRP6.h @@ -41,11 +41,6 @@ namespace Trinity::Crypto static std::array<uint8, 1> const g; static std::array<uint8, 32> const N; - // this is the old sha_pass_hash hack - // YOU SHOULD NEVER STORE THIS HASH, if you do you are breaking SRP6 guarantees - // use MakeRegistrationData instead - static std::pair<Salt, Verifier> MakeRegistrationDataFromHash_DEPRECATED_DONOTUSE(SHA1::Digest const& hash); - // username + password must be passed through Utf8ToUpperOnlyLatin FIRST! static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password); // username + password must be passed through Utf8ToUpperOnlyLatin FIRST! @@ -66,7 +61,6 @@ namespace Trinity::Crypto bool _used = false; // a single instance can only be used to verify once static Verifier CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt); - static Verifier CalculateVerifierFromHash(SHA1::Digest const& hash, Salt const& salt); static SessionKey SHA1Interleave(EphemeralKey const& S); /* global algorithm parameters */ diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index f5566355a3d..7a6a5037676 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -143,8 +143,6 @@ int main(int argc, char** argv) sSecretMgr->Initialize(); - AuthSession::ServerStartup(); - // Load IP Location Database sIPLocation->Load(); diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index b8e498c3a26..0acfa47db1e 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -121,76 +121,6 @@ std::array<uint8, 16> VersionChallenge = { { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B, #define AUTH_LOGON_CHALLENGE_INITIAL_SIZE 4 #define REALM_LIST_PACKET_SIZE 5 -/*static*/ void AuthSession::ServerStartup() -{ - TC_LOG_INFO("server.authserver", "Updating password hashes..."); - uint32 const start = getMSTime(); - // the auth update query nulls salt/verifier if they cannot be converted - // if they are non-null but s/v have been cleared, that means a legacy tool touched our auth DB (otherwise, the core might've done it itself, it used to use those hacks too) - QueryResult result = LoginDatabase.Query("SELECT id, sha_pass_hash, IF((salt IS null) AND (verifier IS null), 0, 1) AS shouldWarn FROM account WHERE s != DEFAULT(s) OR v != DEFAULT(v) OR salt IS NULL OR verifier IS NULL"); - if (!result) - { - TC_LOG_INFO("server.authserver", ">> No password hashes to update - this took us %u ms to realize", GetMSTimeDiffToNow(start)); - return; - } - - bool const shouldUpdate = sConfigMgr->GetBoolDefault("AllowDeprecatedExternalPasswords", false, true); - bool hadWarning = false; - uint32 c = 0; - LoginDatabaseTransaction tx = LoginDatabase.BeginTransaction(); - do - { - uint32 const id = (*result)[0].GetUInt32(); - auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationDataFromHash_DEPRECATED_DONOTUSE( - HexStrToByteArray<Trinity::Crypto::SHA1::DIGEST_LENGTH>((*result)[1].GetString()) - ); - - if ((*result)[2].GetInt64()) - { - if (!hadWarning) - { - hadWarning = true; - if (shouldUpdate) - { - TC_LOG_WARN("server.authserver", - " ========\n" - "(!) You appear to be using an outdated external account management tool.\n" - "(!!) This is INSECURE, has been deprecated, and will cease to function entirely on September 6, 2020.\n" - "(!) Update your external tool.\n" - "(!!) If no update is available, refer your tool's developer to https://github.com/TrinityCore/TrinityCore/issues/25157.\n" - " ========"); - } - else - { - TC_LOG_ERROR("server.authserver", - " ========\n" - "(!) You appear to be using an outdated external account management tool.\n" - "(!!) This is INSECURE, and the account(s) in question will not be able to log in.\n" - "(!) Update your external tool.\n" - "(!!) If no update is available, refer your tool's developer to https://github.com/TrinityCore/TrinityCore/issues/25157.\n" - "(!) You can override this behavior by adding \"AllowDeprecatedExternalPasswords = 1\" to your authserver.conf file.\n" - "(!!) Note that this override will cease to function entirely on September 6, 2020.\n" - " ========"); - } - } - - if (!shouldUpdate) - continue; - } - - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->setBinary(0, salt); - stmt->setBinary(1, verifier); - stmt->setUInt32(2, id); - tx->Append(stmt); - - ++c; - } while (result->NextRow()); - LoginDatabase.CommitTransaction(tx); - - TC_LOG_INFO("server.authserver", ">> %u password hashes updated in %u ms", c, GetMSTimeDiffToNow(start)); -} - std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers() { std::unordered_map<uint8, AuthHandler> handlers; @@ -210,8 +140,8 @@ void AccountInfo::LoadResult(Field* fields) { // 0 1 2 3 4 5 6 //SELECT a.id, a.username, a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, - // 7 8 9 10 11 12 - // ab.unbandate = ab.bandate, aa.SecurityLevel, a.totp_secret, a.sha_pass_hash, a.v, a.s + // 7 8 + // ab.unbandate = ab.bandate, aa.SecurityLevel (, more query-specific fields) //FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ? Id = fields[0].GetUInt32(); @@ -467,51 +397,11 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result) } } - if (!fields[10].IsNull()) - { - if (!sConfigMgr->GetBoolDefault("AllowDeprecatedExternalPasswords", false, true)) - { - TC_LOG_ERROR("server.authserver", - " ========\n" - "(!) You appear to be using an outdated external account management tool.\n" - "(!!) This is INSECURE, and the login attempt from account '%s' was BLOCKED.\n" - "(!) Update your external tool.\n" - "(!!) If no update is available, refer your tool's developer to https://github.com/TrinityCore/TrinityCore/issues/25157.\n" - "(!) You can override this behavior by adding \"AllowDeprecatedExternalPasswords = 1\" to your authserver.conf file.\n" - "(!!) Note that this override will cease to function entirely on September 6, 2020.\n" - " ========", _accountInfo.Login.c_str()); - - pkt << uint8(WOW_FAIL_UNLOCKABLE_LOCK); - SendPacket(pkt); - return; - } - - // if this is reached, s/v were reset and we need to recalculate from sha_pass_hash - Trinity::Crypto::SHA1::Digest sha_pass_hash; - HexStrToByteArray(fields[10].GetString(), sha_pass_hash); - auto [salt, verifier] = Trinity::Crypto::SRP6::MakeRegistrationDataFromHash_DEPRECATED_DONOTUSE(sha_pass_hash); - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON); - stmt->setBinary(0, salt); - stmt->setBinary(1, verifier); - stmt->setUInt32(2, _accountInfo.Id); - LoginDatabase.Execute(stmt); - - TC_LOG_WARN("server.authserver", - " ========\n" - "(!) You appear to be using an outdated external account management tool.\n" - "(!!) This is INSECURE, has been deprecated, and will cease to function entirely on September 6, 2020.\n" - "(!) Update your external tool.\n" - "(!!) If no update is available, refer your tool's developer to https://github.com/TrinityCore/TrinityCore/issues/25157.\n" - " ========"); - - _srp6.emplace(_accountInfo.Login, salt, verifier); - } - else - { - Trinity::Crypto::SRP6::Salt salt = fields[11].GetBinary<Trinity::Crypto::SRP6::SALT_LENGTH>(); - Trinity::Crypto::SRP6::Verifier verifier = fields[12].GetBinary<Trinity::Crypto::SRP6::VERIFIER_LENGTH>(); - _srp6.emplace(_accountInfo.Login, salt, verifier); - } + _srp6.emplace( + _accountInfo.Login, + fields[10].GetBinary<Trinity::Crypto::SRP6::SALT_LENGTH>(), + fields[11].GetBinary<Trinity::Crypto::SRP6::VERIFIER_LENGTH>() + ); // Fill the response packet with the result if (AuthHelper::IsAcceptedClientBuild(_build)) diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 47973d0ff1d..9982399bcbc 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -65,7 +65,6 @@ class AuthSession : public Socket<AuthSession> typedef Socket<AuthSession> AuthSocket; public: - static void ServerStartup(); static std::unordered_map<uint8, AuthHandler> InitHandlers(); AuthSession(tcp::socket&& socket); diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 737d9c4a8f3..f0745584d7b 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp @@ -35,11 +35,10 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username = ? GROUP BY account.id", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned (id, bandate, unbandate, bannedby, banreason, active) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity Auth', 'Failed login autoban', 1)", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ?, s = DEFAULT, v = DEFAULT WHERE id = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_UPD_LOGON_LEGACY, "UPDATE account SET sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET session_key_auth = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.id, a.username, a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, " - "ab.unbandate = ab.bandate, aa.SecurityLevel, a.totp_secret, IF(a.s != DEFAULT(a.s) OR a.v != DEFAULT(a.v) OR a.salt IS NULL OR a.verifier IS NULL, a.sha_pass_hash, NULL), a.salt, a.verifier " + "ab.unbandate = ab.bandate, aa.SecurityLevel, a.totp_secret, a.salt, a.verifier " "FROM account a LEFT JOIN account_access aa ON a.id = aa.AccountID LEFT JOIN account_banned ab ON ab.id = a.id AND ab.active = 1 WHERE a.username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_RECONNECTCHALLENGE, "SELECT a.id, UPPER(a.username), a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, " "ab.unbandate = ab.bandate, aa.SecurityLevel, a.session_key_auth " @@ -84,8 +83,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1) ORDER BY RealmID DESC", CONNECTION_BOTH); PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.SecurityLevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.AccountID AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.SecurityLevel FROM account a, account_access aa WHERE a.id = aa.AccountID AND aa.SecurityLevel >= ? AND (aa.RealmID = -1 OR aa.RealmID = ?)", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index 28eae7180ae..1986fb78850 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -39,7 +39,6 @@ enum LoginDatabaseStatements : uint32 LOGIN_INS_ACCOUNT_AUTO_BANNED, LOGIN_DEL_ACCOUNT_BANNED, LOGIN_UPD_LOGON, - LOGIN_UPD_LOGON_LEGACY, LOGIN_UPD_LOGONPROOF, LOGIN_SEL_LOGONCHALLENGE, LOGIN_SEL_RECONNECTCHALLENGE, diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 244e463563d..ba54cf686d5 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -149,13 +149,6 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accountId) return AccountOpResult::AOR_OK; } -// Do not use this. Use the appropriate methods on Trinity::Crypto::SRP6 to do whatever you are trying to do. -// See issue #25157. -static std::string CalculateShaPassHash_DEPRECATED_DONOTUSE(std::string const& name, std::string const& password) -{ - return ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(name, ":", password)); -} - AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword) { // Check if accounts exists @@ -187,14 +180,6 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser stmt->setUInt32(2, accountId); LoginDatabase.Execute(stmt); - if (sWorld->getBoolConfig(CONFIG_SET_SHAPASSHASH)) - { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON_LEGACY); - stmt->setString(0, CalculateShaPassHash_DEPRECATED_DONOTUSE(newUsername, newPassword)); - stmt->setUInt32(1, accountId); - LoginDatabase.Execute(stmt); - } - return AccountOpResult::AOR_OK; } @@ -224,14 +209,6 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass stmt->setUInt32(2, accountId);; LoginDatabase.Execute(stmt); - if (sWorld->getBoolConfig(CONFIG_SET_SHAPASSHASH)) - { - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGON_LEGACY); - stmt->setString(0, CalculateShaPassHash_DEPRECATED_DONOTUSE(username, newPassword)); - stmt->setUInt32(1, accountId); - LoginDatabase.Execute(stmt); - } - sScriptMgr->OnPasswordChange(accountId); return AccountOpResult::AOR_OK; } |