1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_banning.cpp Fri Sep 14 02:11:10 2007 +0000
1.3 @@ -0,0 +1,378 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "sm_globals.h"
1.36 +#include "sm_stringutil.h"
1.37 +#include "HalfLife2.h"
1.38 +#include "PlayerManager.h"
1.39 +#include "ForwardSys.h"
1.40 +#include <inetchannel.h>
1.41 +#include <iclient.h>
1.42 +
1.43 +#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
1.44 +#define BANFLAG_IP (1<<1) /**< Always ban by IP address */
1.45 +#define BANFLAG_AUTHID (1<<2) /**< Ban by SteamID */
1.46 +#define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */
1.47 +#define BANFLAG_NOWRITE (1<<4) /**< Ban is not written to SourceDS's files if permanent */
1.48 +
1.49 +IForward *g_pOnBanClient = NULL;
1.50 +IForward *g_pOnBanIdentity = NULL;
1.51 +IForward *g_pOnRemoveBan = NULL;
1.52 +
1.53 +class BanNativeHelpers : public SMGlobalClass
1.54 +{
1.55 +public:
1.56 + void OnSourceModAllInitialized()
1.57 + {
1.58 + g_pOnBanClient = g_Forwards.CreateForward(
1.59 + "OnBanClient",
1.60 + ET_Ignore,
1.61 + 7,
1.62 + NULL,
1.63 + Param_Cell,
1.64 + Param_Cell,
1.65 + Param_Cell,
1.66 + Param_String,
1.67 + Param_String,
1.68 + Param_String,
1.69 + Param_Cell);
1.70 + g_pOnBanIdentity = g_Forwards.CreateForward(
1.71 + "OnBanIdentity",
1.72 + ET_Ignore,
1.73 + 6,
1.74 + NULL,
1.75 + Param_String,
1.76 + Param_Cell,
1.77 + Param_Cell,
1.78 + Param_String,
1.79 + Param_String,
1.80 + Param_Cell);
1.81 + g_pOnRemoveBan = g_Forwards.CreateForward(
1.82 + "OnRemoveBan",
1.83 + ET_Ignore,
1.84 + 4,
1.85 + NULL,
1.86 + Param_String,
1.87 + Param_Cell,
1.88 + Param_String,
1.89 + Param_Cell);
1.90 + }
1.91 + void OnSourceModShutdown()
1.92 + {
1.93 + g_Forwards.ReleaseForward(g_pOnBanClient);
1.94 + g_Forwards.ReleaseForward(g_pOnBanIdentity);
1.95 + g_Forwards.ReleaseForward(g_pOnRemoveBan);
1.96 +
1.97 + g_pOnBanClient = NULL;
1.98 + g_pOnBanIdentity = NULL;
1.99 + g_pOnRemoveBan = NULL;
1.100 + }
1.101 +} s_BanNativeHelpers;
1.102 +
1.103 +
1.104 +static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
1.105 +{
1.106 + char *r_identity, *ban_reason, *ban_cmd;
1.107 + int ban_time, ban_flags, ban_source;
1.108 +
1.109 + pContext->LocalToString(params[1], &r_identity);
1.110 + pContext->LocalToString(params[4], &ban_reason);
1.111 + pContext->LocalToString(params[5], &ban_cmd);
1.112 + ban_time = params[2];
1.113 + ban_flags = params[3];
1.114 + ban_source = params[6];
1.115 +
1.116 + /* Make sure we can ban by one of the two methods! */
1.117 + bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
1.118 + if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
1.119 + {
1.120 + return pContext->ThrowNativeError("No valid ban flags specified");
1.121 + }
1.122 +
1.123 + /* Sanitize the input */
1.124 + char identity[64];
1.125 + strncopy(identity, r_identity, sizeof(identity));
1.126 + UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
1.127 +
1.128 + if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
1.129 + {
1.130 + g_pOnBanIdentity->PushString(identity);
1.131 + g_pOnBanIdentity->PushCell(ban_time);
1.132 + g_pOnBanIdentity->PushCell(ban_flags);
1.133 + g_pOnBanIdentity->PushString(ban_reason);
1.134 + g_pOnBanIdentity->PushString(ban_cmd);
1.135 + g_pOnBanIdentity->PushCell(ban_source);
1.136 + g_pOnBanIdentity->Execute(NULL);
1.137 + }
1.138 +
1.139 + bool write_ban = ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE);
1.140 +
1.141 + char command[256];
1.142 + if (ban_by_ip)
1.143 + {
1.144 + UTIL_Format(
1.145 + command,
1.146 + sizeof(command),
1.147 + "addip %d %s\n",
1.148 + ban_time,
1.149 + identity);
1.150 + engine->ServerCommand(command);
1.151 +
1.152 + if (write_ban && ban_time == 0)
1.153 + {
1.154 + engine->ServerCommand("writeip\n");
1.155 + }
1.156 + }
1.157 + else if (!g_HL2.IsLANServer())
1.158 + {
1.159 + UTIL_Format(
1.160 + command,
1.161 + sizeof(command),
1.162 + "banid %d %s\n",
1.163 + ban_time,
1.164 + identity);
1.165 + engine->ServerCommand(command);
1.166 +
1.167 + if (write_ban && ban_time == 0)
1.168 + {
1.169 + engine->ServerCommand("writeid\n");
1.170 + }
1.171 + }
1.172 + else
1.173 + {
1.174 + return 0;
1.175 + }
1.176 +
1.177 + return 1;
1.178 +}
1.179 +
1.180 +static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
1.181 +{
1.182 + char *r_identity, *ban_cmd;
1.183 + int ban_flags, ban_source;
1.184 +
1.185 + pContext->LocalToString(params[1], &r_identity);
1.186 + pContext->LocalToString(params[3], &ban_cmd);
1.187 + ban_flags = params[2];
1.188 + ban_source = params[4];
1.189 +
1.190 + /* Make sure we can ban by one of the two methods! */
1.191 + bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
1.192 + if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
1.193 + {
1.194 + return pContext->ThrowNativeError("No valid ban flags specified");
1.195 + }
1.196 +
1.197 + char identity[64];
1.198 + strncopy(identity, r_identity, sizeof(identity));
1.199 + UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
1.200 +
1.201 + if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
1.202 + {
1.203 + g_pOnRemoveBan->PushString(identity);
1.204 + g_pOnRemoveBan->PushCell(ban_flags);
1.205 + g_pOnRemoveBan->PushString(ban_cmd);
1.206 + g_pOnRemoveBan->PushCell(ban_source);
1.207 + g_pOnRemoveBan->Execute(NULL);
1.208 + }
1.209 +
1.210 + char command[256];
1.211 + if (ban_by_ip)
1.212 + {
1.213 + UTIL_Format(
1.214 + command,
1.215 + sizeof(command),
1.216 + "removeip %s\n",
1.217 + identity);
1.218 + engine->ServerCommand(command);
1.219 + engine->ServerCommand("writeip\n");
1.220 + }
1.221 + else if (!g_HL2.IsLANServer())
1.222 + {
1.223 + UTIL_Format(
1.224 + command,
1.225 + sizeof(command),
1.226 + "removeid %s\n",
1.227 + identity);
1.228 + engine->ServerCommand(command);
1.229 + engine->ServerCommand("writeid\n");
1.230 + }
1.231 + else
1.232 + {
1.233 + return 0;
1.234 + }
1.235 +
1.236 + return 1;
1.237 +}
1.238 +
1.239 +static cell_t BanClient(IPluginContext *pContext, const cell_t *params)
1.240 +{
1.241 + const char *kick_message;
1.242 + char *ban_reason, *ban_cmd;
1.243 + int client, ban_flags, ban_source, ban_time;
1.244 +
1.245 + client = params[1];
1.246 +
1.247 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.248 + if (!pPlayer || !pPlayer->IsConnected())
1.249 + {
1.250 + return pContext->ThrowNativeError("Client index %d is invalid", client);
1.251 + }
1.252 +
1.253 + pContext->LocalToString(params[4], &ban_reason);
1.254 + pContext->LocalToString(params[5], (char **)&kick_message);
1.255 + pContext->LocalToString(params[6], &ban_cmd);
1.256 + ban_time = params[2];
1.257 + ban_flags = params[3];
1.258 + ban_source = params[7];
1.259 +
1.260 + INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
1.261 + IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
1.262 +
1.263 + /* Check how we should ban the player */
1.264 + if ((ban_flags & BANFLAG_AUTO) == BANFLAG_AUTO)
1.265 + {
1.266 + if (g_HL2.IsLANServer() || !pPlayer->IsAuthorized())
1.267 + {
1.268 + ban_flags |= BANFLAG_IP;
1.269 + ban_flags &= BANFLAG_AUTHID;
1.270 + }
1.271 + else
1.272 + {
1.273 + ban_flags |= BANFLAG_AUTHID;
1.274 + ban_flags &= BANFLAG_IP;
1.275 + }
1.276 + }
1.277 + else if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
1.278 + {
1.279 + ban_flags |= BANFLAG_IP;
1.280 + ban_flags &= BANFLAG_AUTHID;
1.281 + }
1.282 + else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
1.283 + {
1.284 + if (pPlayer->IsAuthorized())
1.285 + {
1.286 + ban_flags |= BANFLAG_AUTHID;
1.287 + ban_flags &= BANFLAG_IP;
1.288 + }
1.289 + else
1.290 + {
1.291 + return 0;
1.292 + }
1.293 + }
1.294 + else
1.295 + {
1.296 + return pContext->ThrowNativeError("No valid ban method flags specified");
1.297 + }
1.298 +
1.299 + if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0)
1.300 + {
1.301 + g_pOnBanClient->PushCell(client);
1.302 + g_pOnBanClient->PushCell(ban_time);
1.303 + g_pOnBanClient->PushCell(ban_flags);
1.304 + g_pOnBanClient->PushString(ban_reason);
1.305 + g_pOnBanClient->PushString(kick_message);
1.306 + g_pOnBanClient->PushString(ban_cmd);
1.307 + g_pOnBanClient->PushCell(ban_source);
1.308 + g_pOnBanClient->Execute(NULL);
1.309 + }
1.310 +
1.311 + if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
1.312 + {
1.313 + /* Build a kick message */
1.314 + const char *kick_message = "";
1.315 + pContext->LocalToString(params[5], (char **)&kick_message);
1.316 + if (kick_message[0] == '\0')
1.317 + {
1.318 + kick_message = "Kicked";
1.319 + }
1.320 +
1.321 + /* Disconnect the client now */
1.322 + pClient->Disconnect("%s", kick_message);
1.323 + }
1.324 +
1.325 + if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
1.326 + {
1.327 + /* Get the IP address and strip the port */
1.328 + char ip[24], *ptr;
1.329 + strncopy(ip, pPlayer->GetIPAddress(), sizeof(ip));
1.330 + if ((ptr = strchr(ip, ':')) != NULL)
1.331 + {
1.332 + *ptr = '\0';
1.333 + }
1.334 +
1.335 + /* Tell the server to ban the ip */
1.336 + char command[256];
1.337 + UTIL_Format(
1.338 + command,
1.339 + sizeof(command),
1.340 + "addip %d %s\n",
1.341 + ban_time,
1.342 + ip);
1.343 + engine->ServerCommand(command);
1.344 +
1.345 + /* Physically write the ban */
1.346 + if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
1.347 + {
1.348 + engine->ServerCommand("writeip\n");
1.349 + }
1.350 + }
1.351 + else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
1.352 + {
1.353 + /* Tell the server to ban the auth string */
1.354 + char command[256];
1.355 + UTIL_Format(
1.356 + command,
1.357 + sizeof(command),
1.358 + "banid %d %s\n",
1.359 + ban_time,
1.360 + pPlayer->GetAuthString());
1.361 + engine->ServerCommand(command);
1.362 +
1.363 + /* Physically write the ban if it's permanent */
1.364 + if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
1.365 + {
1.366 + engine->ServerCommand("writeid\n");
1.367 + }
1.368 + }
1.369 +
1.370 +
1.371 + return 1;
1.372 +}
1.373 +
1.374 +REGISTER_NATIVES(banNatives)
1.375 +{
1.376 + {"BanClient", BanClient},
1.377 + {"BanIdentity", BanIdentity},
1.378 + {"RemoveBan", RemoveBan},
1.379 + {NULL, NULL}
1.380 +};
1.381 +