aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql24
-rw-r--r--sql/updates/characters/3.3.5/2019_07_15_01_characters.sql25
-rw-r--r--src/server/game/Addons/AddonMgr.cpp10
-rw-r--r--src/server/game/Addons/AddonMgr.h19
-rw-r--r--src/server/game/Server/WorldSession.cpp122
-rw-r--r--src/server/game/Server/WorldSession.h24
6 files changed, 148 insertions, 76 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 3b1ceb58b66..426ac3cfc4f 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -114,6 +114,30 @@ CREATE TABLE `addons` (
LOCK TABLES `addons` WRITE;
/*!40000 ALTER TABLE `addons` DISABLE KEYS */;
+INSERT INTO `addons` VALUES
+('Blizzard_AchievementUI', 1276933997),
+('Blizzard_ArenaUI', 1276933997),
+('Blizzard_AuctionUI', 1276933997),
+('Blizzard_BarbershopUI', 1276933997),
+('Blizzard_BattlefieldMinimap', 1276933997),
+('Blizzard_BindingUI', 1276933997),
+('Blizzard_Calendar', 1276933997),
+('Blizzard_CombatLog', 1276933997),
+('Blizzard_CombatText', 1276933997),
+('Blizzard_DebugTools', 1276933997),
+('Blizzard_GlyphUI', 1276933997),
+('Blizzard_GMChatUI', 1276933997),
+('Blizzard_GMSurveyUI', 1276933997),
+('Blizzard_GuildBankUI', 1276933997),
+('Blizzard_InspectUI', 1276933997),
+('Blizzard_ItemSocketingUI', 1276933997),
+('Blizzard_MacroUI', 1276933997),
+('Blizzard_RaidUI', 1276933997),
+('Blizzard_TalentUI', 1276933997),
+('Blizzard_TimeManager', 1276933997),
+('Blizzard_TokenUI', 1276933997),
+('Blizzard_TradeSkillUI', 1276933997),
+('Blizzard_TrainerUI', 1276933997);
/*!40000 ALTER TABLE `addons` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/3.3.5/2019_07_15_01_characters.sql b/sql/updates/characters/3.3.5/2019_07_15_01_characters.sql
new file mode 100644
index 00000000000..5864c766927
--- /dev/null
+++ b/sql/updates/characters/3.3.5/2019_07_15_01_characters.sql
@@ -0,0 +1,25 @@
+TRUNCATE `addons`;
+INSERT INTO `addons` VALUES
+('Blizzard_AchievementUI', 1276933997),
+('Blizzard_ArenaUI', 1276933997),
+('Blizzard_AuctionUI', 1276933997),
+('Blizzard_BarbershopUI', 1276933997),
+('Blizzard_BattlefieldMinimap', 1276933997),
+('Blizzard_BindingUI', 1276933997),
+('Blizzard_Calendar', 1276933997),
+('Blizzard_CombatLog', 1276933997),
+('Blizzard_CombatText', 1276933997),
+('Blizzard_DebugTools', 1276933997),
+('Blizzard_GlyphUI', 1276933997),
+('Blizzard_GMChatUI', 1276933997),
+('Blizzard_GMSurveyUI', 1276933997),
+('Blizzard_GuildBankUI', 1276933997),
+('Blizzard_InspectUI', 1276933997),
+('Blizzard_ItemSocketingUI', 1276933997),
+('Blizzard_MacroUI', 1276933997),
+('Blizzard_RaidUI', 1276933997),
+('Blizzard_TalentUI', 1276933997),
+('Blizzard_TimeManager', 1276933997),
+('Blizzard_TokenUI', 1276933997),
+('Blizzard_TradeSkillUI', 1276933997),
+('Blizzard_TrainerUI', 1276933997);
diff --git a/src/server/game/Addons/AddonMgr.cpp b/src/server/game/Addons/AddonMgr.cpp
index d8fd909c7fc..209e1a5663c 100644
--- a/src/server/game/Addons/AddonMgr.cpp
+++ b/src/server/game/Addons/AddonMgr.cpp
@@ -66,7 +66,7 @@ void LoadFromDB()
TC_LOG_INFO("server.loading", ">> Loaded 0 known addons. DB table `addons` is empty!");
oldMSTime = getMSTime();
- result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons");
+ result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons ORDER BY timestamp");
if (result)
{
uint32 count = 0;
@@ -96,18 +96,16 @@ void LoadFromDB()
}
}
-void SaveAddon(AddonInfo const& addon)
+void SaveAddon(std::string const& name, uint32 publicKeyCrc)
{
- std::string name = addon.Name;
-
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ADDON);
stmt->setString(0, name);
- stmt->setUInt32(1, addon.CRC);
+ stmt->setUInt32(1, publicKeyCrc);
CharacterDatabase.Execute(stmt);
- m_knownAddons.push_back(SavedAddon(addon.Name, addon.CRC));
+ m_knownAddons.emplace_back(name, publicKeyCrc);
}
SavedAddon const* GetAddonInfo(const std::string& name)
diff --git a/src/server/game/Addons/AddonMgr.h b/src/server/game/Addons/AddonMgr.h
index d6d1a6e90c9..89c4575591d 100644
--- a/src/server/game/Addons/AddonMgr.h
+++ b/src/server/game/Addons/AddonMgr.h
@@ -21,20 +21,7 @@
#include "Define.h"
#include <string>
-#include <list>
-
-struct AddonInfo
-{
- AddonInfo(const std::string& name, uint8 enabled, uint32 crc, uint8 state, bool crcOrPubKey)
- : Name(name), Enabled(enabled), CRC(crc), State(state), UsePublicKeyOrCRC(crcOrPubKey)
- { }
-
- std::string Name;
- uint8 Enabled;
- uint32 CRC;
- uint8 State;
- bool UsePublicKeyOrCRC;
-};
+#include <vector>
struct SavedAddon
{
@@ -60,10 +47,10 @@ struct BannedAddon
namespace AddonMgr
{
void LoadFromDB();
- void SaveAddon(AddonInfo const& addon);
+ void SaveAddon(std::string const& name, uint32 publicKeyCrc);
SavedAddon const* GetAddonInfo(const std::string& name);
- typedef std::list<BannedAddon> BannedAddonList;
+ typedef std::vector<BannedAddon> BannedAddonList;
BannedAddonList const* GetBannedAddons();
}
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 2393eac3c7f..fdc494d2c01 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -1010,48 +1010,57 @@ void WorldSession::ReadAddonsInfo(ByteBuffer &data)
if (uncompress(addonInfo.contents(), &uSize, data.contents() + pos, data.size() - pos) == Z_OK)
{
- uint32 addonsCount;
- addonInfo >> addonsCount; // addons count
-
- for (uint32 i = 0; i < addonsCount; ++i)
+ try
{
- std::string addonName;
- uint8 enabled;
- uint32 crc, unk1;
-
- // check next addon data format correctness
- if (addonInfo.rpos() + 1 > addonInfo.size())
- return;
-
- addonInfo >> addonName;
+ uint32 addonsCount = std::min(addonInfo.read<uint32>(), Addons::MaxSecureAddons);
+ _addons.SecureAddons.resize(addonsCount);
- addonInfo >> enabled >> crc >> unk1;
+ for (uint32 i = 0; i < addonsCount; ++i)
+ {
+ Addons::SecureAddonInfo& addon = _addons.SecureAddons[i];
+ uint32 publicKeyCrc, urlCrc;
- TC_LOG_DEBUG("addon", "AddOn: %s (CRC: 0x%x) - enabled: 0x%x - Unknown2: 0x%x", addonName.c_str(), crc, enabled, unk1);
+ addonInfo >> addon.Name >> addon.HasKey;
+ addonInfo >> publicKeyCrc >> urlCrc;
- AddonInfo addon(addonName, enabled, crc, 2, true);
+ TC_LOG_DEBUG("addon", "AddOn: %s (CRC: 0x%x) - has key: 0x%x - URL CRC: 0x%x", addon.Name.c_str(), publicKeyCrc, addon.HasKey, urlCrc);
- SavedAddon const* savedAddon = AddonMgr::GetAddonInfo(addonName);
- if (savedAddon)
- {
- if (addon.CRC != savedAddon->CRC)
- TC_LOG_WARN("addon", " Addon: %s: modified (CRC: 0x%x) - accountID %d)", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
+ SavedAddon const* savedAddon = AddonMgr::GetAddonInfo(addon.Name);
+ if (savedAddon)
+ {
+ if (publicKeyCrc != savedAddon->CRC)
+ {
+ if (addon.HasKey)
+ {
+ addon.Status = Addons::SecureAddonInfo::BANNED;
+ TC_LOG_WARN("addon", " Addon: %s: modified (CRC: 0x%x) - accountID %d)", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
+ }
+ else
+ addon.Status = Addons::SecureAddonInfo::SECURE_HIDDEN;
+ }
+ else
+ {
+ addon.Status = Addons::SecureAddonInfo::SECURE_HIDDEN;
+ TC_LOG_DEBUG("addon", "Addon: %s: validated (CRC: 0x%x) - accountID %d", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
+ }
+ }
else
- TC_LOG_DEBUG("addon", "Addon: %s: validated (CRC: 0x%x) - accountID %d", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
- }
- else
- {
- AddonMgr::SaveAddon(addon);
- TC_LOG_WARN("addon", "Addon: %s: unknown (CRC: 0x%x) - accountId %d (storing addon name and checksum to database)", addon.Name.c_str(), addon.CRC, GetAccountId());
+ {
+ addon.Status = Addons::SecureAddonInfo::BANNED;
+ TC_LOG_WARN("addon", "Addon: %s: not registered as known secure addon - accountId %d", addon.Name.c_str(), GetAccountId());
+ }
}
- /// @todo Find out when to not use CRC/pubkey, and other possible states.
- m_addonsList.push_back(addon);
- }
+ addonInfo.rpos(addonInfo.size() - 4);
- uint32 currentTime;
- addonInfo >> currentTime;
- TC_LOG_DEBUG("addon", "AddOn: CurrentTime: %u", currentTime);
+ uint32 lastBannedAddOnTimestamp;
+ addonInfo >> lastBannedAddOnTimestamp;
+ TC_LOG_DEBUG("addon", "AddOn: Newest banned addon timestamp: %u", lastBannedAddOnTimestamp);
+ }
+ catch (ByteBufferException const& e)
+ {
+ TC_LOG_DEBUG("addon", "AddOn: Addon packet read error! %s", e.what());
+ }
}
else
TC_LOG_DEBUG("addon", "AddOn: Addon packet uncompress error!");
@@ -1059,7 +1068,7 @@ void WorldSession::ReadAddonsInfo(ByteBuffer &data)
void WorldSession::SendAddonsInfo()
{
- uint8 addonPublicKey[256] =
+ uint8 constexpr addonPublicKey[256] =
{
0xC3, 0x5B, 0x50, 0x84, 0xB9, 0x3E, 0x32, 0x42, 0x8C, 0xD0, 0xC7, 0x48, 0xFA, 0x0E, 0x5D, 0x54,
0x5A, 0xA3, 0x0E, 0x14, 0xBA, 0x9E, 0x0D, 0xB9, 0x5D, 0x8B, 0xEE, 0xB6, 0x84, 0x93, 0x45, 0x75,
@@ -1081,37 +1090,46 @@ void WorldSession::SendAddonsInfo()
WorldPacket data(SMSG_ADDON_INFO, 4);
- for (AddonsList::iterator itr = m_addonsList.begin(); itr != m_addonsList.end(); ++itr)
+ for (Addons::SecureAddonInfo const& addonInfo : _addons.SecureAddons)
{
- data << uint8(itr->State);
+ // fresh install, not yet created Interface\Addons\addon_name\addon_name.pub files
+ uint8 infoProvided = (addonInfo.Status == Addons::SecureAddonInfo::SECURE_HIDDEN && !addonInfo.HasKey)
+ || addonInfo.Status == Addons::SecureAddonInfo::SECURE_VISIBLE;
- uint8 crcpub = itr->UsePublicKeyOrCRC;
- data << uint8(crcpub);
- if (crcpub)
+ data << uint8(addonInfo.Status); // Status
+ data << uint8(infoProvided); // InfoProvided
+ if (infoProvided)
{
- uint8 usepk = (itr->CRC != STANDARD_ADDON_CRC); // If addon is Standard addon CRC
- data << uint8(usepk);
- if (usepk) // if CRC is wrong, add public key (client need it)
+ data << uint8(!addonInfo.HasKey); // KeyProvided
+ if (!addonInfo.HasKey) // if CRC is wrong, add public key (client need it)
{
- TC_LOG_DEBUG("addon", "AddOn: %s: CRC checksum mismatch: got 0x%x - expected 0x%x - sending pubkey to accountID %d",
- itr->Name.c_str(), itr->CRC, STANDARD_ADDON_CRC, GetAccountId());
+ TC_LOG_DEBUG("addon", "AddOn: %s: key missing: sending pubkey to accountID %d", addonInfo.Name.c_str(), GetAccountId());
data.append(addonPublicKey, sizeof(addonPublicKey));
}
- data << uint32(0); /// @todo Find out the meaning of this.
+ data << uint32(0); // Revision (from .toc), can be used by SECURE_VISIBLE to display "update available" in client addon controls
}
- data << uint8(0); // uses URL
+ data << uint8(0); // UrlProvided
//if (usesURL)
- // data << uint8(0); // URL
+ // data << uint8(0); // URL, client will create internet shortcut with this destination in Interface\Addons\addon_name\addon_name.url
}
- m_addonsList.clear();
-
+ // Send new uncached banned addons
AddonMgr::BannedAddonList const* bannedAddons = AddonMgr::GetBannedAddons();
- data << uint32(bannedAddons->size());
- for (AddonMgr::BannedAddonList::const_iterator itr = bannedAddons->begin(); itr != bannedAddons->end(); ++itr)
+ uint32 lastBannedAddOnTimestamp = _addons.LastBannedAddOnTimestamp;
+ if (!bannedAddons->empty() && bannedAddons->back().Timestamp < lastBannedAddOnTimestamp) // cheating attempt OR connecting to a realm with different configured banned addons, send everything
+ lastBannedAddOnTimestamp = 0;
+
+ std::size_t sizePos = data.wpos();
+ uint32 bannedAddonCount = 0;
+ data << uint32(0);
+ auto itr = std::lower_bound(bannedAddons->begin(), bannedAddons->end(), _addons.LastBannedAddOnTimestamp, [](BannedAddon const& bannedAddon, uint32 timestamp)
+ {
+ return bannedAddon.Timestamp < timestamp;
+ });
+ for (; itr != bannedAddons->end(); ++itr)
{
data << uint32(itr->Id);
data.append(itr->NameMD5, sizeof(itr->NameMD5));
@@ -1120,6 +1138,8 @@ void WorldSession::SendAddonsInfo()
data << uint32(1); // IsBanned
}
+ data.put<uint32>(sizePos, bannedAddonCount);
+
SendPacket(&data);
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 27098fc60ce..b29b633b061 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -1057,8 +1057,6 @@ class TC_GAME_API WorldSession
std::string _accountName;
uint8 m_expansion;
- typedef std::list<AddonInfo> AddonsList;
-
// Warden
Warden* _warden; // Remains NULL if Warden system is not enabled by config
@@ -1074,7 +1072,27 @@ class TC_GAME_API WorldSession
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
uint8 m_TutorialsChanged;
- AddonsList m_addonsList;
+ struct Addons
+ {
+ struct SecureAddonInfo
+ {
+ enum SecureAddonStatus : uint8
+ {
+ BANNED = 0,
+ SECURE_VISIBLE = 1,
+ SECURE_HIDDEN = 2
+ };
+
+ std::string Name;
+ SecureAddonStatus Status = BANNED;
+ bool HasKey = false;
+ };
+
+ static uint32 constexpr MaxSecureAddons = 25;
+
+ std::vector<SecureAddonInfo> SecureAddons;
+ uint32 LastBannedAddOnTimestamp = 0;
+ } _addons;
uint32 recruiterId;
bool isRecruiter;
LockedQueue<WorldPacket*> _recvQueue;