From e77a848843d6e5bf17f1a69aa0f71f0707336306 Mon Sep 17 00:00:00 2001 From: Gravit Date: Thu, 27 Sep 2018 04:18:26 +0700 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../launchserver/response/Response.java | 2 + .../response/auth/AuthResponse.java | 17 +++- .../response/auth/AuthServerResponse.java | 95 +++++++++++++++++++ .../ru/gravit/launchserver/socket/Client.java | 14 ++- .../request/auth/ServerAuthRequest.java | 80 ++++++++++++++++ .../gravit/launcher/request/RequestType.java | 2 +- 6 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java create mode 100644 LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/ServerAuthRequest.java diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/response/Response.java b/LaunchServer/src/main/java/ru/gravit/launchserver/response/Response.java index cb72d827..ceee57bd 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/response/Response.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/response/Response.java @@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentHashMap; import ru.gravit.launcher.LauncherAPI; +import ru.gravit.launchserver.response.auth.AuthServerResponse; import ru.gravit.utils.helper.LogHelper; import ru.gravit.launcher.request.RequestException; import ru.gravit.launcher.request.RequestType; @@ -53,6 +54,7 @@ public static void registerResponses() { registerResponse(RequestType.UPDATE_LIST.getNumber(), UpdateListResponse::new); registerResponse(RequestType.UPDATE.getNumber(), UpdateResponse::new); registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new); + registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new); } @LauncherAPI 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 fa59af7e..52a8b2c8 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 @@ -7,6 +7,7 @@ import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; +import ru.gravit.launchserver.socket.Client; import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.SecurityHelper; @@ -60,6 +61,8 @@ public void reply() throws Exception { debug("Login: '%s', Password: '%s'", login, echo(password.length())); AuthProviderResult result; AuthProvider provider = server.config.authProvider[auth_id]; + Client clientData = server.sessionManager.getClient(session); + clientData.type = Client.Type.USER; try { if (server.limiter.isLimit(ip)) { AuthProvider.authError(server.config.authRejectString); @@ -71,10 +74,17 @@ public void reply() throws Exception { return; } Collection> profiles = server.getProfiles(); - for (SignedObjectHolder p : profiles) - if (p.object.getTitle().equals(client)) - if (!p.object.isWhitelistContains(login)) + for (SignedObjectHolder p : profiles) { + if (p.object.getTitle().equals(client)) { + if (!p.object.isWhitelistContains(login)) { throw new AuthException(server.config.whitelistRejectString); + } + clientData.profile = p.object; + } + } + if(clientData.profile == null) { + throw new AuthException("You profile not found"); + } server.config.hwidHandler.check(HWID.gen(hwid_hdd, hwid_bios, hwid_cpu), result.username); } catch (AuthException | HWIDException e) { requestError(e.getMessage()); @@ -85,6 +95,7 @@ public void reply() throws Exception { return; } debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken); + clientData.isAuth = true; // Authenticate on server (and get UUID) UUID uuid; try { diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java new file mode 100644 index 00000000..ff86a97b --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java @@ -0,0 +1,95 @@ +package ru.gravit.launchserver.response.auth; + +import ru.gravit.launcher.profiles.ClientProfile; +import ru.gravit.launcher.serialize.HInput; +import ru.gravit.launcher.serialize.HOutput; +import ru.gravit.launcher.serialize.SerializeLimits; +import ru.gravit.launcher.serialize.signed.SignedObjectHolder; +import ru.gravit.launchserver.LaunchServer; +import ru.gravit.launchserver.auth.AuthException; +import ru.gravit.launchserver.auth.hwid.HWID; +import ru.gravit.launchserver.auth.hwid.HWIDException; +import ru.gravit.launchserver.auth.provider.AuthProvider; +import ru.gravit.launchserver.auth.provider.AuthProviderResult; +import ru.gravit.launchserver.response.Response; +import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse; +import ru.gravit.launchserver.socket.Client; +import ru.gravit.utils.helper.IOHelper; +import ru.gravit.utils.helper.LogHelper; +import ru.gravit.utils.helper.SecurityHelper; +import ru.gravit.utils.helper.VerifyHelper; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import java.util.Arrays; +import java.util.Collection; +import java.util.UUID; + +public final class AuthServerResponse extends Response { + private static String echo(int length) { + char[] chars = new char[length]; + Arrays.fill(chars, '*'); + return new String(chars); + } + + public AuthServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip) { + super(server, session, input, output, ip); + } + + @Override + public void reply() throws Exception { + String login = input.readString(SerializeLimits.MAX_LOGIN); + String client = input.readString(SerializeLimits.MAX_CLIENT); + int auth_id = input.readInt(); + if(auth_id + 1 > server.config.authProvider.length || auth_id < 0) auth_id = 0; + byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH); + // Decrypt password + String password; + try { + password = IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey). + doFinal(encryptedPassword)); + } catch (IllegalBlockSizeException | BadPaddingException ignored) { + requestError("ServerPassword decryption error"); + return; + } + if(client.length() == 0) requestError("Request error. You is cheater?"); + // Authenticate + debug("ServerLogin: '%s', Password: '%s'", login, echo(password.length())); + AuthProviderResult result; + AuthProvider provider = server.config.authProvider[auth_id]; + Client clientData = server.sessionManager.getClient(session); + try { + if (server.limiter.isLimit(ip)) { + AuthProvider.authError(server.config.authRejectString); + return; + } + result = provider.auth(login, password, ip); + if (!VerifyHelper.isValidUsername(result.username)) { + AuthProvider.authError(String.format("Illegal result: '%s'", result.username)); + return; + } + Collection> profiles = server.getProfiles(); + for (SignedObjectHolder p : profiles) { + if (p.object.getTitle().equals(client)) { + if (!p.object.isWhitelistContains(login)) { + throw new AuthException(server.config.whitelistRejectString); + } + clientData.profile = p.object; + } + } + if(clientData.profile == null) { + throw new AuthException("You profile not found"); + } + clientData.type = Client.Type.SERVER; + } catch (AuthException | HWIDException e) { + requestError(e.getMessage()); + return; + } catch (Exception e) { + LogHelper.error(e); + requestError("Internal auth provider error"); + return; + } + debug("ServerAuth: '%s' -> '%s', '%s'", login, result.username, result.accessToken); + clientData.isAuth = true; + } +} 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 ab464f96..f49919c9 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/socket/Client.java @@ -1,16 +1,28 @@ package ru.gravit.launchserver.socket; +import ru.gravit.launcher.profiles.ClientProfile; + public class Client { public long session; public long timestamp; + public Type type; + public ClientProfile profile; + public boolean isAuth; public Client(long session) { this.session = session; timestamp = System.currentTimeMillis(); + type = Type.USER; + isAuth = false; } - + //Данные ваторизации public void up() { timestamp = System.currentTimeMillis(); } + public enum Type + { + SERVER, + USER + } } diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/ServerAuthRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/ServerAuthRequest.java new file mode 100644 index 00000000..b9a0d8cc --- /dev/null +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/ServerAuthRequest.java @@ -0,0 +1,80 @@ +package ru.gravit.launcher.request.auth; + +import ru.gravit.launcher.Launcher; +import ru.gravit.launcher.LauncherAPI; +import ru.gravit.launcher.LauncherConfig; +import ru.gravit.launcher.profiles.PlayerProfile; +import ru.gravit.launcher.request.Request; +import ru.gravit.launcher.request.RequestType; +import ru.gravit.launcher.serialize.HInput; +import ru.gravit.launcher.serialize.HOutput; +import ru.gravit.launcher.serialize.SerializeLimits; +import ru.gravit.utils.helper.JVMHelper; +import ru.gravit.utils.helper.SecurityHelper; +import ru.gravit.utils.helper.VerifyHelper; +import ru.zaxar163.GuardBind; + +import java.io.IOException; + +public final class ServerAuthRequest extends Request { + public static final class Result { + @LauncherAPI + public final PlayerProfile pp; + @LauncherAPI + public final String accessToken; + + private Result(PlayerProfile pp, String accessToken) { + this.pp = pp; + this.accessToken = accessToken; + } + } + + private final String login; + + private final byte[] encryptedPassword; + private final int auth_id; + + @LauncherAPI + public ServerAuthRequest(LauncherConfig config, String login, byte[] encryptedPassword) { + super(config); + this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty"); + this.encryptedPassword = encryptedPassword.clone(); + auth_id = 0; + } + @LauncherAPI + public ServerAuthRequest(LauncherConfig config, String login, byte[] encryptedPassword, int auth_id) { + super(config); + this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty"); + this.encryptedPassword = encryptedPassword.clone(); + this.auth_id = auth_id; + } + + @LauncherAPI + public ServerAuthRequest(String login, byte[] encryptedPassword) { + this(null, login, encryptedPassword); + } + @LauncherAPI + public ServerAuthRequest(String login, byte[] encryptedPassword, int auth_id) { + this(null, login, encryptedPassword,auth_id); + } + + @Override + public Integer getType() { + return RequestType.SERVERAUTH.getNumber(); + } + + @Override + protected Result requestDo(HInput input, HOutput output) throws IOException { + output.writeString(login, SerializeLimits.MAX_LOGIN); + output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT); + output.writeInt(auth_id); + output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH); + output.flush(); + + // Read UUID and access token + readError(input); + PlayerProfile pp = new PlayerProfile(input); + String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH); + return new Result(pp, accessToken); + } +} diff --git a/libLauncher/src/main/java/ru/gravit/launcher/request/RequestType.java b/libLauncher/src/main/java/ru/gravit/launcher/request/RequestType.java index f14555bb..e664b73b 100644 --- a/libLauncher/src/main/java/ru/gravit/launcher/request/RequestType.java +++ b/libLauncher/src/main/java/ru/gravit/launcher/request/RequestType.java @@ -11,7 +11,7 @@ public enum RequestType implements EnumSerializer.Itf { LAUNCHER(1), UPDATE(2), UPDATE_LIST(3), // Update requests AUTH(4), JOIN_SERVER(5), CHECK_SERVER(6), // Auth requests PROFILE_BY_USERNAME(7), PROFILE_BY_UUID(8), BATCH_PROFILE_BY_USERNAME(9), // Profile requests - PROFILES(10), + PROFILES(10),SERVERAUTH(11), CUSTOM(255); // Custom requests private static final EnumSerializer SERIALIZER = new EnumSerializer<>(RequestType.class);