bool CanOpenMailBox(ObjectGuid guid) { if (guid == GetPlayer().GetGUID()) { if (!HasPermission(RBACPermissions.CommandMailbox)) { Log.outWarn(LogFilter.ChatSystem, "{0} attempt open mailbox in cheating way.", GetPlayer().GetName()); return(false); } } else if (guid.IsGameObject()) { if (!GetPlayer().GetGameObjectIfCanInteractWith(guid, GameObjectTypes.Mailbox)) { return(false); } } else if (guid.IsAnyTypeCreature()) { if (!GetPlayer().GetNPCIfCanInteractWith(guid, NPCFlags.Mailbox, NPCFlags2.None)) { return(false); } } else { return(false); } return(true); }
void HandleMoveTimeSkipped(MoveTimeSkipped moveTimeSkipped) { Unit mover = GetPlayer().GetUnitBeingMoved(); if (mover == null) { Log.outWarn(LogFilter.Player, $"WorldSession.HandleMoveTimeSkipped wrong mover state from the unit moved by {GetPlayer().GetGUID()}"); return; } // prevent tampered movement data if (moveTimeSkipped.MoverGUID != mover.GetGUID()) { Log.outWarn(LogFilter.Player, $"WorldSession.HandleMoveTimeSkipped wrong guid from the unit moved by {GetPlayer().GetGUID()}"); return; } mover.m_movementInfo.Time += moveTimeSkipped.TimeSkipped; MoveSkipTime moveSkipTime = new(); moveSkipTime.MoverGUID = moveTimeSkipped.MoverGUID; moveSkipTime.TimeSkipped = moveTimeSkipped.TimeSkipped; mover.SendMessageToSet(moveSkipTime, _player); }
uint AdjustClientMovementTime(uint time) { long movementTime = (long)time + _timeSyncClockDelta; if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF) { Log.outWarn(LogFilter.Misc, "The computed movement time using clockDelta is erronous. Using fallback instead"); return(GameTime.GetGameTimeMS()); } else { return((uint)movementTime); } }
public void Update() { if (_initialized) { uint currentTimestamp = Time.GetMSTime(); uint diff = currentTimestamp - _previousTimestamp; _previousTimestamp = currentTimestamp; if (_dataSent) { uint maxClientResponseDelay = WorldConfig.GetUIntValue(WorldCfg.WardenClientResponseDelay); if (maxClientResponseDelay > 0) { // Kick player if client response delays more than set in config if (_clientResponseTimer > maxClientResponseDelay * Time.InMilliseconds) { Log.outWarn(LogFilter.Warden, "{0} (latency: {1}, IP: {2}) exceeded Warden module response delay for more than {3} - disconnecting client", _session.GetPlayerInfo(), _session.GetLatency(), _session.GetRemoteAddress(), Time.secsToTimeString(maxClientResponseDelay, true)); _session.KickPlayer(); } else { _clientResponseTimer += diff; } } } else { if (diff >= _checkTimer) { RequestData(); } else { _checkTimer -= diff; } } } }
public override void HandleHashResult(ByteBuffer buff) { // Verify key if (buff.ReadBytes(20) != WardenModuleWin.ClientKeySeedHash) { Log.outWarn(LogFilter.Warden, "{0} failed hash reply. Action: {0}", _session.GetPlayerInfo(), Penalty()); return; } Log.outDebug(LogFilter.Warden, "Request hash reply: succeed"); // Change keys here _inputKey = WardenModuleWin.ClientKeySeed; _outputKey = WardenModuleWin.ServerKeySeed; _inputCrypto.PrepareKey(_inputKey); _outputCrypto.PrepareKey(_outputKey); _initialized = true; _previousTimestamp = GameTime.GetGameTimeMS(); }
//todo fix me public bool EvaluateOpcode(WorldPacket packet, long time) { uint maxPacketCounterAllowed = 0;// GetMaxPacketCounterAllowed(p.GetOpcode()); // Return true if there no limit for the opcode if (maxPacketCounterAllowed == 0) { return(true); } if (!_PacketThrottlingMap.ContainsKey(packet.GetOpcode())) { _PacketThrottlingMap[packet.GetOpcode()] = new PacketCounter(); } PacketCounter packetCounter = _PacketThrottlingMap[packet.GetOpcode()]; if (packetCounter.lastReceiveTime != time) { packetCounter.lastReceiveTime = time; packetCounter.amountCounter = 0; } // Check if player is flooding some packets if (++packetCounter.amountCounter <= maxPacketCounterAllowed) { return(true); } Log.outWarn(LogFilter.Network, "AntiDOS: Account {0}, IP: {1}, Ping: {2}, Character: {3}, flooding packet (opc: {4} (0x{4}), count: {5})", Session.GetAccountId(), Session.GetRemoteAddress(), Session.GetLatency(), Session.GetPlayerName(), packet.GetOpcode(), packetCounter.amountCounter); switch (_policy) { case Policy.Log: return(true); case Policy.Kick: Log.outInfo(LogFilter.Network, "AntiDOS: Player kicked!"); return(false); case Policy.Ban: BanMode bm = (BanMode)WorldConfig.GetIntValue(WorldCfg.PacketSpoofBanmode); uint duration = WorldConfig.GetUIntValue(WorldCfg.PacketSpoofBanduration); // in seconds string nameOrIp = ""; switch (bm) { case BanMode.Character: // not supported, ban account case BanMode.Account: Global.AccountMgr.GetName(Session.GetAccountId(), out nameOrIp); break; case BanMode.IP: nameOrIp = Session.GetRemoteAddress(); break; } Global.WorldMgr.BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); Log.outInfo(LogFilter.Network, "AntiDOS: Player automatically banned for {0} seconds.", duration); return(false); } return(true); }
public override void HandleData(ByteBuffer buff) { Log.outDebug(LogFilter.Warden, "Handle data"); _dataSent = false; _clientResponseTimer = 0; ushort Length = buff.ReadUInt16(); uint Checksum = buff.ReadUInt32(); if (!IsValidCheckSum(Checksum, buff.GetData(), Length)) { Log.outWarn(LogFilter.Warden, "{0} failed checksum. Action: {1}", _session.GetPlayerInfo(), Penalty()); return; } // TIMING_CHECK { byte result = buff.ReadUInt8(); // @todo test it. if (result == 0x00) { Log.outWarn(LogFilter.Warden, "{0} failed timing check. Action: {1}", _session.GetPlayerInfo(), Penalty()); return; } uint newClientTicks = buff.ReadUInt32(); uint ticksNow = GameTime.GetGameTimeMS(); uint ourTicks = newClientTicks + (ticksNow - _serverTicks); Log.outDebug(LogFilter.Warden, "ServerTicks {0}", ticksNow); // Now Log.outDebug(LogFilter.Warden, "RequestTicks {0}", _serverTicks); // At request Log.outDebug(LogFilter.Warden, "Ticks {0}", newClientTicks); // At response Log.outDebug(LogFilter.Warden, "Ticks diff {0}", ourTicks - newClientTicks); } BigInteger rs; WardenCheck rd; WardenCheckType type; ushort checkFailed = 0; foreach (var id in _currentChecks) { rd = Global.WardenCheckMgr.GetWardenDataById(id); rs = Global.WardenCheckMgr.GetWardenResultById(id); type = rd.Type; switch (type) { case WardenCheckType.Memory: { byte Mem_Result = buff.ReadUInt8(); if (Mem_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK not 0x00, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } if (buff.ReadBytes(rd.Length).Compare(rs.ToByteArray())) { Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK fail CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } case WardenCheckType.PageA: case WardenCheckType.PageB: case WardenCheckType.Driver: case WardenCheckType.Module: { byte value = 0xE9; if (buff.ReadUInt8() != value) { if (type == WardenCheckType.PageA || type == WardenCheckType.PageB) { Log.outDebug(LogFilter.Warden, "RESULT PAGE_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } if (type == WardenCheckType.Module) { Log.outDebug(LogFilter.Warden, "RESULT MODULE_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } if (type == WardenCheckType.Driver) { Log.outDebug(LogFilter.Warden, "RESULT DRIVER_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } checkFailed = id; continue; } if (type == WardenCheckType.PageA || type == WardenCheckType.PageB) { Log.outDebug(LogFilter.Warden, "RESULT PAGE_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } else if (type == WardenCheckType.Module) { Log.outDebug(LogFilter.Warden, "RESULT MODULE_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } else if (type == WardenCheckType.Driver) { Log.outDebug(LogFilter.Warden, "RESULT DRIVER_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } break; } case WardenCheckType.LuaStr: { byte Lua_Result = buff.ReadUInt8(); if (Lua_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT LUA_STR_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } byte luaStrLen = buff.ReadUInt8(); if (luaStrLen != 0) { Log.outDebug(LogFilter.Warden, "Lua string: {0}", buff.ReadString(luaStrLen)); } Log.outDebug(LogFilter.Warden, "RESULT LUA_STR_CHECK passed, CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } case WardenCheckType.MPQ: { byte Mpq_Result = buff.ReadUInt8(); if (Mpq_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK not 0x00 account id {0}", _session.GetAccountId()); checkFailed = id; continue; } if (!buff.ReadBytes(20).Compare(rs.ToByteArray())) // SHA1 { Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK passed, CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } default: // Should never happen break; } } if (checkFailed > 0) { WardenCheck check = Global.WardenCheckMgr.GetWardenDataById(checkFailed); Log.outWarn(LogFilter.Warden, "{0} failed Warden check {1}. Action: {2}", _session.GetPlayerInfo(), checkFailed, Penalty(check)); } // Set hold off timer, minimum timer should at least be 1 second uint holdOff = WorldConfig.GetUIntValue(WorldCfg.WardenClientCheckHoldoff); _checkTimer = (holdOff < 1 ? 1 : holdOff) * Time.InMilliseconds; }
void HandleSendMail(SendMail packet) { if (packet.Info.Attachments.Count > SharedConst.MaxMailItems) // client limit { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.TooManyAttachments); return; } if (!CanOpenMailBox(packet.Info.Mailbox)) { return; } if (string.IsNullOrEmpty(packet.Info.Target)) { return; } Player player = GetPlayer(); if (player.getLevel() < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailSenderReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } ObjectGuid receiverGuid = ObjectGuid.Empty; if (ObjectManager.NormalizePlayerName(ref packet.Info.Target)) { receiverGuid = Global.CharacterCacheStorage.GetCharacterGuidByName(packet.Info.Target); } if (receiverGuid.IsEmpty()) { Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} (GUID: not existed!) with subject {2}" + "and body {3} includes {4} items, {5} copper and {6} COD copper with StationeryID = {7}", GetPlayerInfo(), packet.Info.Target, packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientNotFound); return; } if (packet.Info.SendMoney < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative money value (SendMoney: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.SendMoney); return; } if (packet.Info.Cod < 0) { GetPlayer().SendMailResult(0, MailResponseType.Send, MailResponseResult.InternalError); Log.outWarn(LogFilter.Server, "Player {0} attempted to send mail to {1} ({2}) with negative COD value (Cod: {3})", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Cod); return; } Log.outInfo(LogFilter.Network, "Player {0} is sending mail to {1} ({2}) with subject {3} and body {4}" + "includes {5} items, {6} copper and {7} COD copper with StationeryID = {8}", GetPlayerInfo(), packet.Info.Target, receiverGuid.ToString(), packet.Info.Subject, packet.Info.Body, packet.Info.Attachments.Count, packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID); if (player.GetGUID() == receiverGuid) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CannotSendToSelf); return; } uint cost = (uint)(!packet.Info.Attachments.Empty() ? 30 * packet.Info.Attachments.Count : 30); // price hardcoded in client long reqmoney = cost + packet.Info.SendMoney; // Check for overflow if (reqmoney < packet.Info.SendMoney) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } if (!player.HasEnoughMoney(reqmoney) && !player.IsGameMaster()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotEnoughMoney); return; } Player receiver = Global.ObjAccessor.FindPlayer(receiverGuid); Team receiverTeam = 0; byte mailsCount = 0; //do not allow to send to one player more than 100 mails byte receiverLevel = 0; uint receiverAccountId = 0; uint receiverBnetAccountId = 0; if (receiver) { receiverTeam = receiver.GetTeam(); mailsCount = (byte)receiver.GetMails().Count; receiverLevel = (byte)receiver.getLevel(); receiverAccountId = receiver.GetSession().GetAccountId(); receiverBnetAccountId = receiver.GetSession().GetBattlenetAccountId(); } else { CharacterCacheEntry characterInfo = Global.CharacterCacheStorage.GetCharacterCacheByGuid(receiverGuid); if (characterInfo != null) { receiverTeam = Player.TeamForRace(characterInfo.RaceId); receiverLevel = characterInfo.Level; receiverAccountId = characterInfo.AccountId; } PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAIL_COUNT); stmt.AddValue(0, receiverGuid.GetCounter()); SQLResult result = DB.Characters.Query(stmt); if (!result.IsEmpty()) { mailsCount = (byte)result.Read <ulong>(0); } receiverBnetAccountId = Global.BNetAccountMgr.GetIdByGameAccount(receiverAccountId); } // do not allow to have more than 100 mails in mailbox.. mails count is in opcode byte!!! - so max can be 255.. if (mailsCount > 100) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.RecipientCapReached); return; } // test the receiver's Faction... or all items are account bound bool accountBound = !packet.Info.Attachments.Empty(); foreach (var att in packet.Info.Attachments) { Item item = player.GetItemByGuid(att.ItemGUID); if (item) { ItemTemplate itemProto = item.GetTemplate(); if (itemProto == null || !itemProto.GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount)) { accountBound = false; break; } } } if (!accountBound && player.GetTeam() != receiverTeam && !HasPermission(RBACPermissions.TwoSideInteractionMail)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.NotYourTeam); return; } if (receiverLevel < WorldConfig.GetIntValue(WorldCfg.MailLevelReq)) { SendNotification(CypherStrings.MailReceiverReq, WorldConfig.GetIntValue(WorldCfg.MailLevelReq)); return; } List <Item> items = new List <Item>(); foreach (var att in packet.Info.Attachments) { if (att.ItemGUID.IsEmpty()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } Item item = player.GetItemByGuid(att.ItemGUID); // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail) if (!item) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.MailAttachmentInvalid); return; } if (!item.CanBeTraded(true)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (item.IsBoundAccountWide() && item.IsSoulBound() && player.GetSession().GetAccountId() != receiverAccountId) { if (!item.IsBattlenetAccountBound() || player.GetSession().GetBattlenetAccountId() == 0 || player.GetSession().GetBattlenetAccountId() != receiverBnetAccountId) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.NotSameAccount); return; } } if (item.GetTemplate().GetFlags().HasAnyFlag(ItemFlags.Conjured) || item.m_itemData.Expiration != 0) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.MailBoundItem); return; } if (packet.Info.Cod != 0 && item.HasItemFlag(ItemFieldFlags.Wrapped)) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.CantSendWrappedCod); return; } if (item.IsNotEmptyBag()) { player.SendMailResult(0, MailResponseType.Send, MailResponseResult.EquipError, InventoryResult.DestroyNonemptyBag); return; } items.Add(item); } player.SendMailResult(0, MailResponseType.Send, MailResponseResult.Ok); player.ModifyMoney(-reqmoney); player.UpdateCriteria(CriteriaTypes.GoldSpentForMail, cost); bool needItemDelay = false; MailDraft draft = new MailDraft(packet.Info.Subject, packet.Info.Body); SQLTransaction trans = new SQLTransaction(); if (!packet.Info.Attachments.Empty() || packet.Info.SendMoney > 0) { bool log = HasPermission(RBACPermissions.LogGmTrade); if (!packet.Info.Attachments.Empty()) { foreach (var item in items) { if (log) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {2}) mail item: {3} (Entry: {4} Count: {5}) to player: {6} ({7}) (Account: {8})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), item.GetTemplate().GetName(), item.GetEntry(), item.GetCount(), packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } item.SetNotRefundable(GetPlayer()); // makes the item no longer refundable player.MoveItemFromInventory(item.GetBagSlot(), item.GetSlot(), true); item.DeleteFromInventoryDB(trans); // deletes item from character's inventory item.SetOwnerGUID(receiverGuid); item.SetState(ItemUpdateState.Changed); item.SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone draft.AddItem(item); } // if item send to character at another account, then apply item delivery delay needItemDelay = player.GetSession().GetAccountId() != receiverAccountId; } if (log && packet.Info.SendMoney > 0) { Log.outCommand(GetAccountId(), "GM {0} ({1}) (Account: {{2}) mail money: {3} to player: {4} ({5}) (Account: {6})", GetPlayerName(), GetPlayer().GetGUID().ToString(), GetAccountId(), packet.Info.SendMoney, packet.Info.Target, receiverGuid.ToString(), receiverAccountId); } } // If theres is an item, there is a one hour delivery delay if sent to another account's character. uint deliver_delay = needItemDelay ? WorldConfig.GetUIntValue(WorldCfg.MailDeliveryDelay) : 0; // Mail sent between guild members arrives instantly Guild guild = Global.GuildMgr.GetGuildById(player.GetGuildId()); if (guild) { if (guild.IsMember(receiverGuid)) { deliver_delay = 0; } } // don't ask for COD if there are no items if (packet.Info.Attachments.Empty()) { packet.Info.Cod = 0; } // will delete item or place to receiver mail list draft.AddMoney((ulong)packet.Info.SendMoney).AddCOD((uint)packet.Info.Cod).SendMailTo(trans, new MailReceiver(receiver, receiverGuid.GetCounter()), new MailSender(player), string.IsNullOrEmpty(packet.Info.Body) ? MailCheckMask.Copied : MailCheckMask.HasBody, deliver_delay); player.SaveInventoryAndGoldToDB(trans); DB.Characters.CommitTransaction(trans); }