- added amb733 - running admin auth CheckSetAdmin
authorDavid Anderson <dvander@alliedmods.net>
Wed Aug 08 16:22:51 2007 +0000 (2007-08-08)
changeset 12739afc766f8e9c
parent 1272 95787f8d2b77
child 1274 6845d215692f
- 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
core/PlayerManager.cpp
core/PlayerManager.h
core/smn_console.cpp
core/smn_player.cpp
plugins/include/clients.inc
plugins/reservedslots.sp
     1.1 --- a/core/PlayerManager.cpp	Wed Aug 08 15:08:01 2007 +0000
     1.2 +++ b/core/PlayerManager.cpp	Wed Aug 08 16:22:51 2007 +0000
     1.3 @@ -45,6 +45,8 @@
     1.4  
     1.5  PlayerManager g_Players;
     1.6  bool g_OnMapStarted = false;
     1.7 +IForward *PreAdminCheck = NULL;
     1.8 +IForward *PostAdminCheck = NULL;
     1.9  
    1.10  SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
    1.11  SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
    1.12 @@ -112,6 +114,9 @@
    1.13  	m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
    1.14  	m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
    1.15  	m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
    1.16 +
    1.17 +	PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
    1.18 +	PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
    1.19  }
    1.20  
    1.21  void PlayerManager::OnSourceModShutdown()
    1.22 @@ -135,6 +140,9 @@
    1.23  	g_Forwards.ReleaseForward(m_onActivate);
    1.24  	g_Forwards.ReleaseForward(m_onActivate2);
    1.25  
    1.26 +	g_Forwards.ReleaseForward(PreAdminCheck);
    1.27 +	g_Forwards.ReleaseForward(PostAdminCheck);
    1.28 +
    1.29  	delete [] m_Players;
    1.30  }
    1.31  
    1.32 @@ -751,6 +759,7 @@
    1.33  	m_Admin = INVALID_ADMIN_ID;
    1.34  	m_TempAdmin = false;
    1.35  	m_Info = NULL;
    1.36 +	m_bAdminCheckSignalled = false;
    1.37  	m_LastPassword.clear();
    1.38  }
    1.39  
    1.40 @@ -760,6 +769,7 @@
    1.41  	m_Name.assign(name);
    1.42  	m_Ip.assign(ip);
    1.43  	m_pEdict = pEntity;
    1.44 +	m_iIndex = engine->IndexOfEdict(pEntity);
    1.45  
    1.46  	char ip2[24], *ptr;
    1.47  	strncopy(ip2, ip, sizeof(ip2));
    1.48 @@ -791,7 +801,7 @@
    1.49  
    1.50  	if (m_IsAuthorized)
    1.51  	{
    1.52 -		DoBasicAdminChecks();
    1.53 +		DoPostConnectAuthorization();
    1.54  	}
    1.55  }
    1.56  
    1.57 @@ -817,6 +827,7 @@
    1.58  	m_AuthID.clear();
    1.59  	m_pEdict = NULL;
    1.60  	m_Info = NULL;
    1.61 +	m_bAdminCheckSignalled = false;
    1.62  }
    1.63  
    1.64  void CPlayer::SetName(const char *name)
    1.65 @@ -902,8 +913,7 @@
    1.66  
    1.67  void CPlayer::Kick(const char *str)
    1.68  {
    1.69 -	int client = engine->IndexOfEdict(m_pEdict);
    1.70 -	INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
    1.71 +	INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
    1.72  	IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
    1.73  	pClient->Disconnect("%s", str);
    1.74  }
    1.75 @@ -912,8 +922,47 @@
    1.76  {
    1.77  	if (m_IsInGame)
    1.78  	{
    1.79 -		DoBasicAdminChecks();
    1.80 +		DoPostConnectAuthorization();
    1.81 +	}
    1.82 +}
    1.83 +
    1.84 +void CPlayer::DoPostConnectAuthorization()
    1.85 +{
    1.86 +	cell_t result;
    1.87 +	PreAdminCheck->PushCell(m_iIndex);
    1.88 +	PreAdminCheck->Execute(&result);
    1.89 +
    1.90 +	/* Defer, for better or worse */
    1.91 +	if ((ResultType)result >= Pl_Handled)
    1.92 +	{
    1.93 +		return;
    1.94 +	}
    1.95 +
    1.96 +	/* Sanity check */
    1.97 +	if (!IsConnected())
    1.98 +	{
    1.99 +		return;
   1.100  	}
   1.101 +
   1.102 +	/* Otherwise, go ahead and do admin checks */
   1.103 +	DoBasicAdminChecks();
   1.104 +
   1.105 +	/* Send the notification out */
   1.106 +	NotifyPostAdminChecks();
   1.107 +}
   1.108 +
   1.109 +void CPlayer::NotifyPostAdminChecks()
   1.110 +{
   1.111 +	if (m_bAdminCheckSignalled)
   1.112 +	{
   1.113 +		return;
   1.114 +	}
   1.115 +
   1.116 +	/* Block beforehand so they can't double-call */
   1.117 +	m_bAdminCheckSignalled = true;
   1.118 +
   1.119 +	PostAdminCheck->PushCell(m_iIndex);
   1.120 +	PostAdminCheck->Execute(NULL);
   1.121  }
   1.122  
   1.123  void CPlayer::DoBasicAdminChecks()
     2.1 --- a/core/PlayerManager.h	Wed Aug 08 15:08:01 2007 +0000
     2.2 +++ b/core/PlayerManager.h	Wed Aug 08 16:22:51 2007 +0000
     2.3 @@ -62,8 +62,10 @@
     2.4  	void SetAdminId(AdminId id, bool temporary);
     2.5  	AdminId GetAdminId();
     2.6  	void Kick(const char *str);
     2.7 +	IPlayerInfo *GetPlayerInfo();
     2.8  public:
     2.9 -	IPlayerInfo *GetPlayerInfo();
    2.10 +	void NotifyPostAdminChecks();
    2.11 +	void DoBasicAdminChecks();
    2.12  private:
    2.13  	void Initialize(const char *name, const char *ip, edict_t *pEntity);
    2.14  	void Connect();
    2.15 @@ -72,7 +74,7 @@
    2.16  	void DumpAdmin(bool deleting);
    2.17  	void Authorize(const char *auth);
    2.18  	void Authorize_Post();
    2.19 -	void DoBasicAdminChecks();
    2.20 +	void DoPostConnectAuthorization();
    2.21  private:
    2.22  	bool m_IsConnected;
    2.23  	bool m_IsInGame;
    2.24 @@ -86,6 +88,8 @@
    2.25  	edict_t *m_pEdict;
    2.26  	IPlayerInfo *m_Info;
    2.27  	String m_LastPassword;
    2.28 +	bool m_bAdminCheckSignalled;
    2.29 +	int m_iIndex;
    2.30  };
    2.31  
    2.32  class PlayerManager : 
     3.1 --- a/core/smn_console.cpp	Wed Aug 08 15:08:01 2007 +0000
     3.2 +++ b/core/smn_console.cpp	Wed Aug 08 16:22:51 2007 +0000
     3.3 @@ -702,10 +702,15 @@
     3.4  
     3.5  static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
     3.6  {
     3.7 +	g_SourceMod.SetGlobalTarget(LANG_SERVER);
     3.8 +
     3.9  	char buffer[1024];
    3.10  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
    3.11  
    3.12 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    3.13 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    3.14 +	{
    3.15 +		return 0;
    3.16 +	}
    3.17  
    3.18  	/* One byte for null terminator, one for newline */
    3.19  	buffer[len++] = '\n';
    3.20 @@ -718,10 +723,15 @@
    3.21  
    3.22  static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
    3.23  {
    3.24 +	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    3.25 +
    3.26  	char buffer[1024];
    3.27  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
    3.28  
    3.29 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    3.30 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    3.31 +	{
    3.32 +		return 0;
    3.33 +	}
    3.34  
    3.35  	/* One byte for null terminator, one for newline */
    3.36  	buffer[len++] = '\n';
    3.37 @@ -758,6 +768,11 @@
    3.38  	char buffer[256];
    3.39  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
    3.40  
    3.41 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    3.42 +	{
    3.43 +		return 0;
    3.44 +	}
    3.45 +
    3.46  	engine->ClientCommand(pPlayer->GetEdict(), "%s", buffer);
    3.47  
    3.48  	return 1;
    3.49 @@ -781,6 +796,11 @@
    3.50  	char buffer[256];
    3.51  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
    3.52  
    3.53 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    3.54 +	{
    3.55 +		return 0;
    3.56 +	}
    3.57 +
    3.58  	unsigned int old = g_ChatTriggers.SetReplyTo(SM_REPLY_CONSOLE);
    3.59  	serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), buffer);
    3.60  	g_ChatTriggers.SetReplyTo(old);
    3.61 @@ -796,6 +816,11 @@
    3.62  	char buffer[1024];
    3.63  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 2);
    3.64  
    3.65 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    3.66 +	{
    3.67 +		return 0;
    3.68 +	}
    3.69 +
    3.70  	/* If we're printing to the server, shortcut out */
    3.71  	if (params[1] == 0)
    3.72  	{
     4.1 --- a/core/smn_player.cpp	Wed Aug 08 15:08:01 2007 +0000
     4.2 +++ b/core/smn_player.cpp	Wed Aug 08 16:22:51 2007 +0000
     4.3 @@ -1020,6 +1020,11 @@
     4.4  	char buffer[256];
     4.5  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
     4.6  
     4.7 +	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
     4.8 +	{
     4.9 +		return 0;
    4.10 +	}
    4.11 +
    4.12  	pClient->Disconnect("%s", buffer);
    4.13  
    4.14  	return 1;
    4.15 @@ -1048,6 +1053,45 @@
    4.16  	return 1;
    4.17  }
    4.18  
    4.19 +static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
    4.20 +{
    4.21 +	int client = params[1];
    4.22 +
    4.23 +	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
    4.24 +	if (!pPlayer)
    4.25 +	{
    4.26 +		return pContext->ThrowNativeError("Client index %d is invalid", client);
    4.27 +	} else if (!pPlayer->IsInGame()) {
    4.28 +		return pContext->ThrowNativeError("Client %d is not in game", client);
    4.29 +	} else if (!pPlayer->IsAuthorized()) {
    4.30 +		return pContext->ThrowNativeError("Client %d is not authorized", client);
    4.31 +	}
    4.32 +
    4.33 +	AdminId id = pPlayer->GetAdminId();
    4.34 +	pPlayer->DoBasicAdminChecks();
    4.35 +
    4.36 +	return (id != pPlayer->GetAdminId()) ? 1 : 0;
    4.37 +}
    4.38 +
    4.39 +static cell_t NotifyPostAdminCheck(IPluginContext *pContext, const cell_t *params)
    4.40 +{
    4.41 +	int client = params[1];
    4.42 +
    4.43 +	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
    4.44 +	if (!pPlayer)
    4.45 +	{
    4.46 +		return pContext->ThrowNativeError("Client index %d is invalid", client);
    4.47 +	} else if (!pPlayer->IsInGame()) {
    4.48 +		return pContext->ThrowNativeError("Client %d is not in game", client);
    4.49 +	} else if (!pPlayer->IsAuthorized()) {
    4.50 +		return pContext->ThrowNativeError("Client %d is not authorized", client);
    4.51 +	}
    4.52 +
    4.53 +	pPlayer->NotifyPostAdminChecks();
    4.54 +
    4.55 +	return 1;
    4.56 +}
    4.57 +
    4.58  REGISTER_NATIVES(playernatives)
    4.59  {
    4.60  	{"AddUserFlags",			AddUserFlags},
    4.61 @@ -1095,5 +1139,7 @@
    4.62  	{"ShowActivity",			ShowActivity},
    4.63  	{"ShowActivityEx",			ShowActivityEx},
    4.64  	{"KickClient",				KickClient},
    4.65 +	{"RunAdminCacheChecks",		RunAdminCacheChecks},
    4.66 +	{"NotifyPostAdminCheck",	NotifyPostAdminCheck},
    4.67  	{NULL,						NULL}
    4.68  };
     5.1 --- a/plugins/include/clients.inc	Wed Aug 08 15:08:01 2007 +0000
     5.2 +++ b/plugins/include/clients.inc	Wed Aug 08 16:22:51 2007 +0000
     5.3 @@ -30,7 +30,7 @@
     5.4  /**
     5.5   * Called on client connection.
     5.6   *
     5.7 - * @param client		Player index.
     5.8 + * @param client		Client index.
     5.9   * @param rejectmsg		Buffer to store the rejection message when the connection is refused.
    5.10   * @param maxlen		Maximum number of characters for rejection buffer.
    5.11   * @return				True to validate client's connection, false to refuse it.
    5.12 @@ -40,7 +40,7 @@
    5.13  /**
    5.14   * Called when a client is entering to the game.
    5.15   *
    5.16 - * @param client		Player index.
    5.17 + * @param client		Client index.
    5.18   * @noreturn
    5.19   */
    5.20  forward OnClientPutInServer(client);
    5.21 @@ -48,7 +48,7 @@
    5.22  /**
    5.23   * Called when a client is disconnecting from the server.
    5.24   *
    5.25 - * @param client		Player index.
    5.26 + * @param client		Client index.
    5.27   * @noreturn
    5.28   */
    5.29  forward OnClientDisconnect(client);
    5.30 @@ -56,7 +56,7 @@
    5.31  /**
    5.32   * Called when a client is disconnected from the server.
    5.33   *
    5.34 - * @param client		Player index.
    5.35 + * @param client		Client index.
    5.36   * @noreturn
    5.37   */
    5.38  forward OnClientDisconnect_Post(client);
    5.39 @@ -64,7 +64,7 @@
    5.40  /**
    5.41   * Called when a client is sending a command.
    5.42   *
    5.43 - * @param client		Player index.
    5.44 + * @param client		Client index.
    5.45   * @param args			Number of arguments.
    5.46   * @noreturn
    5.47   */
    5.48 @@ -73,21 +73,46 @@
    5.49  /**
    5.50   * Called whenever the client's settings are changed.
    5.51   *
    5.52 - * @param client		Player index.
    5.53 + * @param client		Client index.
    5.54   * @noreturn
    5.55   */
    5.56  forward OnClientSettingsChanged(client);
    5.57  
    5.58  /**
    5.59   * Called when a client receives a Steam ID.
    5.60 - * @note This is called by bots, but the ID will be "BOT"
    5.61 + 
    5.62 + * Admin properties are not assigned here, but on OnClientPostAdminCheck().
    5.63 + * This is called by bots, but the ID will be "BOT".
    5.64   *
    5.65 - * @param client		Player index.
    5.66 - * @param auth			Player auth string.
    5.67 + * @param client		Client index.
    5.68 + * @param auth			Client auth string.
    5.69 + * @noreturn
    5.70   */
    5.71  forward OnClientAuthorized(client, const String:auth[]);
    5.72  
    5.73  /**
    5.74 + * Called once a client is authorized and fully in-game, but 
    5.75 + * before admin checks are done.  This can be used to override 
    5.76 + * the default admin checks for a client.
    5.77 + *
    5.78 + * Note: If handled/blocked, PostAdminCheck must be signalled 
    5.79 + * manually via NotifyPostAdminCheck().
    5.80 + *
    5.81 + * @param client		Client index.
    5.82 + * @return				Plugin_Handled to block admin checks.
    5.83 + */
    5.84 +forward Action:OnClientPreAdminCheck(client);
    5.85 +
    5.86 +/**
    5.87 + * Called once a client is authorized and fully in-game, and 
    5.88 + * after all post-connection authorizations have been performed.
    5.89 + *
    5.90 + * @param client		Client index.
    5.91 + * @noreturn
    5.92 + */
    5.93 +forward OnClientPostAdminCheck(client);
    5.94 +
    5.95 +/**
    5.96   * Returns the maximum number of clients allowed on the server.
    5.97   *
    5.98   * @return				Maximum number of clients allowed.
    5.99 @@ -290,6 +315,30 @@
   5.100   */
   5.101  native bool:CanUserTarget(client, target);
   5.102  
   5.103 +/**
   5.104 + * Runs through the Core-defined admin authorization checks on a player.
   5.105 + * Has no effect if the player is already an admin.
   5.106 + *
   5.107 + * Note: This function is based on the internal cache only.
   5.108 + *
   5.109 + * @param client		Client index.
   5.110 + * @return				True if access was changed, false if it did not.
   5.111 + * @error				Invalid client index or client not in-game AND authorized.
   5.112 + */
   5.113 +native bool:RunAdminCacheChecks(client);
   5.114 +
   5.115 +/**
   5.116 + * Signals that a player has completed post-connection admin checks.
   5.117 + * Has no effect if the player has already had this event signalled.
   5.118 + *
   5.119 + * Note: This must be sent even if no admin id was assigned.
   5.120 + *
   5.121 + * @param client		Client index.
   5.122 + * @noreturn
   5.123 + * @error				Invalid client index or client not in-game AND authorized.
   5.124 + */
   5.125 +native NotifyPostAdminCheck(client);
   5.126 +
   5.127  /** 
   5.128   * Creates a fake client.
   5.129   *
     6.1 --- a/plugins/reservedslots.sp	Wed Aug 08 15:08:01 2007 +0000
     6.2 +++ b/plugins/reservedslots.sp	Wed Aug 08 16:22:51 2007 +0000
     6.3 @@ -63,7 +63,7 @@
     6.4  	}	
     6.5  }
     6.6  
     6.7 -public OnClientAuthorized(client, const String:auth[])
     6.8 +public OnClientPostAdminCheck(client)
     6.9  {
    6.10  	new reserved = GetConVarInt(sm_reserved_slots);
    6.11