Skip to content

Commit

Permalink
Double auth for RCON, setemail cmd
Browse files Browse the repository at this point in the history
  • Loading branch information
necropotame committed Nov 14, 2016
1 parent 7adf347 commit 482fcef
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 33 deletions.
1 change: 1 addition & 0 deletions src/engine/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ class IServer : public IInterface
#ifdef CONF_SQL
virtual void Login(int ClientID, const char* pUsername, const char* pPassword) = 0;
virtual void Logout(int ClientID) = 0;
virtual void SetEmail(int ClientID, const char* pEmail) = 0;
virtual void Register(int ClientID, const char* pUsername, const char* pPassword, const char* pEmail) = 0;
virtual void ShowTop10(int ClientID, int ScoreType) = 0;
virtual void ShowChallenge(int ClientID) = 0;
Expand Down
157 changes: 125 additions & 32 deletions src/engine/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ void CServer::CClient::Reset(bool ResetScore)
m_WasInfected = 0;

m_UserID = -1;
m_UserLevel = SQL_USERLEVEL_NORMAL;
m_LogInstance = -1;

m_CustomSkin = 0;
Expand Down Expand Up @@ -963,6 +964,7 @@ int CServer::DelClientCallback(int ClientID, int Type, const char *pReason, void
pThis->m_aClients[ClientID].m_Snapshots.PurgeAll();
pThis->m_aClients[ClientID].m_WaitingTime = 0;
pThis->m_aClients[ClientID].m_UserID = -1;
pThis->m_aClients[ClientID].m_UserLevel = SQL_USERLEVEL_NORMAL;
pThis->m_aClients[ClientID].m_LogInstance = -1;
pThis->m_aClients[ClientID].m_Quitting = false;

Expand Down Expand Up @@ -1310,38 +1312,66 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
{
SendRconLine(ClientID, "You must use a client that support anti-spoof protection (DDNet-like)");
}
#ifdef CONF_SQL
else if(m_aClients[ClientID].m_UserID < 0)
{
SendRconLine(ClientID, "You must be logged to your account. Please use /login");
}
#endif
else if(g_Config.m_SvRconPassword[0] && str_comp(pPw, g_Config.m_SvRconPassword) == 0)
{
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
Msg.AddInt(1); //authed
Msg.AddInt(1); //cmdlist
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);

m_aClients[ClientID].m_Authed = AUTHED_ADMIN;
GameServer()->OnSetAuthed(ClientID, m_aClients[ClientID].m_Authed);
int SendRconCmds = Unpacker.GetInt();
if(Unpacker.Error() == 0 && SendRconCmds)
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER);
SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
#ifdef CONF_SQL
if(m_aClients[ClientID].m_UserLevel == SQL_USERLEVEL_ADMIN)
{
#endif
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
Msg.AddInt(1); //authed
Msg.AddInt(1); //cmdlist
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);

m_aClients[ClientID].m_Authed = AUTHED_ADMIN;
GameServer()->OnSetAuthed(ClientID, m_aClients[ClientID].m_Authed);
int SendRconCmds = Unpacker.GetInt();
if(Unpacker.Error() == 0 && SendRconCmds)
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_ADMIN, CFGFLAG_SERVER);
SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (admin)", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}
#ifdef CONF_SQL
else
{
SendRconLine(ClientID, "You are not admin.");
}
#endif
}
else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0)
{
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
Msg.AddInt(1); //authed
Msg.AddInt(1); //cmdlist
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);

m_aClients[ClientID].m_Authed = AUTHED_MOD;
int SendRconCmds = Unpacker.GetInt();
if(Unpacker.Error() == 0 && SendRconCmds)
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER);
SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
#ifdef CONF_SQL
if(m_aClients[ClientID].m_UserLevel == SQL_USERLEVEL_ADMIN || m_aClients[ClientID].m_UserLevel == SQL_USERLEVEL_MOD)
{
#endif
CMsgPacker Msg(NETMSG_RCON_AUTH_STATUS);
Msg.AddInt(1); //authed
Msg.AddInt(1); //cmdlist
SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true);

m_aClients[ClientID].m_Authed = AUTHED_MOD;
int SendRconCmds = Unpacker.GetInt();
if(Unpacker.Error() == 0 && SendRconCmds)
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_MOD, CFGFLAG_SERVER);
SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed (moderator)", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}
#ifdef CONF_SQL
else
{
SendRconLine(ClientID, "You are not moderator.");
}
#endif
}
else if(g_Config.m_SvRconMaxTries)
{
Expand Down Expand Up @@ -2739,7 +2769,7 @@ class CSqlJob_Server_Login : public CSqlJob
{
//Check for username/password
str_format(aBuf, sizeof(aBuf),
"SELECT UserId FROM %s_Users "
"SELECT UserId, Level FROM %s_Users "
"WHERE Username = '%s' AND PasswordHash = '%s';"
, pSqlServer->GetPrefix(), m_sName.ClrStr(), m_sPasswordHash.ClrStr());
pSqlServer->executeSqlQuery(aBuf);
Expand All @@ -2750,22 +2780,27 @@ class CSqlJob_Server_Login : public CSqlJob
if(m_pServer->m_aClients[m_ClientID].m_LogInstance == GetInstance())
{
int UserID = (int)pSqlServer->GetResults()->getInt("UserId");
int UserLevel = (int)pSqlServer->GetResults()->getInt("Level");
m_pServer->m_aClients[m_ClientID].m_UserID = UserID;
m_pServer->m_aClients[m_ClientID].m_UserLevel = UserLevel;
str_copy(m_pServer->m_aClients[m_ClientID].m_aUsername, m_sName.Str(), sizeof(m_pServer->m_aClients[m_ClientID].m_aUsername));

CServer::CGameServerCmd* pCmd = new CGameServerCmd_SendChatTarget_Language(m_ClientID, CHATCATEGORY_DEFAULT, "You are now logged.");
m_pServer->AddGameServerCmd(pCmd);

//If we are really unlucky, the client can deconnect and an another one connect during this small code
if(m_pServer->m_aClients[m_ClientID].m_LogInstance != GetInstance())
{
m_pServer->m_aClients[m_ClientID].m_UserID = -1;
m_pServer->m_aClients[m_ClientID].m_UserLevel = SQL_USERLEVEL_NORMAL;
}
else
{
CServer::CGameServerCmd* pCmd = new CGameServerCmd_SendChatTarget_Language(m_ClientID, CHATCATEGORY_DEFAULT, _("You are now logged."));
m_pServer->AddGameServerCmd(pCmd);
}
}
}
else
{
CServer::CGameServerCmd* pCmd = new CGameServerCmd_SendChatTarget_Language(m_ClientID, CHATCATEGORY_DEFAULT, "Wrong username/password.");
CServer::CGameServerCmd* pCmd = new CGameServerCmd_SendChatTarget_Language(m_ClientID, CHATCATEGORY_DEFAULT, _("Wrong username/password."));
m_pServer->AddGameServerCmd(pCmd);
}
}
Expand Down Expand Up @@ -2804,6 +2839,64 @@ void CServer::Login(int ClientID, const char* pUsername, const char* pPassword)
void CServer::Logout(int ClientID)
{
m_aClients[ClientID].m_UserID = -1;
m_aClients[ClientID].m_UserLevel = SQL_USERLEVEL_NORMAL;
}

class CSqlJob_Server_SetEmail : public CSqlJob
{
private:
CServer* m_pServer;
int m_ClientID;
int m_UserID;
CSqlString<64> m_sEmail;

public:
CSqlJob_Server_SetEmail(CServer* pServer, int ClientID, int UserID, const char* pEmail)
{
m_pServer = pServer;
m_ClientID = ClientID;
m_UserID = UserID;
m_sEmail = CSqlString<64>(pEmail);
}

virtual bool Job(CSqlServer* pSqlServer)
{
char aBuf[512];

try
{
str_format(aBuf, sizeof(aBuf),
"UPDATE %s_Users "
"SET Email = '%s' "
"WHERE UserId = '%d';"
, pSqlServer->GetPrefix(), m_sEmail.ClrStr(), m_UserID);

pSqlServer->executeSqlQuery(aBuf);
}
catch (sql::SQLException &e)
{
CServer::CGameServerCmd* pCmd = new CGameServerCmd_SendChatTarget_Language(m_ClientID, CHATCATEGORY_DEFAULT, _("An error occured during the operation."));
m_pServer->AddGameServerCmd(pCmd);
dbg_msg("sql", "Can't change email (MySQL Error: %s)", e.what());

return false;
}

return true;
}
};

void CServer::SetEmail(int ClientID, const char* pEmail)
{
if(m_aClients[ClientID].m_UserID < 0 && m_pGameServer)
{
m_pGameServer->SendChatTarget_Localization(ClientID, CHATCATEGORY_DEFAULT, _("You must be logged for this operation"), NULL);
}
else
{
CSqlJob* pJob = new CSqlJob_Server_SetEmail(this, ClientID, m_aClients[ClientID].m_UserID, pEmail);
pJob->Start();
}
}

class CSqlJob_Server_Register : public CSqlJob
Expand Down
2 changes: 2 additions & 0 deletions src/engine/server/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class CServer : public IServer
//Login
int m_LogInstance;
int m_UserID;
int m_UserLevel;
char m_aUsername[MAX_NAME_LENGTH];
};

Expand Down Expand Up @@ -324,6 +325,7 @@ class CServer : public IServer
#ifdef CONF_SQL
virtual void Login(int ClientID, const char* pUsername, const char* pPassword);
virtual void Logout(int ClientID);
virtual void SetEmail(int ClientID, const char* pEmail);
virtual void Register(int ClientID, const char* pUsername, const char* pPassword, const char* pEmail);
virtual void ShowChallenge(int ClientID);
virtual void ShowTop10(int ClientID, int ScoreType);
Expand Down
1 change: 1 addition & 0 deletions src/engine/server/sql_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ void CSqlServer::CreateTables()
"Username VARCHAR(64) BINARY NOT NULL, "
"Email VARCHAR(64) BINARY NOT NULL, "
"PasswordHash VARCHAR(64) BINARY NOT NULL, "
"Level INT DEFAULT '0' NOT NULL, "
"RegisterDate DATETIME NOT NULL, "
"RegisterIp VARCHAR(64) NOT NULL, " //The IP is kept in order to prevent registration flooding
"PRIMARY KEY (UserId)"
Expand Down
7 changes: 7 additions & 0 deletions src/engine/server/sql_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ enum
SQL_SCORE_NUMROUND=32,
};

enum
{
SQL_USERLEVEL_NORMAL = 0,
SQL_USERLEVEL_MOD = 1,
SQL_USERLEVEL_ADMIN = 2,
};

class CSqlServer
{
public:
Expand Down
18 changes: 17 additions & 1 deletion src/game/server/gamecontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2501,6 +2501,18 @@ bool CGameContext::ConLogout(IConsole::IResult *pResult, void *pUserData)
return true;
}

bool CGameContext::ConSetEmail(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
int ClientID = pResult->GetClientID();

const char *pEmail = pResult->GetString(0);

pSelf->Server()->SetEmail(ClientID, pEmail);

return true;
}

bool CGameContext::ConChallenge(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
Expand Down Expand Up @@ -3063,7 +3075,9 @@ bool CGameContext::ConCmdList(IConsole::IResult *pResult, void *pUserData)
pSelf->Server()->Localization()->Format_L(Buffer, pLanguage, "/alwaysrandom, /customskin, /help, /info, /language", NULL);
Buffer.append("\n\n");
#ifdef CONF_SQL
pSelf->Server()->Localization()->Format_L(Buffer, pLanguage, "/register, /login, /logout, /challenge, /top10, /rank, /goal", NULL);
pSelf->Server()->Localization()->Format_L(Buffer, pLanguage, "/register, /login, /logout, /setemail", NULL);
Buffer.append("\n\n");
pSelf->Server()->Localization()->Format_L(Buffer, pLanguage, "/challenge, /top10, /rank, /goal", NULL);
Buffer.append("\n\n");
#endif
pSelf->Server()->Localization()->Format_L(Buffer, pLanguage, _("Press <F3> or <F4> to enable or disable hook protection"), NULL);
Expand Down Expand Up @@ -3144,6 +3158,8 @@ void CGameContext::OnConsoleInit()
Console()->Register("register", "s<username> s<password> ?s<email>", CFGFLAG_CHAT|CFGFLAG_USER, ConRegister, this, "Create an account");
Console()->Register("login", "s<username> s<password>", CFGFLAG_CHAT|CFGFLAG_USER, ConLogin, this, "Login to an account");
Console()->Register("logout", "", CFGFLAG_CHAT|CFGFLAG_USER, ConLogout, this, "Logout");
Console()->Register("setemail", "s<email>", CFGFLAG_CHAT|CFGFLAG_USER, ConSetEmail, this, "Change your email");

Console()->Register("top10", "?s<classname>", CFGFLAG_CHAT|CFGFLAG_USER, ConTop10, this, "Show the top 10 on the current map");
Console()->Register("challenge", "", CFGFLAG_CHAT|CFGFLAG_USER, ConChallenge, this, "Show the current winner of the challenge");
Console()->Register("rank", "?s<classname>", CFGFLAG_CHAT|CFGFLAG_USER, ConRank, this, "Show your rank");
Expand Down
1 change: 1 addition & 0 deletions src/game/server/gamecontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ class CGameContext : public IGameServer
static bool ConRegister(IConsole::IResult *pResult, void *pUserData);
static bool ConLogin(IConsole::IResult *pResult, void *pUserData);
static bool ConLogout(IConsole::IResult *pResult, void *pUserData);
static bool ConSetEmail(IConsole::IResult *pResult, void *pUserData);
static bool ConTop10(IConsole::IResult *pResult, void *pUserData);
static bool ConChallenge(IConsole::IResult *pResult, void *pUserData);
static bool ConRank(IConsole::IResult *pResult, void *pUserData);
Expand Down

0 comments on commit 482fcef

Please sign in to comment.