"
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index e6d258b3386..37c6a60bcdd 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -2,38 +2,42 @@
world/IsBanned(key,address,computer_id)
if (!key || !address || !computer_id)
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
- return list("reason"="invalid login data", "desc"="Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]' If you continue to get this error, please restart byond or contact byond support.")
- if(ckey(key) in admin_datums)
- return ..()
+ return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
+ var/admin = 0
+ var/ckey = ckey(key)
+ if((ckey in admin_datums) || (ckey in deadmins))
+ admin = 1
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
- log_access("Failed Login: [key] - Guests not allowed")
+ log_access("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("\blue Failed Login: [key] - Guests not allowed")
- return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
+ return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
- //check if the IP address is a known TOR node
- if(config && config.ToRban && ToRban_isbanned(address))
- log_access("Failed Login: [src] - Banned: ToR")
- message_admins("\blue Failed Login: [src] - Banned: ToR")
+ //check if the IP address is a known Tor node
+ if(config.ToRban && ToRban_isbanned(address))
+ log_access("Failed Login: [key] [computer_id] [address] - Banned: Tor")
+ message_admins("Failed Login: [key] - Banned: Tor")
//ban their computer_id and ckey for posterity
- AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0)
- return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]")
+ AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0)
+ var/mistakemessage = ""
+ if(config.banappeals)
+ mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
+ return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
if(config.ban_legacy_system)
-
//Ban Checking
- . = CheckBan( ckey(key), computer_id, address )
+ . = CheckBan(ckey(key), computer_id, address)
if(.)
- log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
- message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
- return .
-
- return ..() //default pager ban stuff
-
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]].")
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
else
-
var/ckeytext = ckey(key)
if(!establish_db_connection())
@@ -49,7 +53,7 @@ world/IsBanned(key,address,computer_id)
if(computer_id)
cidquery = " OR computerid = '[computer_id]' "
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
@@ -63,18 +67,47 @@ world/IsBanned(key,address,computer_id)
var/duration = query.item[7]
var/bantime = query.item[8]
var/bantype = query.item[9]
-
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ //admin bans MUST match on ckey to prevent cid-spoofing attacks
+ // as well as dynamic ip abuse
+ if (pckey != ckey)
+ continue
+ if (admin)
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ log_admin("The admin [key] is admin banned, and has been disallowed access")
+ message_admins("The admin [key] is admin banned, and has been disallowed access")
+ else
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [pckey].")
+ continue
var/expires = ""
if(text2num(duration) > 0)
- expires = "The ban is for [duration] minutes and expires on [expiration] (server time)."
- if(istext(bantype) && (bantype == "PERMABAN"))
- var/appealmsg = ""
- if(config && config.banappeals)
- appealmsg = " You may appeal it at [config.banappeals]."
- expires = "The ban is permanent.[appealmsg]"
+ expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
+ else
+ var/appealmessage = ""
+ if(config.banappeals)
+ appealmessage = " You may appeal it at [config.banappeals]."
+ expires = " The is a permanent ban.[appealmessage]"
- var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime]. [expires]"
+ var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
- return list("reason"="[bantype]", "desc"="[desc]")
+ . = list("reason"="[bantype]", "desc"="[desc]")
- return ..() //default pager ban stuff
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
+
+ . = ..() //default pager ban stuff
+ if (.)
+ //byond will not trigger isbanned() for "global" host bans,
+ //ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked)
+ //So it's safe to let admins walk thru host/sticky bans here
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ message_admins("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban.")
+ return null
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]")
+
+ return .
diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm
index 03fc3767b8e..355a82aa697 100644
--- a/code/modules/admin/admin_memo.dm
+++ b/code/modules/admin/admin_memo.dm
@@ -11,7 +11,7 @@
return
admin_memo_output(memotask)
-/client/proc/admin_memo_output(task, checkrights = 1)
+/client/proc/admin_memo_output(task, checkrights = 1, silent = 0)
if(checkrights && !check_rights(R_SERVER))
return
if(!task)
@@ -99,7 +99,7 @@
if(last_editor)
output += " Last edit by [last_editor] (Click here to see edit log)"
output += " [memotext] "
- if(!output)
+ if(!output && !silent)
src << "No memos found in database."
return
src << output
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index a7e9cf0fd3e..e2b26e7c491 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -74,7 +74,8 @@ var/list/admin_verbs_admin = list(
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
- /client/proc/jobbans
+ /client/proc/jobbans,
+ /client/proc/stickybanpanel
)
var/list/admin_verbs_sounds = list(
/client/proc/play_local_sound,
@@ -225,6 +226,7 @@ var/list/admin_verbs_proccall = list (
admin_verbs_spawn,
admin_verbs_mod,
admin_verbs_mentor,
+ admin_verbs_proccall,
admin_verbs_show_debug_verbs,
/client/proc/readmin,
)
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
new file mode 100644
index 00000000000..474b7c76265
--- /dev/null
+++ b/code/modules/admin/stickyban.dm
@@ -0,0 +1,211 @@
+/datum/admins/proc/stickyban(action,data)
+ if(!check_rights(R_BAN))
+ return
+
+ switch (action)
+ if ("show")
+ stickyban_show()
+ return
+ if ("add")
+ var/list/ban = list()
+ var/ckey
+ ban["admin"] = usr.key
+ ban["type"] = list("sticky")
+ ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
+
+ if (data["ckey"])
+ ckey = ckey(data["ckey"])
+ else
+ ckey = input(usr,"Ckey","Ckey","") as text|null
+ if (!ckey)
+ return
+ ckey = ckey(ckey)
+ if (get_stickyban_from_ckey(ckey))
+ usr << "Error: Can not add a stickyban: User already has a current sticky ban"
+
+ if (data["reason"])
+ ban["message"] = data["reason"]
+ else
+ var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null
+ if (!reason)
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban", ckey, list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+ message_admins("[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+
+ if ("remove")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
+ return
+ if (!get_stickyban_from_ckey(ckey))
+ usr << "Error: The ban disappeared."
+ return
+ world.SetConfig("ban", ckey, null)
+
+ log_admin("[key_name(usr)] removed [ckey]'s stickyban")
+ message_admins("[key_name_admin(usr)] removed [ckey]'s stickyban")
+
+ if ("remove_alt")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ if (!data["alt"])
+ return
+ var/alt = ckey(data["alt"])
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+
+ var/found = 0
+ //we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] is not linked to [ckey]'s sticky ban!"
+ return
+
+ if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
+ return
+
+ //we have to do this again incase something changes
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+
+ found = 0
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ ban["keys"] -= key
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] link to [ckey]'s sticky ban disappeared."
+ return
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+ message_admins("[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+
+ if ("edit")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ var/oldreason = ban["message"]
+ var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
+ if (!reason || reason == oldreason)
+ return
+ //we have to do this again incase something changed while we waited for input
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+ message_admins("[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+
+ spawn(10)
+ stickyban_show()
+
+/datum/admins/proc/stickyban_gethtml(ckey, ban)
+ . = "\[-\][ckey] "
+ . += "[ban["message"]] \[Edit\] "
+ if (ban["admin"])
+ . += "[ban["admin"]] "
+ else
+ . += "LEGACY "
+ . += "Caught keys \n"
+ for (var/key in ban["keys"])
+ if (ckey(key) == ckey)
+ continue
+ . += "