- added amb733 - running admin auth CheckSetAdmin

- fixed amb737 - reservedslots uses the new auth api
- fixed various FormatString() usage bugs in functions such as KickClient() and ServeRCommand()
- added API so sql admins will be fit into the whole system

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401279
This commit is contained in:
David Anderson 2007-08-08 16:22:51 +00:00
parent 77e46d363d
commit 6da3335588
6 changed files with 191 additions and 18 deletions

View File

@ -45,6 +45,8 @@
PlayerManager g_Players;
bool g_OnMapStarted = false;
IForward *PreAdminCheck = NULL;
IForward *PostAdminCheck = NULL;
SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
@ -112,6 +114,9 @@ void PlayerManager::OnSourceModAllInitialized()
m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
}
void PlayerManager::OnSourceModShutdown()
@ -135,6 +140,9 @@ void PlayerManager::OnSourceModShutdown()
g_Forwards.ReleaseForward(m_onActivate);
g_Forwards.ReleaseForward(m_onActivate2);
g_Forwards.ReleaseForward(PreAdminCheck);
g_Forwards.ReleaseForward(PostAdminCheck);
delete [] m_Players;
}
@ -751,6 +759,7 @@ CPlayer::CPlayer()
m_Admin = INVALID_ADMIN_ID;
m_TempAdmin = false;
m_Info = NULL;
m_bAdminCheckSignalled = false;
m_LastPassword.clear();
}
@ -760,6 +769,7 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
m_Name.assign(name);
m_Ip.assign(ip);
m_pEdict = pEntity;
m_iIndex = engine->IndexOfEdict(pEntity);
char ip2[24], *ptr;
strncopy(ip2, ip, sizeof(ip2));
@ -791,7 +801,7 @@ void CPlayer::Connect()
if (m_IsAuthorized)
{
DoBasicAdminChecks();
DoPostConnectAuthorization();
}
}
@ -817,6 +827,7 @@ void CPlayer::Disconnect()
m_AuthID.clear();
m_pEdict = NULL;
m_Info = NULL;
m_bAdminCheckSignalled = false;
}
void CPlayer::SetName(const char *name)
@ -902,8 +913,7 @@ void CPlayer::DumpAdmin(bool deleting)
void CPlayer::Kick(const char *str)
{
int client = engine->IndexOfEdict(m_pEdict);
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
pClient->Disconnect("%s", str);
}
@ -912,10 +922,49 @@ void CPlayer::Authorize_Post()
{
if (m_IsInGame)
{
DoBasicAdminChecks();
DoPostConnectAuthorization();
}
}
void CPlayer::DoPostConnectAuthorization()
{
cell_t result;
PreAdminCheck->PushCell(m_iIndex);
PreAdminCheck->Execute(&result);
/* Defer, for better or worse */
if ((ResultType)result >= Pl_Handled)
{
return;
}
/* Sanity check */
if (!IsConnected())
{
return;
}
/* Otherwise, go ahead and do admin checks */
DoBasicAdminChecks();
/* Send the notification out */
NotifyPostAdminChecks();
}
void CPlayer::NotifyPostAdminChecks()
{
if (m_bAdminCheckSignalled)
{
return;
}
/* Block beforehand so they can't double-call */
m_bAdminCheckSignalled = true;
PostAdminCheck->PushCell(m_iIndex);
PostAdminCheck->Execute(NULL);
}
void CPlayer::DoBasicAdminChecks()
{
if (GetAdminId() != INVALID_ADMIN_ID)

View File

@ -62,8 +62,10 @@ public:
void SetAdminId(AdminId id, bool temporary);
AdminId GetAdminId();
void Kick(const char *str);
public:
IPlayerInfo *GetPlayerInfo();
public:
void NotifyPostAdminChecks();
void DoBasicAdminChecks();
private:
void Initialize(const char *name, const char *ip, edict_t *pEntity);
void Connect();
@ -72,7 +74,7 @@ private:
void DumpAdmin(bool deleting);
void Authorize(const char *auth);
void Authorize_Post();
void DoBasicAdminChecks();
void DoPostConnectAuthorization();
private:
bool m_IsConnected;
bool m_IsInGame;
@ -86,6 +88,8 @@ private:
edict_t *m_pEdict;
IPlayerInfo *m_Info;
String m_LastPassword;
bool m_bAdminCheckSignalled;
int m_iIndex;
};
class PlayerManager :

View File

@ -702,10 +702,15 @@ static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params)
static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
{
g_SourceMod.SetGlobalTarget(LANG_SERVER);
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
g_SourceMod.SetGlobalTarget(LANG_SERVER);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
/* One byte for null terminator, one for newline */
buffer[len++] = '\n';
@ -718,10 +723,15 @@ static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
{
g_SourceMod.SetGlobalTarget(LANG_SERVER);
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
g_SourceMod.SetGlobalTarget(LANG_SERVER);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
/* One byte for null terminator, one for newline */
buffer[len++] = '\n';
@ -758,6 +768,11 @@ static cell_t sm_ClientCommand(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
return 1;
@ -781,6 +796,11 @@ static cell_t FakeClientCommand(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
unsigned int old = g_ChatTriggers.SetReplyTo(SM_REPLY_CONSOLE);
serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
g_ChatTriggers.SetReplyTo(old);
@ -796,6 +816,11 @@ static cell_t ReplyToCommand(IPluginContext *pContext, const cell_t *params)
char buffer[1024];
size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
/* If we're printing to the server, shortcut out */
if (params[1] == 0)
{

View File

@ -1020,6 +1020,11 @@ static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
char buffer[256];
g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
if (pContext->GetContext()->n_err != SP_ERROR_NONE)
{
return 0;
}
pClient->Disconnect("%s", buffer);
return 1;
@ -1048,6 +1053,45 @@ static cell_t ChangeClientTeam(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is invalid", client);
} else if (!pPlayer->IsInGame()) {
return pContext->ThrowNativeError("Client %d is not in game", client);
} else if (!pPlayer->IsAuthorized()) {
return pContext->ThrowNativeError("Client %d is not authorized", client);
}
AdminId id = pPlayer->GetAdminId();
pPlayer->DoBasicAdminChecks();
return (id != pPlayer->GetAdminId()) ? 1 : 0;
}
static cell_t NotifyPostAdminCheck(IPluginContext *pContext, const cell_t *params)
{
int client = params[1];
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer)
{
return pContext->ThrowNativeError("Client index %d is invalid", client);
} else if (!pPlayer->IsInGame()) {
return pContext->ThrowNativeError("Client %d is not in game", client);
} else if (!pPlayer->IsAuthorized()) {
return pContext->ThrowNativeError("Client %d is not authorized", client);
}
pPlayer->NotifyPostAdminChecks();
return 1;
}
REGISTER_NATIVES(playernatives)
{
{"AddUserFlags", AddUserFlags},
@ -1095,5 +1139,7 @@ REGISTER_NATIVES(playernatives)
{"ShowActivity", ShowActivity},
{"ShowActivityEx", ShowActivityEx},
{"KickClient", KickClient},
{"RunAdminCacheChecks", RunAdminCacheChecks},
{"NotifyPostAdminCheck", NotifyPostAdminCheck},
{NULL, NULL}
};

View File

@ -30,7 +30,7 @@ enum NetFlow
/**
* Called on client connection.
*
* @param client Player index.
* @param client Client index.
* @param rejectmsg Buffer to store the rejection message when the connection is refused.
* @param maxlen Maximum number of characters for rejection buffer.
* @return True to validate client's connection, false to refuse it.
@ -40,7 +40,7 @@ forward bool:OnClientConnect(client, String:rejectmsg[], maxlen);
/**
* Called when a client is entering to the game.
*
* @param client Player index.
* @param client Client index.
* @noreturn
*/
forward OnClientPutInServer(client);
@ -48,7 +48,7 @@ forward OnClientPutInServer(client);
/**
* Called when a client is disconnecting from the server.
*
* @param client Player index.
* @param client Client index.
* @noreturn
*/
forward OnClientDisconnect(client);
@ -56,7 +56,7 @@ forward OnClientDisconnect(client);
/**
* Called when a client is disconnected from the server.
*
* @param client Player index.
* @param client Client index.
* @noreturn
*/
forward OnClientDisconnect_Post(client);
@ -64,7 +64,7 @@ forward OnClientDisconnect_Post(client);
/**
* Called when a client is sending a command.
*
* @param client Player index.
* @param client Client index.
* @param args Number of arguments.
* @noreturn
*/
@ -73,20 +73,45 @@ forward Action:OnClientCommand(client, args);
/**
* Called whenever the client's settings are changed.
*
* @param client Player index.
* @param client Client index.
* @noreturn
*/
forward OnClientSettingsChanged(client);
/**
* Called when a client receives a Steam ID.
* @note This is called by bots, but the ID will be "BOT"
* Admin properties are not assigned here, but on OnClientPostAdminCheck().
* This is called by bots, but the ID will be "BOT".
*
* @param client Player index.
* @param auth Player auth string.
* @param client Client index.
* @param auth Client auth string.
* @noreturn
*/
forward OnClientAuthorized(client, const String:auth[]);
/**
* Called once a client is authorized and fully in-game, but
* before admin checks are done. This can be used to override
* the default admin checks for a client.
*
* Note: If handled/blocked, PostAdminCheck must be signalled
* manually via NotifyPostAdminCheck().
*
* @param client Client index.
* @return Plugin_Handled to block admin checks.
*/
forward Action:OnClientPreAdminCheck(client);
/**
* Called once a client is authorized and fully in-game, and
* after all post-connection authorizations have been performed.
*
* @param client Client index.
* @noreturn
*/
forward OnClientPostAdminCheck(client);
/**
* Returns the maximum number of clients allowed on the server.
*
@ -290,6 +315,30 @@ native GetUserFlagBits(client);
*/
native bool:CanUserTarget(client, target);
/**
* Runs through the Core-defined admin authorization checks on a player.
* Has no effect if the player is already an admin.
*
* Note: This function is based on the internal cache only.
*
* @param client Client index.
* @return True if access was changed, false if it did not.
* @error Invalid client index or client not in-game AND authorized.
*/
native bool:RunAdminCacheChecks(client);
/**
* Signals that a player has completed post-connection admin checks.
* Has no effect if the player has already had this event signalled.
*
* Note: This must be sent even if no admin id was assigned.
*
* @param client Client index.
* @noreturn
* @error Invalid client index or client not in-game AND authorized.
*/
native NotifyPostAdminCheck(client);
/**
* Creates a fake client.
*

View File

@ -63,7 +63,7 @@ public OnConfigsExecuted()
}
}
public OnClientAuthorized(client, const String:auth[])
public OnClientPostAdminCheck(client)
{
new reserved = GetConVarInt(sm_reserved_slots);