From 9c3f31d86bfb863d181500c867e2fa14622f6ee6 Mon Sep 17 00:00:00 2001 From: VistaPOWA Date: Mon, 21 Apr 2014 10:51:04 +0200 Subject: [PATCH] Security fixes for PR announcer Thanks @Giacom for the info! PR announcer is now able to authenticate with Nickserv. Communications key moved out of config controller. Even better Regex validation. Reading now has even more exception handling. --- code/_globalvars/configuration.dm | 4 + code/controllers/configuration.dm | 7 +- code/modules/client/client procs.dm | 2 +- code/world.dm | 4 +- tools/PR_announcer_bot/config.txt | 3 +- tools/PR_announcer_bot/sendkeys_ss13.exe | Bin 11776 -> 12288 bytes .../PR_announcer_bot/sendkeys_ss13/Program.cs | 74 ++++++++++++------ 7 files changed, 63 insertions(+), 31 deletions(-) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index 58c6dd7913c..6522caafe81 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -21,6 +21,10 @@ var/tinted_weldhelh = 1 var/Debug = 0 // global debug switch var/Debug2 = 0 +//Server API key +var/global/comms_key = "default_pwd" +var/global/comms_allowed = 0 //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming vulnerable) + //This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage var/MAX_EX_DEVESTATION_RANGE = 3 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index f0f0f727089..f11d2fdebc5 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -101,9 +101,6 @@ var/rename_cyborg = 0 var/ooc_during_round = 0 - var/comms_key = "default_pwd" //Server API key - var/comms_allowed = 0 //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming victims) - //Used for modifying movement speed for mobs. //Unversal modifiers var/run_speed = 0 @@ -269,9 +266,9 @@ if("automute_on") automute_on = 1 if("comms_key") - comms_key = value + global.comms_key = value if(value != "default_pwd" && length(value) > 6) //It's the default value or less than 6 characters long, warn badmins - comms_allowed = 1 + global.comms_allowed = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index d87d0e987a4..c95d27a2a7d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -130,7 +130,7 @@ var/next_external_rsc = 0 if(holder) add_admin_verbs() admin_memo_show() - if((config.comms_key == "default_pwd" || length(config.comms_key) <= 6) && config.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms. + if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms. src << "The server's API key is either too short or is the default value! Consider changing it immediately!" log_client_to_db() diff --git a/code/world.dm b/code/world.dm index 506b0cdd7b4..34f73a49f4b 100644 --- a/code/world.dm +++ b/code/world.dm @@ -162,8 +162,8 @@ return list2params(s) else if (copytext(T,1,9) == "announce") var/input[] = params2list(T) - if(config.comms_allowed) - if(input["key"] != config.comms_key) + if(global.comms_allowed) + if(input["key"] != global.comms_key) return "Bad Key" else #define CHAT_PULLR 2048 diff --git a/tools/PR_announcer_bot/config.txt b/tools/PR_announcer_bot/config.txt index 2919a9b96a2..f5cc606b2b3 100644 --- a/tools/PR_announcer_bot/config.txt +++ b/tools/PR_announcer_bot/config.txt @@ -4,4 +4,5 @@ commskey = this_is_a_test_key //API key of the server GitHub_bot_name = testbot_github //It'll get the data from this bot IRC_bot_name = testbot_BYOND //This'll be our name IRC_server = irc.rizon.net:6670 //format - server:port -IRC_channel = #ircchannel \ No newline at end of file +IRC_channel = #ircchannel +Nickserv_auth = _NONE_ //leave _NONE_ if your bot does not require nickserv authentication \ No newline at end of file diff --git a/tools/PR_announcer_bot/sendkeys_ss13.exe b/tools/PR_announcer_bot/sendkeys_ss13.exe index 4f9332811d96c633b60d655faeb75d65115812ad..acdc57f094e54f1afd5e6ce5b0af3a090192fe9e 100644 GIT binary patch delta 4975 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 delta 4292 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 diff --git a/tools/PR_announcer_bot/sendkeys_ss13/Program.cs b/tools/PR_announcer_bot/sendkeys_ss13/Program.cs index 8d7d5856a98..440f85b691c 100644 --- a/tools/PR_announcer_bot/sendkeys_ss13/Program.cs +++ b/tools/PR_announcer_bot/sendkeys_ss13/Program.cs @@ -37,6 +37,7 @@ namespace sendkeys_ss13 public static string IRC_server = "test.net"; public static int IRC_port = 11111; public static string IRC_channel = "#channel"; + public static string NickServAuth = null; public static string[] merge_archive; public static bool mergeflag = false; @@ -57,10 +58,10 @@ namespace sendkeys_ss13 catch (Exception) { IRCReconnectAttempt++; - if (IRCReconnectAttempt <= 3) + if (IRCReconnectAttempt <= 5) { Console.WriteLine("IRC server is unavaible at the moment. Reconnect attempt {0}...", IRCReconnectAttempt); - System.Threading.Thread.Sleep(3000); //Reconnecting after 5 seconds. + System.Threading.Thread.Sleep(5000); //Reconnecting after 5 seconds. Main(args); } else @@ -71,7 +72,17 @@ namespace sendkeys_ss13 } } Console.WriteLine("Connected to IRC"); - irc.Login(IRC_bot_name, IRC_bot_name); + try + { + irc.Login(IRC_bot_name, IRC_bot_name); + } + catch (Exception) + { + irc.Login(IRC_bot_name + "_1", IRC_bot_name + "_1"); + Console.WriteLine("Bot name is already taken, trying alternate..."); + } + if (NickServAuth != null) + irc.SendMessage(SendType.Message, "NickServ", "identify " + NickServAuth); Console.WriteLine("Logged in"); irc.RfcJoin(IRC_channel); Console.WriteLine("Joining {0}", IRC_channel); @@ -83,10 +94,10 @@ namespace sendkeys_ss13 if (File.Exists("config.txt")) { StreamReader reader = new StreamReader("config.txt"); - string[] line = reader.ReadLine().Split(' '); + string[] line = ReadLine_exception(reader); if (line[2] != null) { - Match match1 = Regex.Match(line[2], @"(\d{1,3}.?){4}"); //rudimentary IP validation + Match match1 = Regex.Match(line[2], @"^(\d{1,3}.?){4}$"); //rudimentary IP validation if (match1.Success) { serverIP = line[2]; @@ -95,13 +106,12 @@ namespace sendkeys_ss13 else { Console.WriteLine("IP cannot be validated."); - return; } } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { - Match match2 = Regex.Match(line[2], @"\d{1,5}"); //rudimentary port validation + Match match2 = Regex.Match(line[2], @"^\d{1,5}$"); //rudimentary port validation if (match2.Success && (Convert.ToInt32(line[2]) < 65535)) { serverPort = Convert.ToInt32(line[2]); @@ -110,10 +120,9 @@ namespace sendkeys_ss13 else { Console.WriteLine("Port cannot be validated."); - return; } } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { commskey = line[2]; @@ -122,9 +131,8 @@ namespace sendkeys_ss13 else { Console.WriteLine("No Commskey!"); - return; } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { Github_bot_name = line[2]; @@ -133,23 +141,21 @@ namespace sendkeys_ss13 else { Console.WriteLine("No botname found."); - return; } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { IRC_bot_name = line[2]; - Console.WriteLine("Read IRC bot name: " + Github_bot_name); + Console.WriteLine("Read IRC bot name: " + IRC_bot_name); } else { Console.WriteLine("No botname found."); - return; } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { - Match match3 = Regex.Match(line[2], @"(.+)\:(\d{1,5})"); //rudimentary port validation + Match match3 = Regex.Match(line[2], @"^(.+)\:(\d{1,5})$"); //rudimentary port validation if (match3.Success) { IRC_server = Convert.ToString(match3.Groups[1]); @@ -159,10 +165,9 @@ namespace sendkeys_ss13 else { Console.WriteLine("Server:port invalid."); - return; } } - line = reader.ReadLine().Split(' '); + line = ReadLine_exception(reader); if (line[2] != null) { IRC_channel = line[2]; @@ -171,7 +176,16 @@ namespace sendkeys_ss13 else { Console.WriteLine("No channel found."); - return; + } + line = ReadLine_exception(reader); + if (line[2] != null && line[2] != "_NONE_") + { + NickServAuth = line[2]; + Console.WriteLine("Read Nickserv auth"); + } + else + { + Console.WriteLine("No NickServ auth chosen."); } reader.Close(); } @@ -182,6 +196,21 @@ namespace sendkeys_ss13 } } + private static string[] ReadLine_exception(StreamReader reader) + { + string[] readline = null; + try + { + readline = reader.ReadLine().Split(' '); + } + catch (Exception) + { + readline[3] = "Error, couldn't read all lines of config file! Are you sure the config file has the right format?"; + return readline; + } + return readline; + } + public static void OnChannelMessage(object sender, IrcEventArgs e) { if (e.Data.Nick == Github_bot_name) @@ -260,6 +289,7 @@ namespace sendkeys_ss13 server.Connect(ip); server.Send(PACKETS); Console.WriteLine("- sent ;)"); + ServerReconnectAttempt = 0; output.Close(); Console.WriteLine(); } @@ -269,7 +299,7 @@ namespace sendkeys_ss13 if(ServerReconnectAttempt <= 5) { Console.WriteLine("Server is not available at the moment. Reconnect attempt {0}...", ServerReconnectAttempt); - System.Threading.Thread.Sleep(5000); //Reconnecting after 5 seconds. + System.Threading.Thread.Sleep(15000); //Reconnecting after 15 seconds. SendPacket(output, PACKETS); } else