#define BAD_CKEY 1 #define BAD_IP 2 #define BAD_CID 4 /proc/handle_ban_mirroring(var/ckey, var/address, var/computer_id, var/ban_id) if (!ckey || !address || !computer_id || !ban_id) return if (!establish_db_connection(GLOB.dbcon)) log_world("ERROR: Ban database connection failure while attempting to mirror. Key passed for mirror handling: [ckey].") log_misc("Ban database connection failure while attempting to mirror. Key passed for mirror handling: [ckey].") return var/bad_data = BAD_CKEY|BAD_IP|BAD_CID var/DBQuery/original_ban = GLOB.dbcon.NewQuery("SELECT ckey, ip, computerid FROM ss13_ban WHERE id = :ban_id:") original_ban.Execute(list("ban_id" = ban_id)) if (original_ban.NextRow()) var/original_ckey = original_ban.item[1] var/original_address = original_ban.item[2] var/original_computerid = original_ban.item[3] if (original_ckey == ckey) bad_data &= ~BAD_CKEY if (original_address == address) bad_data &= ~BAD_IP if (original_computerid == computer_id) bad_data &= ~BAD_CID if (bad_data) var/DBQuery/mirrored_bans = GLOB.dbcon.NewQuery("SELECT ckey, ip, computerid FROM ss13_ban_mirrors WHERE isnull(deleted_at) AND ban_id = :ban_id:") mirrored_bans.Execute(list("ban_id" = ban_id)) while (mirrored_bans.NextRow()) var/mirrored_ckey = mirrored_bans.item[1] var/mirrored_address = mirrored_bans.item[2] var/mirrored_computerid = mirrored_bans.item[3] if ((bad_data & BAD_CKEY) && mirrored_ckey == ckey) bad_data &= ~BAD_CKEY if ((bad_data & BAD_IP) && mirrored_address == address) bad_data &= ~BAD_IP if ((bad_data & BAD_CID) && mirrored_computerid == computer_id) bad_data &= ~BAD_CID if (bad_data) apply_ban_mirror(ckey, address, computer_id, ban_id, 3) return else log_world("ERROR: No ban retreived while attempting to handle ban mirroring. Passed ban_id: [ban_id], ckey: [ckey].") log_misc("No ban retreived while attempting to handle ban mirroring. Passed ban_id: [ban_id], ckey: [ckey].") return /proc/get_active_mirror(var/ckey, var/address, var/computer_id) if (!ckey || !address || !computer_id) return null if (!establish_db_connection(GLOB.dbcon)) log_world("ERROR: Ban database connection failure while attempting to check mirrors. Key passed for mirror checking: [ckey].") log_misc("Ban database connection failure while attempting to check mirrors. Key passed for mirror checking: [ckey].") return null var/DBQuery/initial_query = GLOB.dbcon.NewQuery("SELECT DISTINCT ban_id FROM ss13_ban_mirrors WHERE isnull(deleted_at) AND (ckey = :ckey: OR ip = :address: OR computerid = :computerid:)") initial_query.Execute(list("ckey" = ckey, "address" = address, "computerid" = computer_id)) var/list/ban_ids = list() while (initial_query.NextRow()) ban_ids += text2num(initial_query.item[1]) // No mirrors exist. if (!ban_ids.len) return null var/DBQuery/search_query = GLOB.dbcon.NewQuery("SELECT id FROM ss13_ban WHERE id IN :vars: AND isnull(unbanned) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now()))") search_query.Execute(list("vars" = ban_ids)) var/list/active_bans = list() while (search_query.NextRow()) active_bans += text2num(search_query.item[1]) if (!active_bans.len) // None are active. return null else // Return the latest entry, if multiple bans are active. // Just in case. return active_bans[active_bans.len] /proc/apply_ban_mirror(var/ckey, var/address, var/computer_id, var/ban_id, var/source = 1, var/list/extra_info = list()) if (!ckey || !address || !computer_id || !ban_id) return . = list() for (var/i = 1; i <= extra_info.len && i <= 50; i++) . |= extra_info[i][1] var/DBQuery/new_mirror = GLOB.dbcon.NewQuery("INSERT INTO ss13_ban_mirrors (id, ban_id, ckey, ip, computerid, source, extra_info, datetime) VALUES (NULL, :ban_id:, :ckey:, :address:, :computerid:, :source:, :info:, NOW())") new_mirror.Execute(list("ban_id" = ban_id, "ckey" = ckey, "address" = address, "computerid" = computer_id, "source" = source, "info" = json_encode(.))) log_misc("Mirrored ban #[ban_id] for player [ckey] from [address]-[computer_id].") /proc/get_ban_mirrors(var/ban_id) if (!ban_id) return null if (!establish_db_connection(GLOB.dbcon)) return null var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, ckey, ip, computerid, date(datetime) as datetime, source, extra_info, deleted_at FROM ss13_ban_mirrors WHERE ban_id = :ban_id:") query.Execute(list("ban_id" = ban_id)) var/list/mirrors = list() while (query.NextRow()) var/list/items = list(7) items["id"] = text2num(query.item[1]) items["ckey"] = query.item[2] items["ip"] = query.item[3] items["computerid"] = query.item[4] items["date"] = query.item[5] items["source"] = query.item[6] items["extra"] = FALSE if (query.item[7]) try var/list/temp = json_decode(query.item[7]) if (temp.len) items["extra"] = TRUE catch() if (query.item[8]) items["inactive"] = TRUE else items["inactive"] = FALSE mirrors += list(items) return mirrors /proc/display_mirrors_panel(mob/user, ban_id) if (!user || !check_rights(R_MOD|R_ADMIN) || !ban_id) return var/list/mirrors = get_ban_mirrors(ban_id) if (!mirrors) to_chat(user, SPAN_WARNING("Something went horribly wrong.")) return if (!mirrors.len) to_chat(user, SPAN_WARNING("No mirrors for this ban found.")) return var/output = "
Ban mirrors for ban #[ban_id]

" output += "
Each line indicates a new bypass attempt.

" output += "" output += "" output += "" output += "" output += "" output += "" output += "" var/static/list/bg_colors = list("#ffeeee", "#ffdddd") var/i = 0 for (var/mirror in mirrors) var/list/details = mirror var/bg = details["inactive"] ? "#aaaaaa" : bg_colors[i + 1] output += "" output += "" output += "" output += "" output += "" output += "" output += "" output += "" output += "" i = (++i % 2) output += "
TYPECKEYTIME APPLIEDOPTIONS
[details["source"]][details["ckey"]][details["date"]][details["inactive"] ? "Reactivate" : "Deactivate"]" if (details["extra"]) output += " | View Ckeys" output += "
IP: [details["ip"]]CID: [details["computerid"]]
" user << browse(HTML_SKELETON(output), "window=banmirrors;size=600x400") /proc/display_mirrors_ckeys(mob/user, mirror_id) if (!user || !check_rights(R_MOD|R_ADMIN) || !mirror_id) return if (!establish_db_connection(GLOB.dbcon)) to_chat(user, SPAN_WARNING("Database connection failed!")) return var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT extra_info, ban_id FROM ss13_ban_mirrors WHERE id = :id:") query.Execute(list("id" = mirror_id)) if (!query.NextRow()) to_chat(user, SPAN_NOTICE("Unable to locate mirror with ID #[mirror_id].")) return if (!query.item[1] || !length(query.item[1])) to_chat(user, SPAN_NOTICE("No attached ckeys were found.")) return var/output = "Back

" try var/list/ckeys = json_decode(query.item[1]) if (!ckeys.len) to_chat(user, SPAN_NOTICE("No alternate ckeys to report.")) return output += ckeys.Join("
") catch() to_chat(user, SPAN_NOTICE("Maligned data found. Please alert the system administrator.")) return output += "

Back" user << browse(HTML_SKELETON(output), "window=banmirrors") /proc/toggle_mirror_status(mob/user, mirror_id, inactive = FALSE) if (!user || !check_rights(R_MOD|R_ADMIN) || !mirror_id) return if (!establish_db_connection(GLOB.dbcon)) to_chat(user, SPAN_WARNING("Database connection failed!")) return var/query_text = inactive ? "UPDATE ss13_ban_mirrors SET deleted_at = NULL WHERE id = :id:" : "UPDATE ss13_ban_mirrors SET deleted_at = NOW() WHERE id = :id:" var/DBQuery/query = GLOB.dbcon.NewQuery(query_text) query.Execute(list("id" = mirror_id)) if (query.ErrorMsg()) to_chat(user, SPAN_WARNING("An error occured while toggling mirror status!")) else to_chat(user, SPAN_NOTICE("Mirror set to [inactive ? "ACTIVE" : "INACTIVE"].")) /proc/handle_connection_info(var/client/C, var/data) if (!C) return if (!data) update_connection_data(C) return var/list/data_object try data_object = json_decode(data) catch(var/exception/E) data_object = list() LOG_DEBUG("CONN DATA: [E] encountered when loading data for [C.ckey].") if (!data_object || !data_object.len) LOG_DEBUG("CONN DATA: [C.ckey] has no connection data to showcase.") return if (data_object["vms"]) var/A = data_object["vms"] var/count = 0 if (A & 1) count++ if (A & 2) count++ if (GLOB.config.access_deny_vms && count >= GLOB.config.access_deny_vms) log_access("Failed Login: [C.ckey] [C.address] [C.computer_id] - Matching [count]/[GLOB.config.access_deny_vms] VM identifiers. IDs: [A].") message_admins("Failed Login: [C.ckey] [C.address] [C.computer_id] - Matching [count]/[GLOB.config.access_deny_vms] VM identifiers. IDs: [A].") spawn(20) if (C) del(C) return if (GLOB.config.access_warn_vms && count >= GLOB.config.access_warn_vms) log_access("Notice: [key_name(C)] [C.address] [C.computer_id] - Matching [count] VM identifiers. IDs: [A].") message_admins("Notice: [key_name(C)] [C.address] [C.computer_id] - Matching [count] VM identifiers. IDs: [A].") var/list/conn_info = data_object["conn"] if (!conn_info || !conn_info.len) return else if (conn_info.len > 100) LOG_DEBUG("MIRROR BANS: [C.ckey] has [conn_info.len] unique sets. They were dropped and not processed.") update_connection_data(C) return var/ding_bannu = 0 var/new_info = BAD_CKEY|BAD_IP|BAD_CID for (var/A in conn_info) var/list/dset = A if (dset.len != 3) continue if (new_info) if (dset[1] == C.ckey) new_info &= ~BAD_CKEY if (dset[2] == C.address) new_info &= ~BAD_IP if (dset[3] == C.computer_id) new_info &= ~BAD_CID var/list/bdata = world.IsBanned(dset[1], dset[2], dset[3], 1, real_bans_only = TRUE, log_connection = FALSE) if (bdata && bdata.len && !isnull(bdata["id"])) ding_bannu = bdata["id"] break if (new_info) update_connection_data(C, conn_info) if (ding_bannu) if (!C.holder) log_and_message_admins("[C.ckey] from [C.address]-[C.computer_id] was caught bandodging. Mirror applied for ban #[ding_bannu], kicking shortly.") apply_ban_mirror(C.ckey, C.address, C.computer_id, ding_bannu, 2, conn_info) spawn(20) del(C) else // Stop kicking me off my test server, fuck. log_and_message_admins("[C.ckey] is a staff but was caught bandodging! Ban ID: #[ding_bannu].") return /proc/update_connection_data(var/client/C, var/list/data = list()) if (!C) return data += list(list(C.ckey, C.address, C.computer_id)) var/data_str = json_encode(data) send_output(C, list2params(list("E-DAT", data_str, 900)), "greeting.browser:setCookie") #undef BAD_CID #undef BAD_IP #undef BAD_CKEY