From 3c0de3727ddb17c654d7f53a06b4c7b933e83af8 Mon Sep 17 00:00:00 2001 From: Gravit Date: Fri, 12 Apr 2019 04:58:45 +0700 Subject: [PATCH] [FEATURE] LaunchServerRuntimeConfig --- .../ru/gravit/launchserver/LaunchServer.java | 35 ++++++++++++++++--- .../auth/protect/NoProtectHandler.java | 15 ++++++++ .../auth/protect/ProtectHandler.java | 4 +++ .../config/LaunchServerRuntimeConfig.java | 16 +++++++++ .../ru/gravit/launchserver/socket/Client.java | 1 + .../websocket/WebSocketService.java | 4 +++ .../websocket/json/auth/AuthResponse.java | 9 +++-- .../json/secure/GetSecureTokenResponse.java | 21 +++++++++++ .../secure/VerifySecureTokenResponse.java | 24 +++++++++++++ .../websockets/ClientWebSocketService.java | 2 ++ .../request/GetSecureTokenRequestEvent.java | 17 +++++++++ .../VerifySecureTokenRequestEvent.java | 17 +++++++++ 12 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 LaunchServer/src/main/java/ru/gravit/launchserver/config/LaunchServerRuntimeConfig.java create mode 100644 LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/GetSecureTokenResponse.java create mode 100644 LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/VerifySecureTokenResponse.java create mode 100644 libLauncher/src/main/java/ru/gravit/launcher/events/request/GetSecureTokenRequestEvent.java create mode 100644 libLauncher/src/main/java/ru/gravit/launcher/events/request/VerifySecureTokenRequestEvent.java diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java index 0e547f35..b7ca5b45 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java @@ -25,6 +25,7 @@ import ru.gravit.launchserver.binary.*; import ru.gravit.launchserver.components.AuthLimiterComponent; import ru.gravit.launchserver.components.Component; +import ru.gravit.launchserver.config.LaunchServerRuntimeConfig; import ru.gravit.launchserver.config.adapter.*; import ru.gravit.launchserver.manangers.*; import ru.gravit.launchserver.manangers.hook.AuthHookManager; @@ -41,10 +42,7 @@ import ru.gravit.utils.config.JsonConfigurable; import ru.gravit.utils.helper.*; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.lang.ProcessBuilder.Redirect; import java.lang.reflect.InvocationTargetException; import java.net.InetSocketAddress; @@ -336,6 +334,7 @@ public static void main(String... args) throws Throwable { public final List args; public final Path configFile; + public final Path runtimeConfigFile; public final Path publicKeyFile; @@ -349,6 +348,7 @@ public static void main(String... args) throws Throwable { // Server config public Config config; + public LaunchServerRuntimeConfig runtime; public final RSAPublicKey publicKey; @@ -413,6 +413,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException launcherLibrariesCompile = dir.resolve("launcher-libraries-compile"); this.args = Arrays.asList(args); configFile = dir.resolve("LaunchServer.conf"); + runtimeConfigFile = dir.resolve("RuntimeLaunchServer.conf"); publicKeyFile = dir.resolve("public.key"); privateKeyFile = dir.resolve("private.key"); updatesDir = dir.resolve("updates"); @@ -486,6 +487,20 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException try (BufferedReader reader = IOHelper.newReader(configFile)) { config = Launcher.gson.fromJson(reader, Config.class); } + if(!Files.exists(runtimeConfigFile)) + { + LogHelper.info("Reset LaunchServer runtime config file"); + runtime = new LaunchServerRuntimeConfig(); + runtime.reset(); + } + else + { + LogHelper.info("Reading LaunchServer runtime config file"); + try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) { + runtime = Launcher.gson.fromJson(reader, LaunchServerRuntimeConfig.class); + } + } + runtime.verify(); config.verify(); Launcher.applyLauncherEnv(config.env); for (AuthProviderPair provider : config.auth) { @@ -633,6 +648,18 @@ public void close() { // Close handlers & providers config.close(); modulesManager.close(); + LogHelper.info("Save LaunchServer runtime config"); + try(Writer writer = IOHelper.newWriter(runtimeConfigFile)) + { + if(LaunchServer.gson != null) + { + LaunchServer.gson.toJson(runtime, writer); + } else { + LogHelper.error("Error writing LaunchServer runtime config file. Gson is null"); + } + } catch (IOException e) { + LogHelper.error(e); + } // Print last message before death :( LogHelper.info("LaunchServer stopped"); } 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 index 915875e6..3f4be0de 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java @@ -9,6 +9,21 @@ public String generateSecureToken(AuthResponse.AuthContext context) { return SecurityHelper.randomStringToken(); } + @Override + public String generateClientSecureToken() { + return SecurityHelper.randomStringToken(); + } + + @Override + public boolean verifyClientSecureToken(String token) { + return true; + } + + @Override + public boolean allowGetAccessToken(AuthResponse.AuthContext context) { + return true; + } + @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 index 1d3401f6..6d0891b5 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java @@ -38,6 +38,10 @@ public static void registerHandlers() { public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface + public abstract String generateClientSecureToken(); + public abstract boolean verifyClientSecureToken(String token); + public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context); + public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии //public abstract } diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/LaunchServerRuntimeConfig.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/LaunchServerRuntimeConfig.java new file mode 100644 index 00000000..19d22034 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/LaunchServerRuntimeConfig.java @@ -0,0 +1,16 @@ +package ru.gravit.launchserver.config; + +import ru.gravit.utils.helper.LogHelper; +import ru.gravit.utils.helper.SecurityHelper; + +public class LaunchServerRuntimeConfig { + public String clientToken; + public void verify() + { + if(clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null"); + } + public void reset() + { + clientToken = SecurityHelper.randomStringToken(); + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java b/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java index e384953e..33a02a81 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java @@ -14,6 +14,7 @@ public class Client { public ClientProfile profile; public boolean isAuth; public boolean checkSign; + public boolean isSecure; public ClientPermissions permissions; public String username; public LogHelper.OutputEnity logOutput; diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/WebSocketService.java b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/WebSocketService.java index 6e108ed2..08e6f35e 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/WebSocketService.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/WebSocketService.java @@ -22,6 +22,8 @@ import ru.gravit.launchserver.websocket.json.profile.BatchProfileByUsername; import ru.gravit.launchserver.websocket.json.profile.ProfileByUUIDResponse; import ru.gravit.launchserver.websocket.json.profile.ProfileByUsername; +import ru.gravit.launchserver.websocket.json.secure.GetSecureTokenResponse; +import ru.gravit.launchserver.websocket.json.secure.VerifySecureTokenResponse; import ru.gravit.launchserver.websocket.json.update.LauncherResponse; import ru.gravit.launchserver.websocket.json.update.UpdateListResponse; import ru.gravit.launchserver.websocket.json.update.UpdateResponse; @@ -88,6 +90,8 @@ public void registerResponses() { registerResponse("batchProfileByUsername", BatchProfileByUsername.class); registerResponse("profileByUsername", ProfileByUsername.class); registerResponse("profileByUUID", ProfileByUUIDResponse.class); + registerResponse("getSecureToken", GetSecureTokenResponse.class); + registerResponse("verifySecureToken", VerifySecureTokenResponse.class); } public void sendObject(ChannelHandlerContext ctx, Object obj) { diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/auth/AuthResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/auth/AuthResponse.java index f6d4b266..5e9bedaf 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/auth/AuthResponse.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/auth/AuthResponse.java @@ -105,7 +105,6 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client //if (clientData.profile == null) { // throw new AuthException("You profile not found"); //} - UUID uuid = pair.handler.auth(aresult); if (authType == ConnectTypes.CLIENT) LaunchServer.server.config.hwidHandler.check(hwid, aresult.username); LaunchServer.server.authHookManager.postHook(context, clientData); @@ -121,8 +120,12 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client LaunchServer.server.sessionManager.addClient(clientData); result.session = clientData.session; } - result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, aresult.username, client, clientData.auth.textureProvider); - LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString()); + if(LaunchServer.server.config.protectHandler.allowGetAccessToken(context)) + { + UUID uuid = pair.handler.auth(aresult); + result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, aresult.username, client, clientData.auth.textureProvider); + LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString()); + } service.sendObject(ctx, result); } catch (AuthException | HWIDException e) { service.sendObject(ctx, new ErrorRequestEvent(e.getMessage())); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/GetSecureTokenResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/GetSecureTokenResponse.java new file mode 100644 index 00000000..8423c70d --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/GetSecureTokenResponse.java @@ -0,0 +1,21 @@ +package ru.gravit.launchserver.websocket.json.secure; + +import io.netty.channel.ChannelHandlerContext; +import ru.gravit.launcher.events.request.GetSecureTokenRequestEvent; +import ru.gravit.launchserver.LaunchServer; +import ru.gravit.launchserver.socket.Client; +import ru.gravit.launchserver.websocket.WebSocketService; +import ru.gravit.launchserver.websocket.json.JsonResponseInterface; + +public class GetSecureTokenResponse implements JsonResponseInterface { + @Override + public String getType() { + return "getSecureToken"; + } + + @Override + public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { + String secureToken = LaunchServer.server.config.protectHandler.generateClientSecureToken(); + service.sendObject(ctx, new GetSecureTokenRequestEvent(secureToken)); + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/VerifySecureTokenResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/VerifySecureTokenResponse.java new file mode 100644 index 00000000..e3c20e03 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/secure/VerifySecureTokenResponse.java @@ -0,0 +1,24 @@ +package ru.gravit.launchserver.websocket.json.secure; + +import io.netty.channel.ChannelHandlerContext; +import ru.gravit.launcher.events.request.VerifySecureTokenRequestEvent; +import ru.gravit.launchserver.LaunchServer; +import ru.gravit.launchserver.socket.Client; +import ru.gravit.launchserver.websocket.WebSocketService; +import ru.gravit.launchserver.websocket.json.JsonResponseInterface; + +public class VerifySecureTokenResponse implements JsonResponseInterface { + public String secureToken; + + @Override + public String getType() { + return "verifySecureToken"; + } + + @Override + public void execute(WebSocketService service, ChannelHandlerContext ctx, Client client) throws Exception { + boolean success = LaunchServer.server.config.protectHandler.verifyClientSecureToken(secureToken); + if(success) client.isSecure = true; + service.sendObject(ctx, new VerifySecureTokenRequestEvent(success)); + } +} diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/ClientWebSocketService.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/ClientWebSocketService.java index 189746cb..9dd11fdf 100644 --- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/ClientWebSocketService.java +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/ClientWebSocketService.java @@ -111,6 +111,8 @@ public void registerResults() { registerResult("error", ErrorRequestEvent.class); registerResult("update", UpdateRequestEvent.class); registerResult("restoreSession", RestoreSessionRequestEvent.class); + registerResult("getSecureToken", GetSecureTokenRequestEvent.class); + registerResult("verifySecureToken", VerifySecureTokenRequestEvent.class); } public void registerHandler(EventHandler eventHandler) { diff --git a/libLauncher/src/main/java/ru/gravit/launcher/events/request/GetSecureTokenRequestEvent.java b/libLauncher/src/main/java/ru/gravit/launcher/events/request/GetSecureTokenRequestEvent.java new file mode 100644 index 00000000..35fece1e --- /dev/null +++ b/libLauncher/src/main/java/ru/gravit/launcher/events/request/GetSecureTokenRequestEvent.java @@ -0,0 +1,17 @@ +package ru.gravit.launcher.events.request; + +import ru.gravit.launcher.LauncherNetworkAPI; +import ru.gravit.launcher.request.ResultInterface; + +public class GetSecureTokenRequestEvent implements ResultInterface { + @LauncherNetworkAPI + public String secureToken; + @Override + public String getType() { + return "GetSecureToken"; + } + + public GetSecureTokenRequestEvent(String secureToken) { + this.secureToken = secureToken; + } +} diff --git a/libLauncher/src/main/java/ru/gravit/launcher/events/request/VerifySecureTokenRequestEvent.java b/libLauncher/src/main/java/ru/gravit/launcher/events/request/VerifySecureTokenRequestEvent.java new file mode 100644 index 00000000..5ad3fca1 --- /dev/null +++ b/libLauncher/src/main/java/ru/gravit/launcher/events/request/VerifySecureTokenRequestEvent.java @@ -0,0 +1,17 @@ +package ru.gravit.launcher.events.request; + +import ru.gravit.launcher.LauncherAPI; +import ru.gravit.launcher.request.ResultInterface; + +public class VerifySecureTokenRequestEvent implements ResultInterface { + @LauncherAPI + public boolean success; + @Override + public String getType() { + return "verifySecureToken"; + } + + public VerifySecureTokenRequestEvent(boolean success) { + this.success = success; + } +}