private void RestoreFromBackup(object sender, EventArgs e) { var log = new LogWindow(MainWindow); var selectedItem = "/etc/openvpn/" + backupList.SelectedItem.ToString(); using (var ssh = MainWindow.ConnectedDirector.ScpClient) { log.WriteNormal($"Connecting to director via SCP.. "); ssh.Connect(); log.WriteSuccess($" .. connected!\n"); // Get the existing certificate using (var stream = new MemoryStream()) { log.WriteNormal($"Downloading {selectedItem}\n"); ssh.Download(selectedItem, stream); log.WriteSuccess($"Done - got {stream.Length} bytes\n\n"); stream.Position = 0; using (StreamReader reader = new StreamReader(stream)) { stream.Position = 0; var certificate = reader.ReadToEnd(); RestoreCert(log, certificate); } } } }
internal async void Reboot(LogWindow log) { log.WriteNormal($"\nRebooting Director\n\n"); using (var ssh = SshClient) { log.WriteTrace($"\nConnecting via SSH.. "); ssh.Connect(); log.WriteTrace($"\n .. connected!"); log.WriteSuccess($"\n\nYour director is now rebooting. This can take a few minutes and it's a nervous wait - I know.\n"); log.WriteSuccess($"But nothing we've done here will stop your director from booting up, so don't worry.\n"); var cmd = ssh.CreateCommand("sysman reboot"); var task = cmd.BeginExecute(); while (!task.IsCompleted) { await Task.Delay(10); } } }
private void RestoreCert(LogWindow log, string certificate) { if (!certificate.Contains("BEGIN CERTIFICATE")) { log.WriteError("This file doesn't seem to be valid?"); return; } using (var ssh = MainWindow.ConnectedDirector.ScpClient) { log.WriteNormal($"Connecting to director via SCP.. "); ssh.Connect(); log.WriteSuccess($" .. connected!\n"); // Get the existing certificate using (var stream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(stream)) { writer.Write(certificate); writer.Flush(); stream.Position = 0; log.WriteNormal($"Uploading /etc/openvpn/clientca-prod.pem\n"); ssh.Upload(stream, "/etc/openvpn/clientca-prod.pem"); log.WriteSuccess($"Done!\n"); } } } MainWindow.ConnectedDirector.Reboot(log); MainWindow.DirectorDisconnected(); }
private void JailbreakDirector(object sender, EventArgs e) { var log = new LogWindow(MainWindow); log.WriteNormal("Generating Certificates\n"); if (!GenerateCertificates(log)) { return; } log.WriteSuccess("Certificate Generation Successful"); log.WriteNormal("\n\n"); log.WriteNormal("Copying To Composer\n"); if (!PatchComposer(log)) { return; } log.WriteNormal("\n\n"); log.WriteNormal("Copying To Director\n"); if (!PatchDirector(log)) { return; } log.WriteNormal("\n\n"); log.WriteNormal("Restarting Director\n"); if (!RestartDirector(log)) { return; } log.WriteNormal("\n\n"); log.WriteSuccess("100% All Done!"); }
private void RebootDirector(object sender, EventArgs e) { var log = new LogWindow(MainWindow); try { var SshConnectionInfo = new ConnectionInfo(Address.Text.ToString(), Username.Text, new PasswordAuthenticationMethod(Username.Text, Password.Text)); SshConnectionInfo.RetryAttempts = 1; SshConnectionInfo.Timeout = TimeSpan.FromSeconds(5); log.WriteTrace("Connecting To Director..\n"); using (var ssh = new SshClient(SshConnectionInfo)) { ssh.Connect(); log.WriteTrace("Connected!\n"); log.WriteTrace("Running Reboot Command..\n"); var r = ssh.RunCommand("reboot"); log.WriteTrace($"Response Was: {r.Result}\n"); log.WriteSuccess($"Your system is rebooting - it can take a while - don't panic, give it 10 minutes!"); } } catch (System.Exception ex) { log.WriteError(ex); } }
private void GenerateCertificates(object sender, EventArgs e) { var log = new LogWindow(MainWindow); log.WriteNormal("Generating Certificates\n"); if (!GenerateCertificates(log)) { return; } log.WriteSuccess("Certificate Generation Successful"); log.WriteNormal("\n\n"); }
bool PatchDirector(LogWindow log) { var SshConnectionInfo = new ConnectionInfo(Address.Text.ToString(), Username.Text, new PasswordAuthenticationMethod(Username.Text, Password.Text)); SshConnectionInfo.RetryAttempts = 1; SshConnectionInfo.Timeout = TimeSpan.FromSeconds(2); using (var ssh = new ScpClient(SshConnectionInfo)) { log.WriteNormal($"Connecting to director via SCP.. "); try { ssh.Connect(); } catch (System.Exception e) { log.WriteError(e); return(false); } log.WriteSuccess($" .. connected!\n"); // Get the existing certificate using (var stream = new MemoryStream()) { log.WriteNormal($"Downloading /etc/openvpn/clientca-prod.pem\n"); ssh.Download("/etc/openvpn/clientca-prod.pem", stream); log.WriteSuccess($"Done - got {stream.Length} bytes\n\n"); stream.Position = 0; var backupName = $"/etc/openvpn/clientca-prod.{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}.backup"; log.WriteNormal($"Uploading {backupName}\n"); ssh.Upload(stream, backupName); log.WriteSuccess($"Done!\n\n"); log.WriteNormal($"Constructing new clientca-prod.pem\n"); using (StreamReader reader = new StreamReader(stream)) { stream.Position = 0; var certificate = reader.ReadToEnd(); certificate += "\n"; log.WriteNormal($" Reading Certs/public.pem\n"); var localCert = System.IO.File.ReadAllText("Certs/public.pem"); var localBackupName = $"Certs/clientca-prod.{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}.backup"; log.WriteNormal($" Downloading to {localBackupName}\n"); System.IO.File.WriteAllText(localBackupName, certificate); if (certificate.Contains(localCert)) { log.WriteError($"The certificate on the director already contains our public key!\n"); return(false); } else { // // We just add our public key to the end // certificate += localCert; } // // This serves no purpose but it doesn't hurt to have it hanging around // localBackupName += ".new"; log.WriteNormal($" Downloading to {localBackupName}\n"); System.IO.File.WriteAllText(localBackupName, certificate); // // Upload the modded certificates to the director // log.WriteNormal($"Uploading New Certificate..\n"); using (var wstream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(wstream)) { writer.Write(certificate); writer.Flush(); wstream.Position = 0; ssh.Upload(wstream, "/etc/openvpn/clientca-prod.pem"); } } log.WriteSuccess($"Done!\n"); } } } return(true); }
bool UpdateComposerCertificate(LogWindow log) { var configFolder = $"{Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData )}\\Control4\\Composer"; log.WriteNormal("\nCreating new Composer Key\n"); var exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"genrsa -out Certs/composer.key 1024 -config \"{Constants.OpenSslConfig}\""); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } log.WriteNormal("\nCreating Signing Request\n"); exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"req -new -nodes -key Certs/composer.key -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -out Certs/composer.csr -config \"{Constants.OpenSslConfig}\""); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } System.IO.Directory.CreateDirectory("ca"); System.IO.Directory.CreateDirectory("ca/newcerts"); System.IO.File.WriteAllText("ca/index.txt", ""); log.WriteNormal("\nSigning Request\n"); exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"ca -subj /C=US/ST=Utah/L=Draper/CN={Constants.CertificateCN}/ -preserveDN -days 365 -batch -create_serial -cert Certs/public.pem -keyfile Certs/private.key -out Certs/composer.pem -in Certs/composer.csr -config \"{Constants.OpenSslConfig}\""); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } // // Create the composer.p12 (public key) which sits in your composer config folder // log.WriteNormal("Creating composer.p12\n"); exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"pkcs12 -export -out \"Certs/composer.p12\" -inkey \"Certs/composer.key\" -in \"Certs/composer.pem\" -passout pass:{Constants.CertPassword}"); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } // // Get the text for the composer cacert-*.pem // log.WriteNormal($"Creating {Constants.ComposerCertName}\n"); var output = RunProcessGetOutput(Constants.OpenSslExe, $"x509 -in \"Certs/public.pem\" -text"); System.IO.File.WriteAllText($"Certs/{Constants.ComposerCertName}", output); CopyFile(log, $"Certs/{Constants.ComposerCertName}", $"{configFolder}\\{Constants.ComposerCertName}"); CopyFile(log, $"Certs/composer.p12", $"{configFolder}\\composer.p12"); log.WriteNormal("\n\n"); log.WriteSuccess("Success - composer should be good for 30 days\n\n"); log.WriteSuccess("Once it starts complaining that you had x days left to renew, just run this step again\n\n"); log.WriteSuccess("You shouldn't need to patch your Director again unless you update to a new version or delete the Certs folder next to this exe.\n\n"); return(true); }
private void PatchComposer(object sender, EventArgs eventargs) { var log = new LogWindow(MainWindow); log.WriteTrace("Asking for ComposerPro.exe location\n"); OpenFileDialog open = new OpenFileDialog(); open.Filter = "Executable Files|*.exe"; open.Title = "Find Original ComposerPro.exe"; open.InitialDirectory = "C:\\Program Files (x86)\\Control4\\Composer\\Pro"; open.FileName = "ComposerPro.exe"; if (open.ShowDialog() != DialogResult.OK) { log.WriteError("Cancelled\n"); return; } if (string.IsNullOrEmpty(open.FileName)) { log.WriteError("Filename was invalid\n"); return; } log.WriteNormal("Opening "); log.WriteHighlight($"{open.FileName}\n"); using (var val = AssemblyDefinition.ReadAssembly(open.FileName)) { log.WriteTrace($"Finding \"Control4.ComposerPro.MainForm\"\n"); var mainForm = val.MainModule.Types.SingleOrDefault(x => x.FullName == "Control4.ComposerPro.MainForm"); if (mainForm == null) { log.WriteError("Oops - couldn't find the class Control4.ComposerPro.MainForm\n"); return; } log.WriteNormal($"Found "); log.WriteHighlight($"{mainForm}\n"); log.WriteTrace($"Finding \"ShowStartupOnFirstRun\"\n"); var showStartupOnFirstRun = mainForm.Methods.SingleOrDefault(x => x.Name == "ShowStartupOnFirstRun"); if (showStartupOnFirstRun == null) { log.WriteError("Oops - couldn't find the method ShowStartupOnFirstRun (Maybe already patched?)\n"); return; } log.WriteNormal($"Found "); log.WriteHighlight($"{showStartupOnFirstRun}\n"); log.WriteNormal($"Removing.."); mainForm.Methods.Remove(showStartupOnFirstRun); log.WriteSuccess($" ..Done!\n"); // TODO - Skip update check // TODO - Add info in window title // TODO - Fix dealeraccount.xml not found exception try { var outFile = System.IO.Path.ChangeExtension(open.FileName, NewExtension); // // We might be re-patching for some reason, so delete the old one // if (System.IO.File.Exists(outFile)) { System.IO.File.Delete(outFile); } log.WriteNormal($"Saving to "); log.WriteHighlight($"{outFile}\n\n"); // Save the file val.Write(outFile); // We need to copy the config and manifest too, or we'll be missing a bunch of settings log.WriteNormal($"Copying "); log.WriteHighlight($"ComposerPro.exe.manifest"); log.WriteNormal($" to "); log.WriteHighlight($"ComposerPro{NewExtension}.manifest\n"); System.IO.File.Copy($"{open.FileName}.manifest", $"{outFile}.manifest", true); log.WriteNormal($"Copying "); log.WriteHighlight($"ComposerPro.exe.config"); log.WriteNormal($" to "); log.WriteHighlight($"ComposerPro{NewExtension}.config\n"); System.IO.File.Copy($"{open.FileName}.config", $"{outFile}.config", true); // Create desktop shortcut { log.WriteNormal($"\nCreating Desktop Shortcut.. "); var shortcutPath = $"{Environment.GetFolderPath( Environment.SpecialFolder.DesktopDirectory )}\\Composer Pro (Patched).url"; if (System.IO.File.Exists(shortcutPath)) { System.IO.File.Delete(shortcutPath); } using (StreamWriter writer = new StreamWriter(shortcutPath)) { var app = outFile.Replace('\\', '/'); writer.WriteLine("[InternetShortcut]"); writer.WriteLine($"URL=file:///{app.Replace( " ", "%20" )}"); writer.WriteLine("IconIndex=0"); writer.WriteLine("IconFile=" + app); writer.Flush(); } log.WriteSuccess($"done!\n"); } log.WriteSuccess($"\nAll done - you can close this window!\n"); } catch (UnauthorizedAccessException e) { log.WriteError($"Exception - {e.Message}\n"); } } }
bool GenerateCertificates(LogWindow log) { // // Don't regenerate the certificates. They might be copying the folder // over to another computer or some shit. // if (System.IO.File.Exists($"Certs/{Constants.ComposerCertName}") && System.IO.File.Exists($"Certs/composer.p12") && System.IO.File.Exists($"Certs/private.key") && System.IO.File.Exists($"Certs/public.pem")) { log.WriteSuccess($"\nThe certificates already exist - so we're going to use them.\n"); System.Threading.Thread.Sleep(1000); log.WriteSuccess($"If you want to generate new certificates delete the Certs folder.\n\n"); System.Threading.Thread.Sleep(1000); return(true); } if (!System.IO.File.Exists(Constants.OpenSslExe)) { log.WriteError($"Couldn't find {Constants.OpenSslExe} - do you have composer installed?"); return(false); } if (!System.IO.File.Exists(Constants.OpenSslConfig)) { log.WriteError($"Couldn't find {Constants.OpenSslConfig} - do you have composer installed?"); return(false); } if (!System.IO.Directory.Exists("Certs")) { log.WriteTrace("Creating Certs Folder\n"); System.IO.Directory.CreateDirectory("Certs"); } // // generate a self signed private and public key // log.WriteNormal("\nGenerating private + public keys\n"); var exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"req -new -x509 -sha256 -nodes -days {Constants.CertificateExpireDays} -newkey rsa:1024 -keyout \"Certs/private.key\" -subj \"/C=US/ST=Utah/L=Draper/O=Control4/OU=Controller Certificates/CN={Constants.CertificateCN}/\" -out \"Certs/public.pem\" -config \"{Constants.OpenSslConfig}\""); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } // // Create the composer.p12 (public key) which sits in your composer config folder // log.WriteNormal("Creating composer.p12\n"); exitCode = RunProcessPrintOutput(log, Constants.OpenSslExe, $"pkcs12 -export -out \"Certs/composer.p12\" -inkey \"Certs/private.key\" -in \"Certs/public.pem\" -passout pass:{Constants.CertPassword}"); if (exitCode != 0) { log.WriteError($"Failed."); return(false); } // // Get the text for the composer cacert-*.pem // log.WriteNormal($"Creating {Constants.ComposerCertName}\n"); var output = RunProcessGetOutput(Constants.OpenSslExe, $"x509 -in \"Certs/public.pem\" -text"); System.IO.File.WriteAllText($"Certs/{Constants.ComposerCertName}", output); return(true); }
bool PatchDirector(LogWindow log) { using (var ssh = MainWindow.ConnectedDirector.ScpClient) { log.WriteNormal($"Connecting to director via SCP.. "); ssh.Connect(); log.WriteSuccess($" .. connected!\n"); // Get the existing certificate using (var stream = new MemoryStream()) { log.WriteNormal($"Downloading /etc/openvpn/clientca-prod.pem\n"); ssh.Download("/etc/openvpn/clientca-prod.pem", stream); log.WriteSuccess($"Done - got {stream.Length} bytes\n\n"); stream.Position = 0; var backupName = $"/etc/openvpn/clientca-prod.{DateTime.Now.ToString( "yyyy-dd-M--HH-mm-ss" )}.backup"; log.WriteNormal($"Uploading {backupName}\n"); ssh.Upload(stream, backupName); log.WriteSuccess($"Done!\n\n"); log.WriteNormal($"Constructing new clientca-prod.pem\n"); using (StreamReader reader = new StreamReader(stream)) { stream.Position = 0; var certificate = reader.ReadToEnd(); certificate += "\n"; log.WriteNormal($" Reading Certs/public.pem\n"); var localCert = System.IO.File.ReadAllText("Certs/public.pem"); if (certificate.Contains(localCert)) { log.WriteError($"The certificate on the director already contains our public key!\n"); } else { // // We just add our public key to the end // certificate += localCert; } // // This serves no purpose but it doesn't hurt to have it hanging around // log.WriteNormal($" Writing to Certs/clientca-prod.pem\n"); System.IO.File.WriteAllText("Certs/clientca-prod.pem", certificate); // // Upload the modded certificates to the director // log.WriteNormal($"Uploading New Certificate..\n"); using (var wstream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(wstream)) { writer.Write(certificate); writer.Flush(); wstream.Position = 0; ssh.Upload(wstream, "/etc/openvpn/clientca-prod.pem"); } } log.WriteSuccess($"Done!\n"); } } } return(true); }