From e96d2a1ba912d6425c1169c19b39ccd5ee5e4f53 Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Wed, 5 Aug 2026 12:45:21 +0300 Subject: [PATCH 1/4] feat(socket): Add CIDR support for ip whitelisting --- addons/sourcemod/scripting/SMJSONAPI.sp | 88 ++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index bea7e5e..10aad63 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -33,7 +33,7 @@ public Plugin myinfo = name = "SM JSON API", author = "BotoX, maxime1907", description = "SourceMod TCP JSON API", - version = "1.2.0", + version = "1.2.1", url = "" } @@ -109,8 +109,7 @@ static void OnAsyncConnect(AsyncSocket socket) char ip[32]; socket.GetClientIP(ip, sizeof(ip)); - bool value; - if (strcmp(ip, LOCALHOST_IP) != 0 && !(g_smWhitelistedIPs && g_smWhitelistedIPs.GetValue(ip, value))) + if (!IsIPWhitelisted(ip)) { LogMessage("Blocked receiving data from: %s", ip); delete socket; @@ -561,3 +560,86 @@ static int ClientFromSocket(AsyncSocket socket) } return -1; } + +/** + * Checks if an IP string (e.g. "172.17.0.5") matches a CIDR range or exact IP (e.g. "172.17.0.0/16" or "192.168.1.50"). + * + * @param clientIp The incoming client IP string. + * @param cidrEntry The whitelist entry (e.g., "172.17.0.0/16" or "192.168.1.1"). + * @return True if the IP matches, false otherwise. + */ +bool IsIPInCIDR(const char[] clientIp, const char[] cidrEntry) +{ + char rangeIp[16]; + char prefixBit[4]; + + int iSlashPos = SplitString(cidrEntry, "/", rangeIp, sizeof(rangeIp)); + int iPrefixLen = 32; + + if (iSlashPos != -1) + { + strcopy(prefixBit, sizeof(prefixBit), cidrEntry[iSlashPos]); + iPrefixLen = StringToInt(prefixBit); + } + else + { + strcopy(rangeIp, sizeof(rangeIp), cidrEntry); + } + + if (iPrefixLen <= 0) + return true; + if (iPrefixLen > 32) + iPrefixLen = 32; + + int iClientIp = IPv4ToInt(clientIp); + int iRangeIp = IPv4ToInt(rangeIp); + + if (iClientIp == 0 || iRangeIp == 0) + return false; + + int iMask = (iPrefixLen == 32) ? -1 : ~((1 << (32 - iPrefixLen)) - 1); + + return (iClientIp & iMask) == (iRangeIp & iMask); +} + +int IPv4ToInt(const char[] ip) +{ + char octets[4][4]; + if (ExplodeString(ip, ".", octets, 4, 4) != 4) + return 0; + + int b1 = StringToInt(octets[0]); + int b2 = StringToInt(octets[1]); + int b3 = StringToInt(octets[2]); + int b4 = StringToInt(octets[3]); + + return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; +} + +bool IsIPWhitelisted(const char[] ip) +{ + if (strcmp(ip, LOCALHOST_IP) == 0 || strcmp(ip, "::1") == 0) + return true; + + if (!g_smWhitelistedIPs) + return false; + + StringMapSnapshot snapshot = g_smWhitelistedIPs.Snapshot(); + + bool match = false; + for (int i = 0; i < snapshot.Length; i++) + { + char thisIp[32]; + if (!snapshot.GetKey(i, thisIp, sizeof(thisIp))) + continue; + + if (IsIPInCIDR(ip, thisIp)) + { + match = true; + break; + } + } + + delete snapshot; + return match; +} From 96ff7e51a3327c31d60269b2dc87278f36167990 Mon Sep 17 00:00:00 2001 From: Dolly <109222243+Dolly132@users.noreply.github.com> Date: Wed, 5 Aug 2026 16:49:58 +0300 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- addons/sourcemod/scripting/SMJSONAPI.sp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index 10aad63..a4bf466 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -624,8 +624,11 @@ bool IsIPWhitelisted(const char[] ip) if (!g_smWhitelistedIPs) return false; - StringMapSnapshot snapshot = g_smWhitelistedIPs.Snapshot(); + bool value; + if (g_smWhitelistedIPs.GetValue(ip, value)) + return true; + StringMapSnapshot snapshot = g_smWhitelistedIPs.Snapshot(); bool match = false; for (int i = 0; i < snapshot.Length; i++) { From 1a8e2748b5a7ae5d5d6d62511b45732c24f1411e Mon Sep 17 00:00:00 2001 From: Dolly132 <109222243+Dolly132@users.noreply.github.com> Date: Wed, 5 Aug 2026 16:54:04 +0300 Subject: [PATCH 3/4] resolve copilot suggestions --- addons/sourcemod/scripting/SMJSONAPI.sp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index a4bf466..70eb33c 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -579,11 +579,15 @@ bool IsIPInCIDR(const char[] clientIp, const char[] cidrEntry) if (iSlashPos != -1) { strcopy(prefixBit, sizeof(prefixBit), cidrEntry[iSlashPos]); - iPrefixLen = StringToInt(prefixBit); + TrimString(prefixBit); + if (!prefixBit[0]) + return false; + + iPrefixLen = StringToInt(prefixBit); } else { - strcopy(rangeIp, sizeof(rangeIp), cidrEntry); + return strcmp(clientIp, cidrEntry) == 0; } if (iPrefixLen <= 0) From 146ac8589972212720704baf5bae71f4221a7da9 Mon Sep 17 00:00:00 2001 From: Rushaway Date: Wed, 5 Aug 2026 16:08:22 +0200 Subject: [PATCH 4/4] trim Trailing Whitespace --- addons/sourcemod/scripting/SMJSONAPI.sp | 88 ++++++++++++------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/addons/sourcemod/scripting/SMJSONAPI.sp b/addons/sourcemod/scripting/SMJSONAPI.sp index 70eb33c..ca0cb32 100644 --- a/addons/sourcemod/scripting/SMJSONAPI.sp +++ b/addons/sourcemod/scripting/SMJSONAPI.sp @@ -80,7 +80,7 @@ public void OnConfigsExecuted() if (StrContains(sWhitelistedAddrs, ",") == -1) { g_smWhitelistedIPs.SetValue(sWhitelistedAddrs, true); - return; + return; } int iAddrsCount = 0; @@ -283,7 +283,7 @@ stock JSONArray HandleRequestFunctionArgs(Request request, Response response) Call_PushString(NULL_STRING); else Fail = true; - + delete jArrayValue; } else @@ -570,54 +570,54 @@ static int ClientFromSocket(AsyncSocket socket) */ bool IsIPInCIDR(const char[] clientIp, const char[] cidrEntry) { - char rangeIp[16]; - char prefixBit[4]; - - int iSlashPos = SplitString(cidrEntry, "/", rangeIp, sizeof(rangeIp)); - int iPrefixLen = 32; - - if (iSlashPos != -1) - { - strcopy(prefixBit, sizeof(prefixBit), cidrEntry[iSlashPos]); - TrimString(prefixBit); - if (!prefixBit[0]) - return false; - - iPrefixLen = StringToInt(prefixBit); - } - else - { - return strcmp(clientIp, cidrEntry) == 0; - } - - if (iPrefixLen <= 0) - return true; - if (iPrefixLen > 32) - iPrefixLen = 32; - - int iClientIp = IPv4ToInt(clientIp); - int iRangeIp = IPv4ToInt(rangeIp); - - if (iClientIp == 0 || iRangeIp == 0) - return false; - - int iMask = (iPrefixLen == 32) ? -1 : ~((1 << (32 - iPrefixLen)) - 1); - - return (iClientIp & iMask) == (iRangeIp & iMask); + char rangeIp[16]; + char prefixBit[4]; + + int iSlashPos = SplitString(cidrEntry, "/", rangeIp, sizeof(rangeIp)); + int iPrefixLen = 32; + + if (iSlashPos != -1) + { + strcopy(prefixBit, sizeof(prefixBit), cidrEntry[iSlashPos]); + TrimString(prefixBit); + if (!prefixBit[0]) + return false; + + iPrefixLen = StringToInt(prefixBit); + } + else + { + return strcmp(clientIp, cidrEntry) == 0; + } + + if (iPrefixLen <= 0) + return true; + if (iPrefixLen > 32) + iPrefixLen = 32; + + int iClientIp = IPv4ToInt(clientIp); + int iRangeIp = IPv4ToInt(rangeIp); + + if (iClientIp == 0 || iRangeIp == 0) + return false; + + int iMask = (iPrefixLen == 32) ? -1 : ~((1 << (32 - iPrefixLen)) - 1); + + return (iClientIp & iMask) == (iRangeIp & iMask); } int IPv4ToInt(const char[] ip) { - char octets[4][4]; - if (ExplodeString(ip, ".", octets, 4, 4) != 4) - return 0; + char octets[4][4]; + if (ExplodeString(ip, ".", octets, 4, 4) != 4) + return 0; - int b1 = StringToInt(octets[0]); - int b2 = StringToInt(octets[1]); - int b3 = StringToInt(octets[2]); - int b4 = StringToInt(octets[3]); + int b1 = StringToInt(octets[0]); + int b2 = StringToInt(octets[1]); + int b3 = StringToInt(octets[2]); + int b4 = StringToInt(octets[3]); - return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; } bool IsIPWhitelisted(const char[] ip)