finished a(nother) rewrite of how players authenticate. name-based authentication has been added and passwords work fully now.
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401167
This commit is contained in:
parent
9ef04b07e7
commit
48d71cae26
@ -22,9 +22,10 @@
|
||||
//
|
||||
// setinfo "KEY" "PASSWORD"
|
||||
//
|
||||
// Where KEY is the "pw_auth" setting in your sourcemod.cfg file, and "PASSWORD"
|
||||
// is their password. This must be done before the authentication matches on the
|
||||
// server.
|
||||
// Where KEY is the "PassInfoVar" setting in your core.cfg file, and "PASSWORD"
|
||||
// is their password. With name based authentication, this must be done before
|
||||
// changing names or connecting. Otherwise, SourceMod will automatically detect
|
||||
// the password being set.
|
||||
//
|
||||
////////////////////////////////
|
||||
// Examples:
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "MenuStyle_Radio.h"
|
||||
#include "sm_stringutil.h"
|
||||
#include "CoreConfig.h"
|
||||
#include <inetchannel.h>
|
||||
#include <iclient.h>
|
||||
#include "TimerSys.h"
|
||||
|
||||
PlayerManager g_Players;
|
||||
bool g_OnMapStarted = false;
|
||||
@ -32,6 +35,25 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *)
|
||||
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
|
||||
SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
|
||||
|
||||
class KickPlayerTimer : public ITimedEvent
|
||||
{
|
||||
public:
|
||||
ResultType OnTimer(ITimer *pTimer, void *pData)
|
||||
{
|
||||
int userid = (int)pData;
|
||||
int client = g_Players.GetClientOfUserId(userid);
|
||||
if (client)
|
||||
{
|
||||
CPlayer *player = g_Players.GetPlayerByIndex(client);
|
||||
player->Kick("Your name is reserved by SourceMod; set your password to use it.");
|
||||
}
|
||||
return Pl_Stop;
|
||||
}
|
||||
void OnTimerEnd(ITimer *pTimer, void *pData)
|
||||
{
|
||||
}
|
||||
} s_KickPlayerTimer;
|
||||
|
||||
PlayerManager::PlayerManager()
|
||||
{
|
||||
m_AuthQueue = NULL;
|
||||
@ -159,6 +181,31 @@ bool PlayerManager::CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlayerManager::CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id)
|
||||
{
|
||||
const char *password = g_Admins.GetAdminPassword(id);
|
||||
if (password == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_PassInfoVar.size() < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Whoa... the user needs a password! */
|
||||
const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
|
||||
if (!given || strcmp(given, password) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pPlayer->SetAdminId(id, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerManager::RunAuthChecks()
|
||||
{
|
||||
CPlayer *pPlayer;
|
||||
@ -172,24 +219,13 @@ void PlayerManager::RunAuthChecks()
|
||||
&& (strcmp(authstr, "STEAM_ID_PENDING") != 0))
|
||||
{
|
||||
/* Set authorization */
|
||||
pPlayer->m_AuthID.assign(authstr);
|
||||
pPlayer->m_IsAuthorized = true;
|
||||
pPlayer->Authorize(authstr);
|
||||
|
||||
/* Mark as removed from queue */
|
||||
unsigned int client = m_AuthQueue[i];
|
||||
m_AuthQueue[i] = 0;
|
||||
removed++;
|
||||
|
||||
/* Do admin lookups */
|
||||
if (pPlayer->GetAdminId() == INVALID_ADMIN_ID)
|
||||
{
|
||||
AdminId id = g_Admins.FindAdminByIdentity("steam", authstr);
|
||||
if (id != INVALID_ADMIN_ID)
|
||||
{
|
||||
CheckSetAdmin(client, pPlayer, id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send to extensions */
|
||||
List<IClientListener *>::iterator iter;
|
||||
IClientListener *pListener;
|
||||
@ -211,6 +247,11 @@ void PlayerManager::RunAuthChecks()
|
||||
m_clauth->PushString(authstr);
|
||||
m_clauth->Execute(NULL);
|
||||
}
|
||||
|
||||
if (pPlayer->IsConnected())
|
||||
{
|
||||
pPlayer->Authorize_Post();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,23 +344,6 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
|
||||
}
|
||||
}
|
||||
|
||||
if (pPlayer->IsConnected())
|
||||
{
|
||||
/* Do an ip based lookup */
|
||||
char ip[24], *ptr;
|
||||
strncopy(ip, pszAddress, sizeof(ip));
|
||||
if ((ptr = strchr(ip, ':')) != NULL)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
AdminId id = g_Admins.FindAdminByIdentity("ip", ip);
|
||||
if (id != INVALID_ADMIN_ID)
|
||||
{
|
||||
CheckSetAdmin(client, pPlayer, id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -370,6 +394,15 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
|
||||
m_clauth->PushCell(client);
|
||||
m_clauth->PushString(authid);
|
||||
m_clauth->Execute(NULL);
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
pPlayer->Authorize_Post();
|
||||
if (!pPlayer->IsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,7 +557,46 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
|
||||
|
||||
m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
|
||||
m_clinfochanged->Execute(&res, NULL);
|
||||
m_Players[client].SetName(engine->GetClientConVarValue(client, "name"));
|
||||
|
||||
IPlayerInfo *info = m_Players[client].GetPlayerInfo();
|
||||
const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
|
||||
const char *old_name = m_Players[client].m_Name.c_str();
|
||||
|
||||
if (strcmp(old_name, new_name) != 0)
|
||||
{
|
||||
AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
|
||||
if (id != INVALID_ADMIN_ID && m_Players[client].GetAdminId() != id)
|
||||
{
|
||||
if (!CheckSetAdminName(client, &m_Players[client], id))
|
||||
{
|
||||
m_Players[client].Kick("Your name is reserved by SourceMod; set your password to use it.");
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
} else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
|
||||
if (id == m_Players[client].GetAdminId())
|
||||
{
|
||||
/* This player is changing their name; force them to drop admin privileges! */
|
||||
m_Players[client].SetAdminId(INVALID_ADMIN_ID, false);
|
||||
}
|
||||
}
|
||||
m_Players[client].SetName(new_name);
|
||||
}
|
||||
|
||||
if (m_PassInfoVar.size() > 0)
|
||||
{
|
||||
/* Try for a password change */
|
||||
const char *old_pass = m_Players[client].m_LastPassword.c_str();
|
||||
const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
|
||||
if (strcmp(old_pass, new_pass) != 0)
|
||||
{
|
||||
m_Players[client].m_LastPassword.assign(new_pass);
|
||||
if (m_Players[client].IsInGame() && m_Players[client].IsAuthorized())
|
||||
{
|
||||
/* If there is already an admin id assigned, this will just bail out. */
|
||||
m_Players[client].DoBasicAdminChecks();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PlayerManager::GetMaxClients()
|
||||
@ -631,6 +703,10 @@ void PlayerManager::ClearAllAdmins()
|
||||
}
|
||||
}
|
||||
|
||||
const char *PlayerManager::GetPassInfoVar()
|
||||
{
|
||||
return m_PassInfoVar.c_str();
|
||||
}
|
||||
|
||||
/*******************
|
||||
*** PLAYER CODE ***
|
||||
@ -645,6 +721,7 @@ CPlayer::CPlayer()
|
||||
m_Admin = INVALID_ADMIN_ID;
|
||||
m_TempAdmin = false;
|
||||
m_Info = NULL;
|
||||
m_LastPassword.clear();
|
||||
}
|
||||
|
||||
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
@ -653,15 +730,48 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
|
||||
m_Name.assign(name);
|
||||
m_Ip.assign(ip);
|
||||
m_pEdict = pEntity;
|
||||
|
||||
char ip2[24], *ptr;
|
||||
strncopy(ip2, ip, sizeof(ip2));
|
||||
if ((ptr = strchr(ip2, ':')) != NULL)
|
||||
{
|
||||
*ptr = '\0';
|
||||
}
|
||||
m_IpNoPort.assign(ip2);
|
||||
}
|
||||
|
||||
void CPlayer::Connect()
|
||||
{
|
||||
if (m_IsInGame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_IsInGame = true;
|
||||
|
||||
const char *var = g_Players.GetPassInfoVar();
|
||||
int client = engine->IndexOfEdict(m_pEdict);
|
||||
if (var[0] != '\0')
|
||||
{
|
||||
const char *pass = engine->GetClientConVarValue(client, var);
|
||||
m_LastPassword.assign(pass ? pass : "");
|
||||
} else {
|
||||
m_LastPassword.assign("");
|
||||
}
|
||||
|
||||
if (m_IsAuthorized)
|
||||
{
|
||||
DoBasicAdminChecks();
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::Authorize(const char *steamid)
|
||||
{
|
||||
if (m_IsAuthorized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_IsAuthorized = true;
|
||||
m_AuthID.assign(steamid);
|
||||
}
|
||||
@ -759,3 +869,59 @@ void CPlayer::DumpAdmin(bool deleting)
|
||||
m_TempAdmin = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::Kick(const char *str)
|
||||
{
|
||||
int client = engine->IndexOfEdict(m_pEdict);
|
||||
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
|
||||
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
|
||||
pClient->Disconnect("%s", str);
|
||||
}
|
||||
|
||||
void CPlayer::Authorize_Post()
|
||||
{
|
||||
if (m_IsInGame)
|
||||
{
|
||||
DoBasicAdminChecks();
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayer::DoBasicAdminChecks()
|
||||
{
|
||||
if (GetAdminId() != INVALID_ADMIN_ID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* First check the name */
|
||||
AdminId id;
|
||||
int client = engine->IndexOfEdict(m_pEdict);
|
||||
|
||||
if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
if (!g_Players.CheckSetAdminName(client, this, id))
|
||||
{
|
||||
int userid = engine->GetPlayerUserId(m_pEdict);
|
||||
g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check IP */
|
||||
if ((id = g_Admins.FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
if (g_Players.CheckSetAdmin(client, this, id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check IP address */
|
||||
if ((id = g_Admins.FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
|
||||
{
|
||||
if (g_Players.CheckSetAdmin(client, this, id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,26 +43,31 @@ public:
|
||||
bool IsFakeClient();
|
||||
void SetAdminId(AdminId id, bool temporary);
|
||||
AdminId GetAdminId();
|
||||
void Kick(const char *str);
|
||||
public:
|
||||
IPlayerInfo *GetPlayerInfo();
|
||||
private:
|
||||
void Initialize(const char *name, const char *ip, edict_t *pEntity);
|
||||
void Connect();
|
||||
void Authorize(const char *steamid);
|
||||
void Disconnect();
|
||||
void SetName(const char *name);
|
||||
void DumpAdmin(bool deleting);
|
||||
void Authorize(const char *auth);
|
||||
void Authorize_Post();
|
||||
void DoBasicAdminChecks();
|
||||
private:
|
||||
bool m_IsConnected;
|
||||
bool m_IsInGame;
|
||||
bool m_IsAuthorized;
|
||||
String m_Name;
|
||||
String m_Ip;
|
||||
String m_IpNoPort;
|
||||
String m_AuthID;
|
||||
AdminId m_Admin;
|
||||
bool m_TempAdmin;
|
||||
edict_t *m_pEdict;
|
||||
IPlayerInfo *m_Info;
|
||||
String m_LastPassword;
|
||||
};
|
||||
|
||||
class PlayerManager :
|
||||
@ -90,6 +95,7 @@ public:
|
||||
void OnClientDisconnect_Post(edict_t *pEntity);
|
||||
void OnClientCommand(edict_t *pEntity);
|
||||
void OnClientSettingsChanged(edict_t *pEntity);
|
||||
//void OnClientSettingsChanged_Pre(edict_t *pEntity);
|
||||
public: //IPlayerManager
|
||||
void AddClientListener(IClientListener *listener);
|
||||
void RemoveClientListener(IClientListener *listener);
|
||||
@ -107,9 +113,11 @@ public:
|
||||
{
|
||||
return m_PlayerCount;
|
||||
}
|
||||
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
||||
bool CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id);
|
||||
const char *GetPassInfoVar();
|
||||
private:
|
||||
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
bool CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id);
|
||||
private:
|
||||
List<IClientListener *> m_hooks;
|
||||
IForward *m_clconnect;
|
||||
|
Loading…
Reference in New Issue
Block a user