diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java index 4cfca822..8f3ec478 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java @@ -4,6 +4,7 @@ import java.io.BufferedWriter; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.MalformedURLException; import java.net.SocketAddress; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; @@ -32,6 +33,8 @@ import ru.gravit.launcher.Launcher; import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.hasher.HashedDir; +import ru.gravit.launcher.serialize.config.entry.*; +import ru.gravit.launchserver.manangers.MirrorManager; import ru.gravit.utils.helper.CommonHelper; import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.JVMHelper; @@ -43,10 +46,6 @@ import ru.gravit.launcher.serialize.config.ConfigObject; import ru.gravit.launcher.serialize.config.TextConfigReader; import ru.gravit.launcher.serialize.config.TextConfigWriter; -import ru.gravit.launcher.serialize.config.entry.BlockConfigEntry; -import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry; -import ru.gravit.launcher.serialize.config.entry.IntegerConfigEntry; -import ru.gravit.launcher.serialize.config.entry.StringConfigEntry; import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launchserver.auth.AuthLimiter; import ru.gravit.launchserver.auth.handler.AuthHandler; @@ -101,6 +100,7 @@ public static final class Config extends ConfigObject { public final boolean genMappings; + public ListConfigEntry mirrors; public final String binaryName; private final StringConfigEntry address; private final String bindAddress; @@ -136,6 +136,7 @@ private Config(BlockConfigEntry block, Path coredir,LaunchServer server) { // Set misc config genMappings = block.getEntryValue("proguardPrintMappings", BooleanConfigEntry.class); + mirrors = block.getEntry("mirrors",ListConfigEntry.class); launch4j = new ExeConf(block.getEntry("launch4J", BlockConfigEntry.class)); sign = new SignConf(block.getEntry("signing", BlockConfigEntry.class), coredir); binaryName = block.getEntryValue("binaryName", StringConfigEntry.class); @@ -314,6 +315,8 @@ public static void main(String... args) throws Throwable { public final ModulesManager modulesManager; + public final MirrorManager mirrorManager; + public final BuildHookManager buildHookManager; @@ -390,7 +393,7 @@ public LaunchServer(Path dir, boolean portable) throws IOException, InvalidKeySp // Print keypair fingerprints CRC32 crc = new CRC32(); - crc.update(publicKey.getModulus().toByteArray()); + crc.update(publicKey.getModulus().toByteArray()); // IDEA говорит, что это Java 9 API. WTF? LogHelper.subInfo("Modulus CRC32: 0x%08x", crc.getValue()); // pre init modules @@ -411,8 +414,16 @@ public LaunchServer(Path dir, boolean portable) throws IOException, InvalidKeySp limiter = new AuthLimiter(this); proguardConf = new ProguardConf(this); sessionManager = new SessionManager(); + mirrorManager = new MirrorManager(); GarbageManager.registerNeedGC(sessionManager); GarbageManager.registerNeedGC(limiter); + config.mirrors.stream(StringConfigEntry.class).forEach(s -> { + try { + mirrorManager.addMirror(s); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + }); // init modules modulesManager.initModules(); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java index dda5377a..7528945d 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java @@ -172,7 +172,7 @@ private void stdBuild() throws IOException { jaConfigurator.setAddress(server.config.getAddress()); jaConfigurator.setPort(server.config.port); jaConfigurator.setProjectName(server.config.projectName); - jaConfigurator.setSecretKey(SecurityHelper.randomStringToken()); + jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey()); jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512)); server.buildHookManager.registerAllClientModuleClass(jaConfigurator); try (ZipInputStream input = new ZipInputStream( diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadAssetCommand.java b/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadAssetCommand.java index a52913c8..5705445e 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadAssetCommand.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadAssetCommand.java @@ -13,7 +13,6 @@ import ru.gravit.launchserver.command.Command; public final class DownloadAssetCommand extends Command { - private static final String ASSET_URL_MASK = "http://launcher.sashok724.net/download/assets/%s.zip"; public DownloadAssetCommand(LaunchServer server) { super(server); @@ -42,7 +41,7 @@ public void invoke(String... args) throws Exception { // Download required asset LogHelper.subInfo("Downloading asset, it may take some time"); - HttpDownloader.downloadZip(new URL(String.format(ASSET_URL_MASK, IOHelper.urlEncode(version.name))), assetDir); + HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getAssetsURL(version.name), assetDir); // Finished server.syncUpdatesDir(Collections.singleton(dirName)); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadClientCommand.java b/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadClientCommand.java index 31944dcd..53196bde 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadClientCommand.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/command/hash/DownloadClientCommand.java @@ -21,7 +21,6 @@ import ru.gravit.launchserver.command.CommandException; public final class DownloadClientCommand extends Command { - private static final String CLIENT_URL_MASK = "http://launcher.sashok724.net/download/clients/%s.zip"; public DownloadClientCommand(LaunchServer server) { super(server); @@ -50,8 +49,7 @@ public void invoke(String... args) throws IOException, CommandException { // Download required client LogHelper.subInfo("Downloading client, it may take some time"); - HttpDownloader.downloadZip(new URL(String.format(CLIENT_URL_MASK, - IOHelper.urlEncode(version.name))), clientDir); + HttpDownloader.downloadZip(server.mirrorManager.getDefaultMirror().getClientsURL(version.name), clientDir); // Create profile file LogHelper.subInfo("Creaing profile file: '%s'", dirName); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/MirrorManager.java b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/MirrorManager.java new file mode 100644 index 00000000..c1f41383 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/MirrorManager.java @@ -0,0 +1,64 @@ +package ru.gravit.launchserver.manangers; + +import ru.gravit.utils.helper.IOHelper; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; + +public class MirrorManager { + public class Mirror + { + URL url; + String assetsURLMask; + String clientsURLMask; + boolean enabled; + Mirror(String url) + { + assetsURLMask = url.concat("assets/%s.zip"); + clientsURLMask = url.concat("clients/%s.zip"); + } + private URL formatArg(String mask,String arg) throws MalformedURLException { + return new URL(String.format(mask, IOHelper.urlEncode(arg))); + } + public URL getAssetsURL(String assets) throws MalformedURLException { + return formatArg(assetsURLMask,assets); + } + public URL getClientsURL(String client) throws MalformedURLException { + return formatArg(clientsURLMask,client); + } + } + protected ArrayList list = new ArrayList<>(); + private Mirror defaultMirror; + public void addMirror(String mirror) throws MalformedURLException { + Mirror m = new Mirror(mirror); + m.enabled = true; + if(defaultMirror == null) defaultMirror = m; + } + public void addMirror(String mirror,boolean enabled) throws MalformedURLException { + Mirror m = new Mirror(mirror); + m.url = new URL(mirror); + m.enabled = enabled; + if(defaultMirror == null && enabled) defaultMirror = m; + } + public Mirror getDefaultMirror() + { + return defaultMirror; + } + public void setDefaultMirror(Mirror m) + { + defaultMirror = m; + } + public void disableMirror(int index) + { + list.get(index).enabled = false; + } + public void enableMirror(int index) + { + list.get(index).enabled = true; + } + public int size() + { + return list.size(); + } +} diff --git a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg index 788f827c..7f29a108 100644 --- a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg +++ b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/config.cfg @@ -1,7 +1,7 @@ address: "x"; bindAddress: "0.0.0.0"; port: 7240; - +mirrors: ["http://launcher.sashok724.net/download/"]; # Auth rate limit authRateLimit: 2; authRateLimitMilis: 5000; diff --git a/libLauncher/src/main/java/ru/gravit/utils/helper/SecurityHelper.java b/libLauncher/src/main/java/ru/gravit/utils/helper/SecurityHelper.java index 774e7478..bea77600 100644 --- a/libLauncher/src/main/java/ru/gravit/utils/helper/SecurityHelper.java +++ b/libLauncher/src/main/java/ru/gravit/utils/helper/SecurityHelper.java @@ -90,6 +90,8 @@ public byte[] verify(byte[] digest) { @LauncherAPI public static final int TOKEN_LENGTH = 16; @LauncherAPI + public static final int AES_KEY_LENGTH = 24; + @LauncherAPI public static final int TOKEN_STRING_LENGTH = TOKEN_LENGTH << 1; @LauncherAPI public static final int RSA_KEY_LENGTH_BITS = 2048; @@ -310,6 +312,25 @@ public static byte[] randomToken(Random random) { return randomBytes(random, TOKEN_LENGTH); } + @LauncherAPI + public static String randomStringAESKey() { + return toHex(randomAESKey(newRandom())); + } + @LauncherAPI + public static String randomStringAESKey(Random random) { + return toHex(randomAESKey(random)); + } + + @LauncherAPI + public static byte[] randomAESKey() { + return randomAESKey(newRandom()); + } + + @LauncherAPI + public static byte[] randomAESKey(Random random) { + return randomBytes(random, AES_KEY_LENGTH); + } + @LauncherAPI public static String randomUsername() { return randomUsername(newRandom());