Fix 'Bad file data'
This commit is contained in:
s1lentq 2016-01-08 20:09:39 +06:00
parent cbdd67c575
commit 9e4c02b587
9 changed files with 154 additions and 60 deletions

49
engine/consistency.h Normal file
View File

@ -0,0 +1,49 @@
/*
*
* 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 2 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, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#ifndef CONSISTENCY_H
#define CONSISTENCY_H
#ifdef _WIN32
#pragma once
#endif
#define MAX_CONSISTENCY_LIST 512
/* <7508> ../engine/consistency.h:9 */
typedef struct consistency_s
{
char * filename;
int issound;
int orig_index;
int value;
int check_type;
float mins[3];
float maxs[3];
} consistency_t;
#endif // CONSISTENCY_H

View File

@ -35,7 +35,7 @@
#include "model.h"
#define REHLDS_API_VERSION_MAJOR 2
#define REHLDS_API_VERSION_MINOR 2
#define REHLDS_API_VERSION_MINOR 5
//Steam_NotifyClientConnect hook
typedef IHookChain<qboolean, IGameClient*, const void*, unsigned int> IRehldsHook_Steam_NotifyClientConnect;
@ -153,6 +153,14 @@ typedef IVoidHookChainRegistry<IGameClient*, bool, const char*> IRehldsHookRegis
typedef IVoidHookChain<int> IRehldsHook_SV_ActivateServer;
typedef IVoidHookChainRegistry<int> IRehldsHookRegistry_SV_ActivateServer;
//SV_WriteVoiceCodec hook
typedef IVoidHookChain<sizebuf_t *> IRehldsHook_SV_WriteVoiceCodec;
typedef IVoidHookChainRegistry<sizebuf_t *> IRehldsHookRegistry_SV_WriteVoiceCodec;
//Steam_GSGetSteamID hook
typedef IHookChain<uint64> IRehldsHook_Steam_GSGetSteamID;
typedef IHookChainRegistry<uint64> IRehldsHookRegistry_Steam_GSGetSteamID;
class IRehldsHookchains {
public:
virtual ~IRehldsHookchains() { }
@ -186,6 +194,8 @@ public:
virtual IRehldsHookRegistry_SV_CheckConsistencyResponse* SV_CheckConsistencyResponse() = 0;
virtual IRehldsHookRegistry_SV_DropClient* SV_DropClient() = 0;
virtual IRehldsHookRegistry_SV_ActivateServer* SV_ActivateServer() = 0;
virtual IRehldsHookRegistry_SV_WriteVoiceCodec* SV_WriteVoiceCodec() = 0;
virtual IRehldsHookRegistry_Steam_GSGetSteamID* Steam_GSGetSteamID() = 0;
};
struct RehldsFuncs_t {
@ -222,6 +232,14 @@ struct RehldsFuncs_t {
cvar_t*(*GetCvarVars)();
int (*SV_GetChallenge)(const netadr_t& adr);
void (*SV_AddResource)(resourcetype_t type, const char *name, int size, unsigned char flags, int index);
int(*MSG_ReadShort)(void);
int(*MSG_ReadBuf)(int iSize, void *pbuf);
void(*MSG_WriteBuf)(sizebuf_t *sb, int iSize, void *buf);
void(*MSG_WriteByte)(sizebuf_t *sb, int c);
void(*MSG_WriteShort)(sizebuf_t *sb, int c);
void(*MSG_WriteString)(sizebuf_t *sb, const char *s);
void*(*GetPluginApi)(const char *name);
void(*RegisterPluginApi)(const char *name, void *impl);
};
class IRehldsApi {

View File

@ -67,6 +67,10 @@ public:
virtual bool IsConnected() = 0;
virtual void SetConnected(bool connected) = 0;
virtual uint32 GetVoiceStream(int stream_id) = 0;
virtual void SetLastVoiceTime(double time) = 0;
virtual double GetLastVoiceTime() = 0;
virtual bool GetLoopback() = 0;
// this must be the last virtual function in class
#ifdef REHLDS_SELF
@ -117,4 +121,8 @@ public:
virtual int GetConsistencyNum() = 0;
virtual int GetResourcesNum() = 0;
virtual int GetDecalNameNum() = 0;
virtual double GetTime() = 0;
virtual void SetResourcesNum(int num) = 0;
virtual struct resource_s *GetResource(int index) = 0;
};

View File

@ -37,8 +37,6 @@ void StringReplace(char *src, const char *strold, const char *strnew)
}
}
extern uint32 swap_endian(uint32 value);
char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32 responseHash)
{
int len;
@ -57,7 +55,7 @@ char *GetExecCmdPrepare(IGameClient *pClient, CResourceBuffer *pResource, uint32
// replace key values
StringReplace(string, "[file_name]", pResource->GetFileName());
StringReplace(string, "[file_hash]", UTIL_VarArgs("%x", responseHash));
StringReplace(string, "[file_md5hash]", UTIL_VarArgs("%x", swap_endian(responseHash)));
StringReplace(string, "[file_md5hash]", UTIL_VarArgs("%x", _byteswap_ulong(responseHash)));
// replace of templates for identification
StringReplace(string, "[userid]", UTIL_VarArgs("#%u", g_engfuncs.pfnGetPlayerUserId(pClient->GetEdict())));

View File

@ -4,7 +4,7 @@ plugin_info_t Plugin_info =
{
META_INTERFACE_VERSION,
"Rechecker",
"1.2",
"1.3",
__DATE__,
"s1lent",
"http://www.dedicated-server.ru/",

View File

@ -14,6 +14,7 @@
#include <list>
#include <vector>
#include <cstring> // strrchr
#include <algorithm> // std::sort
#include <time.h> // time, localtime etc
#include <extdll.h>
@ -24,6 +25,7 @@
#include "rehlds_api.h"
#include "engine_rehlds.h"
#include "consistency.h"
#include "main.h"
//#include "task.h"

View File

@ -9,7 +9,7 @@ cvar_t *pcv_rch_log = NULL;
void CResourceFile::CreateResourceList()
{
int nConsistency = g_RehldsServerData->GetConsistencyNum();
m_DecalsNum = g_RehldsServerData->GetDecalNameNum();
/*m_DecalsNum = g_RehldsServerData->GetDecalNameNum();*/
for (auto iter = m_resourceList.cbegin(), end = m_resourceList.cend(); iter != end; ++iter)
{
@ -26,14 +26,52 @@ void CResourceFile::CreateResourceList()
break;
}
// check limit consistency
if (nConsistency >= MAX_CONSISTENCY_LIST)
{
UTIL_Printf(__FUNCTION__ ": can't add consistency \"%s\" on line %d; exceeded the limit of consistency max '%d'\n", pRes->GetFileName(), pRes->GetLine(), MAX_CONSISTENCY_LIST);
break;
}
Log(__FUNCTION__ " -> file: (%s), cmdexc: (%s), hash: (%x)", pRes->GetFileName(), pRes->GetCmdExec(), pRes->GetFileHash());
SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, m_DecalsNum++);
SV_AddResource(t_decal, pRes->GetFileName(), 0, RES_CHECKFILE, 4095/*m_DecalsNum++*/);
nConsistency++;
}
}
m_DecalsNum = g_RehldsServerData->GetDecalNameNum();
/*m_DecalsNum = g_RehldsServerData->GetDecalNameNum();*/
g_RehldsServerData->SetConsistencyNum(nConsistency);
// sort
std::vector<resource_t *> sortList;
for (int i = 0; i < g_RehldsServerData->GetResourcesNum(); ++i)
{
resource_t *r = g_RehldsServerData->GetResource(i);
sortList.push_back(new resource_t(*r));
}
// Start a first resource list
g_RehldsServerData->SetResourcesNum(0);
class SortFiles
{
public:
bool operator()(const resource_t *a, const resource_t *b) const
{
return (a->ucFlags & RES_CHECKFILE) != 0;
}
};
// sort by flag RES_CHECKFILE
std::sort(sortList.begin(), sortList.end(), SortFiles());
for (auto iter = sortList.cbegin(), end = sortList.cend(); iter != end; ++iter)
{
// Add new resource in the own order
resource_t *r = (*iter);
SV_AddResource(r->type, r->szFileName, r->nDownloadSize, r->ucFlags, r->nIndex);
}
}
void CResourceFile::Clear(IGameClient *pClient)
@ -43,7 +81,7 @@ void CResourceFile::Clear(IGameClient *pClient)
auto iter = m_responseList.begin();
while (iter != m_responseList.end())
{
ResponseBuffer *pFiles = (*iter);
CResponseBuffer *pFiles = (*iter);
if (pFiles->GetGameClient() != pClient)
{
@ -61,10 +99,11 @@ void CResourceFile::Clear(IGameClient *pClient)
}
m_PrevHash = 0;
m_DecalsNum = 0;
/*m_DecalsNum = 0;*/
// clear resources
m_resourceList.clear();
m_responseList.clear();
ClearStringsCache();
}
@ -159,16 +198,6 @@ void CResourceFile::Init()
pcv_rch_log = g_engfuncs.pfnCVarGetPointer(cv_rch_log.name);
}
uint32 __declspec(naked) swap_endian(uint32 value)
{
__asm
{
mov eax, dword ptr[esp + 4]
bswap eax
ret
}
}
inline uint8 hexbyte(uint8 *hex)
{
return ((hex[0] > '9' ? toupper(hex[0]) - 'A' + 10 : hex[0] - '0') << 4)
@ -300,12 +329,16 @@ void CResourceFile::LoadResources()
{
flag = FLAG_TYPE_HASH_ANY;
}
else if (_stricmp((const char *)pbuf, "MISSING") == 0)
{
flag = FLAG_TYPE_MISSING;
}
else
{
for (int i = 0; i < sizeof(pbuf) / 2; i++)
hash[i] = hexbyte(&pbuf[i * 2]);
flag = (*(uint32 *)&hash[0] != 0x00000000) ? FLAG_TYPE_EXISTS : FLAG_TYPE_MISSING;
flag = FLAG_TYPE_EXISTS;
}
break;
}
@ -357,40 +390,39 @@ void CResourceFile::LoadResources()
}
}
#define LOG_PRINT_FAILED(str, argv)\
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; " str, argv);\
continue;
if (argc >= MAX_PARSE_ARGUMENT)
{
char pchar;
if (strlen(filename) <= 0)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; path to filename is empty on line %d\n", cline);
continue;
LOG_PRINT_FAILED("path to filename is empty on line %d\n", cline);
}
else if (!IsFileHasExtension(filename))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has no extension on line %d\n", cline);
continue;
LOG_PRINT_FAILED("filename has no extension on line %d\n", cline);
}
else if (!IsValidFilename(filename, pchar))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; filename has invalid character '%c' on line %d\n", pchar, cline);
continue;
LOG_PRINT_FAILED("filename has invalid character '%c' on line %d\n", (pchar, cline));
}
else if (flag == FLAG_TYPE_NONE)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing hash failed on line %d\n", cline);
continue;
LOG_PRINT_FAILED("parsing hash failed on line %d\n", cline);
}
else if (strlen(cmdBufExec) <= 0 && (flag != FLAG_TYPE_IGNORE && !bBreak))
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing command line is empty on line %d\n", cline);
continue;
LOG_PRINT_FAILED("parsing command line is empty on line %d\n", cline);
}
AddElement(filename, cmdBufExec, flag, *(uint32 *)&hash[0], cline, bBreak);
}
else if (pToken != NULL || argc > ARG_TYPE_FILE_NAME)
{
UTIL_Printf(__FUNCTION__ ": Failed to load \"" FILE_INI_RESOURCES "\"; parsing not enough arguments on line %d (got '%d', expected '%d')\n", cline, argc, MAX_PARSE_ARGUMENT);
LOG_PRINT_FAILED("parsing not enough arguments on line %d (got '%d', expected '%d')\n", (cline, argc, MAX_PARSE_ARGUMENT));
}
}
@ -484,7 +516,7 @@ void CResourceFile::AddElement(char *filename, char *cmdExec, flag_type_resource
void CResourceFile::AddFileResponse(IGameClient *pSenderClient, char *filename, uint32 hash)
{
m_responseList.push_back(new ResponseBuffer(pSenderClient, filename, hash));
m_responseList.push_back(new CResponseBuffer(pSenderClient, filename, hash));
}
bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource_t *resource, uint32 hash)
@ -492,11 +524,9 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
bool bHandled = false;
flag_type_resources typeFind;
std::vector<CResourceBuffer *> tempResourceList;
const char *hashFoundFile;
const char *prevHashFoundFile;
if (resource->type != t_decal
|| resource->nIndex < m_DecalsNum) // if by some miracle the decals will have the flag RES_CHECKFILE
|| resource->nIndex != 4095/*< m_DecalsNum*/) // if by some miracle the decals will have the flag RES_CHECKFILE
// to be sure not bypass the decals
{
AddFileResponse(pSenderClient, resource->szFileName, hash);
@ -561,23 +591,13 @@ bool CResourceFile::FileConsistencyResponse(IGameClient *pSenderClient, resource
}
if (typeFind != FLAG_TYPE_NONE)
{
if (hash != 0x0)
{
// push exec cmd
Exec.AddElement(pSenderClient, pRes, hash);
}
hashFoundFile = FindFilenameOfHash(hash);
prevHashFoundFile = FindFilenameOfHash(m_PrevHash);
if (prevHashFoundFile == NULL)
prevHashFoundFile = "null";
if (hashFoundFile == NULL)
hashFoundFile = "null";
Log(" -> file: (%s), exphash: (%x), got: (%x), typeFind: (%d), prevhash: (%x), (%s), prevfiles: (%s), findathash: (%s), md5hex: (%x)", pRes->GetFileName(), pRes->GetFileHash(), hash, typeFind, m_PrevHash, pSenderClient->GetName(), prevHashFoundFile, hashFoundFile, swap_endian(hash));
Log(" -> file: (%s), exphash: (%x), got: (%x), typeFind: (%d), prevhash: (%x), (%s), prevfile: (%s), findathash: (%s), md5hex: (%x)",
pRes->GetFileName(), pRes->GetFileHash(), hash, typeFind, m_PrevHash, pSenderClient->GetName(),
FindFilenameOfHash(m_PrevHash), FindFilenameOfHash(hash), _byteswap_ulong(hash));
}
bHandled = true;
@ -622,7 +642,7 @@ CResourceBuffer::CResourceBuffer(char *filename, char *cmdExec, flag_type_resour
m_Break = bBreak;
}
CResourceFile::ResponseBuffer::ResponseBuffer(IGameClient *pSenderClient, char *filename, uint32 hash)
CResourceFile::CResponseBuffer::CResponseBuffer(IGameClient *pSenderClient, char *filename, uint32 hash)
{
m_pClient = pSenderClient;
m_FileName = DuplicateString(filename);
@ -637,6 +657,5 @@ const char *CResourceFile::FindFilenameOfHash(uint32 hash)
return (*iter)->GetFileName();
}
return NULL;
return "null";
}

View File

@ -65,10 +65,10 @@ public:
private:
// buffer for response list
class ResponseBuffer
class CResponseBuffer
{
public:
ResponseBuffer(IGameClient *pSenderClient, char *filename, uint32 hash);
CResponseBuffer(IGameClient *pSenderClient, char *filename, uint32 hash);
IGameClient *GetGameClient() const { return m_pClient; };
const char *GetFileName() const { return m_FileName; };
@ -92,7 +92,7 @@ private:
private:
typedef std::vector<CResourceBuffer *> ResourceList;
typedef std::vector<ResponseBuffer *> ResponseList;
typedef std::vector<CResponseBuffer *> ResponseList;
ResourceList m_resourceList;
ResponseList m_responseList;