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 e4291d50..213e4241 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java @@ -67,6 +67,36 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO } } + private final class GuardDirVisitor extends SimpleFileVisitor { + private final ZipOutputStream output; + private final Map runtime; + + private GuardDirVisitor(ZipOutputStream output, Map runtime) { + this.output = output; + this.runtime = runtime; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + String dirName = IOHelper.toString(guardDir.relativize(dir)); + output.putNextEntry(newEntry(dirName + '/')); + return super.preVisitDirectory(dir, attrs); + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String fileName = IOHelper.toString(guardDir.relativize(file)); + runtime.put(fileName, SecurityHelper.digest(DigestAlgorithm.MD5, file)); + + // Create zip entry and transfer contents + output.putNextEntry(newEntry(fileName)); + IOHelper.transfer(file, output); + + // Return result + return super.visitFile(file, attrs); + } + } + private static ZipEntry newEntry(String fileName) { return newZipEntry(Launcher.RUNTIME_DIR + IOHelper.CROSS_SEPARATOR + fileName); } @@ -224,6 +254,7 @@ private void stdBuild() throws IOException { throw new IOException(String.format("Missing init script file ('%s')", Launcher.INIT_SCRIPT_FILE)); // Write launcher runtime dir IOHelper.walk(runtimeDir, new RuntimeDirVisitor(output, runtime), false); + IOHelper.walk(guardDir, new GuardDirVisitor(output, runtime), false); } // Create launcher config file byte[] launcherConfigBytes; @@ -242,13 +273,6 @@ private void stdBuild() throws IOException { output.putNextEntry(e); jaConfigurator.compile(); output.write(jaConfigurator.getBytecode()); - for(String file : guardFileList) - { - Path path = guardDir.resolve(file); - ZipEntry en = newZipEntry(file); - output.putNextEntry(en); - IOHelper.transfer(path,output); - } server.buildHookManager.postHook(context); } catch (CannotCompileException | NotFoundException e) { LogHelper.error(e); diff --git a/Launcher/src/main/java/ru/gravit/launcher/AvanguardStarter.java b/Launcher/src/main/java/ru/gravit/launcher/AvanguardStarter.java index 80a16e05..ddab14f1 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/AvanguardStarter.java +++ b/Launcher/src/main/java/ru/gravit/launcher/AvanguardStarter.java @@ -96,8 +96,10 @@ public static void start(Path path1) throws IOException { Files.createDirectories(path); Path avanguard = path.resolve(JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll"); Path wrapper = path.resolve(JVMHelper.JVM_BITS == 64 ? NAME + "64.exe" : NAME + "32.exe"); - UnpackHelper.unpack(JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll",avanguard); - UnpackHelper.unpack(JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe",wrapper); + String avanguardResource = JVMHelper.JVM_BITS == 64 ? "Avanguard64.dll" : "Avanguard32.dll"; + String wrapperResource = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe"; + UnpackHelper.unpack(Launcher.getResourceURL(avanguardResource,"guard"),avanguard); + UnpackHelper.unpack(Launcher.getResourceURL(wrapperResource,"guard"),wrapper); AvanguardStarter.wrapper = wrapper; AvanguardStarter.avanguard = avanguard; HashedDir guard = new HashedDir(path, null, true, false); diff --git a/libLauncher/src/main/java/ru/gravit/launcher/Launcher.java b/libLauncher/src/main/java/ru/gravit/launcher/Launcher.java index 184929b1..bbbed701 100644 --- a/libLauncher/src/main/java/ru/gravit/launcher/Launcher.java +++ b/libLauncher/src/main/java/ru/gravit/launcher/Launcher.java @@ -103,6 +103,21 @@ public static URL getResourceURL(String name) throws IOException { return url; } + public static URL getResourceURL(String name,String prefix) throws IOException { + LauncherConfig config = getConfig(); + byte[] validDigest = config.runtime.get(name); + if (validDigest == null) + throw new NoSuchFileException(name); + + // Resolve URL and verify digest + URL url = IOHelper.getResourceURL(prefix + '/' + name); + if (!Arrays.equals(validDigest, SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, url))) + throw new NoSuchFileException(name); // Digest mismatch + + // Return verified URL + return url; + } + @LauncherAPI public static String toHash(UUID uuid) { return UUID_PATTERN.matcher(uuid.toString()).replaceAll(""); diff --git a/libLauncher/src/main/java/ru/gravit/utils/helper/UnpackHelper.java b/libLauncher/src/main/java/ru/gravit/utils/helper/UnpackHelper.java index d9e14b9f..faf0861d 100644 --- a/libLauncher/src/main/java/ru/gravit/utils/helper/UnpackHelper.java +++ b/libLauncher/src/main/java/ru/gravit/utils/helper/UnpackHelper.java @@ -1,13 +1,14 @@ package ru.gravit.utils.helper; import java.io.IOException; +import java.net.URL; import java.nio.file.Path; import java.util.Arrays; public class UnpackHelper { @SuppressWarnings("ResultOfMethodCallIgnored") - public static boolean unpack(String resource, Path target) throws IOException { - byte[] orig = IOHelper.read(IOHelper.getResourceURL(resource)); + public static boolean unpack(URL resource, Path target) throws IOException { + byte[] orig = IOHelper.read(resource); if(IOHelper.exists(target)) { if(matches(target,orig)) return false;