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