diff --git a/FactorioWrapper/FactorioWrapper.cs b/FactorioWrapper/FactorioWrapper.cs index 979c03c..cffb1ae 100644 --- a/FactorioWrapper/FactorioWrapper.cs +++ b/FactorioWrapper/FactorioWrapper.cs @@ -2,6 +2,7 @@ using Serilog; using System; using System.IO; +using System.Linq; namespace FactorioWrapper { @@ -55,6 +56,13 @@ public static void Main(string[] args) settings.Url = url; } + // The password is passed to factorio as a command line argument, so it can't contain whitespace or quotes. + if (settings.RconPassword != null && settings.RconPassword.Any(c => char.IsWhiteSpace(c) || c == '"')) + { + Log.Fatal("rcon_password in settings.json must not contain whitespace or quotes"); + return; + } + if (args.Length < 3) { Log.Fatal("Missing arguments"); diff --git a/FactorioWrapper/MainLoop.cs b/FactorioWrapper/MainLoop.cs index 4af72b0..d57ba86 100644 --- a/FactorioWrapper/MainLoop.cs +++ b/FactorioWrapper/MainLoop.cs @@ -7,6 +7,7 @@ using System; using System.Diagnostics; using System.Linq; +using System.Security.Cryptography; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -25,7 +26,7 @@ public class MainLoop : IDisposable private readonly Settings settings; private readonly string serverId; private readonly string factorioFileName; - private string factorioArguments; + private readonly string factorioArguments; // This is to stop multiple threads writing to the factorio process concurrently. private readonly SemaphoreSlim factorioProcessLock = new SemaphoreSlim(1, 1); @@ -45,9 +46,9 @@ public class MainLoop : IDisposable private volatile RconMessenger rcon; private int rconPort; - private const string rconPassword = "no_one_will_guess_this_awesome_password."; + private readonly string rconPassword; - private void PrependRconArguments() + private void SetRconPort() { int index = factorioArguments.IndexOf("--port"); @@ -61,8 +62,6 @@ private void PrependRconArguments() string port = factorioArguments.Substring(start, end - start); int.TryParse(port, out rconPort); - - factorioArguments += $" --rcon-port {rconPort} --rcon-password {rconPassword}"; } private async Task ConnectRCON() @@ -88,7 +87,12 @@ public MainLoop(Settings settings, string serverId, string factorioFileName, str this.factorioFileName = factorioFileName; this.factorioArguments = factorioArguments; - PrependRconArguments(); + // Fall back to a random password so RCON is never left with a known password. + rconPassword = string.IsNullOrWhiteSpace(settings.RconPassword) + ? Convert.ToHexString(RandomNumberGenerator.GetBytes(32)) + : settings.RconPassword; + + SetRconPort(); messageQueue = new SingleConsumerQueue>(maxMessageQueueSize, async func => { @@ -384,7 +388,9 @@ private async Task StartFactorioProcess() factorioProcess = new Process(); var startInfo = factorioProcess.StartInfo; startInfo.FileName = factorioFileName; - startInfo.Arguments = factorioArguments; + // The rcon password is added after logging so that it doesn't end up in the log file. + // Rcon is bound to localhost so that it isn't reachable from outside this machine. + startInfo.Arguments = $"{factorioArguments} --rcon-bind 127.0.0.1:{rconPort} --rcon-password {rconPassword}"; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; startInfo.RedirectStandardInput = true; diff --git a/FactorioWrapper/Settings.cs b/FactorioWrapper/Settings.cs index e0f119e..72642cb 100644 --- a/FactorioWrapper/Settings.cs +++ b/FactorioWrapper/Settings.cs @@ -12,5 +12,9 @@ public class Settings [JsonProperty(PropertyName = "url")] [JsonPropertyName("url")] public string Url { get; set; } + + [JsonProperty(PropertyName = "rcon_password")] + [JsonPropertyName("rcon_password")] + public string RconPassword { get; set; } } } diff --git a/FactorioWrapper/settings.template.json b/FactorioWrapper/settings.template.json index 4b0e126..4ee04aa 100644 --- a/FactorioWrapper/settings.template.json +++ b/FactorioWrapper/settings.template.json @@ -1,4 +1,5 @@ { "token": "asdasdjuteoinbjnlkrutpeoplp.fkgcldfooklisfgsdlafhlfreFGTRydegsJJKGHURTDSwaerqsdfdfsgtJFHDfbgsDASDASDFERGDFBGsdfsdfSFQAWSEAZBBVJNHGJdfghfghSERWSFSVXBGFDgtDRTDGFJHJKykjHjHBKJfyjutygj_bLJyuhHUIOgJKBLnoOUiohuiGh_JKBjkGj-guiGhfu", - "url": "http://localhost/factorioProcessHub" + "url": "http://localhost/factorioProcessHub", + "rcon_password": "" }