Skip to content
17 changes: 17 additions & 0 deletions code/__DEFINES/_globals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@
/// Creates an empty global initializer, do not use
#define GLOBAL_UNMANAGED(X) /datum/controller/global_vars/proc/InitGlobal##X() { return; }

#define GLOBAL_MANAGED_MULTIPLE(X)\
/datum/controller/global_vars/proc/InitGlobal##X(){\
##X = CollectGlobal##X();\
}\
/datum/controller/global_vars/proc/CollectGlobal##X(){\
CAN_BE_REDEFINED(TRUE);\
return list();\
}

#define GLOBAL_MULTIPLE_UPDATE(X, NewValue)\
/datum/controller/global_vars/CollectGlobal##X(){\
. = ..();\
. += ##NewValue;\
}

/// Creates name keyed subtype instance list
#define GLOBAL_SUBTYPE_INDEXED(X, TypePath, Index)\
/datum/controller/global_vars/proc/InitGlobal##X(){\
Expand Down Expand Up @@ -69,6 +84,8 @@
/// Create a global const var, do not use
#define GLOBAL_VAR_CONST(X, InitValue) GLOBAL_RAW(/const/##X) = InitValue; GLOBAL_UNMANAGED(X)

#define GLOBAL_MULTIPLE(X) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED_MULTIPLE(X)

/// Create a list global with an initializer expression
#define GLOBAL_LIST_INIT(X, InitValue) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED(X, InitValue)

Expand Down
9 changes: 9 additions & 0 deletions code/__DEFINES/_protect.dm
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
GLOBAL_MULTIPLE(protected_sentry_procs)
#define SET_PROTECTED_PROC(proc) GLOBAL_MULTIPLE_UPDATE(protected_sentry_procs, proc)

GLOBAL_MULTIPLE(protected_sentry_datums)
#define SET_PROTECTED_DATUM(datum) GLOBAL_MULTIPLE_UPDATE(protected_sentry_datums, datum)

GLOBAL_LIST_EMPTY(protected_config_entries)

#define GENERAL_PROTECT_DATUM(Path)\
SET_PROTECTED_DATUM(Path)\
##Path/can_vv_get(var_name){\
return FALSE;\
}\
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/client.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
/// This gathers all the client *procs* that we are pretending are verbs - but only particularly want
/// authorized users to be able to use
/client/proc/collect_client_verbs() as /list
CAN_BE_REDEFINED(TRUE);
CAN_BE_REDEFINED(TRUE)

return list()
2 changes: 2 additions & 0 deletions code/__DEFINES/configuration.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//flags
#define CONFIG_ENTRY_LOCKED (1<<0) //can't edit
#define CONFIG_ENTRY_HIDDEN (1<<1) //can't see value
#define CONFIG_ENTRY_SENSITIVE (1<<2) //scrubbed from public logging, if a list assumes value is sensitive
#define CONFIG_ENTRY_SENSITIVE_KEY (1<<3) //scrubbed from public logging, if a list assumes key is sensitive

#define ON_CONFIG_LOAD(type) \
##type/New() { \
Expand Down
3 changes: 3 additions & 0 deletions code/_globalvars/lists/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ GLOBAL_PROTECT(admins)

GLOBAL_LIST_EMPTY(directory) //all ckeys with associated client

GLOBAL_LIST_EMPTY(all_player_ckeys)
GLOBAL_LIST_EMPTY(all_player_cids)

GLOBAL_LIST_EMPTY(player_list) //all mobs **with clients attached**.
GLOBAL_LIST_EMPTY(living_player_list) // all /mob/living with clients

Expand Down
2 changes: 2 additions & 0 deletions code/controllers/configuration/config_entry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#define KEY_MODE_TYPE 1
#define KEY_MODE_TEXT_UNALTERED 2

SET_PROTECTED_DATUM(/datum/config_entry)

/datum/config_entry
var/name //read-only, this is determined by the last portion of the derived entry type
var/config_entry_value
Expand Down
5 changes: 5 additions & 0 deletions code/controllers/configuration/configuration.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
SET_PROTECTED_DATUM(/datum/controller/configuration)

/datum/controller/configuration
name = "Configuration"

Expand Down Expand Up @@ -162,6 +164,9 @@
_entries[esname] = E
_entries_by_type[I] = E

if(E.protection & (CONFIG_ENTRY_SENSITIVE|CONFIG_ENTRY_SENSITIVE_KEY))
GLOB.protected_config_entries += E


/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
entries -= CE.name
Expand Down
4 changes: 2 additions & 2 deletions code/controllers/configuration/entries/achievements.dm
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/// The base URL for the achievements API endpoint
/datum/config_entry/string/achievements_api_url
protection = CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_SENSITIVE

/// The API key for authenticating with the achievements service
/datum/config_entry/string/achievements_api_key
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE

/// Additional parameter passed to the backend service
/datum/config_entry/string/achievements_instance
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/configuration/entries/dbconfig.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED

/datum/config_entry/string/db_password
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE

/datum/config_entry/flag/db_debug_mode
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED
Expand Down
15 changes: 8 additions & 7 deletions code/controllers/configuration/entries/general.dm
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Administrative related.
protection = CONFIG_ENTRY_LOCKED

/datum/config_entry/string/tgs3_commandline_path
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_SENSITIVE
config_entry_value = "C:\\Program Files (x86)\\TG Station Server\\TGCommandLine.exe"

/datum/config_entry/number/minute_topic_limit
Expand Down Expand Up @@ -375,14 +375,14 @@ or your package manager
The default value assumes youtube-dl is in your system PATH
*/
/datum/config_entry/string/invoke_youtubedl
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_SENSITIVE

/datum/config_entry/string/cobalt_base_api
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_SENSITIVE


/datum/config_entry/string/cobalt_api_key
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_SENSITIVE

/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
config_entry_value = 600
Expand Down Expand Up @@ -589,7 +589,7 @@ This maintains a list of ip addresses that are able to bypass topic filtering.
/datum/config_entry/keyed_list/topic_tokens
key_mode = KEY_MODE_TEXT
value_mode = VALUE_MODE_TEXT
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE_KEY

/datum/config_entry/keyed_list/topic_tokens/ValidateListEntry(key_name, key_value)
return key_value != "topic_token" && ..()
Expand Down Expand Up @@ -627,7 +627,7 @@ This maintains a list of ip addresses that are able to bypass topic filtering.

/datum/config_entry/string/redis_connection
config_entry_value = "redis://127.0.0.1/"
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE

/datum/config_entry/string/instance_name
config_entry_value = "game"
Expand Down Expand Up @@ -724,9 +724,10 @@ This maintains a list of ip addresses that are able to bypass topic filtering.
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN

/datum/config_entry/string/sentry_endpoint
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE

/datum/config_entry/string/sentry_dsn
protection = CONFIG_ENTRY_HIDDEN
protection = CONFIG_ENTRY_HIDDEN|CONFIG_ENTRY_LOCKED|CONFIG_ENTRY_SENSITIVE

/datum/config_entry/str_list/ignored_cids
protection = CONFIG_ENTRY_LOCKED
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/mc/globals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
gvars_datum_protected_varlist = list(NAMEOF(src, gvars_datum_protected_varlist) = TRUE)
var/list/global_procs = typesof(/datum/controller/global_vars/proc)
var/expected_len = length(vars) - length(gvars_datum_in_built_vars)
if(length(global_procs) != expected_len)
if(length(global_procs) < expected_len)
warning("Unable to detect all global initialization procs! Expected [expected_len] got [length(global_procs)]!")
if(length(global_procs))
var/list/expected_global_procs = vars - gvars_datum_in_built_vars
Expand Down
2 changes: 1 addition & 1 deletion code/controllers/subsystem/cmtv.dm
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ SUBSYSTEM_DEF(cmtv)
protection = CONFIG_ENTRY_LOCKED

/datum/config_entry/string/cmtv_api_key
protection = CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_SENSITIVE

/atom/movable/screen/cmtv
plane = ESCAPE_MENU_PLANE
Expand Down
60 changes: 50 additions & 10 deletions code/controllers/subsystem/sentry.dm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ SUBSYSTEM_DEF(sentry)
can_fire = FALSE
return SS_INIT_NO_NEED

return SS_INIT_SUCCESS

/datum/controller/subsystem/sentry/fire(resumed)
var/static/list/headers = list(
"Content-Type" = "application/x-sentry-envelope",
Expand All @@ -37,6 +39,8 @@ SUBSYSTEM_DEF(sentry)
if(!endpoint)
endpoint = ENDPOINT_CONFIG

var/static/regex/ip_regex = regex(@"(((?!25?[6-9])[12]\d|[1-9])?\d\.?\b){4}", "g")

for(var/datum/error_envelope/error as anything in envelopes)
var/event_id = get_uuid()

Expand All @@ -46,12 +50,12 @@ SUBSYSTEM_DEF(sentry)
for(var/datum/static_callee/called as anything in error.stacktrace)

var/list/parsed_args = list(
"src" = called._src,
"usr" = called._usr,
"src" = isnull(called._src) ? "null" : called._src,
"usr" = isnull(called._usr) ? "null" : called._usr,
)
var/index = 1
for(var/arg in called._args)
parsed_args["argument #[index]"] = arg
parsed_args["argument #[index]"] = isnull(arg) ? "null" : arg
index++

var/pre_context, context, post_context
Expand All @@ -72,16 +76,29 @@ SUBSYSTEM_DEF(sentry)

var/procpath/proc_path = called.proc

stacktrace += list(list(
var/censor_args = FALSE
if(proc_path.type in GLOB.protected_sentry_procs)
censor_args = TRUE

for(var/protected in GLOB.protected_sentry_datums)
if(findtext("[proc_path.type]", "[protected]"))
censor_args = TRUE
break

var/to_add = list(
"filename" = called.file,
"function" = proc_path.type,
"lineno" = called.line,
"vars" = parsed_args,
"pre_context" = pre_context,
"context_line" = context,
"post_context" = post_context,
"source_link" = "https://github.com/cmss13-devs/cmss13/blob/[git_revision]/[called.file]#L[called.line]"
))
)

if(!censor_args)
to_add["vars"] = parsed_args

stacktrace += list(to_add)

var/list/event_parts = list(
"event_id" = event_id,
Expand All @@ -92,17 +109,40 @@ SUBSYSTEM_DEF(sentry)
"round_id" = GLOB.round_id,
),
"exception" = list(
"type" = error.error,
"value" = "Runtime Error",
"stacktrace" = list("frames" = stacktrace),
"values" = list(list(
"type" = error.error,
"value" = "Runtime Error",
"stacktrace" = list("frames" = stacktrace),
))
),
)

var/event = json_encode(event_parts)

event = ip_regex.Replace(event, "ip address")
for(var/replacement in GLOB.all_player_ckeys)
event = replacetext(event, replacement, "player ckey")

for(var/replacement in GLOB.all_player_cids)
event = replacetext(event, replacement, "player computer id")

for(var/datum/config_entry/protected_entry in GLOB.protected_config_entries)
if(islist(protected_entry.config_entry_value))
for(var/key, value in protected_entry.config_entry_value)
if(protected_entry.protection & CONFIG_ENTRY_SENSITIVE_KEY || isnull(value))
event = replacetext(event, key, "config entry key [protected_entry.type]")
else
event = replacetext(event, value, "config entry value [protected_entry.type]")
else
if(length(protected_entry.config_entry_value))
event = replacetext(event, protected_entry.config_entry_value, "config entry [protected_entry.type]")

var/event_header = "{\"type\":\"event\",\"length\":[length(event)]}"
var/assembled = "[header]\n[event_header]\n[event]\n"

rustg_http_request_fire_and_forget(RUSTG_HTTP_METHOD_POST, endpoint, assembled, headers, null)
var/request = rustg_http_request_blocking(RUSTG_HTTP_METHOD_POST, endpoint, assembled, headers, null)
log_debug("SENTRY: REQUEST [request]")
log_debug("SENTRY: EVENT: [assembled]")

envelopes.Cut()

Expand Down
2 changes: 1 addition & 1 deletion code/modules/admin/admin_ranks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ GLOBAL_LIST_EMPTY(admin_ranks) //list of all ranks with associated rights
protection = CONFIG_ENTRY_LOCKED

/datum/config_entry/string/cmdb_api_key
protection = CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_LOCKED
protection = CONFIG_ENTRY_HIDDEN | CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_SENSITIVE

/**
* Using the API backed admins/admin_ranks requires a response from the endpoint following this schema:
Expand Down
2 changes: 2 additions & 0 deletions code/modules/admin/tabs/admin_tab.dm
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@

cmd_admin_say(msg)

SET_PROTECTED_PROC(/client/proc/cmd_admin_say)
/client/proc/cmd_admin_say(msg as text)
set name = "Asay" //Gave this shit a shorter name so you only have to time out "asay" rather than "admin say" to use it --NeoFite
set category = "Admin"
Expand Down Expand Up @@ -386,6 +387,7 @@
var/msg = input(src, null, "asay \"text\"") as text|null
cmd_admin_say(msg)

SET_PROTECTED_PROC(/client/proc/cmd_mentor_say)
/client/proc/cmd_mentor_say(msg as text)
set name = "MentorSay"
set category = "Admin.Mentor"
Expand Down
4 changes: 4 additions & 0 deletions code/modules/admin/verbs/adminhelp.dm
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
#define WEBHOOK_URGENT 1
#define WEBHOOK_NON_URGENT 2

SET_PROTECTED_DATUM(/datum/admin_help)

/**
* # Adminhelp Ticket
*/
Expand Down Expand Up @@ -804,6 +806,8 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)

GLOBAL_DATUM_INIT(admin_help_ui_handler, /datum/admin_help_ui_handler, new)

SET_PROTECTED_DATUM(/datum/admin_help_ui_handler)

/datum/admin_help_ui_handler
var/list/ahelp_cooldowns = list()

Expand Down
1 change: 1 addition & 0 deletions code/modules/admin/verbs/adminpm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
return
cmd_admin_pm(whom, msg)

SET_PROTECTED_PROC(/client/proc/cmd_admin_pm)
//takes input from cmd_admin_pm_context, cmd_admin_pm_panel or /client/Topic and sends them a PM.
//Fetching a message if needed. src is the sender and C is the target client
/client/proc/cmd_admin_pm(whom, msg)
Expand Down
3 changes: 3 additions & 0 deletions code/modules/client/client_procs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,9 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list(
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CLIENT_LOGGED_IN, src)
SEND_SIGNAL(src, COMSIG_CLIENT_LOGGED_IN)

GLOB.all_player_ckeys |= ckey
GLOB.all_player_cids |= computer_id

if(CONFIG_GET(flag/ooc_country_flags))
spawn if(src)
ip2country(address, src)
Expand Down