Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.Cryptography;
|
||||
using Framework.IO;
|
||||
using Game.Network.Packets;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public abstract class Warden
|
||||
{
|
||||
public Warden()
|
||||
{
|
||||
_inputCrypto = new SARC4();
|
||||
_outputCrypto = new SARC4();
|
||||
_checkTimer = 10 * Time.InMilliseconds;
|
||||
}
|
||||
|
||||
public abstract void Init(WorldSession session, BigInteger k);
|
||||
public abstract ClientWardenModule GetModuleForClient();
|
||||
public abstract void InitializeModule();
|
||||
public abstract void RequestHash();
|
||||
public abstract void HandleHashResult(ByteBuffer buff);
|
||||
public abstract void RequestData();
|
||||
public abstract void HandleData(ByteBuffer buff);
|
||||
|
||||
public void SendModuleToClient()
|
||||
{
|
||||
Log.outDebug(LogFilter.Warden, "Send module to client");
|
||||
|
||||
uint sizeLeft = _module.CompressedSize;
|
||||
int pos = 0;
|
||||
uint burstSize;
|
||||
while (sizeLeft > 0)
|
||||
{
|
||||
WardenModuleTransfer transfer = new WardenModuleTransfer();
|
||||
|
||||
burstSize = sizeLeft < 500 ? sizeLeft : 500u;
|
||||
transfer.Command = WardenOpcodes.Smsg_ModuleCache;
|
||||
transfer.DataSize = (ushort)burstSize;
|
||||
Buffer.BlockCopy(_module.CompressedData, pos, transfer.Data, 0, (int)burstSize);
|
||||
sizeLeft -= burstSize;
|
||||
pos += (int)burstSize;
|
||||
|
||||
WardenDataServer packet = new WardenDataServer();
|
||||
packet.Data = EncryptData(transfer.Write());
|
||||
_session.SendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestModule()
|
||||
{
|
||||
Log.outDebug(LogFilter.Warden, "Request module");
|
||||
|
||||
// Create packet structure
|
||||
WardenModuleUse request = new WardenModuleUse();
|
||||
request.Command = WardenOpcodes.Smsg_ModuleUse;
|
||||
|
||||
request.ModuleId = _module.Id;
|
||||
request.ModuleKey = _module.Key;
|
||||
request.Size = _module.CompressedSize;
|
||||
|
||||
WardenDataServer packet = new WardenDataServer();
|
||||
packet.Data = EncryptData(request.Write());
|
||||
_session.SendPacket(packet);
|
||||
}
|
||||
|
||||
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 byte[] DecryptData(byte[] buffer)
|
||||
{
|
||||
_inputCrypto.ProcessBuffer(buffer, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public ByteBuffer EncryptData(byte[] buffer)
|
||||
{
|
||||
_outputCrypto.ProcessBuffer(buffer, buffer.Length);
|
||||
return new ByteBuffer(buffer);
|
||||
}
|
||||
|
||||
public bool IsValidCheckSum(uint checksum, byte[] data, ushort length)
|
||||
{
|
||||
uint newChecksum = BuildChecksum(data, length);
|
||||
|
||||
if (checksum != newChecksum)
|
||||
{
|
||||
Log.outDebug(LogFilter.Warden, "CHECKSUM IS NOT VALID");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.outDebug(LogFilter.Warden, "CHECKSUM IS VALID");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public uint BuildChecksum(byte[] data, uint length)
|
||||
{
|
||||
SHA1 sha = SHA1.Create();
|
||||
|
||||
var hash = sha.ComputeHash(data, 0, (int)length);
|
||||
uint checkSum = 0;
|
||||
for (byte i = 0; i < 5; ++i)
|
||||
checkSum = checkSum ^ BitConverter.ToUInt32(hash, i * 4);
|
||||
|
||||
return checkSum;
|
||||
}
|
||||
|
||||
public string Penalty(WardenCheck check = null)
|
||||
{
|
||||
WardenActions action;
|
||||
|
||||
if (check != null)
|
||||
action = check.Action;
|
||||
else
|
||||
action = (WardenActions)WorldConfig.GetIntValue(WorldCfg.WardenClientFailAction);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case WardenActions.Log:
|
||||
return "None";
|
||||
case WardenActions.Kick:
|
||||
_session.KickPlayer();
|
||||
return "Kick";
|
||||
case WardenActions.Ban:
|
||||
{
|
||||
string duration = WorldConfig.GetIntValue(WorldCfg.WardenClientBanDuration) + "s";
|
||||
string accountName;
|
||||
Global.AccountMgr.GetName(_session.GetAccountId(), out accountName);
|
||||
string banReason = "Warden Anticheat Violation";
|
||||
// Check can be NULL, for example if the client sent a wrong signature in the warden packet (CHECKSUM FAIL)
|
||||
if (check != null)
|
||||
banReason += ": " + check.Comment + " (CheckId: " + check.CheckId + ")";
|
||||
|
||||
Global.WorldMgr.BanAccount(BanMode.Account, accountName, duration, banReason, "Server");
|
||||
return "Ban";
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Undefined";
|
||||
}
|
||||
|
||||
internal WorldSession _session;
|
||||
internal byte[] _inputKey = new byte[16];
|
||||
internal byte[] _outputKey = new byte[16];
|
||||
internal byte[] _seed = new byte[16];
|
||||
internal SARC4 _inputCrypto;
|
||||
internal SARC4 _outputCrypto;
|
||||
internal uint _checkTimer; // Timer for sending check requests
|
||||
internal uint _clientResponseTimer; // Timer for client response delay
|
||||
internal bool _dataSent;
|
||||
internal uint _previousTimestamp;
|
||||
internal ClientWardenModule _module;
|
||||
internal bool _initialized;
|
||||
}
|
||||
|
||||
public class ClientWardenModule
|
||||
{
|
||||
public byte[] Id = new byte[16];
|
||||
public byte[] Key = new byte[16];
|
||||
public uint CompressedSize;
|
||||
public byte[] CompressedData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user