diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java index 1a01c2c9..4784317a 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java @@ -8,6 +8,8 @@ import ru.gravit.launcher.managers.GarbageManager; import ru.gravit.launcher.profiles.ClientProfile; import ru.gravit.launcher.serialize.signed.SignedObjectHolder; +import ru.gravit.launchserver.auth.protect.NoProtectHandler; +import ru.gravit.launchserver.auth.protect.ProtectHandler; import ru.gravit.launchserver.components.AuthLimiterComponent; import ru.gravit.launchserver.auth.handler.AuthHandler; import ru.gravit.launchserver.auth.handler.MemoryAuthHandler; @@ -89,6 +91,8 @@ public static final class Config { public AuthHandler authHandler; + public ProtectHandler protectHandler; + public PermissionsHandler permissionsHandler; public TextureProvider textureProvider; @@ -159,6 +163,10 @@ public void verify() { if (authHandler == null) { throw new NullPointerException("AuthHandler must not be null"); } + if(protectHandler == null) + { + throw new NullPointerException("ProtectHandler must not be null"); + } if (authProvider == null || authProvider[0] == null) { throw new NullPointerException("AuthProvider must not be null"); } @@ -377,6 +385,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE PermissionsHandler.registerHandlers(); Response.registerResponses(); Component.registerComponents(); + ProtectHandler.registerHandlers(); LaunchServer.server = this; // Set command handler @@ -435,6 +444,10 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE for (AuthProvider provider : config.authProvider) { provider.init(); } + if(config.protectHandler != null) + { + config.protectHandler.checkLaunchServerLicense(); + } config.authHandler.init(); if(config.components != null) { @@ -546,6 +559,7 @@ public static void initGson() { Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); + Launcher.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter()); Launcher.gson = Launcher.gsonBuilder.create(); //Human readable @@ -557,6 +571,7 @@ public static void initGson() { LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); + LaunchServer.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter()); LaunchServer.gson = LaunchServer.gsonBuilder.create(); } @@ -608,6 +623,7 @@ private void generateConfigIfNotExists() throws IOException { newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh"; newConfig.authHandler = new MemoryAuthHandler(); newConfig.hwidHandler = new AcceptHWIDHandler(); + newConfig.protectHandler = new NoProtectHandler(); newConfig.authProvider = new AuthProvider[]{new RejectAuthProvider("Настройте authProvider")}; newConfig.textureProvider = new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png"); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java new file mode 100644 index 00000000..400c9a3e --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java @@ -0,0 +1,16 @@ +package ru.gravit.launchserver.auth.protect; + +import ru.gravit.launchserver.response.auth.AuthResponse; +import ru.gravit.utils.helper.SecurityHelper; + +public class NoProtectHandler extends ProtectHandler { + @Override + public String generateSecureToken(AuthResponse.AuthContext context) { + return SecurityHelper.randomStringToken(); + } + + @Override + public void checkLaunchServerLicense() { + // None + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java new file mode 100644 index 00000000..9145df79 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java @@ -0,0 +1,46 @@ +package ru.gravit.launchserver.auth.protect; + +import ru.gravit.launchserver.auth.AuthException; +import ru.gravit.launchserver.auth.handler.AuthHandler; +import ru.gravit.launchserver.response.auth.AuthResponse; +import ru.gravit.utils.helper.VerifyHelper; + +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class ProtectHandler { + private static final Map> PROTECT_HANDLERS = new ConcurrentHashMap<>(4); + private static boolean registredHandl = false; + + + public static void registerHandler(String name, Class adapter) { + VerifyHelper.verifyIDName(name); + VerifyHelper.putIfAbsent(PROTECT_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"), + String.format("Protect handler has been already registered: '%s'", name)); + } + + public static Class getHandlerClass(String name) { + return PROTECT_HANDLERS.get(name); + } + + public static String getHandlerName(Class clazz) { + for (Map.Entry> e : PROTECT_HANDLERS.entrySet()) { + if (e.getValue().equals(clazz)) return e.getKey(); + } + return null; + } + + public static void registerHandlers() { + if (!registredHandl) { + registerHandler("none", NoProtectHandler.class); + registredHandl = true; + } + } + + public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface + + public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии + //public abstract +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java new file mode 100644 index 00000000..6e6fcd19 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java @@ -0,0 +1,37 @@ +package ru.gravit.launchserver.config; + +import com.google.gson.*; +import ru.gravit.launchserver.auth.handler.AuthHandler; +import ru.gravit.launchserver.auth.protect.ProtectHandler; +import ru.gravit.utils.helper.LogHelper; + +import java.lang.reflect.Type; + +public class ProtectHandlerAdapter implements JsonSerializer, JsonDeserializer { + private static final String PROP_NAME = "type"; + + @Override + public ProtectHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); + Class cls = ProtectHandler.getHandlerClass(typename); + if(cls == null) + { + LogHelper.error("ProtectHandler %s not found", typename); + return null; + } + + + return (ProtectHandler) context.deserialize(json, cls); + } + + @Override + public JsonElement serialize(ProtectHandler src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jo = context.serialize(src).getAsJsonObject(); + + @SuppressWarnings("unchecked") + String classPath = ProtectHandler.getHandlerName((Class) src.getClass()); + jo.add(PROP_NAME, new JsonPrimitive(classPath)); + + return jo; + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthResponse.java index 6e4574b6..1b29cedc 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthResponse.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthResponse.java @@ -137,10 +137,12 @@ public void reply() throws Exception { requestError("Internal auth handler error"); return; } + String protectToken = server.config.protectHandler.generateSecureToken(context); writeNoError(output); // Write profile and UUID ProfileByUUIDResponse.getProfile(server, uuid, result.username, client).write(output); output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH); clientData.permissions.write(output); + output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT); } } diff --git a/Launcher/runtime/dialog/dialog.js b/Launcher/runtime/dialog/dialog.js index dfa26435..712b3fcb 100644 --- a/Launcher/runtime/dialog/dialog.js +++ b/Launcher/runtime/dialog/dialog.js @@ -215,6 +215,7 @@ function doAuth(login, rsaPassword) { overlay.show(processing.overlay, function (event) { FunctionalBridge.getHWID.join(); makeAuthRequest(login, rsaPassword, function (result) { + FunctionalBridge.setAuthParams(result); loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions}; overlay.hide(0, function () { diff --git a/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java b/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java index f055ebda..d001f8da 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java +++ b/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java @@ -3,6 +3,7 @@ import javafx.concurrent.Task; import ru.gravit.launcher.HWID; import ru.gravit.launcher.LauncherAPI; +import ru.gravit.launcher.events.request.AuthRequestEvent; import ru.gravit.launcher.guard.LauncherGuardManager; import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.HashedDir; @@ -103,6 +104,12 @@ public static HasherStore getDefaultHasherStore() { return HasherManager.getDefaultStore(); } + @LauncherAPI + public static void setAuthParams(AuthRequestEvent event) + { + LauncherGuardManager.guard.setProtectToken(event.protectToken); + } + @FunctionalInterface public interface HashedDirRunnable { SignedObjectHolder run() throws Exception; diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java index fb6e8fdd..be71089c 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java @@ -11,4 +11,5 @@ public interface LauncherGuardInterface { void init(boolean clientInstance); void addCustomParams(ClientLauncherContext context); void addCustomEnv(ClientLauncherContext context); + void setProtectToken(String token); } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java index 77c4606a..31ef0941 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java @@ -43,4 +43,9 @@ public void addCustomParams(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) { } + + @Override + public void setProtectToken(String token) { + + } } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java index 9bd1923c..2fbc872b 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java @@ -40,4 +40,9 @@ public void addCustomParams(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) { } + + @Override + public void setProtectToken(String token) { + + } } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java index bd97ebbb..44c60875 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java @@ -69,4 +69,9 @@ public void addCustomEnv(ClientLauncherContext context) { env.put("GUARD_LICENSE_KEY", config.guardLicenseKey); } } + + @Override + public void setProtectToken(String token) { + + } } diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java index f9e2e7f5..0302dfd5 100644 --- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java @@ -118,7 +118,8 @@ protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOExce PlayerProfile pp = new PlayerProfile(input); String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH); ClientPermissions permissions = new ClientPermissions(input); - return new AuthRequestEvent(pp, accessToken, permissions); + String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT); + return new AuthRequestEvent(permissions, pp, accessToken, protectToken); } @Override diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java index 80352243..96c01bc4 100644 --- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java @@ -303,9 +303,16 @@ public Integer getLegacyType() { } @Override - protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException { + public UpdateRequestEvent request() throws Exception { Files.createDirectories(dir); localDir = new HashedDir(dir, matcher, false, digest); + + // Start request + return super.request(); + } + + @Override + protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException { // Write update dir name output.writeString(dirName, 255); output.flush(); diff --git a/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java b/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java index a61a0a18..aab137be 100644 --- a/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java +++ b/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java @@ -20,6 +20,8 @@ public AuthRequestEvent() { public PlayerProfile playerProfile; @LauncherNetworkAPI public String accessToken; + @LauncherNetworkAPI + public String protectToken; public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) { this.playerProfile = pp; @@ -27,6 +29,13 @@ public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions this.permissions = permissions; } + public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken) { + this.permissions = permissions; + this.playerProfile = playerProfile; + this.accessToken = accessToken; + this.protectToken = protectToken; + } + @Override public UUID getUUID() { return uuid;