Adds proc call security

This commit is contained in:
AffectedArc07
2020-07-09 10:29:51 +01:00
parent 07597b9480
commit 608c71c6e5
10 changed files with 161 additions and 5 deletions
+63 -3
View File
@@ -85,18 +85,78 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return
message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
returnval = WrapAdminProcCall(target, procname, lst) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
returnval = WrapAdminProcCall(GLOBAL_PROC, procname, lst) // Pass the lst as an argument list to the proc
to_chat(usr, "<font color='blue'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</font>")
feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
// All these vars are related to proc call protection
// If you add more of these, for the love of fuck, protect them
/// Who is currently calling procs
GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
/// How many procs have been called
GLOBAL_VAR_INIT(AdminProcCallCount, 0)
GLOBAL_PROTECT(AdminProcCallCount)
/// UID of the admin who last called
GLOBAL_VAR(LastAdminCalledTargetUID)
GLOBAL_PROTECT(LastAdminCalledTargetUID)
/// Last target to have a proc called on it
GLOBAL_VAR(LastAdminCalledTarget)
GLOBAL_PROTECT(LastAdminCalledTarget)
/// Last proc called
GLOBAL_VAR(LastAdminCalledProc)
GLOBAL_PROTECT(LastAdminCalledProc)
/// List to handle proc call spam prevention
GLOBAL_LIST_EMPTY(AdminProcCallSpamPrevention)
GLOBAL_PROTECT(AdminProcCallSpamPrevention)
// Wrapper for proccalls where the datum is flagged as vareditted
/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target && procname == "Del")
to_chat(usr, "Calling Del() is not allowed")
return
if(target != GLOBAL_PROC && !target.CanProcCall(procname))
to_chat(usr, "Proccall on [target.type]/proc/[procname] is disallowed!")
return
var/current_caller = GLOB.AdminProcCaller
var/ckey = usr ? usr.client.ckey : GLOB.AdminProcCaller
if(!ckey)
CRASH("WrapAdminProcCall with no ckey: [target] [procname] [english_list(arguments)]")
if(current_caller && current_caller != ckey)
if(!GLOB.AdminProcCallSpamPrevention[ckey])
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
GLOB.AdminProcCallSpamPrevention[ckey] = TRUE
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.AdminProcCallSpamPrevention -= ckey
else
UNTIL(!GLOB.AdminProcCaller)
GLOB.LastAdminCalledProc = procname
if(target != GLOBAL_PROC)
GLOB.LastAdminCalledTargetUID = target.UID()
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
++GLOB.AdminProcCallCount
. = world.WrapAdminProcCall(target, procname, arguments)
if(--GLOB.AdminProcCallCount == 0)
GLOB.AdminProcCaller = null
//adv proc call this, ya nerds
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
if(target == GLOBAL_PROC)
return call(procname)(arglist(arguments))
else if(target != world)
return call(target, procname)(arglist(arguments))
else
log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
/proc/IsAdminAdvancedProcCall()
#ifdef TESTING
@@ -131,7 +191,7 @@ GLOBAL_PROTECT(AdminProcCaller)
log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
spawn()
var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
var/returnval = WrapAdminProcCall(A, procname, lst) // Pass the lst as an argument list to the proc
to_chat(src, "<span class='notice'>[procname] returned: [!isnull(returnval) ? returnval : "null"]</span>")
feedback_add_details("admin_verb","DPC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!