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