diff --git a/SQL/migrate-2023/V015__external_ckeys.sql b/SQL/migrate-2023/V015__external_ckeys.sql new file mode 100644 index 00000000000..878ee12b340 --- /dev/null +++ b/SQL/migrate-2023/V015__external_ckeys.sql @@ -0,0 +1 @@ +ALTER TABLE `ss13_player` ADD COLUMN `ckey_is_external` TINYINT(1) NOT NULL DEFAULT 0 AFTER `ckey`; diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 44a4ca97576..01d74f89312 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -440,8 +440,11 @@ GLOBAL_LIST_EMPTY(gamemode_cache) var/ntsl_port = "1945" var/ntsl_disabled = TRUE - // Is external Auth enabled - var/external_auth = FALSE + /// Is external Auth enabled + // 0 - disabled. + // 1 - only users with linked ckeys can authenticate. + // 2 - users with a forum account and no linked ckeys can also authenticate. + var/external_auth = 0 // fail2topic settings var/fail2topic_rate_limit = 5 SECONDS @@ -1038,7 +1041,9 @@ GENERAL_PROTECT_DATUM(/datum/configuration) ntsl_disabled = text2num(value) if ("external_auth") - external_auth = TRUE + external_auth = text2num(value) + if (external_auth > 2 || external_auth < 0) + external_auth = 0 if ("fail2topic_rate_limit") fail2topic_rate_limit = text2num(value) SECONDS diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 953484e726a..79802fb4a6e 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -29,6 +29,8 @@ var/discord_admin //IRC- no more IRC, K? Discord admin that spoke with them last. var/mute_discord = 0 + var/ckey_is_external = FALSE // Will be set to TRUE if the user is using a "fake" ckey from an external source, like the forums. + // Database var/player_age = "Requires database" // So admins know why it isn't working - Used to determine how old the account is - in days. var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 4188f859321..12998f6d576 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -564,7 +564,7 @@ GLOBAL_LIST_INIT(localhost_addresses, list( if(!establish_db_connection(GLOB.dbcon)) return - var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT datediff(Now(),firstseen) as age, whitelist_status, account_join_date, DATEDIFF(NOW(), account_join_date) FROM ss13_player WHERE ckey = :ckey:") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT datediff(Now(),firstseen) as age, whitelist_status, account_join_date, DATEDIFF(NOW(), account_join_date, ckey_is_external) FROM ss13_player WHERE ckey = :ckey:") if(!query.Execute(list("ckey"=ckey(key)))) return @@ -578,6 +578,7 @@ GLOBAL_LIST_INIT(localhost_addresses, list( whitelist_status = text2num(query.item[2]) account_join_date = query.item[3] account_age = text2num(query.item[4]) + ckey_is_external = !!text2num(query.item[5]) if (!account_age) account_join_date = sanitizeSQL(findJoinDate()) if (!account_join_date) @@ -613,8 +614,8 @@ GLOBAL_LIST_INIT(localhost_addresses, list( query_update.Execute(list("ckey"=ckey(key),"ip"=src.address,"computerid"=src.computer_id,"lastadminrank"=admin_rank,"account_join_date"=account_join_date,"byond_version"=byond_version,"byond_build"=byond_build)) else if (!GLOB.config.access_deny_new_players) //New player!! Need to insert all the stuff - var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO ss13_player (ckey, firstseen, lastseen, ip, computerid, lastadminrank, account_join_date, byond_version, byond_build) VALUES (:ckey:, Now(), Now(), :ip:, :computerid:, :lastadminrank:, :account_join_date:, :byond_version:, :byond_build:)") - query_insert.Execute(list("ckey"=ckey(key),"ip"=src.address,"computerid"=src.computer_id,"lastadminrank"=admin_rank,"account_join_date"=account_join_date,"byond_version"=byond_version,"byond_build"=byond_build)) + var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO ss13_player (ckey, ckey_is_external, firstseen, lastseen, ip, computerid, lastadminrank, account_join_date, byond_version, byond_build) VALUES (:ckey:, :ckey_is_external:, Now(), Now(), :ip:, :computerid:, :lastadminrank:, :account_join_date:, :byond_version:, :byond_build:)") + query_insert.Execute(list("ckey"=ckey(key), "ckey_is_external"=src.ckey_is_external,"ip"=src.address,"computerid"=src.computer_id,"lastadminrank"=admin_rank,"account_join_date"=account_join_date,"byond_version"=byond_version,"byond_build"=byond_build)) else // Flag as -1 to know we have to kiiick them. player_age = -1 diff --git a/code/modules/mob/abstract/unauthed/login.dm b/code/modules/mob/abstract/unauthed/login.dm index 23a41eeb25c..64631edacc7 100644 --- a/code/modules/mob/abstract/unauthed/login.dm +++ b/code/modules/mob/abstract/unauthed/login.dm @@ -41,7 +41,7 @@ GLOBAL_LIST_EMPTY(unauthed) qdel(client) qdel(src) -/mob/abstract/unauthed/proc/ClientLogin(var/newkey) +/mob/abstract/unauthed/proc/ClientLogin(var/newkey, var/ckey_is_external) if(!client) qdel(src) deltimer(timeout_timer) @@ -64,7 +64,8 @@ GLOBAL_LIST_EMPTY(unauthed) GLOB.directory -= c.ckey if(newkey) - c.key = newkey // Try seeting ckey + c.ckey_is_external = ckey_is_external + c.key = newkey // Try setting ckey // ^^^^ THIS INVOKES mob/Login()! // and also modifies the c.mob to the actual mob they disconnected out of. diff --git a/code/modules/world_api/commands/misc.dm b/code/modules/world_api/commands/misc.dm index 3f9799bd783..fa1e325b2d1 100644 --- a/code/modules/world_api/commands/misc.dm +++ b/code/modules/world_api/commands/misc.dm @@ -189,24 +189,37 @@ var/mob/abstract/unauthed/una = GLOB.unauthed[queryparams["clienttoken"]] if(!istype(una) || !una.client) statuscode = 500 - response = "Somethnig went horribly wrong." + response = "Something went horribly wrong." return TRUE if(!GLOB.config.external_auth) statuscode = 500 - response = "External auth is disalowed." + response = "External auth is disallowed." del(una.client) del(una) return TRUE - var/client/cl = GLOB.directory[ckey(queryparams["key"])] + var/ckey_is_external = queryparams["use-external-key"] + + if(ckey_is_external && GLOB.config.external_auth != 2) + statuscode = 403 + response = "External auth is disabled for users without linked ckeys." + del(una.client) + del(una) + return TRUE + + var/ckey_to_apply = queryparams["key"] + if (ckey_is_external && ckey_to_apply == null) + ckey_to_apply = "GuestF-[ckey(queryparams["forumuser"])]" + + var/client/cl = GLOB.directory[ckey(ckey_to_apply)] if(cl) to_chat(cl, "Another connection has been made using your login key. This session has been terminated.") del(cl) statuscode = 200 response = "Client has been authenticated sucessfully." - una.ClientLogin(queryparams["key"]) + una.ClientLogin(ckey_to_apply, ckey_is_external) // Authenticates client from external system /datum/topic_command/get_auth_client_ip diff --git a/html/changelogs/skull132-forum-auth.yml b/html/changelogs/skull132-forum-auth.yml new file mode 100644 index 00000000000..83291e1dec0 --- /dev/null +++ b/html/changelogs/skull132-forum-auth.yml @@ -0,0 +1,6 @@ +author: Skull132 + +delete-after: True + +changes: + - rscadd: "Allows users to log in from the forums without having a ckey linked."