diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/authserver/Server/AuthSession.cpp | 175 | ||||
| -rw-r--r-- | src/server/authserver/Server/AuthSession.h | 7 | ||||
| -rw-r--r-- | src/server/database/Updater/UpdateFetcher.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/Accounts/AccountMgr.cpp | 11 | ||||
| -rw-r--r-- | src/server/game/Scripting/ScriptReloadMgr.cpp | 5 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 3 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 49 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.h | 2 | ||||
| -rw-r--r-- | src/server/game/Warden/Warden.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Warden/Warden.h | 11 | ||||
| -rw-r--r-- | src/server/game/Warden/WardenCheckMgr.cpp | 22 | ||||
| -rw-r--r-- | src/server/game/Warden/WardenMac.cpp | 28 | ||||
| -rw-r--r-- | src/server/game/Warden/WardenMac.h | 6 | ||||
| -rw-r--r-- | src/server/game/Warden/WardenWin.cpp | 45 | ||||
| -rw-r--r-- | src/server/game/Warden/WardenWin.h | 4 | ||||
| -rw-r--r-- | src/server/scripts/Commands/cs_account.cpp | 4 | ||||
| -rw-r--r-- | src/server/shared/Packets/ByteBuffer.h | 13 | ||||
| -rw-r--r-- | src/server/shared/Secrets/SecretMgr.cpp | 4 |
19 files changed, 173 insertions, 228 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 748d2145a23..c1f4703ea47 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -20,13 +20,14 @@ #include "AuthCodes.h" #include "Config.h" #include "CryptoGenerics.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "Errors.h" +#include "CryptoHash.h" #include "IPLocation.h" #include "Log.h" #include "RealmList.h" #include "SecretMgr.h" -#include "SHA1.h" #include "TOTP.h" #include "Util.h" #include <boost/lexical_cast.hpp> @@ -74,8 +75,7 @@ typedef struct AUTH_LOGON_PROOF_C { uint8 cmd; uint8 A[32]; - uint8 M1[20]; - uint8 crc_hash[20]; + Trinity::Crypto::SHA1::Digest M1, crc_hash; uint8 number_of_keys; uint8 securityFlags; } sAuthLogonProof_C; @@ -85,7 +85,7 @@ typedef struct AUTH_LOGON_PROOF_S { uint8 cmd; uint8 error; - uint8 M2[20]; + Trinity::Crypto::SHA1::Digest M2; uint32 AccountFlags; uint32 SurveyId; uint16 LoginFlags; @@ -96,7 +96,7 @@ typedef struct AUTH_LOGON_PROOF_S_OLD { uint8 cmd; uint8 error; - uint8 M2[20]; + Trinity::Crypto::SHA1::Digest M2; uint32 unk2; } sAuthLogonProof_S_Old; static_assert(sizeof(sAuthLogonProof_S_Old) == (1 + 1 + 20 + 4)); @@ -105,8 +105,7 @@ typedef struct AUTH_RECONNECT_PROOF_C { uint8 cmd; uint8 R1[16]; - uint8 R2[20]; - uint8 R3[20]; + Trinity::Crypto::SHA1::Digest R2, R3; uint8 number_of_keys; } sAuthReconnectProof_C; static_assert(sizeof(sAuthReconnectProof_C) == (1 + 16 + 20 + 20 + 1)); @@ -115,10 +114,10 @@ static_assert(sizeof(sAuthReconnectProof_C) == (1 + 16 + 20 + 20 + 1)); std::array<uint8, 16> VersionChallenge = { { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B, 0x21, 0x57, 0xFC, 0x37, 0x3F, 0xB3, 0x69, 0xCD, 0xD2, 0xF1 } }; -enum class BufferSizes : uint32 +struct BufferSizes { - SRP_6_V = 0x20, - SRP_6_S = 0x20, + static constexpr size_t SRP_6_V = 0x20; + static constexpr size_t SRP_6_S = 0x20; }; #define MAX_ACCEPTED_CHALLENGE_SIZE (sizeof(AUTH_LOGON_CHALLENGE_C) + 16) @@ -436,12 +435,12 @@ void AuthSession::LogonChallengeCallback(PreparedQueryResult result) pkt << uint8(WOW_SUCCESS); // B may be calculated < 32B so we force minimal length to 32B - pkt.append(B.AsByteArray(32).get(), 32); // 32 bytes + pkt.append(B.ToByteArray<32>()); // 32 bytes pkt << uint8(1); - pkt.append(g.AsByteArray(1).get(), 1); + pkt.append(g.ToByteArray<1>()); pkt << uint8(32); - pkt.append(N.AsByteArray(32).get(), 32); - pkt.append(s.AsByteArray(int32(BufferSizes::SRP_6_S)).get(), size_t(BufferSizes::SRP_6_S)); // 32 bytes + pkt.append(N.ToByteArray<32>()); + pkt.append(s.ToByteArray<BufferSizes::SRP_6_S>()); // 32 bytes pkt.append(VersionChallenge.data(), VersionChallenge.size()); pkt << uint8(securityFlags); // security flags (0x0...0x04) @@ -500,72 +499,42 @@ bool AuthSession::HandleLogonProof() if ((A % N).IsZero()) return false; - SHA1Hash sha; - sha.UpdateBigNumbers(&A, &B, nullptr); - sha.Finalize(); - BigNumber u; - u.SetBinary(sha.GetDigest(), 20); + BigNumber u(Trinity::Crypto::SHA1::GetDigestOf(A.ToByteArray<32>(), B.ToByteArray<32>())); BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); - uint8 t[32]; - uint8 t1[16]; - uint8 vK[40]; - memcpy(t, S.AsByteArray(32).get(), 32); - - for (int i = 0; i < 16; ++i) - t1[i] = t[i * 2]; - - sha.Initialize(); - sha.UpdateData(t1, 16); + std::array<uint8, 32> t = S.ToByteArray<32>(); + std::array<uint8, 16> buf; + Trinity::Crypto::SHA1::Digest part; + std::array<uint8, 40> sessionKey; + + for (size_t i = 0; i < 16; ++i) + buf[i] = t[i * 2]; + part = Trinity::Crypto::SHA1::GetDigestOf(buf); + for (size_t i = 0; i < Trinity::Crypto::SHA1::DIGEST_LENGTH; ++i) + sessionKey[i * 2] = part[i]; + + for (size_t i = 0; i < 16; ++i) + buf[i] = t[i * 2 + 1]; + part = Trinity::Crypto::SHA1::GetDigestOf(buf); + for (size_t i = 0; i < Trinity::Crypto::SHA1::DIGEST_LENGTH; ++i) + sessionKey[i * 2 + 1] = part[i]; + + Trinity::Crypto::SHA1::Digest hash = Trinity::Crypto::SHA1::GetDigestOf(N.ToByteArray<32>()); + Trinity::Crypto::SHA1::Digest hash2 = Trinity::Crypto::SHA1::GetDigestOf(g.ToByteArray<1>()); + std::transform(hash.begin(), hash.end(), hash2.begin(), hash.begin(), std::bit_xor<>()); // hash = H(N) xor H(g) + + Trinity::Crypto::SHA1 sha; + sha.UpdateData(hash); + sha.UpdateData(Trinity::Crypto::SHA1::GetDigestOf(_accountInfo.Login)); + sha.UpdateData(s.ToByteArray<BufferSizes::SRP_6_S>()); + sha.UpdateData(A.ToByteArray<32>()); + sha.UpdateData(B.ToByteArray<32>()); + sha.UpdateData(sessionKey); sha.Finalize(); - - for (int i = 0; i < 20; ++i) - vK[i * 2] = sha.GetDigest()[i]; - - for (int i = 0; i < 16; ++i) - t1[i] = t[i * 2 + 1]; - - sha.Initialize(); - sha.UpdateData(t1, 16); - sha.Finalize(); - - for (int i = 0; i < 20; ++i) - vK[i * 2 + 1] = sha.GetDigest()[i]; - - K.SetBinary(vK, 40); - - uint8 hash[20]; - - sha.Initialize(); - sha.UpdateBigNumbers(&N, nullptr); - sha.Finalize(); - memcpy(hash, sha.GetDigest(), 20); - sha.Initialize(); - sha.UpdateBigNumbers(&g, nullptr); - sha.Finalize(); - - for (int i = 0; i < 20; ++i) - hash[i] ^= sha.GetDigest()[i]; - - BigNumber t3; - t3.SetBinary(hash, 20); - - sha.Initialize(); - sha.UpdateData(_accountInfo.Login); - sha.Finalize(); - uint8 t4[SHA_DIGEST_LENGTH]; - memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); - - sha.Initialize(); - sha.UpdateBigNumbers(&t3, nullptr); - sha.UpdateData(t4, SHA_DIGEST_LENGTH); - sha.UpdateBigNumbers(&s, &A, &B, &K, nullptr); - sha.Finalize(); - BigNumber M; - M.SetBinary(sha.GetDigest(), sha.GetLength()); + Trinity::Crypto::SHA1::Digest M = sha.GetDigest(); // Check if SRP6 results match (password is correct), else send an error - if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20)) + if (M == logonProof->M1) { // Check auth token bool tokenSuccess = false; @@ -607,8 +576,8 @@ bool AuthSession::HandleLogonProof() // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket - LoginDatabasePreparedStatement*stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF); - stmt->setString(0, K.AsHexStr()); + LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF); + stmt->setString(0, ByteArrayToHexStr(sessionKey)); stmt->setString(1, GetRemoteIpAddress().to_string()); stmt->setUInt32(2, GetLocaleByName(_localizationName)); stmt->setString(3, _os); @@ -616,15 +585,13 @@ bool AuthSession::HandleLogonProof() LoginDatabase.DirectExecute(stmt); // Finish SRP6 and send the final result to the client - sha.Initialize(); - sha.UpdateBigNumbers(&A, &M, &K, nullptr); - sha.Finalize(); + Trinity::Crypto::SHA1::Digest M2 = Trinity::Crypto::SHA1::GetDigestOf(A.ToByteArray<32>(), M, sessionKey); ByteBuffer packet; if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { sAuthLogonProof_S proof; - memcpy(proof.M2, sha.GetDigest(), 20); + proof.M2 = M2; proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; proof.AccountFlags = 0x00800000; // 0x01 = GM, 0x08 = Trial, 0x00800000 = Pro pass (arena tournament) @@ -637,7 +604,7 @@ bool AuthSession::HandleLogonProof() else { sAuthLogonProof_S_Old proof; - memcpy(proof.M2, sha.GetDigest(), 20); + proof.M2 = M2; proof.cmd = AUTH_LOGON_PROOF; proof.error = 0; proof.unk2 = 0x00; @@ -760,12 +727,12 @@ void AuthSession::ReconnectChallengeCallback(PreparedQueryResult result) Field* fields = result->Fetch(); _accountInfo.LoadResult(fields); - K.SetHexStr(fields[9].GetCString()); - _reconnectProof.SetRand(16 * 8); + HexStrToByteArray(fields[9].GetCString(), sessionKey.data()); + Trinity::Crypto::GetRandomBytes(_reconnectProof); _status = STATUS_RECONNECT_PROOF; pkt << uint8(WOW_SUCCESS); - pkt.append(_reconnectProof.AsByteArray(16).get(), 16); // 16 bytes random + pkt.append(_reconnectProof); pkt.append(VersionChallenge.data(), VersionChallenge.size()); SendPacket(pkt); @@ -778,19 +745,20 @@ bool AuthSession::HandleReconnectProof() sAuthReconnectProof_C *reconnectProof = reinterpret_cast<sAuthReconnectProof_C*>(GetReadBuffer().GetReadPointer()); - if (_accountInfo.Login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) + if (_accountInfo.Login.empty()) return false; BigNumber t1; t1.SetBinary(reconnectProof->R1, 16); - SHA1Hash sha; - sha.Initialize(); + Trinity::Crypto::SHA1 sha; sha.UpdateData(_accountInfo.Login); - sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, nullptr); + sha.UpdateData(t1.ToByteArray<16>()); + sha.UpdateData(_reconnectProof); + sha.UpdateData(sessionKey); sha.Finalize(); - if (!memcmp(sha.GetDigest(), reconnectProof->R2, SHA_DIGEST_LENGTH)) + if (sha.GetDigest() == reconnectProof->R2) { if (!VerifyVersion(reconnectProof->R1, sizeof(reconnectProof->R1), reconnectProof->R3, true)) { @@ -939,17 +907,14 @@ void AuthSession::SetVSFields(const std::string& rI) I.SetHexStr(rI.c_str()); // In case of leading zeros in the rI hash, restore them - uint8 mDigest[SHA_DIGEST_LENGTH]; - memcpy(mDigest, I.AsByteArray(SHA_DIGEST_LENGTH).get(), SHA_DIGEST_LENGTH); - - std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH); + std::array<uint8, Trinity::Crypto::SHA1::DIGEST_LENGTH> mDigest = I.ToByteArray<Trinity::Crypto::SHA1::DIGEST_LENGTH>(false); - SHA1Hash sha; - sha.UpdateData(s.AsByteArray(uint32(BufferSizes::SRP_6_S)).get(), (uint32(BufferSizes::SRP_6_S))); - sha.UpdateData(mDigest, SHA_DIGEST_LENGTH); + Trinity::Crypto::SHA1 sha; + sha.UpdateData(s.ToByteArray<BufferSizes::SRP_6_S>()); + sha.UpdateData(mDigest); sha.Finalize(); BigNumber x; - x.SetBinary(sha.GetDigest(), sha.GetLength()); + x.SetBinary(sha.GetDigest()); v = g.ModExp(x, N); // No SQL injection (username escaped) @@ -960,13 +925,13 @@ void AuthSession::SetVSFields(const std::string& rI) LoginDatabase.Execute(stmt); } -bool AuthSession::VerifyVersion(uint8 const* a, int32 aLength, uint8 const* versionProof, bool isReconnect) +bool AuthSession::VerifyVersion(uint8 const* a, int32 aLength, Trinity::Crypto::SHA1::Digest const& versionProof, bool isReconnect) { if (!sConfigMgr->GetBoolDefault("StrictVersionCheck", false)) return true; - std::array<uint8, 20> zeros = { {} }; - std::array<uint8, 20> const* versionHash = nullptr; + Trinity::Crypto::SHA1::Digest zeros; + Trinity::Crypto::SHA1::Digest const* versionHash = nullptr; if (!isReconnect) { RealmBuildInfo const* buildInfo = sRealmList->GetBuildInfo(_build); @@ -981,16 +946,16 @@ bool AuthSession::VerifyVersion(uint8 const* a, int32 aLength, uint8 const* vers if (!versionHash) return false; - if (!memcmp(versionHash->data(), zeros.data(), zeros.size())) + if (zeros == *versionHash) return true; // not filled serverside } else versionHash = &zeros; - SHA1Hash version; + Trinity::Crypto::SHA1 version; version.UpdateData(a, aLength); - version.UpdateData(versionHash->data(), versionHash->size()); + version.UpdateData(*versionHash); version.Finalize(); - return memcmp(versionProof, version.GetDigest(), version.GetLength()) == 0; + return (versionProof == version.GetDigest()); } diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 86bbb4a6f9a..44454f6138b 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -22,6 +22,7 @@ #include "BigNumber.h" #include "ByteBuffer.h" #include "Common.h" +#include "CryptoHash.h" #include "Optional.h" #include "Socket.h" #include "QueryResult.h" @@ -89,12 +90,12 @@ private: void SetVSFields(const std::string& rI); - bool VerifyVersion(uint8 const* a, int32 aLength, uint8 const* versionProof, bool isReconnect); + bool VerifyVersion(uint8 const* a, int32 aLength, Trinity::Crypto::SHA1::Digest const& versionProof, bool isReconnect); BigNumber N, s, g, v; BigNumber b, B; - BigNumber K; - BigNumber _reconnectProof; + std::array<uint8, 40> sessionKey; + std::array<uint8, 16> _reconnectProof; AuthStatus _status; AccountInfo _accountInfo; diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index d8f6cafacbc..76dabf37e66 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -19,10 +19,10 @@ #include "Common.h" #include "DBUpdater.h" #include "Field.h" +#include "CryptoHash.h" #include "Log.h" #include "QueryResult.h" #include "Util.h" -#include "SHA1.h" #include <boost/filesystem/operations.hpp> #include <fstream> #include <sstream> @@ -222,7 +222,7 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, } // Calculate a Sha1 hash based on query content. - std::string const hash = CalculateSHA1Hash(ReadSQLUpdate(availableQuery.first)); + std::string const hash = ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(ReadSQLUpdate(availableQuery.first))); UpdateMode mode = MODE_APPLY; diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index cc620e241f4..4b370181dee 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -18,12 +18,12 @@ #include "AccountMgr.h" #include "Config.h" #include "DatabaseEnv.h" +#include "CryptoHash.h" #include "Log.h" #include "ObjectAccessor.h" #include "Player.h" #include "Realm.h" #include "ScriptMgr.h" -#include "SHA1.h" #include "Util.h" #include "World.h" #include "WorldSession.h" @@ -379,14 +379,7 @@ uint32 AccountMgr::GetCharactersCount(uint32 accountId) std::string AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password) { - SHA1Hash sha; - sha.Initialize(); - sha.UpdateData(name); - sha.UpdateData(":"); - sha.UpdateData(password); - sha.Finalize(); - - return ByteArrayToHexStr(sha.GetDigest(), sha.GetLength()); + return ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(name, ":", password)); } bool AccountMgr::IsBannedAccount(std::string const& name) diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index f6619fa7ea9..580642dde66 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -40,13 +40,14 @@ ScriptReloadMgr* ScriptReloadMgr::instance() #include "BuiltInConfig.h" #include "Config.h" #include "GitRevision.h" +#include "CryptoHash.h" #include "Log.h" #include "MPSCQueue.h" #include "Regex.h" #include "ScriptMgr.h" -#include "SHA1.h" #include "StartProcess.h" #include "Timer.h" +#include "Util.h" #include "World.h" #include <boost/algorithm/string/replace.hpp> #include <boost/filesystem.hpp> @@ -756,7 +757,7 @@ private: auto path = fs::temp_directory_path(); path /= Trinity::StringFormat("tc_script_cache_%s_%s", GitRevision::GetBranch(), - CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str()); + ByteArrayToHexStr(Trinity::Crypto::SHA1::GetDigestOf(sConfigMgr->GetFilename())).c_str()); return path; } diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 6c3cf1b43ff..abbf28c8bae 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1209,7 +1209,7 @@ TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& return _transactionCallbacks.AddCallback(std::move(callback)); } -void WorldSession::InitWarden(BigNumber* k, std::string const& os) +void WorldSession::InitWarden(std::array<uint8, 40> const& k, std::string const& os) { if (os == "Win") { diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index e72ade20183..9d7cbc2cde7 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -34,7 +34,6 @@ #include <unordered_map> #include <boost/circular_buffer.hpp> -class BigNumber; class Creature; class GameObject; class InstanceSave; @@ -423,7 +422,7 @@ class TC_GAME_API WorldSession void SetPlayer(Player* player); uint8 Expansion() const { return m_expansion; } - void InitWarden(BigNumber* k, std::string const& os); + void InitWarden(std::array<uint8, 40> const& k, std::string const& os); /// Session in auth.queue currently void SetInQueue(bool state) { m_inQueue = state; } diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 05b5c8bb9b0..6dac06165c8 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -19,6 +19,8 @@ #include "BigNumber.h" #include "DatabaseEnv.h" #include "GameTime.h" +#include "CryptoHash.h" +#include "CryptoRandom.h" #include "IPLocation.h" #include "Opcodes.h" #include "PacketLog.h" @@ -26,7 +28,6 @@ #include "RBAC.h" #include "Realm.h" #include "ScriptMgr.h" -#include "SHA1.h" #include "World.h" #include "WorldSession.h" #include <memory> @@ -34,8 +35,9 @@ using boost::asio::ip::tcp; WorldSocket::WorldSocket(tcp::socket&& socket) - : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096) + : Socket(std::move(socket)), _OverSpeedPings(0), _worldSession(nullptr), _authed(false), _sendBufferSize(4096) { + Trinity::Crypto::GetRandomBytes(_authSeed); _headerBuffer.Resize(sizeof(ClientPktHeader)); } @@ -126,15 +128,9 @@ void WorldSocket::HandleSendAuthSession() { WorldPacket packet(SMSG_AUTH_CHALLENGE, 37); packet << uint32(1); // 1...31 - packet << uint32(_authSeed); + packet.append(_authSeed); - BigNumber seed1; - seed1.SetRand(16 * 8); - packet.append(seed1.AsByteArray(16).get(), 16); // new encryption seeds - - BigNumber seed2; - seed2.SetRand(16 * 8); - packet.append(seed2.AsByteArray(16).get(), 16); // new encryption seeds + packet.append(Trinity::Crypto::GetRandomBytes<32>()); // new encryption seeds SendPacketAndLogOpcode(packet); } @@ -212,7 +208,8 @@ bool WorldSocket::ReadHeaderHandler() { ASSERT(_headerBuffer.GetActiveSize() == sizeof(ClientPktHeader)); - _authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), sizeof(ClientPktHeader)); + if (_authCrypt.IsInitialized()) + _authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), sizeof(ClientPktHeader)); ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer()); EndianConvertReverse(header->size); @@ -236,11 +233,11 @@ struct AuthSession uint32 LoginServerType = 0; uint32 RealmID = 0; uint32 Build = 0; - uint32 LocalChallenge = 0; + std::array<uint8, 4> LocalChallenge; uint32 LoginServerID = 0; uint32 RegionID = 0; uint64 DosResponse = 0; - uint8 Digest[SHA_DIGEST_LENGTH] = {}; + Trinity::Crypto::SHA1::Digest Digest; std::string Account; ByteBuffer AddonInfo; }; @@ -248,7 +245,7 @@ struct AuthSession struct AccountInfo { uint32 Id; - BigNumber SessionKey; + std::array<uint8, 40> SessionKey; std::string LastIP; bool IsLockedToIP; std::string LockCountry; @@ -273,7 +270,7 @@ struct AccountInfo // LEFT JOIN account r ON a.id = r.recruiter // WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1 Id = fields[0].GetUInt32(); - SessionKey.SetHexStr(fields[1].GetCString()); + HexStrToByteArray(fields[1].GetCString(), SessionKey.data()); LastIP = fields[2].GetString(); IsLockedToIP = fields[3].GetBool(); LockCountry = fields[4].GetString(); @@ -428,12 +425,12 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) recvPacket >> authSession->LoginServerID; recvPacket >> authSession->Account; recvPacket >> authSession->LoginServerType; - recvPacket >> authSession->LocalChallenge; + recvPacket.read(authSession->LocalChallenge); recvPacket >> authSession->RegionID; recvPacket >> authSession->BattlegroupID; recvPacket >> authSession->RealmID; // realmId from auth_database.realmlist table recvPacket >> authSession->DosResponse; - recvPacket.read(authSession->Digest, 20); + recvPacket.read(authSession->Digest); authSession->AddonInfo.resize(recvPacket.size() - recvPacket.rpos()); recvPacket.read(authSession->AddonInfo.contents(), authSession->AddonInfo.size()); // .contents will throw if empty, thats what we want @@ -470,7 +467,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes // This also allows to check for possible "hack" attempts on account // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it - _authCrypt.Init(&account.SessionKey); + _authCrypt.Init(account.SessionKey); // First reject the connection if packet contains invalid data or realm state doesn't allow logging in if (sWorld->IsClosed()) @@ -501,17 +498,17 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes } // Check that Key and account name are the same on client and server - uint32 t = 0; + uint8 t[4] = { 0x00,0x00,0x00,0x00 }; - SHA1Hash sha; + Trinity::Crypto::SHA1 sha; sha.UpdateData(authSession->Account); - sha.UpdateData((uint8*)&t, 4); - sha.UpdateData((uint8*)&authSession->LocalChallenge, 4); - sha.UpdateData((uint8*)&_authSeed, 4); - sha.UpdateBigNumbers(&account.SessionKey, nullptr); + sha.UpdateData(t); + sha.UpdateData(authSession->LocalChallenge); + sha.UpdateData(_authSeed); + sha.UpdateData(account.SessionKey); sha.Finalize(); - if (memcmp(sha.GetDigest(), authSession->Digest, SHA_DIGEST_LENGTH) != 0) + if (sha.GetDigest() != authSession->Digest) { SendAuthResponseError(AUTH_FAILED); TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Id, authSession->Account.c_str(), address.c_str()); @@ -601,7 +598,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes // Initialize Warden system only if it is enabled by config if (wardenActive) - _worldSession->InitWarden(&account.SessionKey, account.OS); + _worldSession->InitWarden(account.SessionKey, account.OS); _queryProcessor.AddCallback(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1))); AsyncRead(); diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 4920280acb6..77511f774e3 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -112,7 +112,7 @@ private: bool HandlePing(WorldPacket& recvPacket); - uint32 _authSeed; + std::array<uint8, 4> _authSeed; AuthCrypt _authCrypt; TimePoint _LastPingTime; diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index 9f887cfedae..7fc532fd961 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -29,7 +29,7 @@ #include <openssl/sha.h> -Warden::Warden() : _session(nullptr), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), +Warden::Warden() : _session(nullptr), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0), _dataSent(false), _previousTimestamp(0), _module(nullptr), _initialized(false) { memset(_inputKey, 0, sizeof(_inputKey)); @@ -130,12 +130,12 @@ void Warden::Update() void Warden::DecryptData(uint8* buffer, uint32 length) { - _inputCrypto.UpdateData(length, buffer); + _inputCrypto.UpdateData(buffer, length); } void Warden::EncryptData(uint8* buffer, uint32 length) { - _outputCrypto.UpdateData(length, buffer); + _outputCrypto.UpdateData(buffer, length); } bool Warden::IsValidCheckSum(uint32 checksum, uint8 const* data, const uint16 length) diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h index 24d6cf9bc34..3d9543a7412 100644 --- a/src/server/game/Warden/Warden.h +++ b/src/server/game/Warden/Warden.h @@ -18,11 +18,10 @@ #ifndef _WARDEN_BASE_H #define _WARDEN_BASE_H -#include <map> -#include "Cryptography/ARC4.h" -#include "Cryptography/BigNumber.h" +#include "ARC4.h" #include "ByteBuffer.h" #include "WardenCheckMgr.h" +#include <array> enum WardenOpcodes { @@ -100,7 +99,7 @@ class TC_GAME_API Warden Warden(); virtual ~Warden(); - virtual void Init(WorldSession* session, BigNumber* k) = 0; + virtual void Init(WorldSession* session, std::array<uint8, 40> const& K) = 0; virtual ClientWardenModule* GetModuleForClient() = 0; virtual void InitializeModule() = 0; virtual void RequestHash() = 0; @@ -125,8 +124,8 @@ class TC_GAME_API Warden uint8 _inputKey[16]; uint8 _outputKey[16]; uint8 _seed[16]; - ARC4 _inputCrypto; - ARC4 _outputCrypto; + Trinity::Crypto::ARC4 _inputCrypto; + Trinity::Crypto::ARC4 _outputCrypto; uint32 _checkTimer; // Timer for sending check requests uint32 _clientResponseTimer; // Timer for client response delay bool _dataSent; diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index aa8ca22f079..49ed703d1ca 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -85,19 +85,7 @@ void WardenCheckMgr::LoadWardenChecks() wardenCheck->Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION)); if (checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == DRIVER_CHECK) - { wardenCheck->Data.SetHexStr(data.c_str()); - int len = data.size() / 2; - - if (wardenCheck->Data.GetNumBytes() < len) - { - uint8 temp[24]; - memset(temp, 0, len); - memcpy(temp, wardenCheck->Data.AsByteArray().get(), wardenCheck->Data.GetNumBytes()); - std::reverse(temp, temp + len); - wardenCheck->Data.SetBinary((uint8*)temp, len); - } - } if (checkType == MEM_CHECK || checkType == MODULE_CHECK) MemChecksIdPool.push_back(id); @@ -120,16 +108,6 @@ void WardenCheckMgr::LoadWardenChecks() { WardenCheckResult* wr = new WardenCheckResult(); wr->Result.SetHexStr(checkResult.c_str()); - int len = checkResult.size() / 2; - if (wr->Result.GetNumBytes() < len) - { - uint8 *temp = new uint8[len]; - memset(temp, 0, len); - memcpy(temp, wr->Result.AsByteArray().get(), wr->Result.GetNumBytes()); - std::reverse(temp, temp + len); - wr->Result.SetBinary((uint8*)temp, len); - delete [] temp; - } CheckResultStore[id] = wr; } diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp index 847a3cf69a0..e8a5b45cd76 100644 --- a/src/server/game/Warden/WardenMac.cpp +++ b/src/server/game/Warden/WardenMac.cpp @@ -15,18 +15,18 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cryptography/WardenKeyGeneration.h" +#include "WardenMac.h" +#include "ByteBuffer.h" #include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" +#include "GameTime.h" #include "Log.h" #include "Opcodes.h" -#include "ByteBuffer.h" -#include "GameTime.h" #include "Player.h" +#include "SessionKeyGenerator.h" #include "Util.h" -#include "WardenMac.h" #include "WardenModuleMac.h" +#include "WorldPacket.h" +#include "WorldSession.h" #include <openssl/md5.h> @@ -34,11 +34,11 @@ WardenMac::WardenMac() : Warden() { } WardenMac::~WardenMac() { } -void WardenMac::Init(WorldSession* pClient, BigNumber* K) +void WardenMac::Init(WorldSession* pClient, std::array<uint8, 40> const& K) { _session = pClient; // Generate Warden Key - SHA1Randx WK(K->AsByteArray().get(), K->GetNumBytes()); + SessionKeyGenerator<Trinity::Crypto::SHA1> WK(K); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); /* @@ -154,14 +154,14 @@ void WardenMac::HandleHashResult(ByteBuffer &buff) buff.rpos(buff.wpos()); - SHA1Hash sha1; + Trinity::Crypto::SHA1 sha1; sha1.UpdateData((uint8*)keyIn, 16); sha1.Finalize(); //const uint8 validHash[20] = { 0x56, 0x8C, 0x05, 0x4C, 0x78, 0x1A, 0x97, 0x2A, 0x60, 0x37, 0xA2, 0x29, 0x0C, 0x22, 0xB5, 0x25, 0x71, 0xA0, 0x6F, 0x4E }; // Verify key - if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0) + if (memcmp(buff.contents() + 1, sha1.GetDigest().data(), 20) != 0) { TC_LOG_WARN("warden", "%s failed hash reply. Action: %s", _session->GetPlayerInfo().c_str(), Penalty().c_str()); return; @@ -235,16 +235,16 @@ void WardenMac::HandleData(ByteBuffer &buff) std::string str = "Test string!"; - SHA1Hash sha1; + Trinity::Crypto::SHA1 sha1; sha1.UpdateData(str); uint32 magic = 0xFEEDFACE; // unsure sha1.UpdateData((uint8*)&magic, 4); sha1.Finalize(); - uint8 sha1Hash[20]; - buff.read(sha1Hash, 20); + std::array<uint8, Trinity::Crypto::SHA1::DIGEST_LENGTH> sha1Hash; + buff.read(sha1Hash.data(), sha1Hash.size()); - if (memcmp(sha1Hash, sha1.GetDigest(), 20) != 0) + if (sha1Hash != sha1.GetDigest()) { TC_LOG_DEBUG("warden", "Handle data failed: SHA1 hash is wrong!"); //found = true; diff --git a/src/server/game/Warden/WardenMac.h b/src/server/game/Warden/WardenMac.h index 81ab864cf02..c186e546f9e 100644 --- a/src/server/game/Warden/WardenMac.h +++ b/src/server/game/Warden/WardenMac.h @@ -18,9 +18,7 @@ #ifndef _WARDEN_MAC_H #define _WARDEN_MAC_H -#include "Cryptography/ARC4.h" -#include <map> -#include "Cryptography/BigNumber.h" +#include "ARC4.h" #include "ByteBuffer.h" #include "Warden.h" @@ -33,7 +31,7 @@ class TC_GAME_API WardenMac : public Warden WardenMac(); ~WardenMac(); - void Init(WorldSession* session, BigNumber* k) override; + void Init(WorldSession* session, std::array<uint8, 40> const& k) override; ClientWardenModule* GetModuleForClient() override; void InitializeModule() override; void RequestHash() override; diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index f973bfad79c..f423ab2486e 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -15,34 +15,35 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Cryptography/HMACSHA1.h" -#include "Cryptography/WardenKeyGeneration.h" +#include "WardenWin.h" #include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Log.h" -#include "Opcodes.h" #include "ByteBuffer.h" -#include "Database/DatabaseEnv.h" +#include "CryptoRandom.h" +#include "DatabaseEnv.h" #include "GameTime.h" -#include "World.h" +#include "HMAC.h" +#include "Log.h" +#include "Opcodes.h" #include "Player.h" +#include "Random.h" +#include "SessionKeyGenerator.h" #include "Util.h" -#include "WardenWin.h" #include "WardenModuleWin.h" #include "WardenCheckMgr.h" -#include "Random.h" +#include "World.h" +#include "WorldPacket.h" +#include "WorldSession.h" #include <openssl/md5.h> WardenWin::WardenWin() : Warden(), _serverTicks(0) {} WardenWin::~WardenWin() { } -void WardenWin::Init(WorldSession* session, BigNumber* k) +void WardenWin::Init(WorldSession* session, std::array<uint8, 40> const& K) { _session = session; // Generate Warden Key - SHA1Randx WK(k->AsByteArray().get(), k->GetNumBytes()); + SessionKeyGenerator<Trinity::Crypto::SHA1> WK(K); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); @@ -262,7 +263,8 @@ void WardenWin::RequestData() case PAGE_CHECK_A: case PAGE_CHECK_B: { - buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); + std::vector<uint8> data = wd->Data.ToByteVector(0, false); + buff.append(data.data(), data.size()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; @@ -275,18 +277,16 @@ void WardenWin::RequestData() } case DRIVER_CHECK: { - buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); + std::vector<uint8> data = wd->Data.ToByteVector(0, false); + buff.append(data.data(), data.size()); buff << uint8(index++); break; } case MODULE_CHECK: { - uint32 seed = rand32(); - buff << uint32(seed); - HmacHash hmac(4, (uint8*)&seed); - hmac.UpdateData(wd->Str); - hmac.Finalize(); - buff.append(hmac.GetDigest(), hmac.GetLength()); + std::array<uint8, 4> seed = Trinity::Crypto::GetRandomBytes<4>(); + buff.append(seed); + buff.append(Trinity::Crypto::HMAC_SHA1::GetDigestOf(seed, wd->Str)); break; } /*case PROC_CHECK: @@ -391,7 +391,8 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), rd->Length) != 0) + std::vector<uint8> result = rs->Result.ToByteVector(); + if (memcmp(buff.contents() + buff.rpos(), result.data(), rd->Length) != 0) { TC_LOG_DEBUG("warden", "RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; @@ -470,7 +471,7 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), 20) != 0) // SHA1 + if (memcmp(buff.contents() + buff.rpos(), rs->Result.ToByteArray<20>(false).data(), 20) != 0) // SHA1 { TC_LOG_DEBUG("warden", "RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h index c45d73572be..77f66f621a3 100644 --- a/src/server/game/Warden/WardenWin.h +++ b/src/server/game/Warden/WardenWin.h @@ -18,11 +18,11 @@ #ifndef _WARDEN_WIN_H #define _WARDEN_WIN_H -#include <map> #include "Cryptography/ARC4.h" #include "Cryptography/BigNumber.h" #include "ByteBuffer.h" #include "Warden.h" +#include <list> #pragma pack(push, 1) @@ -67,7 +67,7 @@ class TC_GAME_API WardenWin : public Warden WardenWin(); ~WardenWin(); - void Init(WorldSession* session, BigNumber* K) override; + void Init(WorldSession* session, std::array<uint8, 40> const& K) override; ClientWardenModule* GetModuleForClient() override; void InitializeModule() override; void RequestHash() override; diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 9b87179aa7d..aec025e0301 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "Base32.h" #include "Chat.h" #include "CryptoGenerics.h" +#include "CryptoRandom.h" #include "DatabaseEnv.h" #include "IpAddress.h" #include "IPLocation.h" @@ -39,7 +40,6 @@ EndScriptData */ #include "World.h" #include "WorldSession.h" #include <unordered_map> -#include <openssl/rand.h> using namespace Trinity::ChatCommands; @@ -131,7 +131,7 @@ public: static std::unordered_map<uint32, Trinity::Crypto::TOTP::Secret> suggestions; auto pair = suggestions.emplace(std::piecewise_construct, std::make_tuple(accountId), std::make_tuple(Trinity::Crypto::TOTP::RECOMMENDED_SECRET_LENGTH)); // std::vector 1-argument size_t constructor invokes resize if (pair.second) // no suggestion yet, generate random secret - RAND_bytes(pair.first->second.data(), pair.first->second.size()); + Trinity::Crypto::GetRandomBytes(pair.first->second); if (!pair.second && token) // suggestion already existed and token specified - validate { diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 549786f3aee..149545d10d6 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -20,6 +20,7 @@ #include "Define.h" #include "ByteConverter.h" +#include <array> #include <string> #include <vector> #include <cstring> @@ -351,6 +352,12 @@ class TC_SHARED_API ByteBuffer _rpos += len; } + template <size_t Size> + void read(std::array<uint8, Size>& arr) + { + read(arr.data(), Size); + } + void readPackGUID(uint64& guid) { if (rpos() + 1 > size()) @@ -438,6 +445,12 @@ class TC_SHARED_API ByteBuffer append(buffer.contents(), buffer.wpos()); } + template <size_t Size> + void append(std::array<uint8, Size> const& arr) + { + append(arr.data(), Size); + } + // can be used in SMSG_MONSTER_MOVE opcode void appendPackXYZ(float x, float y, float z) { diff --git a/src/server/shared/Secrets/SecretMgr.cpp b/src/server/shared/Secrets/SecretMgr.cpp index 590440973f5..a0180ae2363 100644 --- a/src/server/shared/Secrets/SecretMgr.cpp +++ b/src/server/shared/Secrets/SecretMgr.cpp @@ -190,13 +190,13 @@ Optional<std::string> SecretMgr::AttemptTransition(Secrets i, Optional<BigNumber if (!oldSecret) return Trinity::StringFormat("Cannot decrypt old TOTP tokens - add config key '%s' to authserver.conf!", secret_info[i].oldKey); - bool success = Trinity::Crypto::AEDecrypt<Trinity::Crypto::AES>(totpSecret, oldSecret->AsByteArray<Trinity::Crypto::AES::KEY_SIZE_BYTES>()); + bool success = Trinity::Crypto::AEDecrypt<Trinity::Crypto::AES>(totpSecret, oldSecret->ToByteArray<Trinity::Crypto::AES::KEY_SIZE_BYTES>()); if (!success) return Trinity::StringFormat("Cannot decrypt old TOTP tokens - value of '%s' is incorrect for some users!", secret_info[i].oldKey); } if (newSecret) - Trinity::Crypto::AEEncryptWithRandomIV<Trinity::Crypto::AES>(totpSecret, newSecret->AsByteArray<Trinity::Crypto::AES::KEY_SIZE_BYTES>()); + Trinity::Crypto::AEEncryptWithRandomIV<Trinity::Crypto::AES>(totpSecret, newSecret->ToByteArray<Trinity::Crypto::AES::KEY_SIZE_BYTES>()); LoginDatabasePreparedStatement* updateStmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_TOTP_SECRET); updateStmt->setBinary(0, totpSecret); |
