aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Server
diff options
context:
space:
mode:
authorMichael <michaelneubert1988@gmail.com>2014-05-25 21:52:27 +0200
committerMichael <michaelneubert1988@gmail.com>2014-05-25 21:52:27 +0200
commit15efe08a60d3ccb277dde03abc6cce562ad0b44b (patch)
tree9c2a48c3e55a000205ed0f3159d0684f29a0d994 /src/server/game/Server
parent49a17c6282fac3d2636e3db740b1a6960fb387ba (diff)
parentc06dc7d37aa8c795ff505550a7bc388d2a66ecac (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/game/Entities/Item/Item.cpp src/server/game/Entities/Pet/Pet.cpp src/server/game/Entities/Player/Player.cpp src/server/game/Entities/Player/Player.h src/server/game/Handlers/MiscHandler.cpp src/server/game/Miscellaneous/SharedDefines.h src/server/game/Reputation/ReputationMgr.cpp src/server/game/Server/Protocol/Opcodes.h src/server/game/Server/WorldSession.cpp src/server/game/Server/WorldSession.h src/server/game/Spells/SpellEffects.cpp src/server/game/Weather/Weather.cpp src/server/game/Weather/WeatherMgr.cpp src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp src/server/scripts/Spells/spell_hunter.cpp
Diffstat (limited to 'src/server/game/Server')
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h13
-rw-r--r--src/server/game/Server/WorldSession.cpp271
-rw-r--r--src/server/game/Server/WorldSession.h15
3 files changed, 289 insertions, 10 deletions
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 8f77f09ba2d..94bfc8e1305 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -1395,11 +1395,18 @@ enum PacketProcessing
PROCESS_THREADSAFE //packet is thread-safe - process it in Map::Update()
};
+class WorldSession;
class WorldPacket;
class WorldSession;
typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket);
+#if defined(__GNUC__)
+#pragma pack(1)
+#else
+#pragma pack(push, 1)
+#endif
+
struct OpcodeHandler
{
OpcodeHandler() {}
@@ -1446,6 +1453,12 @@ class OpcodeTable
extern OpcodeTable opcodeTable;
+#if defined(__GNUC__)
+#pragma pack()
+#else
+#pragma pack(pop)
+#endif
+
void InitOpcodes();
/// Lookup opcode name for human understandable logging
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index a99695206ad..a16af561125 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -124,7 +124,6 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
_filterAddonMessages(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
- timeLastWhoCommand(0),
_RBACData(NULL)
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
@@ -317,12 +316,13 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
//! loop caused by re-enqueueing the same packets over and over again, we stop updating this session
//! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session.
uint32 processedPackets = 0;
+ time_t currentTime = time(NULL);
while (m_Socket && !m_Socket->IsClosed() &&
!_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket &&
_recvQueue.next(packet, updater))
{
- if (!AntiDOS.EvaluateOpcode(*packet))
+ if (!AntiDOS.EvaluateOpcode(*packet, currentTime))
KickPlayer();
OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()];
@@ -1176,14 +1176,38 @@ void WorldSession::InvalidateRBACData()
_RBACData = NULL;
}
-bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p) const
+bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const
{
- if (IsOpcodeAllowed(p.GetOpcode()))
- return true;
+ PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()];
+ if (packetCounter.lastReceiveTime != time)
+ {
+ packetCounter.lastReceiveTime = time;
+ packetCounter.amountCounter = 0;
+ }
+
+ uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode());
+
+ bool dosTriggered = false;
+ // Check if player is flooding some packets
+ if (++packetCounter.amountCounter > maxPacketCounterAllowed)
+ {
+ dosTriggered = true;
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, flooding packet (opc: %s, count: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), packetCounter.amountCounter);
+ }
+
+ // Then check if player is sending packets not allowed
+ if (!IsOpcodeAllowed(p.GetOpcode()))
+ {
+ dosTriggered = true;
+ // Opcode not allowed, let the punishment begin
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ }
- // Opcode not allowed, let the punishment begin
- TC_LOG_INFO("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)",
- Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size());
+ // Return true if everything is fine, otherwise apply the configured policy
+ if (!dosTriggered)
+ return true;
switch (_policy)
{
@@ -1212,3 +1236,234 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p) const
return true;
}
}
+
+
+uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) const
+{
+ uint32 maxPacketCounterAllowed;
+ switch (opcode)
+ {
+ case CMSG_MESSAGECHAT_ADDON_BATTLEGROUND:
+ case CMSG_MESSAGECHAT_ADDON_GUILD:
+ case CMSG_MESSAGECHAT_ADDON_OFFICER:
+ case CMSG_MESSAGECHAT_ADDON_PARTY:
+ case CMSG_MESSAGECHAT_ADDON_RAID:
+ case CMSG_MESSAGECHAT_ADDON_WHISPER:
+ case CMSG_MESSAGECHAT_AFK:
+ case CMSG_MESSAGECHAT_BATTLEGROUND:
+ case CMSG_MESSAGECHAT_CHANNEL:
+ case CMSG_MESSAGECHAT_DND:
+ case CMSG_MESSAGECHAT_EMOTE:
+ case CMSG_MESSAGECHAT_GUILD:
+ case CMSG_MESSAGECHAT_OFFICER:
+ case CMSG_MESSAGECHAT_PARTY:
+ case CMSG_MESSAGECHAT_RAID:
+ case CMSG_MESSAGECHAT_RAID_WARNING:
+ case CMSG_MESSAGECHAT_SAY:
+ case CMSG_MESSAGECHAT_WHISPER:
+ case CMSG_MESSAGECHAT_YELL:
+ {
+ maxPacketCounterAllowed = 500;
+ break;
+ }
+
+ case CMSG_ATTACKSTOP:
+ case CMSG_GUILD_QUERY:
+ case CMSG_NAME_QUERY:
+ case CMSG_PET_NAME_QUERY:
+ case CMSG_GAMEOBJECT_QUERY:
+ case CMSG_CREATURE_QUERY:
+ case CMSG_NPC_TEXT_QUERY:
+ case CMSG_ARENA_TEAM_QUERY:
+ case CMSG_TAXINODE_STATUS_QUERY:
+ case CMSG_TAXIQUERYAVAILABLENODES:
+ case CMSG_QUESTGIVER_QUERY_QUEST:
+ case CMSG_QUEST_QUERY:
+ case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY:
+ case CMSG_QUERY_QUESTS_COMPLETED:
+ case CMSG_QUEST_POI_QUERY:
+ case CMSG_QUERY_TIME:
+ case CMSG_PAGE_TEXT_QUERY:
+ case CMSG_PETITION_QUERY:
+ case CMSG_QUERY_INSPECT_ACHIEVEMENTS:
+ case CMSG_AREA_SPIRIT_HEALER_QUERY:
+ case CMSG_CORPSE_MAP_POSITION_QUERY:
+ case CMSG_MOVE_TIME_SKIPPED:
+ case CMSG_GUILD_BANK_QUERY_TAB:
+ case CMSG_GUILD_BANK_LOG_QUERY:
+ case CMSG_GUILD_EVENT_LOG_QUERY:
+ case MSG_CORPSE_QUERY:
+ case MSG_QUERY_NEXT_MAIL_TIME:
+ case MSG_MOVE_SET_FACING:
+ {
+ maxPacketCounterAllowed = 200;
+ break;
+ }
+
+ case CMSG_REQUEST_PARTY_MEMBER_STATS:
+ case CMSG_WHO:
+ {
+ maxPacketCounterAllowed = 50;
+ break;
+ }
+
+ case CMSG_SETSHEATHED:
+ case CMSG_CONTACT_LIST:
+ {
+ maxPacketCounterAllowed = 10;
+ break;
+ }
+
+ case CMSG_GAMEOBJ_USE:
+ case CMSG_GAMEOBJ_REPORT_USE:
+ case CMSG_SPELLCLICK:
+ case CMSG_PLAYER_LOGOUT:
+ case CMSG_LOGOUT_REQUEST:
+ case CMSG_LOGOUT_CANCEL:
+ case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE:
+ case CMSG_REQUEST_VEHICLE_PREV_SEAT:
+ case CMSG_REQUEST_VEHICLE_NEXT_SEAT:
+ case CMSG_REQUEST_VEHICLE_SWITCH_SEAT:
+ case CMSG_TOGGLE_PVP:
+ case CMSG_ADD_FRIEND:
+ case CMSG_DEL_FRIEND:
+ case CMSG_SET_CONTACT_NOTES:
+ case CMSG_RESET_INSTANCES:
+ case CMSG_HEARTH_AND_RESURRECT:
+ case CMSG_CHAR_CREATE:
+ case CMSG_READY_FOR_ACCOUNT_DATA_TIMES:
+ case CMSG_CHAR_ENUM:
+ case CMSG_REALM_SPLIT:
+ case CMSG_CHAR_DELETE:
+ case CMSG_PLAYER_LOGIN:
+ case CMSG_PET_ABANDON:
+ case CMSG_PET_RENAME:
+ case CMSG_CHAR_RENAME:
+ case CMSG_CHAR_CUSTOMIZE:
+ case CMSG_CHAR_RACE_CHANGE:
+ case CMSG_CHAR_FACTION_CHANGE:
+ case CMSG_GMTICKET_CREATE:
+ case CMSG_GMTICKET_UPDATETEXT:
+ case CMSG_GMTICKET_DELETETICKET:
+ case CMSG_GMSURVEY_SUBMIT:
+ case CMSG_GM_REPORT_LAG:
+ case CMSG_BUG:
+ case CMSG_GMRESPONSE_RESOLVE:
+ case CMSG_ACTIVATETAXIEXPRESS:
+ case CMSG_ACTIVATETAXI:
+ case CMSG_SELF_RES:
+ case CMSG_INITIATE_TRADE:
+ case CMSG_BEGIN_TRADE:
+ case CMSG_UNLEARN_SKILL:
+ case CMSG_DISMISS_CONTROLLED_VEHICLE:
+ case CMSG_REQUEST_VEHICLE_EXIT:
+ case CMSG_LEARN_PREVIEW_TALENTS:
+ case CMSG_LEARN_PREVIEW_TALENTS_PET:
+ case CMSG_PLAYER_VEHICLE_ENTER:
+ case CMSG_EJECT_PASSENGER:
+ case CMSG_EQUIPMENT_SET_SAVE:
+ case CMSG_EQUIPMENT_SET_DELETE:
+ case CMSG_ALTER_APPEARANCE:
+ case CMSG_QUESTGIVER_ACCEPT_QUEST:
+ case CMSG_QUESTGIVER_CHOOSE_REWARD:
+ case CMSG_QUESTGIVER_REQUEST_REWARD:
+ //case CMSG_QUESTGIVER_CANCEL:
+ case CMSG_QUESTLOG_REMOVE_QUEST:
+ case CMSG_QUEST_CONFIRM_ACCEPT:
+ case CMSG_QUESTGIVER_COMPLETE_QUEST:
+ case CMSG_DISMISS_CRITTER:
+ case CMSG_REPOP_REQUEST:
+ case CMSG_PETITION_BUY:
+ case CMSG_PETITION_SIGN:
+ case CMSG_TURN_IN_PETITION:
+ case CMSG_COMPLETE_CINEMATIC:
+ case CMSG_ITEM_REFUND:
+ case CMSG_SOCKET_GEMS:
+ case CMSG_WRAP_ITEM:
+ case CMSG_BUY_BANK_SLOT:
+ case CMSG_GROUP_INVITE_RESPONSE:
+ //case CMSG_GROUP_UNINVITE:
+ case CMSG_GROUP_UNINVITE_GUID:
+ case CMSG_GROUP_SET_LEADER:
+ case CMSG_GROUP_DISBAND:
+ case CMSG_GROUP_RAID_CONVERT:
+ case CMSG_GROUP_CHANGE_SUB_GROUP:
+ case CMSG_GROUP_ASSISTANT_LEADER:
+ case CMSG_OPT_OUT_OF_LOOT:
+ case CMSG_BATTLEMASTER_JOIN_ARENA:
+ case CMSG_BATTLEFIELD_LEAVE:
+ case CMSG_REPORT_PVP_AFK:
+ case CMSG_DUEL_ACCEPTED:
+ case CMSG_DUEL_CANCELLED:
+ case CMSG_CALENDAR_GET_CALENDAR:
+ case CMSG_CALENDAR_ADD_EVENT:
+ case CMSG_CALENDAR_UPDATE_EVENT:
+ case CMSG_CALENDAR_REMOVE_EVENT:
+ case CMSG_CALENDAR_COPY_EVENT:
+ case CMSG_CALENDAR_EVENT_INVITE:
+ case CMSG_CALENDAR_EVENT_SIGNUP:
+ case CMSG_CALENDAR_EVENT_RSVP:
+ case CMSG_CALENDAR_EVENT_REMOVE_INVITE:
+ case CMSG_CALENDAR_EVENT_MODERATOR_STATUS:
+ case CMSG_CALENDAR_COMPLAIN:
+ case CMSG_ARENA_TEAM_INVITE:
+ case CMSG_ARENA_TEAM_ACCEPT:
+ case CMSG_ARENA_TEAM_DECLINE:
+ case CMSG_ARENA_TEAM_LEAVE:
+ case CMSG_ARENA_TEAM_DISBAND:
+ case CMSG_ARENA_TEAM_REMOVE:
+ case CMSG_ARENA_TEAM_LEADER:
+ case CMSG_LOOT_METHOD:
+ case CMSG_GUILD_INVITE:
+ case CMSG_GUILD_ACCEPT:
+ case CMSG_GUILD_DECLINE:
+ case CMSG_GUILD_LEAVE:
+ case CMSG_GUILD_DISBAND:
+ case CMSG_GUILD_SET_GUILD_MASTER:
+ case CMSG_GUILD_MOTD:
+ case SMSG_GUILD_NEWS_UPDATE:
+ case CMSG_GUILD_QUERY_RANKS:
+ case CMSG_GUILD_ADD_RANK:
+ case CMSG_GUILD_DEL_RANK:
+ case CMSG_GUILD_INFO_TEXT:
+ case CMSG_GUILD_BANK_DEPOSIT_MONEY:
+ case CMSG_GUILD_BANK_WITHDRAW_MONEY:
+ case CMSG_GUILD_BANK_BUY_TAB:
+ case CMSG_GUILD_BANK_UPDATE_TAB:
+ case CMSG_SET_GUILD_BANK_TEXT:
+ case MSG_SAVE_GUILD_EMBLEM:
+ case MSG_PETITION_RENAME:
+ case MSG_PETITION_DECLINE:
+ case MSG_TALENT_WIPE_CONFIRM:
+ case MSG_SET_DUNGEON_DIFFICULTY:
+ case MSG_SET_RAID_DIFFICULTY:
+ case MSG_RANDOM_ROLL:
+ case MSG_RAID_TARGET_UPDATE:
+ case MSG_PARTY_ASSIGNMENT:
+ case MSG_RAID_READY_CHECK:
+ {
+ maxPacketCounterAllowed = 3;
+ break;
+ }
+
+ case CMSG_SET_ACTION_BUTTON:
+ {
+ maxPacketCounterAllowed = MAX_ACTION_BUTTONS;
+ break;
+ }
+
+ case CMSG_ITEM_REFUND_INFO:
+ {
+ maxPacketCounterAllowed = PLAYER_SLOTS_COUNT;
+ break;
+ }
+
+ default:
+ {
+ maxPacketCounterAllowed = 100;
+ break;
+ }
+ }
+
+ return maxPacketCounterAllowed;
+}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 2453104c80e..3a3a2730c2d 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -28,6 +28,7 @@
#include "AddonMgr.h"
#include "DatabaseEnv.h"
#include "World.h"
+#include "Opcodes.h"
#include "WorldPacket.h"
#include "Cryptography/BigNumber.h"
#include "Opcodes.h"
@@ -203,6 +204,12 @@ class CharacterCreateInfo
uint8 CharCount;
};
+struct PacketCounter
+{
+ time_t lastReceiveTime;
+ uint32 amountCounter;
+};
+
/// Player session in the World
class WorldSession
{
@@ -985,7 +992,7 @@ class WorldSession
friend class World;
public:
DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { }
- bool EvaluateOpcode(WorldPacket& p) const;
+ bool EvaluateOpcode(WorldPacket& p, time_t time) const;
void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; }
protected:
enum Policy
@@ -1004,12 +1011,17 @@ class WorldSession
return itr->second;
}
+ uint32 GetMaxPacketCounterAllowed(uint16 opcode) const;
+
WorldSession* Session;
private:
typedef std::unordered_map<uint16, bool> OpcodeStatusMap;
OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes
Policy _policy;
+ typedef std::unordered_map<uint16, PacketCounter> PacketThrottlingMap;
+ // mark this member as "mutable" so it can be modified even in const functions
+ mutable PacketThrottlingMap _PacketThrottlingMap;
DosProtection(DosProtection const& right) = delete;
DosProtection& operator=(DosProtection const& right) = delete;
@@ -1066,7 +1078,6 @@ class WorldSession
uint32 recruiterId;
bool isRecruiter;
ACE_Based::LockedQueue<WorldPacket*, ACE_Thread_Mutex> _recvQueue;
- time_t timeLastWhoCommand;
z_stream_s* _compressionStream;
rbac::RBACData* _RBACData;