From 8b7eb11df9449b46372b4af70b411c75e415fb93 Mon Sep 17 00:00:00 2001 From: oranges Date: Tue, 27 Sep 2016 22:04:08 +0000 Subject: [PATCH] Fix multiple href exploits from incorrectly scoped locates Also adds a helper to flatten a keyed list to it's contents as it turns out that byond cannot locate in a keyed list --- code/__HELPERS/lists.dm | 13 +++ code/_globalvars/lists/objects.dm | 3 +- code/game/machinery/computer/prisoner.dm | 18 ++-- code/game/objects/items/devices/camera_bug.dm | 43 ++++++---- .../items/weapons/implants/implant_chem.dm | 4 +- code/game/objects/structures/guncase.dm | 4 +- code/modules/games/cards.dm | 5 +- code/modules/library/lib_machines.dm | 12 +-- .../modules/mob/living/silicon/robot/robot.dm | 86 +------------------ code/modules/stock_market/computer.dm | 11 +-- 10 files changed, 70 insertions(+), 129 deletions(-) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 4deb0080014..9218e4f3c23 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -392,5 +392,18 @@ if(islist(.[i])) .[i] = .(.[i]) +#if DM_VERSION > 512 +#error Remie said that lummox was adding a way to get a lists +#error contents via list.values, if that is true remove this +#error otherwise, update the version and bug lummox +#elseif +//Flattens a keyed list into a list of it's contents +/proc/flatten_list(list/key_list) + if(!islist(key_list)) + return null + . = list() + for(var/key in key_list) + . |= key_list[key] + //Picks from the list, with some safeties, and returns the "default" arg if it fails #define DEFAULTPICK(L, default) ((istype(L, /list) && L:len) ? pick(L) : default) diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 28e55d7e03f..8d971ddbb22 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -21,7 +21,8 @@ var/global/list/crafting_recipes = list() //list of all table craft recipes var/global/list/rcd_list = list() //list of Rapid Construction Devices. var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed. var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented... +var/global/list/tracked_chem_implants = list() //list of implants the prisoner console can track and send inject commands too var/global/list/poi_list = list() //list of points of interest for observe/follow var/global/list/pinpointer_list = list() //list of all pinpointers. Used to change stuff they are pointing to all at once. var/global/list/zombie_infection_list = list() // A list of all zombie_infection organs, for any mass "animation" -var/global/list/meteor_list = list() // List of all meteors. \ No newline at end of file +var/global/list/meteor_list = list() // List of all meteors. diff --git a/code/game/machinery/computer/prisoner.dm b/code/game/machinery/computer/prisoner.dm index 8502e90f4f5..9df931c720a 100644 --- a/code/game/machinery/computer/prisoner.dm +++ b/code/game/machinery/computer/prisoner.dm @@ -32,7 +32,7 @@ dat += "

Prisoner Implant Management

" dat += "
Chemical Implants
" var/turf/Tr = null - for(var/obj/item/weapon/implant/chem/C in tracked_implants) + for(var/obj/item/weapon/implant/chem/C in tracked_chem_implants) Tr = get_turf(C) if((Tr) && (Tr.z != src.z)) continue//Out of range @@ -114,17 +114,17 @@ num = min(num,1000) //Cap the quota to the equivilent of 10 minutes. inserted_id.goal = num else if(href_list["inject1"]) - var/obj/item/weapon/implant/I = locate(href_list["inject1"]) - if(I) + var/obj/item/weapon/implant/I = locate(href_list["inject1"]) in tracked_chem_implants + if(I && istype(I)) I.activate(1) else if(href_list["inject5"]) - var/obj/item/weapon/implant/I = locate(href_list["inject5"]) - if(I) + var/obj/item/weapon/implant/I = locate(href_list["inject5"]) in tracked_chem_implants + if(I && istype(I)) I.activate(5) else if(href_list["inject10"]) - var/obj/item/weapon/implant/I = locate(href_list["inject10"]) - if(I) + var/obj/item/weapon/implant/I = locate(href_list["inject10"]) in tracked_chem_implants + if(I && istype(I)) I.activate(10) else if(href_list["lock"]) @@ -136,8 +136,8 @@ else if(href_list["warn"]) var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN) if(!warning) return - var/obj/item/weapon/implant/I = locate(href_list["warn"]) - if((I)&&(I.imp_in)) + var/obj/item/weapon/implant/I = locate(href_list["warn"]) in tracked_chem_implants + if(I && istype(I) && I.imp_in) var/mob/living/carbon/R = I.imp_in R << "You hear a voice in your head saying: '[warning]'" log_say("[usr]/[usr.ckey] sent an implant message to [R]/[R.ckey]: '[warning]'") diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index fc18c1a4c0d..81405579707 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -136,11 +136,16 @@ return .(cameras) return html +/obj/item/device/camera_bug/proc/get_seens() + if(current && current.can_use()) + var/list/seen = current.can_see() + return seen + /obj/item/device/camera_bug/proc/camera_report() // this should only be called if current exists var/dat = "" - if(current && current.can_use()) - var/list/seen = current.can_see() + var/list/seen = get_seens() + if(seen && seen.len >= 1) var/list/names = list() for(var/obj/singularity/S in seen) // god help you if you see more than one if(S.name in names) @@ -190,23 +195,29 @@ if("mode" in href_list) track_mode = text2num(href_list["mode"]) if("monitor" in href_list) - var/obj/machinery/camera/C = locate(href_list["monitor"]) - if(C) + //You can't locate on a list with keys + var/list/cameras = flatten_list(bugged_cameras) + var/obj/machinery/camera/C = locate(href_list["monitor"]) in cameras + if(C && istype(C)) track_mode = BUGMODE_MONITOR current = C usr.reset_perspective(null) interact() if("track" in href_list) - var/atom/A = locate(href_list["track"]) - if(A) - tracking = A - tracked_name = A.name - last_found = current.c_tag - last_seen = world.time - track_mode = BUGMODE_TRACK + var/list/seen = get_seens() + if(seen && seen.len >= 1) + var/atom/A = locate(href_list["track"]) in seen + if(A && istype(A)) + tracking = A + tracked_name = A.name + last_found = current.c_tag + last_seen = world.time + track_mode = BUGMODE_TRACK if("emp" in href_list) - var/obj/machinery/camera/C = locate(href_list["emp"]) - if(istype(C) && C.bug == src) + //You can't locate on a list with keys + var/list/cameras = flatten_list(bugged_cameras) + var/obj/machinery/camera/C = locate(href_list["emp"]) in cameras + if(C && istype(C) && C.bug == src) C.emp_act(1) C.bug = null bugged_cameras -= C.c_tag @@ -217,8 +228,10 @@ current = null return if("view" in href_list) - var/obj/machinery/camera/C = locate(href_list["view"]) - if(istype(C)) + //You can't locate on a list with keys + var/list/cameras = flatten_list(bugged_cameras) + var/obj/machinery/camera/C = locate(href_list["view"]) in cameras + if(C && istype(C)) if(!C.can_use()) usr << "Something's wrong with that camera! You can't get a feed." return diff --git a/code/game/objects/items/weapons/implants/implant_chem.dm b/code/game/objects/items/weapons/implants/implant_chem.dm index 731fba971fe..c9270f6da58 100644 --- a/code/game/objects/items/weapons/implants/implant_chem.dm +++ b/code/game/objects/items/weapons/implants/implant_chem.dm @@ -24,11 +24,11 @@ /obj/item/weapon/implant/chem/New() ..() create_reagents(50) - tracked_implants += src + tracked_chem_implants += src /obj/item/weapon/implant/chem/Destroy() ..() - tracked_implants -= src + tracked_chem_implants -= src diff --git a/code/game/objects/structures/guncase.dm b/code/game/objects/structures/guncase.dm index abaebce5de3..9477946c356 100644 --- a/code/game/objects/structures/guncase.dm +++ b/code/game/objects/structures/guncase.dm @@ -76,7 +76,9 @@ /obj/structure/guncase/Topic(href, href_list) if(href_list["retrieve"]) - var/obj/item/O = locate(href_list["retrieve"]) + var/obj/item/O = locate(href_list["retrieve"]) in contents + if(!O || !istype(O)) + return if(!usr.canUseTopic(src)) return if(ishuman(usr)) diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index 2f8e95e799c..854d145260b 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -264,9 +264,8 @@ if (istype(hclient)) switch (href_list["action"]) if ("play_card") - var/datum/playingcard/card = locate(href_list["card"]) - - if (card in src.cards) + var/datum/playingcard/card = locate(href_list["card"]) in cards + if (card && istype(card)) src.discard(card) if ("toggle_conceal") src.toggle_conceal() diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index ba15a04fcc6..2d85151c98d 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -374,11 +374,13 @@ var/global/list/datum/cachedbook/cachedbooks // List of our cached book datums b.duedate = world.time + (checkoutperiod * 600) checkouts.Add(b) if(href_list["checkin"]) - var/datum/borrowbook/b = locate(href_list["checkin"]) - checkouts.Remove(b) + var/datum/borrowbook/b = locate(href_list["checkin"]) in checkouts + if(b && istype(b)) + checkouts.Remove(b) if(href_list["delbook"]) - var/obj/item/weapon/book/b = locate(href_list["delbook"]) - inventory.Remove(b) + var/obj/item/weapon/book/b = locate(href_list["delbook"]) in inventory + if(b && istype(b)) + inventory.Remove(b) if(href_list["setauthor"]) var/newauthor = copytext(sanitize(input("Enter the author's name: ") as text|null),1,MAX_MESSAGE_LEN) if(newauthor) @@ -542,4 +544,4 @@ var/global/list/datum/cachedbook/cachedbooks // List of our cached book datums B.icon_state = "book[rand(1,7)]" qdel(P) else - P.loc = loc \ No newline at end of file + P.loc = loc diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 6f56ca375b9..5b3b3ee6e2e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -683,90 +683,6 @@ update_fire() -/mob/living/silicon/robot/proc/installed_modules() - if(!module) - pick_module() - return - var/dat = {"Close -
-
- Activated Modules -
- - - - -
Module 1:[module_state_1 ? "[module_state_1]" : "No Module"]
Module 2:[module_state_2 ? "[module_state_2]" : "No Module"]
Module 3:[module_state_3 ? "[module_state_3]" : "No Module"]

- Installed Modules

- - "} - - for (var/obj in module.modules) - if (!obj) - dat += text("") - else if(activated(obj)) - dat += text("") - else - dat += text("") - if (emagged) - if(activated(module.emag)) - dat += text("") - else - dat += text("") - dat += "
Resource depleted
[obj]Activated
[obj]Activate
[module.emag]Activated
[module.emag]Activate
" -/* - if(activated(obj)) - dat += text("[obj]: \[Activated | Deactivate\]
") - else - dat += text("[obj]: \[Activate | Deactivated\]
") -*/ - var/datum/browser/popup = new(src, "robotmod", "Modules") - popup.set_content(dat) - popup.open() - -/mob/living/silicon/robot/Topic(href, href_list) - ..() - if(usr && (src != usr)) - return - - if (href_list["mach_close"]) - var/t1 = text("window=[href_list["mach_close"]]") - unset_machine() - src << browse(null, t1) - return - - if (href_list["showalerts"]) - robot_alerts() - return - - if (href_list["mod"]) - var/obj/item/O = locate(href_list["mod"]) - if (O) - O.attack_self(src) - - if (href_list["act"]) - var/obj/item/O = locate(href_list["act"]) - activate_module(O) - installed_modules() - - if (href_list["deact"]) - var/obj/item/O = locate(href_list["deact"]) - if(activated(O)) - if(module_state_1 == O) - module_state_1 = null - contents -= O - else if(module_state_2 == O) - module_state_2 = null - contents -= O - else if(module_state_3 == O) - module_state_3 = null - contents -= O - else - src << "Module isn't activated." - else - src << "Module isn't activated" - installed_modules() - #define BORG_CAMERA_BUFFER 30 /mob/living/silicon/robot/Move(a, b, flag) var/oldLoc = src.loc @@ -1161,4 +1077,4 @@ status_flags |= CANPUSH - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/stock_market/computer.dm b/code/modules/stock_market/computer.dm index 97a2bc983b1..91802bb473d 100644 --- a/code/modules/stock_market/computer.dm +++ b/code/modules/stock_market/computer.dm @@ -248,7 +248,7 @@ a.updated { usr.machine = src if (href_list["viewhistory"]) - var/datum/stock/S = locate(href_list["viewhistory"]) + var/datum/stock/S = locate(href_list["viewhistory"]) in stockExchange.stocks if (S) S.displayValues(usr) @@ -256,20 +256,15 @@ a.updated { logged_in = null if (href_list["buyshares"]) - var/datum/stock/S = locate(href_list["buyshares"]) + var/datum/stock/S = locate(href_list["buyshares"]) in stockExchange.stocks if (S) buy_some_shares(S, usr) if (href_list["sellshares"]) - var/datum/stock/S = locate(href_list["sellshares"]) + var/datum/stock/S = locate(href_list["sellshares"]) in stockExchange.stocks if (S) sell_some_shares(S, usr) - if (href_list["take"]) - var/datum/borrow/B = locate(href_list["take"]) - if (B && !B.lease_expires) - do_borrowing_deal(B, usr) - if (href_list["show_logs"]) var/dat = "Stock Transaction Logs

Stock Transaction Logs

Refresh

" for(var/D in stockExchange.logs)