Only allow savegames on same server. Clean up saving a bit and prevent another possible exploit

This commit is contained in:
def 2014-12-17 20:38:05 +01:00
parent f397838741
commit 2750a23792
5 changed files with 81 additions and 50 deletions

View file

@ -209,7 +209,7 @@ CSaveTeam::~CSaveTeam()
int CSaveTeam::save(int Team)
{
if(g_Config.m_SvTeam == 3 || (Team > 0 && Team < 64))
if(g_Config.m_SvTeam == 3 || (Team > 0 && Team < MAX_CLIENTS))
{
CGameTeams* Teams = &(((CGameControllerDDRace*)m_pController)->m_Teams);
@ -225,7 +225,7 @@ int CSaveTeam::save(int Team)
SavedTees = new CSaveTee[m_MembersCount];
int j = 0;
for (int i = 0; i<64; i++)
for (int i = 0; i < MAX_CLIENTS; i++)
{
if(Teams->m_Core.Team(i) == Team)
{
@ -259,53 +259,52 @@ int CSaveTeam::save(int Team)
int CSaveTeam::load(int Team)
{
if(Team > 0 && Team < 64)
if(Team < 0 || Team >= MAX_CLIENTS)
return 1;
CGameTeams* Teams = &(((CGameControllerDDRace*)m_pController)->m_Teams);
Teams->ChangeTeamState(Team, m_TeamState);
Teams->SetTeamLock(Team, m_TeamLocked);
CCharacter* pchr;
for (int i = 0; i<m_MembersCount; i++)
{
CGameTeams* Teams = &(((CGameControllerDDRace*)m_pController)->m_Teams);
Teams->ChangeTeamState(Team, m_TeamState);
Teams->SetTeamLock(Team, m_TeamLocked);
CCharacter* pchr;
for (int i = 0; i<m_MembersCount; i++)
int ID = MatchPlayer(SavedTees[i].GetName());
if(ID == -1) // first check if team can be loaded / do not load half teams
{
int ID = MatchPlayer(SavedTees[i].GetName());
if(ID == -1) // first check if team can be loaded / do not load half teams
{
return i+10; // +10 to let space for other return-values
}
else if (m_pController->GameServer()->m_apPlayers[ID]->GetCharacter() && m_pController->GameServer()->m_apPlayers[ID]->GetCharacter()->m_DDRaceState)
{
return i+100; // +100 to let space for other return-values
}
return i+10; // +10 to let space for other return-values
}
for (int i = 0; i<m_MembersCount; i++)
else if (m_pController->GameServer()->m_apPlayers[ID]->GetCharacter() && m_pController->GameServer()->m_apPlayers[ID]->GetCharacter()->m_DDRaceState)
{
pchr = MatchCharacter(SavedTees[i].GetName(), i);
if(pchr)
{
SavedTees[i].load(pchr, Team);
}
return i+100; // +100 to let space for other return-values
}
if(m_pController->GameServer()->Collision()->m_NumSwitchers)
for(int i=1; i < m_pController->GameServer()->Collision()->m_NumSwitchers+1; i++)
{
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_Status[Team] = m_Switchers[i].m_Status;
if(m_Switchers[i].m_EndTime)
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_EndTick[Team] = m_pController->Server()->Tick() - m_Switchers[i].m_EndTime;
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_Type[Team] = m_Switchers[i].m_Type;
}
return 0;
}
return 1;
for (int i = 0; i<m_MembersCount; i++)
{
pchr = MatchCharacter(SavedTees[i].GetName(), i);
if(pchr)
{
SavedTees[i].load(pchr, Team);
}
}
if(m_pController->GameServer()->Collision()->m_NumSwitchers)
for(int i=1; i < m_pController->GameServer()->Collision()->m_NumSwitchers+1; i++)
{
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_Status[Team] = m_Switchers[i].m_Status;
if(m_Switchers[i].m_EndTime)
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_EndTick[Team] = m_pController->Server()->Tick() - m_Switchers[i].m_EndTime;
m_pController->GameServer()->Collision()->m_pSwitchers[i].m_Type[Team] = m_Switchers[i].m_Type;
}
return 0;
}
int CSaveTeam::MatchPlayer(char name[16])
{
for (int i = 0; i<64; i++)
for (int i = 0; i < MAX_CLIENTS; i++)
{
if(str_comp(m_pController->Server()->ClientName(i), name) == 0)
{
@ -356,7 +355,7 @@ char* CSaveTeam::GetString()
int CSaveTeam::LoadString(const char* String)
{
char TeamStats[64];
char TeamStats[MAX_CLIENTS];
char Switcher[64];
char SaveTee[1024];

View file

@ -175,7 +175,7 @@ void CSqlScore::Init()
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_maps (Map VARCHAR(128) BINARY NOT NULL, Server VARCHAR(32) BINARY NOT NULL, Mapper VARCHAR(128) BINARY NOT NULL, Points INT DEFAULT 0, Stars INT DEFAULT 0, UNIQUE KEY Map (Map)) CHARACTER SET utf8 ;", m_pPrefix);
m_pStatement->execute(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_saves (Savegame TEXT CHARACTER SET utf8 BINARY NOT NULL, Map VARCHAR(128) BINARY NOT NULL, Code VARCHAR(128) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY (Map, Code)) CHARACTER SET utf8 ;", m_pPrefix);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_saves (Savegame TEXT CHARACTER SET utf8 BINARY NOT NULL, Map VARCHAR(128) BINARY NOT NULL, Code VARCHAR(128) BINARY NOT NULL, Timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, Server CHAR(3), UNIQUE KEY (Map, Code)) CHARACTER SET utf8 ;", m_pPrefix);
m_pStatement->execute(aBuf);
str_format(aBuf, sizeof(aBuf), "CREATE TABLE IF NOT EXISTS %s_points (Name VARCHAR(%d) BINARY NOT NULL, Points INT DEFAULT 0, UNIQUE KEY Name (Name)) CHARACTER SET utf8 ;", m_pPrefix, MAX_NAME_LENGTH);
@ -1611,6 +1611,15 @@ void CSqlScore::SaveTeam(int Team, const char* Code, int ClientID)
str_copy(Tmp->m_Code, Code, 32);
Tmp->m_pSqlData = this;
if((g_Config.m_SvTeam == 3 || (Team > 0 && Team < MAX_CLIENTS)) && ((CGameControllerDDRace*)(GameServer()->m_pController))->m_Teams.Count(Team) > 0)
{
if(((CGameControllerDDRace*)(GameServer()->m_pController))->m_Teams.GetSaving(Team))
return;
((CGameControllerDDRace*)(GameServer()->m_pController))->m_Teams.SetSaving(Team, true);
}
else
return;
void *SaveThread = thread_create(SaveTeamThread, Tmp);
#if defined(CONF_FAMILY_UNIX)
pthread_detach((pthread_t)SaveThread);
@ -1634,7 +1643,7 @@ void CSqlScore::SaveTeamThread(void *pUser)
int Num = -1;
if((g_Config.m_SvTeam == 3 || (Team > 0 && Team < 64)) && ((CGameControllerDDRace*)(pData->m_pSqlData->GameServer()->m_pController))->m_Teams.Count(Team) > 0)
if((g_Config.m_SvTeam == 3 || (Team > 0 && Team < MAX_CLIENTS)) && ((CGameControllerDDRace*)(pData->m_pSqlData->GameServer()->m_pController))->m_Teams.Count(Team) > 0)
{
SavedTeam = new CSaveTeam(pData->m_pSqlData->GameServer()->m_pController);
Num = SavedTeam->save(Team);
@ -1671,7 +1680,7 @@ void CSqlScore::SaveTeamThread(void *pUser)
delete pData->m_pSqlData->m_pResults;
char aBuf[65536];
str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_saves(Savegame, Map, Code, Timestamp) VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP())", pData->m_pSqlData->m_pPrefix, TeamString, Map, pData->m_Code);
str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_saves(Savegame, Map, Code, Timestamp, Server) VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP(), '%s')", pData->m_pSqlData->m_pPrefix, TeamString, Map, pData->m_Code, g_Config.m_SvSqlServerName);
pData->m_pSqlData->m_pStatement->execute(aBuf);
char aBuf2[256];
@ -1707,6 +1716,8 @@ void CSqlScore::SaveTeamThread(void *pUser)
if(SavedTeam)
delete SavedTeam;
((CGameControllerDDRace*)(pData->m_pSqlData->GameServer()->m_pController))->m_Teams.SetSaving(Team, false);
lock_release(gs_SqlLock);
}
@ -1743,12 +1754,22 @@ void CSqlScore::LoadTeamThread(void *pUser)
try
{
char aBuf[768];
str_format(aBuf, sizeof(aBuf), "select Savegame, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago from %s_saves where Code = '%s' and Map = '%s';", pData->m_pSqlData->m_pPrefix, pData->m_Code, Map);
str_format(aBuf, sizeof(aBuf), "select Savegame, Server, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago from %s_saves where Code = '%s' and Map = '%s';", pData->m_pSqlData->m_pPrefix, pData->m_Code, Map);
pData->m_pSqlData->m_pResults = pData->m_pSqlData->m_pStatement->executeQuery(aBuf);
if (pData->m_pSqlData->m_pResults->rowsCount() > 0)
{
pData->m_pSqlData->m_pResults->first();
char ServerName[4];
str_copy(ServerName, pData->m_pSqlData->m_pResults->getString("Server").c_str(), sizeof(ServerName));
if(str_comp(ServerName, g_Config.m_SvSqlServerName))
{
str_format(aBuf, sizeof(aBuf), "You have to be on the '%s' server to load this savegame", ServerName);
pData->m_pSqlData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf);
goto end;
}
pData->m_pSqlData->m_pResults->getInt("Ago");
int since = (int)pData->m_pSqlData->m_pResults->getInt("Ago");
if(since < g_Config.m_SvSaveGamesDelay)

View file

@ -19,6 +19,7 @@ void CGameTeams::Reset()
m_MembersCount[i] = 0;
m_LastChat[i] = 0;
m_TeamLocked[i] = false;
m_IsSaving[i] = false;
}
}

View file

@ -11,6 +11,7 @@ class CGameTeams
int m_MembersCount[MAX_CLIENTS];
bool m_TeeFinished[MAX_CLIENTS];
bool m_TeamLocked[MAX_CLIENTS];
bool m_IsSaving[MAX_CLIENTS];
class CGameContext * m_pGameContext;
@ -81,16 +82,17 @@ public:
void OnTeamFinish(CPlayer** Players, unsigned int Size);
void OnFinish(CPlayer* Player);
void KillSavedTeam(int Team);
bool TeeFinished(int ClientID)
{
return m_TeeFinished[ClientID];
}
;
int GetTeamState(int Team)
{
return m_TeamState[Team];
}
;
bool TeamLocked(int Team)
{
if (Team <= TEAM_FLOCK || Team >= TEAM_SUPER)
@ -98,12 +100,21 @@ public:
return m_TeamLocked[Team];
}
;
void SetFinished(int ClientID, bool finished)
{
m_TeeFinished[ClientID] = finished;
}
;
void SetSaving(int TeamID, bool Value)
{
m_IsSaving[TeamID] = Value;
}
bool GetSaving(int TeamID)
{
return m_IsSaving[TeamID];
}
};
#endif

View file

@ -11,7 +11,6 @@ enum
class CTeamsCore
{
int m_Team[MAX_CLIENTS];
bool m_IsSolo[MAX_CLIENTS];
public:
@ -31,7 +30,7 @@ public:
{
m_IsSolo[ClientID] = Value;
}
;
bool GetSolo(int ClientID)
{
return m_IsSolo[ClientID];