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