From 64d200c0b91566811d326235a38583dd79beebe6 Mon Sep 17 00:00:00 2001 From: rjindael Date: Tue, 1 Aug 2023 21:47:56 -0700 Subject: [PATCH] feat: refactor maintenance authentication, part 2 --- Kiseki.Launcher.Windows/Launcher.cs | 42 ++++++++++++++++++++++++++++- Kiseki.Launcher.Windows/Program.cs | 10 ++++++- Kiseki.Launcher/Web.cs | 39 ++++++++++++++++++++------- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/Kiseki.Launcher.Windows/Launcher.cs b/Kiseki.Launcher.Windows/Launcher.cs index df41f63..996538e 100644 --- a/Kiseki.Launcher.Windows/Launcher.cs +++ b/Kiseki.Launcher.Windows/Launcher.cs @@ -7,7 +7,46 @@ namespace Kiseki.Launcher.Windows public class Launcher : ILauncher { public readonly static string Version = Assembly.GetExecutingAssembly().GetName().Version!.ToString()[..^2]; - + +#region Licensing + public static void TryLoadLicense() + { + if (!File.Exists(Directories.License)) + { + AskForLicense(Directories.License); + } + + // ... load the license ... + while (!Web.LoadLicense(File.ReadAllText(Directories.License))) + { + // ... and if it's invalid, keep asking for a new one. + File.Delete(Directories.License); + MessageBox.Show($"Corrupt license file! Please verify the contents of your license file (it should be named \"license.bin\".)", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error); + AskForLicense(Directories.License, false); + } + } + + private static void AskForLicense(string licensePath, bool showDialog = true) + { + DialogResult answer = showDialog ? MessageBox.Show($"{Constants.PROJECT_NAME} is currently under maintenance and requires a license in order to access games. Would you like to look for the license file now?", Constants.PROJECT_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) : DialogResult.Yes; + + if (answer == DialogResult.Yes) + { + using OpenFileDialog dialog = new() + { + Title = "Select your license file", + Filter = "License files (*.bin)|*.bin", + InitialDirectory = Win32.GetDownloadsPath() + }; + + if (dialog.ShowDialog() == DialogResult.OK) + { + File.Copy(dialog.FileName, licensePath, true); + } + } + } +#endregion +#region ILauncher implementation public static void Install() { Directory.CreateDirectory(Directories.Base); @@ -45,5 +84,6 @@ namespace Kiseki.Launcher.Windows { Registry.CurrentUser.DeleteSubKey($@"Software\{Constants.PROJECT_NAME}"); } +#endregion } } \ No newline at end of file diff --git a/Kiseki.Launcher.Windows/Program.cs b/Kiseki.Launcher.Windows/Program.cs index a5ae784..45f2f9d 100644 --- a/Kiseki.Launcher.Windows/Program.cs +++ b/Kiseki.Launcher.Windows/Program.cs @@ -19,7 +19,15 @@ namespace Kiseki.Launcher.Windows Directories.Initialize(Path.Combine(Directories.LocalAppData, Constants.PROJECT_NAME)); } - if (!Web.Initialize()) + bool isConnected = Web.Initialize(); + if (!isConnected && Web.IsInMaintenance) + { + // Try again with the maintenance domain + Launcher.TryLoadLicense(); + isConnected = Web.Initialize(); + } + + if (!isConnected) { MessageBox.Show($"Failed to connect to {Constants.PROJECT_NAME}. Please check your internet connection and try again.", Constants.PROJECT_NAME, MessageBoxButtons.OK, MessageBoxIcon.Error); return; diff --git a/Kiseki.Launcher/Web.cs b/Kiseki.Launcher/Web.cs index e2922da..27e47c7 100644 --- a/Kiseki.Launcher/Web.cs +++ b/Kiseki.Launcher/Web.cs @@ -12,24 +12,21 @@ namespace Kiseki.Launcher public const string BASE_URL = "kiseki.lol"; public const string MAINTENANCE_DOMAIN = "test"; - public static readonly HttpClient HttpClient = new(); public static string CurrentUrl { get; private set; } = ""; + public static bool IsInMaintenance { get; private set; } = false; - public static bool Initialize(bool setBaseUrl = true) + public static readonly HttpClient HttpClient = new(); + + public static bool Initialize() { - if (setBaseUrl) - { - CurrentUrl = BASE_URL; - } + CurrentUrl = IsInMaintenance ? $"{MAINTENANCE_DOMAIN}.{BASE_URL}" : BASE_URL; int response = CheckHealth(); - if (response != RESPONSE_SUCCESS) { if (response == RESPONSE_MAINTENANCE) { - CurrentUrl = $"{MAINTENANCE_DOMAIN}.{BASE_URL}"; - return Initialize(false); + IsInMaintenance = true; } return false; @@ -46,5 +43,29 @@ namespace Kiseki.Launcher return response is null ? RESPONSE_FAILURE : response.Status; } + + public static bool LoadLicense(string license) + { + // the "license" is actually just headers required to access the website. + // this can be cloudflare zero-trust headers (like what Kiseki does), or however + // else you'd like to do auth-walls. either way; it's just a JSON document + + try + { + HttpClient.DefaultRequestHeaders.Clear(); + + var headers = JsonSerializer.Deserialize>(license)!; + for (int i = 0; i < headers.Count; i++) + { + HttpClient.DefaultRequestHeaders.Add(headers.ElementAt(i).Key, headers.ElementAt(i).Value); + } + } + catch + { + return false; + } + + return true; + } } } \ No newline at end of file