From a959414c640e7a8ddfdb3ba5d422498d3beac151 Mon Sep 17 00:00:00 2001 From: Gravita <12893402+gravit0@users.noreply.github.com> Date: Wed, 18 Jun 2025 00:08:22 +0700 Subject: [PATCH] [FEATURE] Use buildSecrets in UpdatesProvider --- .../auth/updates/LocalUpdatesProvider.java | 50 +++++++++++++++---- .../auth/updates/UpdatesProvider.java | 28 ++++++++++- .../launchserver/binary/LauncherBinary.java | 3 +- .../response/update/LauncherResponse.java | 5 +- 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/LocalUpdatesProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/LocalUpdatesProvider.java index 2a7ad5d1..111a921c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/LocalUpdatesProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/LocalUpdatesProvider.java @@ -2,6 +2,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import pro.gravit.launcher.base.config.JsonConfigurable; +import pro.gravit.launcher.base.config.SimpleConfigurable; import pro.gravit.launchserver.LaunchServer; import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.SecurityHelper; @@ -9,23 +11,33 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public class LocalUpdatesProvider extends UpdatesProvider { private transient final Logger logger = LogManager.getLogger(); public String updatesDir = "updates"; public String binaryName = "Launcher"; + public String buildSecretsFile = "build-secrets.json"; public Map urls = new HashMap<>(Map.of( UpdateVariant.JAR, "http://localhost:9274/Launcher.jar", UpdateVariant.EXE, "http://localhost:9274/Launcher.exe" )); + public transient JsonConfigurable buildSecretsJson; private final transient Map hashMap = new HashMap<>(); @Override public void init(LaunchServer server) { super.init(server); + buildSecretsJson = new SimpleConfigurable<>(BuildSecretsInfo.class, Path.of(buildSecretsFile)); + if(server.env == LaunchServer.LaunchServerEnv.TEST) { + return; + } + try { + buildSecretsJson.generateConfigIfNotExists(); + buildSecretsJson.loadConfig(); + } catch (Exception e) { + buildSecretsJson.setConfig(buildSecretsJson.getDefaultConfig()); + } try { sync(UpdateVariant.JAR); sync(UpdateVariant.EXE); @@ -35,11 +47,13 @@ public void init(LaunchServer server) { } @Override - public void pushUpdate(Map files) throws IOException { - for(var e : files.entrySet()) { - IOHelper.copy(e.getValue(), getUpdate(e.getKey())); - sync(e.getKey()); + public void pushUpdate(List files) throws IOException { + for(var e : files) { + IOHelper.copy(e.path(), getUpdate(e.variant())); + buildSecretsJson.getConfig().secrets().put(e.variant(), e.secrets()); + sync(e.variant()); } + buildSecretsJson.saveConfig(); } public void sync(UpdateVariant variant) throws IOException { @@ -69,14 +83,32 @@ public Path getUpdate(UpdateVariant variant) { } @Override - public UpdateInfo checkUpdates(UpdateVariant variant, byte[] digest) { + public UpdateInfo checkUpdates(UpdateVariant variant, BuildSecretsCheck buildSecretsCheck) { byte[] hash = hashMap.get(variant); if (hash == null) { return null; // We dont have this file } - if(Arrays.equals(digest, hash)) { + if(checkSecureHash(buildSecretsCheck.secureHash(), buildSecretsCheck.secureSalt(), buildSecretsJson.getConfig().secrets().get(variant).secureToken()) && Arrays.equals(buildSecretsCheck.digest(), hash)) { return null; // Launcher already updated } return new UpdateInfo(urls.get(variant)); } + + public static final class BuildSecretsInfo { + private Map secrets = new HashMap<>(); + + public BuildSecretsInfo(Map secrets) { + this.secrets = secrets; + } + + public BuildSecretsInfo() { + + } + + public Map secrets() { + return secrets; + } + + + } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/UpdatesProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/UpdatesProvider.java index 568bdaa9..d22ac8a0 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/UpdatesProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/updates/UpdatesProvider.java @@ -2,10 +2,14 @@ import pro.gravit.launchserver.LaunchServer; import pro.gravit.utils.ProviderMap; +import pro.gravit.utils.helper.SecurityHelper; import java.io.IOException; import java.net.URL; import java.nio.file.Path; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; import java.util.Map; public abstract class UpdatesProvider { @@ -25,8 +29,16 @@ public void init(LaunchServer server) { this.server = server; } - public abstract void pushUpdate(Map files) throws IOException; - public abstract UpdateInfo checkUpdates(UpdateVariant variant, byte[] digest); + public abstract void pushUpdate(List files) throws IOException; + public abstract UpdateInfo checkUpdates(UpdateVariant variant, BuildSecretsCheck buildSecretsCheck); + + protected boolean checkSecureHash(String secureHash, String secureSalt, String privateSecureToken) { + if (secureHash == null || secureSalt == null) return false; + byte[] normal_hash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, + privateSecureToken.concat(".").concat(secureSalt)); + byte[] launcher_hash = Base64.getDecoder().decode(secureHash); + return Arrays.equals(normal_hash, launcher_hash); + } public void close() { } @@ -38,4 +50,16 @@ public enum UpdateVariant { public record UpdateInfo(String url) { } + + public record UpdateUploadInfo(Path path, UpdateVariant variant, BuildSecrets secrets) { + + } + + public record BuildSecrets(String secureToken, byte[] digest) { + + } + + public record BuildSecretsCheck(String secureHash, String secureSalt, byte[] digest) { + + } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java index bbc24d7a..7634320b 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/LauncherBinary.java @@ -39,7 +39,8 @@ public void build() throws IOException { } long time_end = System.currentTimeMillis(); if(thisPath != null) { - server.config.updatesProvider.pushUpdate(Map.of(getVariant(), thisPath)); + // TODO fix me + server.config.updatesProvider.pushUpdate(List.of(new UpdatesProvider.UpdateUploadInfo(thisPath, getVariant(), new UpdatesProvider.BuildSecrets(server.runtime.clientCheckSecret, null)))); } else { logger.warn("Missing {} binary file", getVariant()); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java index 5cc946d7..1c769783 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java @@ -49,10 +49,7 @@ public void execute(ChannelHandlerContext ctx, Client client) { variant = UpdatesProvider.UpdateVariant.EXE; } byte[] hashToCheck = bytes; - if(!checkSecure(secureHash, secureSalt)) { - hashToCheck = null; // Always need update - } - UpdatesProvider.UpdateInfo info = server.config.updatesProvider.checkUpdates(variant, hashToCheck); + UpdatesProvider.UpdateInfo info = server.config.updatesProvider.checkUpdates(variant, new UpdatesProvider.BuildSecretsCheck(secureHash, secureSalt, hashToCheck)); if (info != null) { sendResult(new LauncherRequestEvent(true, info.url())); } else {