Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 126 additions & 12 deletions game/addons/sourcemod/scripting/sbpp_main.sp
Original file line number Diff line number Diff line change
Expand Up @@ -1624,8 +1624,7 @@ public void AddedFromSQLiteCallback(Database db, DBResultSet results, const char

} else {
// the insert failed so we leave the record in the queue and increase our temporary ban
FormatEx(buffer, sizeof(buffer), "banid %d %s", ProcessQueueTime, auth);
ServerCommand(buffer);
SBPP_BanIdentity(auth, ProcessQueueTime);
}
delete dataPack;
}
Expand Down Expand Up @@ -1692,7 +1691,7 @@ public void VerifyBan(Database db, DBResultSet results, const char[] error, int

if (results.RowCount > 0)
{
char buffer[40], Name[MAX_NAME_LENGTH], Query[512];
char Name[MAX_NAME_LENGTH], Query[512];

// Amending to ban record's IP field
if (results.FetchRow())
Expand Down Expand Up @@ -1731,9 +1730,15 @@ public void VerifyBan(Database db, DBResultSet results, const char[] error, int

db.Query(ErrorCheckCallback, Query, client, DBPrio_High);

FormatEx(buffer, sizeof(buffer), "banid 5 %s", clientAuth);
ServerCommand(buffer);
KickClient(client, "%t", "Banned Check Site", WebsiteAddress);
// Ban via BanClient() so SourceMod bans with the engine's own auth
// string. The raw "banid <STEAM_...>" console command is rejected by
// some engines (e.g. Synergy), which left the player unbanned.
// SetGlobalTransTarget() keeps the message in the client's language,
// which KickClient() used to do for us.
char BanReason[256];
SetGlobalTransTarget(client);
FormatEx(BanReason, sizeof(BanReason), "%t", "Banned Check Site", WebsiteAddress);
BanClient(client, 5, BANFLAG_AUTHID, BanReason, BanReason, "sbpp");

return;
}
Expand Down Expand Up @@ -2595,11 +2600,7 @@ stock void UTIL_InsertTempBan(int time, const char[] name, const char[] auth, co
delete dataPack;

// we add a temporary ban and then add the record into the queue to be processed when the database is available
char buffer[50];

Format(buffer, sizeof(buffer), "banid %d %s", ProcessQueueTime, auth);

ServerCommand(buffer);
char kickMessage[512] = "";

if (IsClientInGame(client))
{
Expand All @@ -2608,9 +2609,13 @@ stock void UTIL_InsertTempBan(int time, const char[] name, const char[] auth, co
FormatEx(length, sizeof(length), "permanent");
else
FormatEx(length, sizeof(length), "%d %s", time, time == 1 ? "minute" : "minutes");
KickClient(client, "%t\n\n%t", "Banned Check Site", WebsiteAddress, "Kick Reason", admin, reason, length);
// KickClient() used to localise this for us; keep doing so.
SetGlobalTransTarget(client);
FormatEx(kickMessage, sizeof(kickMessage), "%t\n\n%t", "Banned Check Site", WebsiteAddress, "Kick Reason", admin, reason, length);
}

SBPP_BanIdentity(auth, ProcessQueueTime, kickMessage, client);

char banName[MAX_NAME_LENGTH], banReason[256], query[512];

SQLiteDB.Escape(name, banName, sizeof(banName));
Expand Down Expand Up @@ -2838,4 +2843,113 @@ stock void AccountForLateLoading()
}
}

/**
* Converts a SteamID2 ("STEAM_X:Y:Z") into a SteamID3 ("[U:1:W]").
*
* The universe is always rendered as 1 (public), mirroring how SourceMod
* itself renders AuthId_Steam3: mods that set "UseInvalidUniverseInSteam2IDs"
* render public-universe accounts as STEAM_0, so the X field is not a
* trustworthy universe.
*
* @return true on success, false if the input was not a convertible SteamID2.
*/
stock bool SBPP_Steam2ToSteam3(const char[] steam2, char[] buffer, int maxlen)
{
if (strncmp(steam2, "STEAM_", 6) != 0)
return false;

// "STEAM_ID_PENDING" / "STEAM_ID_LAN" carry no account id.
if (strncmp(steam2[6], "ID_", 3) == 0)
return false;

char parts[3][12];
if (ExplodeString(steam2[6], ":", parts, sizeof(parts), sizeof(parts[])) != 3)
return false;

if (parts[1][0] == '\0' || parts[2][0] == '\0')
return false;

int y = StringToInt(parts[1]);
int z = StringToInt(parts[2]);

// %u, not %d: account ids past 2^31 would otherwise render negative.
FormatEx(buffer, maxlen, "[U:1:%u]", (z * 2) + y);
return true;
}

/**
* Bans a player by authid regardless of whether they are still connected.
*
* Uses BanClient() when the player is in game so SourceMod bans with the
* engine's own auth string (SourceMod feeds "banid" the string the engine
* itself reports for that player). Some engines (e.g. Synergy, appid 17520)
* reject the "STEAM_" format passed to the "banid" console command, which
* silently dropped the ban. When the player is offline we ban by identity
* using the SteamID3 form for the same reason.
*
* @param auth SteamID2 of the target.
* @param minutes Ban length in minutes.
* @param kickMessage Message shown to the target if still connected; the
* generic "check the website" phrase is used when empty.
* @param client Optional client index hint for the target.
*/
stock void SBPP_BanIdentity(const char[] auth, int minutes, const char[] kickMessage = "", int client = 0)
{
if (auth[0] == '\0')
return;

// These are always temporary holds until the database catches up, so never
// let a misconfigured length through: "banid 0" is a permanent ban and
// SourceMod additionally writes it out to banned_user.cfg.
if (minutes < 1)
minutes = 5;

int target = 0;

if (client > 0 && client <= MaxClients && IsClientInGame(client) && !IsFakeClient(client)
&& StrEqual(g_sSteamIDs[client], auth, false))
{
target = client;
}
else
{
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i) && !IsFakeClient(i) && StrEqual(g_sSteamIDs[i], auth, false))
{
target = i;
break;
}
}
}

if (target)
{
char message[512];

if (kickMessage[0] != '\0')
{
strcopy(message, sizeof(message), kickMessage);
}
else
{
SetGlobalTransTarget(target);
FormatEx(message, sizeof(message), "%t", "Banned Check Site", WebsiteAddress);
}

// BanClient() kicks on the next frame, so callers passing a global
// buffer (g_sSteamIDs[] & co.) can keep using it after this returns.
BanClient(target, minutes, BANFLAG_AUTHID, message, message, "sbpp");
return;
}

// BanIdentity() rather than a hand-built ServerCommand("banid ..."): it
// strips command separators out of the identity and notifies OnBanIdentity.
char steam3[MAX_AUTHID_LENGTH];
if (SBPP_Steam2ToSteam3(auth, steam3, sizeof(steam3)))
BanIdentity(steam3, minutes, BANFLAG_AUTHID, kickMessage, "sbpp");
else
BanIdentity(auth, minutes, BANFLAG_AUTHID, kickMessage, "sbpp");
}

//Yarr!
Loading