2008-03-30 09:00:22 +02:00
|
|
|
/**
|
|
|
|
* vim: set ts=4 :
|
|
|
|
* =============================================================================
|
|
|
|
* SourceMod
|
|
|
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
|
|
* =============================================================================
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
|
|
* Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
|
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
|
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
|
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
|
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
|
|
* this exception to all derivative works. AlliedModders LLC defines further
|
|
|
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
|
|
* or <http://www.sourcemod.net/license.php>.
|
|
|
|
*
|
|
|
|
* Version: $Id$
|
|
|
|
*/
|
|
|
|
|
2010-05-15 03:22:03 +02:00
|
|
|
#include "common_logic.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <IGameHelpers.h>
|
|
|
|
#include <IPlayerHelpers.h>
|
|
|
|
#include <IForwardSys.h>
|
2010-05-15 05:04:30 +02:00
|
|
|
#include "stringutil.h"
|
2015-08-26 05:58:43 +02:00
|
|
|
#include <am-string.h>
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
|
|
|
|
#define BANFLAG_IP (1<<1) /**< Always ban by IP address */
|
|
|
|
#define BANFLAG_AUTHID (1<<2) /**< Ban by SteamID */
|
|
|
|
#define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */
|
|
|
|
#define BANFLAG_NOWRITE (1<<4) /**< Ban is not written to SourceDS's files if permanent */
|
|
|
|
|
|
|
|
IForward *g_pOnBanClient = NULL;
|
|
|
|
IForward *g_pOnBanIdentity = NULL;
|
|
|
|
IForward *g_pOnRemoveBan = NULL;
|
|
|
|
|
|
|
|
class BanNativeHelpers : public SMGlobalClass
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void OnSourceModAllInitialized()
|
|
|
|
{
|
2010-05-15 03:22:03 +02:00
|
|
|
g_pOnBanClient = forwardsys->CreateForward(
|
2008-03-30 09:00:22 +02:00
|
|
|
"OnBanClient",
|
|
|
|
ET_Event,
|
|
|
|
7,
|
|
|
|
NULL,
|
|
|
|
Param_Cell,
|
|
|
|
Param_Cell,
|
|
|
|
Param_Cell,
|
|
|
|
Param_String,
|
|
|
|
Param_String,
|
|
|
|
Param_String,
|
|
|
|
Param_Cell);
|
2010-05-15 03:22:03 +02:00
|
|
|
g_pOnBanIdentity = forwardsys->CreateForward(
|
2008-03-30 09:00:22 +02:00
|
|
|
"OnBanIdentity",
|
|
|
|
ET_Event,
|
|
|
|
6,
|
|
|
|
NULL,
|
|
|
|
Param_String,
|
|
|
|
Param_Cell,
|
|
|
|
Param_Cell,
|
|
|
|
Param_String,
|
|
|
|
Param_String,
|
|
|
|
Param_Cell);
|
2010-05-15 03:22:03 +02:00
|
|
|
g_pOnRemoveBan = forwardsys->CreateForward(
|
2008-03-30 09:00:22 +02:00
|
|
|
"OnRemoveBan",
|
|
|
|
ET_Event,
|
|
|
|
4,
|
|
|
|
NULL,
|
|
|
|
Param_String,
|
|
|
|
Param_Cell,
|
|
|
|
Param_String,
|
|
|
|
Param_Cell);
|
|
|
|
}
|
|
|
|
void OnSourceModShutdown()
|
|
|
|
{
|
2010-05-15 03:22:03 +02:00
|
|
|
forwardsys->ReleaseForward(g_pOnBanClient);
|
|
|
|
forwardsys->ReleaseForward(g_pOnBanIdentity);
|
|
|
|
forwardsys->ReleaseForward(g_pOnRemoveBan);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
g_pOnBanClient = NULL;
|
|
|
|
g_pOnBanIdentity = NULL;
|
|
|
|
g_pOnRemoveBan = NULL;
|
|
|
|
}
|
|
|
|
} s_BanNativeHelpers;
|
|
|
|
|
|
|
|
|
|
|
|
static cell_t BanIdentity(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
char *r_identity, *ban_reason, *ban_cmd;
|
|
|
|
int ban_time, ban_flags, ban_source;
|
|
|
|
|
|
|
|
pContext->LocalToString(params[1], &r_identity);
|
|
|
|
pContext->LocalToString(params[4], &ban_reason);
|
|
|
|
pContext->LocalToString(params[5], &ban_cmd);
|
|
|
|
ban_time = params[2];
|
|
|
|
ban_flags = params[3];
|
|
|
|
ban_source = params[6];
|
|
|
|
|
|
|
|
/* Make sure we can ban by one of the two methods! */
|
|
|
|
bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
|
|
|
|
if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("No valid ban flags specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanitize the input */
|
|
|
|
char identity[64];
|
2010-05-15 05:04:30 +02:00
|
|
|
strncopy(identity, r_identity, sizeof(identity));
|
|
|
|
UTIL_ReplaceAll(identity, sizeof(identity), ";", "", true);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
cell_t handled = 0;
|
|
|
|
if (ban_cmd[0] != '\0' && g_pOnBanIdentity->GetFunctionCount() > 0)
|
|
|
|
{
|
|
|
|
g_pOnBanIdentity->PushString(identity);
|
|
|
|
g_pOnBanIdentity->PushCell(ban_time);
|
|
|
|
g_pOnBanIdentity->PushCell(ban_flags);
|
|
|
|
g_pOnBanIdentity->PushString(ban_reason);
|
|
|
|
g_pOnBanIdentity->PushString(ban_cmd);
|
|
|
|
g_pOnBanIdentity->PushCell(ban_source);
|
|
|
|
g_pOnBanIdentity->Execute(&handled);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!handled)
|
|
|
|
{
|
|
|
|
bool write_ban = ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE);
|
|
|
|
|
|
|
|
char command[256];
|
|
|
|
if (ban_by_ip)
|
|
|
|
{
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"addip %d %s\n",
|
|
|
|
ban_time,
|
|
|
|
identity);
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
|
|
|
|
if (write_ban && ban_time == 0)
|
|
|
|
{
|
|
|
|
engine->ServerCommand("writeip\n");
|
|
|
|
}
|
|
|
|
}
|
2010-05-15 03:22:03 +02:00
|
|
|
else if (!gamehelpers->IsLANServer())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"banid %d %s\n",
|
|
|
|
ban_time,
|
|
|
|
identity);
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
|
|
|
|
if (write_ban && ban_time == 0)
|
|
|
|
{
|
|
|
|
engine->ServerCommand("writeid\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t RemoveBan(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
char *r_identity, *ban_cmd;
|
|
|
|
int ban_flags, ban_source;
|
|
|
|
|
|
|
|
pContext->LocalToString(params[1], &r_identity);
|
|
|
|
pContext->LocalToString(params[3], &ban_cmd);
|
|
|
|
ban_flags = params[2];
|
|
|
|
ban_source = params[4];
|
|
|
|
|
|
|
|
/* Make sure we can ban by one of the two methods! */
|
|
|
|
bool ban_by_ip = ((ban_flags & BANFLAG_IP) == BANFLAG_IP);
|
|
|
|
if (!ban_by_ip && ((ban_flags & BANFLAG_AUTHID) != BANFLAG_AUTHID))
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("No valid ban flags specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
char identity[64];
|
2010-05-15 05:04:30 +02:00
|
|
|
strncopy(identity, r_identity, sizeof(identity));
|
|
|
|
UTIL_ReplaceAll(identity, sizeof(identity), ";", "", true);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
|
|
|
cell_t handled = 0;
|
|
|
|
if (ban_cmd[0] != '\0' && g_pOnRemoveBan->GetFunctionCount() > 0)
|
|
|
|
{
|
|
|
|
g_pOnRemoveBan->PushString(identity);
|
|
|
|
g_pOnRemoveBan->PushCell(ban_flags);
|
|
|
|
g_pOnRemoveBan->PushString(ban_cmd);
|
|
|
|
g_pOnRemoveBan->PushCell(ban_source);
|
|
|
|
g_pOnRemoveBan->Execute(&handled);
|
|
|
|
}
|
|
|
|
|
|
|
|
char command[256];
|
|
|
|
if (ban_by_ip)
|
|
|
|
{
|
|
|
|
if (!handled)
|
|
|
|
{
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"removeip %s\n",
|
|
|
|
identity);
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
engine->ServerCommand("writeip\n");
|
|
|
|
}
|
|
|
|
}
|
2010-05-15 03:22:03 +02:00
|
|
|
else if (!gamehelpers->IsLANServer())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
if (!handled)
|
|
|
|
{
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"removeid %s\n",
|
|
|
|
identity);
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
engine->ServerCommand("writeid\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t BanClient(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
const char *kick_message;
|
|
|
|
char *ban_reason, *ban_cmd;
|
|
|
|
int client, ban_flags, ban_source, ban_time;
|
|
|
|
|
2010-05-15 03:22:03 +02:00
|
|
|
client = gamehelpers->ReferenceToIndex(params[1]);
|
2008-03-30 09:00:22 +02:00
|
|
|
|
2010-05-15 03:22:03 +02:00
|
|
|
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
|
2008-03-30 09:00:22 +02:00
|
|
|
if (!pPlayer || !pPlayer->IsConnected())
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Client index %d is invalid", client);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pPlayer->IsFakeClient())
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Cannot ban fake client %d", client);
|
|
|
|
}
|
|
|
|
|
|
|
|
pContext->LocalToString(params[4], &ban_reason);
|
|
|
|
pContext->LocalToString(params[5], (char **)&kick_message);
|
|
|
|
pContext->LocalToString(params[6], &ban_cmd);
|
|
|
|
ban_time = params[2];
|
|
|
|
ban_flags = params[3];
|
|
|
|
ban_source = params[7];
|
|
|
|
|
|
|
|
/* Check how we should ban the player */
|
2015-08-30 01:23:50 +02:00
|
|
|
if (!strcmp(bridge->GetSourceEngineName(), "darkmessiah"))
|
2010-11-30 19:09:30 +01:00
|
|
|
{
|
|
|
|
/* Dark Messiah doesn't have Steam IDs so there is only one ban method to choose */
|
|
|
|
ban_flags |= BANFLAG_IP;
|
|
|
|
ban_flags &= ~BANFLAG_AUTHID;
|
|
|
|
}
|
|
|
|
else if ((ban_flags & BANFLAG_AUTO) == BANFLAG_AUTO)
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
2010-05-15 03:22:03 +02:00
|
|
|
if (gamehelpers->IsLANServer() || !pPlayer->IsAuthorized())
|
2008-03-30 09:00:22 +02:00
|
|
|
{
|
|
|
|
ban_flags |= BANFLAG_IP;
|
|
|
|
ban_flags &= ~BANFLAG_AUTHID;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ban_flags |= BANFLAG_AUTHID;
|
|
|
|
ban_flags &= ~BANFLAG_IP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
|
|
|
|
{
|
|
|
|
ban_flags |= BANFLAG_IP;
|
|
|
|
ban_flags &= ~BANFLAG_AUTHID;
|
|
|
|
}
|
|
|
|
else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
|
|
|
|
{
|
|
|
|
if (pPlayer->IsAuthorized())
|
|
|
|
{
|
|
|
|
ban_flags |= BANFLAG_AUTHID;
|
|
|
|
ban_flags &= ~BANFLAG_IP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("No valid ban method flags specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
cell_t handled = 0;
|
|
|
|
if (ban_cmd[0] != '\0' && g_pOnBanClient->GetFunctionCount() > 0)
|
|
|
|
{
|
|
|
|
g_pOnBanClient->PushCell(client);
|
|
|
|
g_pOnBanClient->PushCell(ban_time);
|
|
|
|
g_pOnBanClient->PushCell(ban_flags);
|
|
|
|
g_pOnBanClient->PushString(ban_reason);
|
|
|
|
g_pOnBanClient->PushString(kick_message);
|
|
|
|
g_pOnBanClient->PushString(ban_cmd);
|
|
|
|
g_pOnBanClient->PushCell(ban_source);
|
|
|
|
g_pOnBanClient->Execute(&handled);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanitize the kick message */
|
|
|
|
if (kick_message[0] == '\0')
|
|
|
|
{
|
|
|
|
kick_message = "Kicked";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!handled)
|
|
|
|
{
|
|
|
|
if ((ban_flags & BANFLAG_IP) == BANFLAG_IP)
|
|
|
|
{
|
|
|
|
/* Get the IP address and strip the port */
|
|
|
|
char ip[24], *ptr;
|
2015-08-26 06:35:45 +02:00
|
|
|
strncopy(ip, pPlayer->GetIPAddress(), sizeof(ip));
|
2008-03-30 09:00:22 +02:00
|
|
|
if ((ptr = strchr(ip, ':')) != NULL)
|
|
|
|
{
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell the server to ban the ip */
|
|
|
|
char command[256];
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"addip %d %s\n",
|
|
|
|
ban_time,
|
|
|
|
ip);
|
|
|
|
|
|
|
|
/* Kick, then ban */
|
|
|
|
if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
|
|
|
|
{
|
|
|
|
pPlayer->Kick(kick_message);
|
|
|
|
}
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
|
|
|
|
/* Physically write the ban */
|
|
|
|
if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
|
|
|
|
{
|
|
|
|
engine->ServerCommand("writeip\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((ban_flags & BANFLAG_AUTHID) == BANFLAG_AUTHID)
|
|
|
|
{
|
|
|
|
/* Tell the server to ban the auth string */
|
|
|
|
char command[256];
|
2015-08-26 05:58:43 +02:00
|
|
|
ke::SafeSprintf(
|
2008-03-30 09:00:22 +02:00
|
|
|
command,
|
|
|
|
sizeof(command),
|
|
|
|
"banid %d %s\n",
|
|
|
|
ban_time,
|
|
|
|
pPlayer->GetAuthString());
|
|
|
|
|
|
|
|
/* Kick, then ban */
|
|
|
|
if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
|
|
|
|
{
|
2010-05-15 03:22:03 +02:00
|
|
|
gamehelpers->AddDelayedKick(client, pPlayer->GetUserId(), kick_message);
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
engine->ServerCommand(command);
|
|
|
|
|
|
|
|
/* Physically write the ban if it's permanent */
|
|
|
|
if ((ban_time == 0) && ((ban_flags & BANFLAG_NOWRITE) != BANFLAG_NOWRITE))
|
|
|
|
{
|
|
|
|
engine->ServerCommand("writeid\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((ban_flags & BANFLAG_NOKICK) != BANFLAG_NOKICK)
|
|
|
|
{
|
2010-05-15 03:22:03 +02:00
|
|
|
gamehelpers->AddDelayedKick(client, pPlayer->GetUserId(), kick_message);
|
2008-03-30 09:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
REGISTER_NATIVES(banNatives)
|
|
|
|
{
|
|
|
|
{"BanClient", BanClient},
|
|
|
|
{"BanIdentity", BanIdentity},
|
|
|
|
{"RemoveBan", RemoveBan},
|
|
|
|
{NULL, NULL}
|
|
|
|
};
|
|
|
|
|