diff options
| author | Michael <michaelneubert1988@gmail.com> | 2014-05-25 21:52:27 +0200 |
|---|---|---|
| committer | Michael <michaelneubert1988@gmail.com> | 2014-05-25 21:52:27 +0200 |
| commit | 15efe08a60d3ccb277dde03abc6cce562ad0b44b (patch) | |
| tree | 9c2a48c3e55a000205ed0f3159d0684f29a0d994 /src/server/game/Server | |
| parent | 49a17c6282fac3d2636e3db740b1a6960fb387ba (diff) | |
| parent | c06dc7d37aa8c795ff505550a7bc388d2a66ecac (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.h | 13 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 271 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 15 |
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; |
