core/smn_banning.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 25 18:50:13 2007 +0000 (2007-11-25)
changeset 1725 ea875bcbc286
parent 1576 f36378b2d71f
child 1832 1f97873475e8
permissions -rw-r--r--
small clarification to param2 in MenuAction_End
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include "sm_stringutil.h"
    34 #include "HalfLife2.h"
    35 #include "PlayerManager.h"
    36 #include "ForwardSys.h"
    37 
    38 #define BANFLAG_AUTO	(1<<0)	/**< Auto-detects whether to ban by steamid or IP */
    39 #define BANFLAG_IP   	(1<<1)	/**< Always ban by IP address */
    40 #define BANFLAG_AUTHID	(1<<2)	/**< Ban by SteamID */
    41 #define BANFLAG_NOKICK	(1<<3)	/**< Does not kick the client */
    42 #define BANFLAG_NOWRITE	(1<<4)	/**< Ban is not written to SourceDS's files if permanent */
    43 
    44 IForward *g_pOnBanClient = NULL;
    45 IForward *g_pOnBanIdentity = NULL;
    46 IForward *g_pOnRemoveBan = NULL;
    47 
    48 class BanNativeHelpers : public SMGlobalClass
    49 {
    50 public:
    51 	void OnSourceModAllInitialized()
    52 	{
    53 		g_pOnBanClient = g_Forwards.CreateForward(
    54 			"OnBanClient",
    55 			ET_Event,
    56 			7,
    57 			NULL,
    58 			Param_Cell,
    59 			Param_Cell,
    60 			Param_Cell,
    61 			Param_String,
    62 			Param_String,
    63 			Param_String,
    64 			Param_Cell);
    65 		g_pOnBanIdentity = g_Forwards.CreateForward(
    66 			"OnBanIdentity",
    67 			ET_Event,
    68 			6,
    69 			NULL,
    70 			Param_String,
    71 			Param_Cell,
    72 			Param_Cell,
    73 			Param_String,
    74 			Param_String,
    75 			Param_Cell);
    76 		g_pOnRemoveBan = g_Forwards.CreateForward(
    77 			"OnRemoveBan",
    78 			ET_Event,
    79 			4,
    80 			NULL,
    81 			Param_String,
    82 			Param_Cell,
    83 			Param_String,
    84 			Param_Cell);
    85 	}
    86 	void OnSourceModShutdown()
    87 	{
    88 		g_Forwards.ReleaseForward(g_pOnBanClient);
    89 		g_Forwards.ReleaseForward(g_pOnBanIdentity);
    90 		g_Forwards.ReleaseForward(g_pOnRemoveBan);
    91 
    92 		g_pOnBanClient = NULL;
    93 		g_pOnBanIdentity = NULL;
    94 		g_pOnRemoveBan = NULL;
    95 	}
    96 } s_BanNativeHelpers;
    97 
    98 
    99 static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
   100 {
   101 	char *r_identity, *ban_reason, *ban_cmd;
   102 	int ban_time, ban_flags, ban_source;
   103 
   104 	pContext->LocalToString(params[1], &r_identity);
   105 	pContext->LocalToString(params[4], &ban_reason);
   106 	pContext->LocalToString(params[5], &ban_cmd);
   107 	ban_time = params[2];
   108 	ban_flags = params[3];
   109 	ban_source = params[6];
   110 
   111 	/* Make sure we can ban by one of the two methods! */
   112 	bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
   113 	if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
   114 	{
   115 		return pContext->ThrowNativeError("No valid ban flags specified");
   116 	}
   117 
   118 	/* Sanitize the input */
   119 	char identity[64];
   120 	strncopy(identity, r_identity, sizeof(identity));
   121 	UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
   122 
   123 	cell_t handled = 0;
   124 	if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
   125 	{
   126 		g_pOnBanIdentity->PushString(identity);
   127 		g_pOnBanIdentity->PushCell(ban_time);
   128 		g_pOnBanIdentity->PushCell(ban_flags);
   129 		g_pOnBanIdentity->PushString(ban_reason);
   130 		g_pOnBanIdentity->PushString(ban_cmd);
   131 		g_pOnBanIdentity->PushCell(ban_source);
   132 		g_pOnBanIdentity->Execute(&handled);
   133 	}
   134 
   135 	if (!handled)
   136 	{
   137 		bool write_ban = ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE);
   138 
   139 		char command[256];
   140 		if (ban_by_ip)
   141 		{
   142 			UTIL_Format(
   143 				command,
   144 				sizeof(command),
   145 				"addip %d %s\n",
   146 				ban_time,
   147 				identity);
   148 			engine->ServerCommand(command);
   149 	
   150 			if (write_ban && ban_time == 0)
   151 			{
   152 				engine->ServerCommand("writeip\n");
   153 			}
   154 		}
   155 		else if (!g_HL2.IsLANServer())
   156 		{
   157 			UTIL_Format(
   158 				command,
   159 				sizeof(command),
   160 				"banid %d %s\n",
   161 				ban_time,
   162 				identity);
   163 			engine->ServerCommand(command);
   164 	
   165 			if (write_ban && ban_time == 0)
   166 			{
   167 				engine->ServerCommand("writeid\n");
   168 			}
   169 		}
   170 		else
   171 		{
   172 			return 0;
   173 		}
   174 	}
   175 
   176 	return 1;
   177 }
   178 
   179 static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
   180 {
   181 	char *r_identity, *ban_cmd;
   182 	int ban_flags, ban_source;
   183 
   184 	pContext->LocalToString(params[1], &r_identity);
   185 	pContext->LocalToString(params[3], &ban_cmd);
   186 	ban_flags = params[2];
   187 	ban_source = params[4];
   188 
   189 	/* Make sure we can ban by one of the two methods! */
   190 	bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
   191 	if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
   192 	{
   193 		return pContext->ThrowNativeError("No valid ban flags specified");
   194 	}
   195 
   196 	char identity[64];
   197 	strncopy(identity, r_identity, sizeof(identity));
   198 	UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
   199 
   200 	cell_t handled = 0;
   201 	if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
   202 	{
   203 		g_pOnRemoveBan->PushString(identity);
   204 		g_pOnRemoveBan->PushCell(ban_flags);
   205 		g_pOnRemoveBan->PushString(ban_cmd);
   206 		g_pOnRemoveBan->PushCell(ban_source);
   207 		g_pOnRemoveBan->Execute(&handled);
   208 	}
   209 
   210 	char command[256];
   211 	if (ban_by_ip)
   212 	{
   213 		if (!handled)
   214 		{
   215 			UTIL_Format(
   216 				command,
   217 				sizeof(command),
   218 				"removeip %s\n",
   219 				identity);
   220 			engine->ServerCommand(command);	
   221 			engine->ServerCommand("writeip\n");
   222 		}
   223 	}
   224 	else if (!g_HL2.IsLANServer())
   225 	{
   226 		if (!handled)
   227 		{
   228 			UTIL_Format(
   229 				command,
   230 				sizeof(command),
   231 				"removeid %s\n",
   232 				identity);
   233 			engine->ServerCommand(command);
   234 			engine->ServerCommand("writeid\n");
   235 		}
   236 	}
   237 	else
   238 	{
   239 		return 0;
   240 	}
   241 
   242 	return 1;
   243 }
   244 
   245 static cell_t BanClient(IPluginContext *pContext, const cell_t *params)
   246 {
   247 	const char *kick_message;
   248 	char *ban_reason, *ban_cmd;
   249 	int client, ban_flags, ban_source, ban_time;
   250 
   251 	client = params[1];
   252 
   253 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   254 	if (!pPlayer || !pPlayer->IsConnected())
   255 	{
   256 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   257 	}
   258 
   259 	pContext->LocalToString(params[4], &ban_reason);
   260 	pContext->LocalToString(params[5], (char **)&kick_message);
   261 	pContext->LocalToString(params[6], &ban_cmd);
   262 	ban_time = params[2];
   263 	ban_flags = params[3];
   264 	ban_source = params[7];
   265 
   266 	/* Check how we should ban the player */
   267 	if ((ban_flags & BANFLAG_AUTO) == BANFLAG_AUTO)
   268 	{
   269 		if (g_HL2.IsLANServer() || !pPlayer->IsAuthorized())
   270 		{
   271 			ban_flags |= BANFLAG_IP;
   272 			ban_flags &= ~BANFLAG_AUTHID;
   273 		}
   274 		else
   275 		{
   276 			ban_flags |= BANFLAG_AUTHID;
   277 			ban_flags &= ~BANFLAG_IP;
   278 		}
   279 	}
   280 	else if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
   281 	{
   282 		ban_flags |= BANFLAG_IP;
   283 		ban_flags &= ~BANFLAG_AUTHID;
   284 	}
   285 	else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
   286 	{
   287 		if (pPlayer->IsAuthorized())
   288 		{
   289 			ban_flags |= BANFLAG_AUTHID;
   290 			ban_flags &= ~BANFLAG_IP;
   291 		}
   292 		else
   293 		{
   294 			return 0;
   295 		}
   296 	}
   297 	else
   298 	{
   299 		return pContext->ThrowNativeError("No valid ban method flags specified");
   300 	}
   301 
   302 	cell_t handled = 0;
   303 	if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0)
   304 	{
   305 		g_pOnBanClient->PushCell(client);
   306 		g_pOnBanClient->PushCell(ban_time);
   307 		g_pOnBanClient->PushCell(ban_flags);
   308 		g_pOnBanClient->PushString(ban_reason);
   309 		g_pOnBanClient->PushString(kick_message);
   310 		g_pOnBanClient->PushString(ban_cmd);
   311 		g_pOnBanClient->PushCell(ban_source);
   312 		g_pOnBanClient->Execute(&handled);
   313 	}
   314 
   315 	/* Sanitize the kick message */
   316 	if (kick_message[0] == '\0')
   317 	{
   318 		kick_message = "Kicked";
   319 	}
   320 
   321 	if (!handled)
   322 	{
   323 		if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
   324 		{
   325 			/* Get the IP address and strip the port */
   326 			char ip[24], *ptr;
   327 			strncopy(ip, pPlayer->GetIPAddress(), sizeof(ip));
   328 			if ((ptr = strchr(ip, ':')) != NULL)
   329 			{
   330 				*ptr = '\0';
   331 			}
   332 		
   333 			/* Tell the server to ban the ip */
   334 			char command[256];
   335 			UTIL_Format(
   336 				command,
   337 				sizeof(command),
   338 				"addip %d %s\n",
   339 				ban_time,
   340 				ip);
   341 	
   342 			/* Kick, then ban */
   343 			if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
   344 			{
   345    		 		pPlayer->Kick(kick_message);
   346 			}
   347 			engine->ServerCommand(command);
   348 	
   349 			/* Physically write the ban */
   350 			if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
   351 			{
   352 				engine->ServerCommand("writeip\n");
   353 			}	
   354 		} 
   355 		else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
   356 		{
   357 			/* Tell the server to ban the auth string */
   358 			char command[256];
   359 			UTIL_Format(
   360 				command, 
   361 				sizeof(command), 
   362 				"banid %d %s\n", 
   363 				ban_time,
   364 				pPlayer->GetAuthString());
   365 	
   366 			/* Kick, then ban */
   367 			if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
   368 			{
   369    		 		pPlayer->Kick(kick_message);
   370 			}
   371 			engine->ServerCommand(command);
   372 
   373 			/* Physically write the ban if it's permanent */
   374 			if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
   375 			{
   376 				engine->ServerCommand("writeid\n");
   377 			}
   378 		}
   379 	}
   380 	else if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
   381 	{
   382 		pPlayer->Kick(kick_message);	
   383 	}
   384 
   385 
   386 	return 1;
   387 }
   388 
   389 REGISTER_NATIVES(banNatives)
   390 {
   391 	{"BanClient",				BanClient},
   392 	{"BanIdentity",				BanIdentity},
   393 	{"RemoveBan",				RemoveBan},
   394 	{NULL,						NULL}
   395 };
   396