From b6267bbaa7dbcaf1b652d7f4983e62dce2b11434 Mon Sep 17 00:00:00 2001 From: Enerdy Date: Fri, 14 Oct 2016 23:07:29 +0100 Subject: [PATCH 1/6] Auth system now checks if a superadmin exists The 'auth-verify' command was also removed and its alias was added to 'auth', which now does both things. --- TShockAPI/Commands.cs | 71 +++++++++++++++++-------------------------- TShockAPI/TShock.cs | 49 ++++++++++++++++------------- 2 files changed, 56 insertions(+), 64 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 089bf6d2..a00c5900 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -208,15 +208,11 @@ namespace TShockAPI ChatCommands.Add(cmd); }; - add(new Command(AuthToken, "auth") + add(new Command(AuthToken, "auth", "auth-verify") { AllowServer = false, HelpText = "Used to authenticate as superadmin when first setting up TShock." }); - add(new Command(Permissions.authverify, AuthVerify, "auth-verify") - { - HelpText = "Used to verify that you have correctly set up TShock." - }); add(new Command(Permissions.user, ManageUsers, "user") { DoLog = false, @@ -4627,56 +4623,45 @@ namespace TShockAPI TShock.Log.Warn("{0} attempted to use {1}auth even though it's disabled.", args.Player.IP, Specifier); return; } - int givenCode = Convert.ToInt32(args.Parameters[0]); - if (givenCode == TShock.AuthToken && args.Player.Group.Name != "superadmin") + + // If the user account is already a superadmin (permanent), disable the system + if (args.Player.IsLoggedIn && args.Player.tempGroup == null && args.Player.Group.Name == new SuperAdminGroup().Name) { - try - { - args.Player.Group = TShock.Utils.GetGroup("superadmin"); - args.Player.SendInfoMessage("Superadmin has been temporarily given to you. It will be removed on logout."); - args.Player.SendInfoMessage("Please use the following to create a permanent account for you."); - args.Player.SendInfoMessage("{0}user add superadmin", Specifier); - args.Player.SendInfoMessage("Creates: with the password as part of the superadmin group."); - args.Player.SendInfoMessage("Please use {0}login after this process.", Specifier); - args.Player.SendInfoMessage("If you understand, please {0}login now, and type {0}auth-verify.", Specifier); - } - catch (UserManagerException ex) - { - TShock.Log.ConsoleError(ex.ToString()); - args.Player.SendErrorMessage(ex.Message); - } + args.Player.SendSuccessMessage("Your new account has been verified, and the {0}auth system has been turned off.", Specifier); + args.Player.SendSuccessMessage("You can always use the {0}user command to manage players.", Specifier); + args.Player.SendSuccessMessage("The auth system will remain disabled as long as a superadmin exists (even if you delete auth.lck)."); + args.Player.SendSuccessMessage("Share your server, talk with other admins, and more on our forums -- https://tshock.co/"); + args.Player.SendSuccessMessage("Thank you for using TShock for Terraria!"); + FileTools.CreateFile(Path.Combine(TShock.SavePath, "auth.lck")); + File.Delete(Path.Combine(TShock.SavePath, "authcode.txt")); + TShock.AuthToken = 0; return; } - if (args.Player.Group.Name == "superadmin") + if (args.Parameters.Count == 0) { - args.Player.SendInfoMessage("Please disable the auth system! If you need help, consult the forums. https://tshock.co/"); - args.Player.SendInfoMessage("This account is superadmin, please do the following to finish your install:"); - args.Player.SendInfoMessage("Please use {0}login to login from now on.", Specifier); - args.Player.SendInfoMessage("If you understand, please {0}login now, and type {0}auth-verify.", Specifier); + args.Player.SendErrorMessage("You must provide an auth code!"); return; } - args.Player.SendErrorMessage("Incorrect auth code. This incident has been logged."); - TShock.Log.Warn(args.Player.IP + " attempted to use an incorrect auth code."); - } - - private static void AuthVerify(CommandArgs args) - { - if (TShock.AuthToken == 0) + int givenCode; + if (!Int32.TryParse(args.Parameters[0], out givenCode) || givenCode != TShock.AuthToken) { - args.Player.SendWarningMessage("It appears that you have already turned off the auth token."); - args.Player.SendWarningMessage("If this is a mistake, delete auth.lck."); + args.Player.SendErrorMessage("Incorrect auth code. This incident has been logged."); + TShock.Log.Warn(args.Player.IP + " attempted to use an incorrect auth code."); return; } - args.Player.SendSuccessMessage("Your new account has been verified, and the /auth system has been turned off."); - args.Player.SendSuccessMessage("You can always use the /user command to manage players. Don't just delete the auth.lck."); - args.Player.SendSuccessMessage("Share your server, talk with other admins, and more on our forums -- https://tshock.co/"); - args.Player.SendSuccessMessage("Thank you for using TShock for Terraria!"); - FileTools.CreateFile(Path.Combine(TShock.SavePath, "auth.lck")); - File.Delete(Path.Combine(TShock.SavePath, "authcode.txt")); - TShock.AuthToken = 0; + if (args.Player.Group.Name != "superadmin") + args.Player.tempGroup = new SuperAdminGroup(); + + args.Player.SendInfoMessage("Superadmin has been temporarily given to you. It will be removed on logout."); + args.Player.SendInfoMessage("Please use the following to create a permanent account for you."); + args.Player.SendInfoMessage("{0}user add superadmin", Specifier); + args.Player.SendInfoMessage("Creates: with the password as part of the superadmin group."); + args.Player.SendInfoMessage("Please use {0}login after this process.", Specifier); + args.Player.SendInfoMessage("If you understand, please {0}login now, and then type {0}auth.", Specifier); + return; } private static void ThirdPerson(CommandArgs args) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 629afdc3..96c88944 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -789,36 +789,43 @@ namespace TShockAPI private void OnPostInit(EventArgs args) { SetConsoleTitle(false); - if (!File.Exists(Path.Combine(SavePath, "auth.lck")) && !File.Exists(Path.Combine(SavePath, "authcode.txt"))) + + // Disable the auth system if "auth.lck" is present or a superadmin exists + if (File.Exists(Path.Combine(SavePath, "auth.lck")) || Users.GetUsers().Exists(u => u.Group == new SuperAdminGroup().Name)) + { + AuthToken = 0; + + if (File.Exists(Path.Combine(SavePath, "authcode.txt"))) + { + Log.ConsoleInfo("A superadmin account has been detected in the user database, but authcode.txt is still present."); + Log.ConsoleInfo("TShock will now disable the auth system and remove authcode.txt as it is no longer needed."); + File.Delete(Path.Combine(SavePath, "authcode.txt")); + } + + if (!File.Exists(Path.Combine(SavePath, "auth.lck"))) + { + // This avoids unnecessary database work, which can get ridiculously high on old servers as all users need to be fetched + File.Create(Path.Combine(SavePath, "auth.lck")); + } + } + else if (!File.Exists(Path.Combine(SavePath, "authcode.txt"))) { var r = new Random((int)DateTime.Now.ToBinary()); AuthToken = r.Next(100000, 10000000); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("TShock Notice: To become SuperAdmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); Console.WriteLine("This token will display until disabled by verification. ({0}auth-verify)", Commands.Specifier); - Console.ForegroundColor = ConsoleColor.Gray; - FileTools.CreateFile(Path.Combine(SavePath, "authcode.txt")); - using (var tw = new StreamWriter(Path.Combine(SavePath, "authcode.txt"))) - { - tw.WriteLine(AuthToken); - } - } - else if (File.Exists(Path.Combine(SavePath, "authcode.txt"))) - { - using (var tr = new StreamReader(Path.Combine(SavePath, "authcode.txt"))) - { - AuthToken = Convert.ToInt32(tr.ReadLine()); - } - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine( - "TShock Notice: authcode.txt is still present, and the AuthToken located in that file will be used."); - Console.WriteLine("To become superadmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); - Console.WriteLine("This token will display until disabled by verification. ({0}auth-verify)", Commands.Specifier); - Console.ForegroundColor = ConsoleColor.Gray; + Console.ResetColor(); + File.WriteAllText(Path.Combine(SavePath, "authcode.txt"), AuthToken.ToString()); } else { - AuthToken = 0; + AuthToken = Convert.ToInt32(File.ReadAllText(Path.Combine(SavePath, "authcode.txt"))); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("TShock Notice: authcode.txt is still present, and the AuthToken located in that file will be used."); + Console.WriteLine("To become superadmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); + Console.WriteLine("This token will display until disabled by verification. ({0}auth)", Commands.Specifier); + Console.ResetColor(); } Regions.Reload(); From 2320a913b446f8ab614096b625d2ebed0139126e Mon Sep 17 00:00:00 2001 From: Enerdy Date: Fri, 14 Oct 2016 23:13:02 +0100 Subject: [PATCH 2/6] Mark pointless permission as obsolete --- TShockAPI/Permissions.cs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index e8c7d18d..0bd00281 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -29,16 +29,16 @@ namespace TShockAPI { // tshock.account nodes - [Description("User can register account in game")] + [Description("User can register account in game.")] public static readonly string canregister = "tshock.account.register"; - [Description("User can login in game")] + [Description("User can login in game.")] public static readonly string canlogin = "tshock.account.login"; - [Description("User can logout in game")] + [Description("User can logout in game.")] public static readonly string canlogout = "tshock.account.logout"; - [Description("User can change password in game")] + [Description("User can change password in game.")] public static readonly string canchangepassword = "tshock.account.changepassword"; // tshock.admin nodes @@ -79,10 +79,10 @@ namespace TShockAPI [Description("User can manage regions.")] public static readonly string manageregion = "tshock.admin.region"; - [Description("User can mute and unmute users")] + [Description("User can mute and unmute users.")] public static readonly string mute = "tshock.admin.mute"; - [Description("User can see the id of players with /who")] + [Description("User can see the id of players with /who.")] public static readonly string seeids = "tshock.admin.seeplayerids"; [Description("User can save all the players SSI state.")] @@ -148,7 +148,7 @@ namespace TShockAPI [Description("Prevents your actions from being ignored if damage is too high.")] public static readonly string ignoredamagecap = "tshock.ignore.damage"; - [Description("Bypass server side character checks")] + [Description("Bypass server side character checks.")] public static readonly string bypassssc = "tshock.ignore.ssc"; [Description("Allow unrestricted SendTileSquare usage, for client side world editing.")] @@ -200,10 +200,10 @@ namespace TShockAPI [Description("User can kill all enemy npcs.")] public static readonly string butcher = "tshock.npc.butcher"; - [Description("User can summon bosses using items")] + [Description("User can summon bosses using items.")] public static readonly string summonboss = "tshock.npc.summonboss"; - [Description("User can start invasions (Goblin/Snow Legion) using items")] + [Description("User can start invasions (Goblin/Snow Legion) using items.")] public static readonly string startinvasion = "tshock.npc.startinvasion"; [Description("User can clear the list of users who have completed an angler quest that day.")] @@ -211,7 +211,8 @@ namespace TShockAPI // tshock.superadmin nodes - [Description("Meant for super admins only.")] + [Description("This permission is no longer used.")] + [Obsolete("No longer used.")] public static readonly string authverify = "tshock.superadmin.authverify"; [Description("Meant for super admins only.")] @@ -252,7 +253,7 @@ namespace TShockAPI [Description("User can use /spawn.")] public static readonly string spawn = "tshock.tp.spawn"; - [Description("User can use the Rod of Discor.")] + [Description("User can use the Rod of Discord.")] public static readonly string rod = "tshock.tp.rod"; [Description("User can use wormhole potions.")] @@ -287,7 +288,7 @@ namespace TShockAPI [Description("User can change the homes of NPCs.")] public static readonly string movenpc = "tshock.world.movenpc"; - [Description("User can convert hallow into corruption and vice-versa")] + [Description("User can convert hallow into corruption and vice-versa.")] public static readonly string converthardmode = "tshock.world.converthardmode"; [Description("User can force the server to Halloween mode.")] @@ -322,7 +323,7 @@ namespace TShockAPI [Description("User can modify the world.")] public static readonly string canbuild = "tshock.world.modify"; - + [Description("User can paint tiles.")] public static readonly string canpaint = "tshock.world.paint"; @@ -345,7 +346,7 @@ namespace TShockAPI [Description("User can kill others.")] public static readonly string kill = "tshock.kill"; - + [Description("Allows you to bypass the max slots for up to 5 slots above your max.")] public static readonly string reservedslot = "tshock.reservedslot"; @@ -364,10 +365,10 @@ namespace TShockAPI [Description("User can heal players.")] public static readonly string heal = "tshock.heal"; - [Description("User can use party chat in game")] + [Description("User can use party chat in game.")] public static readonly string canpartychat = "tshock.partychat"; - [Description("User can talk in third person")] + [Description("User can talk in third person.")] public static readonly string cantalkinthird = "tshock.thirdperson"; [Description("User can get the server info.")] @@ -376,10 +377,10 @@ namespace TShockAPI [Description("Player recovers health as damage is taken. Can be one shotted.")] public static readonly string godmode = "tshock.godmode"; - [Description("User can godmode other players")] + [Description("User can godmode other players.")] public static readonly string godmodeother = "tshock.godmode.other"; - [Description("Player can chat")] + [Description("Player can chat.")] public static readonly string canchat = "tshock.canchat"; [Description("Player can use banned projectiles.")] From 97b6f08523bd81b4fa682f17b651a2e3c50b7478 Mon Sep 17 00:00:00 2001 From: Enerdy Date: Sat, 15 Oct 2016 00:31:57 +0100 Subject: [PATCH 3/6] 'auth' no longer kicks superadmins when disabled --- TShockAPI/Commands.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index a00c5900..db3ff9ab 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -4618,10 +4618,15 @@ namespace TShockAPI { if (TShock.AuthToken == 0) { - args.Player.SendWarningMessage("Auth is disabled. This incident has been logged."); - TShock.Utils.ForceKick(args.Player, "Auth system is disabled.", true, true); - TShock.Log.Warn("{0} attempted to use {1}auth even though it's disabled.", args.Player.IP, Specifier); - return; + if (args.Player.Group.Name == new SuperAdminGroup().Name) + args.Player.SendInfoMessage("The auth system is already disabled."); + else + { + args.Player.SendWarningMessage("The auth system is disabled. This incident has been logged."); + TShock.Utils.ForceKick(args.Player, "Auth system is disabled.", true, true); + TShock.Log.Warn("{0} attempted to use {1}auth even though it's disabled.", args.Player.IP, Specifier); + return; + } } // If the user account is already a superadmin (permanent), disable the system From a49a7f35cca098fa080aadf780ed3fd7dc9cd093 Mon Sep 17 00:00:00 2001 From: Enerdy Date: Sat, 15 Oct 2016 00:34:32 +0100 Subject: [PATCH 4/6] Fully remove 'auth-verify' because it was unclassy --- TShockAPI/Commands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index db3ff9ab..48f5a194 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -208,7 +208,7 @@ namespace TShockAPI ChatCommands.Add(cmd); }; - add(new Command(AuthToken, "auth", "auth-verify") + add(new Command(AuthToken, "auth") { AllowServer = false, HelpText = "Used to authenticate as superadmin when first setting up TShock." From dcaae17ffe29075fabea5c1d871f2152c356ba9a Mon Sep 17 00:00:00 2001 From: Enerdy Date: Sat, 15 Oct 2016 00:39:13 +0100 Subject: [PATCH 5/6] Fix that one missing message & Update CHANGELOG.md --- CHANGELOG.md | 2 ++ TShockAPI/TShock.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c4e4301..a59c1aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ This is the rolling changelog for TShock for Terraria. Use past tense when adding new entries; sign your name off when you add or change something. This should primarily be things like user changes, not necessarily codebase changes unless it's really relevant or large. ## Upcoming Changes +* Security improvement: The auth system is now automatically disabled if a superadmin exists in the database (@Enerdy) +* Removed the `auth-verify` command since `auth` now serves its purpose when necessary (@Enerdy) ## TShock 4.3.19 * Compatibility with Terraria 1.3.3.3 (@Simon311) diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 96c88944..bb2f1702 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -814,7 +814,7 @@ namespace TShockAPI AuthToken = r.Next(100000, 10000000); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("TShock Notice: To become SuperAdmin, join the game and type {0}auth {1}", Commands.Specifier, AuthToken); - Console.WriteLine("This token will display until disabled by verification. ({0}auth-verify)", Commands.Specifier); + Console.WriteLine("This token will display until disabled by verification. ({0}auth)", Commands.Specifier); Console.ResetColor(); File.WriteAllText(Path.Combine(SavePath, "authcode.txt"), AuthToken.ToString()); } From f35d84213be79d27e2bd0a0914899f3b04f7ec3b Mon Sep 17 00:00:00 2001 From: Lucas Nicodemus Date: Fri, 14 Oct 2016 21:25:10 -0600 Subject: [PATCH 6/6] Put the logo in the readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 472eaee5..ecd710a1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# TShock [![Build Status](https://travis-ci.org/NyxStudios/TShock.png?branch=general-devel)](https://travis-ci.org/NyxStudios/TShock) +

+ TShock for Terraria
+ Build Status
+


+

TShock is a server modification for Terraria, written in C#, and based upon the [Terraria Server API](https://github.com/NyxStudios/TerrariaAPI-Server). It uses JSON for configuration management, and offers several features not present in the Terraria Server normally.