dvander@1423: /**
dvander@1423: * vim: set ts=4 :
dvander@1423: * =============================================================================
dvander@1423: * SourceMod
dvander@1423: * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
dvander@1423: * =============================================================================
dvander@1423: *
dvander@1423: * This program is free software; you can redistribute it and/or modify it under
dvander@1423: * the terms of the GNU General Public License, version 3.0, as published by the
dvander@1423: * Free Software Foundation.
dvander@1423: *
dvander@1423: * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@1423: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@1423: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
dvander@1423: * details.
dvander@1423: *
dvander@1423: * You should have received a copy of the GNU General Public License along with
dvander@1423: * this program. If not, see .
dvander@1423: *
dvander@1423: * As a special exception, AlliedModders LLC gives you permission to link the
dvander@1423: * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@1423: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@1423: * by the Valve Corporation. You must obey the GNU General Public License in
dvander@1423: * all respects for all other code used. Additionally, AlliedModders LLC grants
dvander@1423: * this exception to all derivative works. AlliedModders LLC defines further
dvander@1423: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@1423: * or .
dvander@1423: *
dvander@1423: * Version: $Id$
dvander@1423: */
dvander@1423:
dvander@1423: #include "sm_globals.h"
dvander@1423: #include "sm_stringutil.h"
dvander@1423: #include "HalfLife2.h"
dvander@1423: #include "PlayerManager.h"
dvander@1423: #include "ForwardSys.h"
dvander@1423:
dvander@1423: #define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
dvander@1423: #define BANFLAG_IP (1<<1) /**< Always ban by IP address */
dvander@1423: #define BANFLAG_AUTHID (1<<2) /**< Ban by SteamID */
dvander@1423: #define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */
dvander@1423: #define BANFLAG_NOWRITE (1<<4) /**< Ban is not written to SourceDS's files if permanent */
dvander@1423:
dvander@1423: IForward *g_pOnBanClient = NULL;
dvander@1423: IForward *g_pOnBanIdentity = NULL;
dvander@1423: IForward *g_pOnRemoveBan = NULL;
dvander@1423:
dvander@1423: class BanNativeHelpers : public SMGlobalClass
dvander@1423: {
dvander@1423: public:
dvander@1423: void OnSourceModAllInitialized()
dvander@1423: {
dvander@1423: g_pOnBanClient = g_Forwards.CreateForward(
dvander@1423: "OnBanClient",
dvander@1426: ET_Event,
dvander@1423: 7,
dvander@1423: NULL,
dvander@1423: Param_Cell,
dvander@1423: Param_Cell,
dvander@1423: Param_Cell,
dvander@1423: Param_String,
dvander@1423: Param_String,
dvander@1423: Param_String,
dvander@1423: Param_Cell);
dvander@1423: g_pOnBanIdentity = g_Forwards.CreateForward(
dvander@1423: "OnBanIdentity",
dvander@1426: ET_Event,
dvander@1423: 6,
dvander@1423: NULL,
dvander@1423: Param_String,
dvander@1423: Param_Cell,
dvander@1423: Param_Cell,
dvander@1423: Param_String,
dvander@1423: Param_String,
dvander@1423: Param_Cell);
dvander@1423: g_pOnRemoveBan = g_Forwards.CreateForward(
dvander@1423: "OnRemoveBan",
dvander@1426: ET_Event,
dvander@1423: 4,
dvander@1423: NULL,
dvander@1423: Param_String,
dvander@1423: Param_Cell,
dvander@1423: Param_String,
dvander@1423: Param_Cell);
dvander@1423: }
dvander@1423: void OnSourceModShutdown()
dvander@1423: {
dvander@1423: g_Forwards.ReleaseForward(g_pOnBanClient);
dvander@1423: g_Forwards.ReleaseForward(g_pOnBanIdentity);
dvander@1423: g_Forwards.ReleaseForward(g_pOnRemoveBan);
dvander@1423:
dvander@1423: g_pOnBanClient = NULL;
dvander@1423: g_pOnBanIdentity = NULL;
dvander@1423: g_pOnRemoveBan = NULL;
dvander@1423: }
dvander@1423: } s_BanNativeHelpers;
dvander@1423:
dvander@1423:
dvander@1423: static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
dvander@1423: {
dvander@1423: char *r_identity, *ban_reason, *ban_cmd;
dvander@1423: int ban_time, ban_flags, ban_source;
dvander@1423:
dvander@1423: pContext->LocalToString(params[1], &r_identity);
dvander@1423: pContext->LocalToString(params[4], &ban_reason);
dvander@1423: pContext->LocalToString(params[5], &ban_cmd);
dvander@1423: ban_time = params[2];
dvander@1423: ban_flags = params[3];
dvander@1423: ban_source = params[6];
dvander@1423:
dvander@1423: /* Make sure we can ban by one of the two methods! */
dvander@1423: bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
dvander@1423: if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
dvander@1423: {
dvander@1423: return pContext->ThrowNativeError("No valid ban flags specified");
dvander@1423: }
dvander@1423:
dvander@1423: /* Sanitize the input */
dvander@1423: char identity[64];
dvander@1423: strncopy(identity, r_identity, sizeof(identity));
dvander@1423: UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
dvander@1423:
dvander@1426: cell_t handled = 0;
dvander@1423: if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
dvander@1423: {
dvander@1423: g_pOnBanIdentity->PushString(identity);
dvander@1423: g_pOnBanIdentity->PushCell(ban_time);
dvander@1423: g_pOnBanIdentity->PushCell(ban_flags);
dvander@1423: g_pOnBanIdentity->PushString(ban_reason);
dvander@1423: g_pOnBanIdentity->PushString(ban_cmd);
dvander@1423: g_pOnBanIdentity->PushCell(ban_source);
dvander@1426: g_pOnBanIdentity->Execute(&handled);
dvander@1423: }
dvander@1423:
dvander@1426: if (!handled)
dvander@1423: {
dvander@1426: bool write_ban = ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE);
dvander@1423:
dvander@1426: char command[256];
dvander@1426: if (ban_by_ip)
dvander@1423: {
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "addip %d %s\n",
dvander@1426: ban_time,
dvander@1426: identity);
dvander@1426: engine->ServerCommand(command);
dvander@1426:
dvander@1426: if (write_ban && ban_time == 0)
dvander@1426: {
dvander@1426: engine->ServerCommand("writeip\n");
dvander@1426: }
dvander@1423: }
dvander@1426: else if (!g_HL2.IsLANServer())
dvander@1423: {
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "banid %d %s\n",
dvander@1426: ban_time,
dvander@1426: identity);
dvander@1426: engine->ServerCommand(command);
dvander@1426:
dvander@1426: if (write_ban && ban_time == 0)
dvander@1426: {
dvander@1426: engine->ServerCommand("writeid\n");
dvander@1426: }
dvander@1423: }
dvander@1426: else
dvander@1426: {
dvander@1426: return 0;
dvander@1426: }
dvander@1423: }
dvander@1423:
dvander@1423: return 1;
dvander@1423: }
dvander@1423:
dvander@1423: static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
dvander@1423: {
dvander@1423: char *r_identity, *ban_cmd;
dvander@1423: int ban_flags, ban_source;
dvander@1423:
dvander@1423: pContext->LocalToString(params[1], &r_identity);
dvander@1423: pContext->LocalToString(params[3], &ban_cmd);
dvander@1423: ban_flags = params[2];
dvander@1423: ban_source = params[4];
dvander@1423:
dvander@1423: /* Make sure we can ban by one of the two methods! */
dvander@1423: bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
dvander@1423: if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
dvander@1423: {
dvander@1423: return pContext->ThrowNativeError("No valid ban flags specified");
dvander@1423: }
dvander@1423:
dvander@1423: char identity[64];
dvander@1423: strncopy(identity, r_identity, sizeof(identity));
dvander@1423: UTIL_ReplaceAll(identity, sizeof(identity), ";", "");
dvander@1423:
dvander@1426: cell_t handled = 0;
dvander@1423: if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
dvander@1423: {
dvander@1423: g_pOnRemoveBan->PushString(identity);
dvander@1423: g_pOnRemoveBan->PushCell(ban_flags);
dvander@1423: g_pOnRemoveBan->PushString(ban_cmd);
dvander@1423: g_pOnRemoveBan->PushCell(ban_source);
dvander@1426: g_pOnRemoveBan->Execute(&handled);
dvander@1423: }
dvander@1423:
dvander@1423: char command[256];
dvander@1423: if (ban_by_ip)
dvander@1423: {
dvander@1426: if (!handled)
dvander@1426: {
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "removeip %s\n",
dvander@1426: identity);
dvander@1426: engine->ServerCommand(command);
dvander@1426: engine->ServerCommand("writeip\n");
dvander@1426: }
dvander@1423: }
dvander@1423: else if (!g_HL2.IsLANServer())
dvander@1423: {
dvander@1426: if (!handled)
dvander@1426: {
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "removeid %s\n",
dvander@1426: identity);
dvander@1426: engine->ServerCommand(command);
dvander@1426: engine->ServerCommand("writeid\n");
dvander@1426: }
dvander@1423: }
dvander@1423: else
dvander@1423: {
dvander@1423: return 0;
dvander@1423: }
dvander@1423:
dvander@1423: return 1;
dvander@1423: }
dvander@1423:
dvander@1423: static cell_t BanClient(IPluginContext *pContext, const cell_t *params)
dvander@1423: {
dvander@1423: const char *kick_message;
dvander@1423: char *ban_reason, *ban_cmd;
dvander@1423: int client, ban_flags, ban_source, ban_time;
dvander@1423:
dvander@1423: client = params[1];
dvander@1423:
dvander@1423: CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
dvander@1423: if (!pPlayer || !pPlayer->IsConnected())
dvander@1423: {
dvander@1423: return pContext->ThrowNativeError("Client index %d is invalid", client);
dvander@1423: }
dvander@1423:
dvander@1423: pContext->LocalToString(params[4], &ban_reason);
dvander@1423: pContext->LocalToString(params[5], (char **)&kick_message);
dvander@1423: pContext->LocalToString(params[6], &ban_cmd);
dvander@1423: ban_time = params[2];
dvander@1423: ban_flags = params[3];
dvander@1423: ban_source = params[7];
dvander@1423:
dvander@1423: /* Check how we should ban the player */
dvander@1423: if ((ban_flags & BANFLAG_AUTO) == BANFLAG_AUTO)
dvander@1423: {
dvander@1423: if (g_HL2.IsLANServer() || !pPlayer->IsAuthorized())
dvander@1423: {
dvander@1423: ban_flags |= BANFLAG_IP;
dvander@1424: ban_flags &= ~BANFLAG_AUTHID;
dvander@1423: }
dvander@1423: else
dvander@1423: {
dvander@1423: ban_flags |= BANFLAG_AUTHID;
dvander@1424: ban_flags &= ~BANFLAG_IP;
dvander@1423: }
dvander@1423: }
dvander@1423: else if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
dvander@1423: {
dvander@1423: ban_flags |= BANFLAG_IP;
dvander@1424: ban_flags &= ~BANFLAG_AUTHID;
dvander@1423: }
dvander@1423: else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
dvander@1423: {
dvander@1423: if (pPlayer->IsAuthorized())
dvander@1423: {
dvander@1423: ban_flags |= BANFLAG_AUTHID;
dvander@1424: ban_flags &= ~BANFLAG_IP;
dvander@1423: }
dvander@1423: else
dvander@1423: {
dvander@1423: return 0;
dvander@1423: }
dvander@1423: }
dvander@1423: else
dvander@1423: {
dvander@1423: return pContext->ThrowNativeError("No valid ban method flags specified");
dvander@1423: }
dvander@1423:
dvander@1426: cell_t handled = 0;
dvander@1423: if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0)
dvander@1423: {
dvander@1423: g_pOnBanClient->PushCell(client);
dvander@1423: g_pOnBanClient->PushCell(ban_time);
dvander@1423: g_pOnBanClient->PushCell(ban_flags);
dvander@1423: g_pOnBanClient->PushString(ban_reason);
dvander@1423: g_pOnBanClient->PushString(kick_message);
dvander@1423: g_pOnBanClient->PushString(ban_cmd);
dvander@1423: g_pOnBanClient->PushCell(ban_source);
dvander@1426: g_pOnBanClient->Execute(&handled);
dvander@1423: }
dvander@1423:
dvander@1425: /* Sanitize the kick message */
dvander@1425: if (kick_message[0] == '\0')
dvander@1423: {
dvander@1425: kick_message = "Kicked";
dvander@1423: }
dvander@1423:
dvander@1426: if (!handled)
dvander@1423: {
dvander@1426: if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
dvander@1423: {
dvander@1426: /* Get the IP address and strip the port */
dvander@1426: char ip[24], *ptr;
dvander@1426: strncopy(ip, pPlayer->GetIPAddress(), sizeof(ip));
dvander@1426: if ((ptr = strchr(ip, ':')) != NULL)
dvander@1426: {
dvander@1426: *ptr = '\0';
dvander@1426: }
dvander@1426:
dvander@1426: /* Tell the server to ban the ip */
dvander@1426: char command[256];
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "addip %d %s\n",
dvander@1426: ban_time,
dvander@1426: ip);
dvander@1426:
dvander@1426: /* Kick, then ban */
dvander@1426: if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
dvander@1426: {
dvander@1576: pPlayer->Kick(kick_message);
dvander@1426: }
dvander@1426: engine->ServerCommand(command);
dvander@1426:
dvander@1426: /* Physically write the ban */
dvander@1426: if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
dvander@1426: {
dvander@1426: engine->ServerCommand("writeip\n");
dvander@1426: }
dvander@1426: }
dvander@1426: else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
dvander@1425: {
dvander@1426: /* Tell the server to ban the auth string */
dvander@1426: char command[256];
dvander@1426: UTIL_Format(
dvander@1426: command,
dvander@1426: sizeof(command),
dvander@1426: "banid %d %s\n",
dvander@1426: ban_time,
dvander@1426: pPlayer->GetAuthString());
dvander@1426:
dvander@1426: /* Kick, then ban */
dvander@1426: if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
dvander@1426: {
dvander@1576: pPlayer->Kick(kick_message);
dvander@1426: }
dvander@1426: engine->ServerCommand(command);
dvander@1423:
dvander@1426: /* Physically write the ban if it's permanent */
dvander@1426: if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
dvander@1426: {
dvander@1426: engine->ServerCommand("writeid\n");
dvander@1426: }
dvander@1426: }
dvander@1426: }
dvander@1426: else if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
dvander@1423: {
dvander@1576: pPlayer->Kick(kick_message);
dvander@1423: }
dvander@1423:
dvander@1423:
dvander@1423: return 1;
dvander@1423: }
dvander@1423:
dvander@1423: REGISTER_NATIVES(banNatives)
dvander@1423: {
dvander@1423: {"BanClient", BanClient},
dvander@1423: {"BanIdentity", BanIdentity},
dvander@1423: {"RemoveBan", RemoveBan},
dvander@1423: {NULL, NULL}
dvander@1423: };
dvander@1423: