From 76361cda8460e28c1cdb39311818872bfc6ed46e Mon Sep 17 00:00:00 2001 From: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Date: Fri, 18 Sep 2020 17:47:37 +0100 Subject: [PATCH] Ports TG's topic limiting (#14330) --- code/modules/client/client defines.dm | 5 ++- code/modules/client/client procs.dm | 50 ++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index 72537f8ccc3..46ec605e71d 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -36,7 +36,10 @@ //////////// //SECURITY// //////////// - var/next_allowed_topic_time = 10 + + ///Used for limiting the rate of topic sends by the client to avoid abuse + var/list/topiclimiter + // comment out the line below when debugging locally to enable the options & messages menu //control_freak = 1 diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index ae503be111b..f8ef211d5de 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -11,6 +11,13 @@ #define SUGGESTED_CLIENT_VERSION 511 // only integers (e.g: 510, 511) useful here. Does not properly handle minor versions (e.g: 510.58, 511.848) #define SSD_WARNING_TIMER 30 // cycles, not seconds, so 30=60s +#define LIMITER_SIZE 5 +#define CURRENT_SECOND 1 +#define SECOND_COUNT 2 +#define CURRENT_MINUTE 3 +#define MINUTE_COUNT 4 +#define ADMINSWARNED_AT 5 + /* When somebody clicks a link in game, this Topic is called first. It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever] @@ -59,10 +66,38 @@ if(href_list["_src_"] == "chat") return chatOutput.Topic(href, href_list) - //Reduces spamming of links by dropping calls that happen during the delay period - if(next_allowed_topic_time > world.time) - return - next_allowed_topic_time = world.time + TOPIC_SPAM_DELAY + // Rate limiting + var/mtl = 100 // 100 topics per minute + if (!holder) // Admins are allowed to spam click, deal with it. + var/minute = round(world.time, 600) + if (!topiclimiter) + topiclimiter = new(LIMITER_SIZE) + if (minute != topiclimiter[CURRENT_MINUTE]) + topiclimiter[CURRENT_MINUTE] = minute + topiclimiter[MINUTE_COUNT] = 0 + topiclimiter[MINUTE_COUNT] += 1 + if (topiclimiter[MINUTE_COUNT] > mtl) + var/msg = "Your previous action was ignored because you've done too many in a minute." + if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them) + topiclimiter[ADMINSWARNED_AT] = minute + msg += " Administrators have been informed." + log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") + message_admins("[ADMIN_LOOKUPFLW(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") + to_chat(src, "[msg]") + return + + var/stl = 10 // 10 topics a second + if (!holder) // Admins are allowed to spam click, deal with it. + var/second = round(world.time, 10) + if (!topiclimiter) + topiclimiter = new(LIMITER_SIZE) + if (second != topiclimiter[CURRENT_SECOND]) + topiclimiter[CURRENT_SECOND] = second + topiclimiter[SECOND_COUNT] = 0 + topiclimiter[SECOND_COUNT] += 1 + if (topiclimiter[SECOND_COUNT] > stl) + to_chat(src, "Your previous action was ignored because you've done too many in a second") + return //search the href for script injection if( findtext(href,"UI resource files resent successfully. If you are still having issues, please try manually clearing your BYOND cache. This can be achieved by opening your BYOND launcher, pressing the cog in the top right, selecting preferences, going to the Games tab, and pressing 'Clear Cache'.") + +#undef LIMITER_SIZE +#undef CURRENT_SECOND +#undef SECOND_COUNT +#undef CURRENT_MINUTE +#undef MINUTE_COUNT +#undef ADMINSWARNED_AT