aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2020-09-06 16:04:10 +0200
committerShauren <shauren.trinity@gmail.com>2022-02-05 13:29:21 +0100
commite0e3bae82cfb6c70ba810997104054ab6ca77e99 (patch)
tree33c02a81521514ffe392e27dcccd13a49b0fcb69
parent3bf33628fc4833e8682f96c679982200fcbd1674 (diff)
Core/Authserver: Removal of sha_pass_hash, compatibility fields, and everything that uses them (PR #25156)
(cherry picked from commit bcdbdd6f23ce65cc0e381e61d2840140dce79311)
-rw-r--r--sql/base/auth_database.sql8
-rw-r--r--sql/updates/auth/master/2020_09_06_00_auth.sql8
-rw-r--r--src/common/Cryptography/Authentication/SRP6.cpp21
-rw-r--r--src/common/Cryptography/Authentication/SRP6.h6
-rw-r--r--src/server/bnetserver/Main.cpp2
-rw-r--r--src/server/bnetserver/Server/SessionManager.cpp71
-rw-r--r--src/server/bnetserver/Server/SessionManager.h2
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp7
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h1
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp23
10 files changed, 20 insertions, 129 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 098319b982c..d0388e6907b 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 unsigned NOT NULL AUTO_INCREMENT COMMENT 'Identifier',
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 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) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
- `v` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dummy value, use `verifier` instead',
- `s` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'dummy value, use `salt` instead',
`totp_secret` varbinary(128) DEFAULT NULL,
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`reg_mail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
@@ -2487,6 +2484,7 @@ INSERT INTO `updates` VALUES
('2020_08_11_00_auth.sql','14C99177E43003D83A4D6F2227722F15FC15A1D0','ARCHIVED','2020-08-11 00:00:00',0),
('2020_08_14_00_auth.sql','DFB9B07A7846FC0E124EE4CC099E49FE5742FB66','ARCHIVED','2020-08-14 21:41:24',0),
('2020_08_26_00_auth.sql','D5EF787DECB41D898379588F101A0453B46F04D9','ARCHIVED','2020-08-26 21:00:34',0),
+('2020_09_06_00_auth.sql','DC4B5D4C65EB138D5609F137799C3289B9CC2493','ARCHIVED','2020-09-06 00:00:00',0),
('2020_09_25_00_auth.sql','3CCA78EF89223724BA6784A4F3783DED30416637','ARCHIVED','2020-09-25 19:52:40',0),
('2020_10_20_00_auth.sql','1835C5EFD5816DEF914F27E867C8C8D5E08B3F68','ARCHIVED','2020-10-20 21:36:49',0),
('2020_12_06_00_auth.sql','FA254400D3D7D53E9C350EABFEABFF4EC3AD40DA','ARCHIVED','2020-12-06 20:25:10',0),
diff --git a/sql/updates/auth/master/2020_09_06_00_auth.sql b/sql/updates/auth/master/2020_09_06_00_auth.sql
new file mode 100644
index 00000000000..d04bdf6f4fe
--- /dev/null
+++ b/sql/updates/auth/master/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 4d96a28960d..a2266f35f71 100644
--- a/src/common/Cryptography/Authentication/SRP6.cpp
+++ b/src/common/Cryptography/Authentication/SRP6.cpp
@@ -42,24 +42,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 3c511d6f7f3..0f5a79803d6 100644
--- a/src/common/Cryptography/Authentication/SRP6.h
+++ b/src/common/Cryptography/Authentication/SRP6.h
@@ -43,11 +43,6 @@ namespace 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!
@@ -68,7 +63,6 @@ namespace 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/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp
index ad336565fbc..1062233dc7d 100644
--- a/src/server/bnetserver/Main.cpp
+++ b/src/server/bnetserver/Main.cpp
@@ -164,8 +164,6 @@ int main(int argc, char** argv)
sSecretMgr->Initialize(SECRET_OWNER_BNETSERVER);
- sSessionMgr.FixLegacyAuthHashes();
-
// Load IP Location Database
sIPLocation->Load();
diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp
index 9b074d3bcad..a0a0ff7aa47 100644
--- a/src/server/bnetserver/Server/SessionManager.cpp
+++ b/src/server/bnetserver/Server/SessionManager.cpp
@@ -16,7 +16,6 @@
*/
#include "SessionManager.h"
-#include "Config.h"
#include "DatabaseEnv.h"
#include "SRP6.h"
#include "Util.h"
@@ -31,76 +30,6 @@ bool Battlenet::SessionManager::StartNetwork(Trinity::Asio::IoContext& ioContext
return true;
}
-void Battlenet::SessionManager::FixLegacyAuthHashes()
-{
- TC_LOG_INFO("server.bnetserver", "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.bnetserver", ">> 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();
- std::pair<Trinity::Crypto::SRP6::Salt, Trinity::Crypto::SRP6::Verifier> registrationData = 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.bnetserver",
- " ========\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.bnetserver",
- " ========\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, registrationData.first);
- stmt->setBinary(1, registrationData.second);
- stmt->setUInt32(2, id);
- tx->Append(stmt);
-
- ++c;
- } while (result->NextRow());
- LoginDatabase.CommitTransaction(tx);
-
- TC_LOG_INFO("server.bnetserver", ">> %u password hashes updated in %u ms", c, GetMSTimeDiffToNow(start));
-}
-
NetworkThread<Battlenet::Session>* Battlenet::SessionManager::CreateThreads() const
{
return new NetworkThread<Session>[GetNetworkThreadCount()];
diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h
index ae0e714971a..f2c3c19fa64 100644
--- a/src/server/bnetserver/Server/SessionManager.h
+++ b/src/server/bnetserver/Server/SessionManager.h
@@ -32,8 +32,6 @@ namespace Battlenet
bool StartNetwork(Trinity::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int threadCount = 1) override;
- void FixLegacyAuthHashes();
-
protected:
NetworkThread<Session>* CreateThreads() const override;
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 199c298576a..b7612d841a7 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -36,8 +36,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION, "UPDATE account SET session_key_bnet = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, "SELECT username, session_key_bnet FROM account WHERE id = ? AND LENGTH(session_key_bnet) = 40", 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_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.session_key_bnet, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.SecurityLevel, "
@@ -79,8 +78,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 e83675bd394..4248e3f047b 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -40,7 +40,6 @@ enum LoginDatabaseStatements : uint32
LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION,
LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION,
LOGIN_UPD_LOGON,
- LOGIN_UPD_LOGON_LEGACY,
LOGIN_SEL_ACCOUNT_ID_BY_NAME,
LOGIN_SEL_ACCOUNT_LIST_BY_NAME,
LOGIN_SEL_ACCOUNT_INFO_BY_NAME,
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index bb7434a49f3..ce517bb470b 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -160,13 +160,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
@@ -198,14 +191,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;
}
@@ -235,14 +220,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;
}