diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index 97619788..7e2d6a76 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -278,11 +278,11 @@ public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception { verifyArgs(args, 1); AuthProviderPair pair = config.getAuthProviderPair(args[0]); - if(pair == null) { + if (pair == null) { logger.error("Pair not found"); return; } - if(pair.isUseCore()){ + if (pair.isUseCore()) { pair.core.close(); } else { pair.provider.close(); @@ -293,7 +293,8 @@ public void invoke(String... args) throws Exception { pair.core = new RejectAuthCoreProvider(); pair.core.init(instance); } - };commands.put("resetauth", resetauth); + }; + commands.put("resetauth", resetauth); return commands; } @@ -394,7 +395,7 @@ public void run() { modulesManager.invokeEvent(new LaunchServerFullInitEvent(this)); logger.info("LaunchServer started"); } catch (Throwable e) { - logger.error("LaunchServer startup failed",e); + logger.error("LaunchServer startup failed", e); JVMHelper.RUNTIME.exit(-1); } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java index 6859b40f..e9b9609b 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java @@ -46,6 +46,29 @@ public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social, Textur this.textureProvider = textureProvider; } + public static Set getFeatures(Class clazz) { + Set list = new HashSet<>(); + getFeatures(clazz, list); + return list; + } + + public static void getFeatures(Class clazz, Set list) { + Features features = clazz.getAnnotation(Features.class); + if (features != null) { + for (Feature feature : features.value()) { + list.add(feature.value()); + } + } + Class superClass = clazz.getSuperclass(); + if (superClass != null && superClass != Object.class) { + getFeatures(superClass, list); + } + Class[] interfaces = clazz.getInterfaces(); + for (Class i : interfaces) { + getFeatures(i, list); + } + } + public final T isSupport(Class clazz) { if (core == null) return null; T result = null; @@ -118,29 +141,6 @@ public final void close() throws IOException { } } - public static Set getFeatures(Class clazz) { - Set list = new HashSet<>(); - getFeatures(clazz, list); - return list; - } - - public static void getFeatures(Class clazz, Set list) { - Features features = clazz.getAnnotation(Features.class); - if (features != null) { - for (Feature feature : features.value()) { - list.add(feature.value()); - } - } - Class superClass = clazz.getSuperclass(); - if (superClass != null && superClass != Object.class) { - getFeatures(superClass, list); - } - Class[] interfaces = clazz.getInterfaces(); - for (Class i : interfaces) { - getFeatures(i, list); - } - } - public final boolean isUseCore() { return core != null; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthSocialProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthSocialProvider.java index 63a59955..7897bbc0 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthSocialProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthSocialProvider.java @@ -24,6 +24,21 @@ public static void registerProviders() { } } + public abstract void init(LaunchServer server, AuthCoreProvider provider); + + public abstract List getDetails(Client client); + + public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException; + + @SuppressWarnings("unchecked") + public T isSupport(Class clazz) { + if (clazz.isAssignableFrom(getClass())) return (T) this; + return null; + } + + @Override + public abstract void close() throws IOException; + public static class SocialResult { public String login; public AuthRequest.AuthPasswordInterface password; @@ -43,19 +58,4 @@ public static SocialResult ofUser(User user) { return new SocialResult(null, null, user); } } - - public abstract void init(LaunchServer server, AuthCoreProvider provider); - - public abstract List getDetails(Client client); - - public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException; - - @SuppressWarnings("unchecked") - public T isSupport(Class clazz) { - if (clazz.isAssignableFrom(getClass())) return (T) this; - return null; - } - - @Override - public abstract void close() throws IOException; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/JsonCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/JsonCoreProvider.java index 8fe0d1e9..50a875df 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/JsonCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/JsonCoreProvider.java @@ -41,6 +41,140 @@ public class JsonCoreProvider extends AuthCoreProvider { public PasswordVerifier passwordVerifier; private transient HttpClient client; + public static R jsonRequest(T request, String url, String bearerToken, Class clazz, HttpClient client) { + HttpRequest.BodyPublisher publisher; + if (request != null) { + publisher = HttpRequest.BodyPublishers.ofString(request.toString()); + } else { + publisher = HttpRequest.BodyPublishers.noBody(); + } + try { + HttpRequest.Builder request1 = HttpRequest.newBuilder() + .method("POST", publisher) + .uri(new URI(url)) + .header("Content-Type", "application/json; charset=UTF-8") + .header("Accept", "application/json") + .timeout(Duration.ofMillis(10000)); + if (bearerToken != null) { + request1.header("Authentication", "Bearer ".concat(bearerToken)); + } + HttpResponse response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream()); + int statusCode = response.statusCode(); + if (200 > statusCode || statusCode > 300) { + if (statusCode >= 500) { + logger.error("JsonCoreProvider: {} return {}", url, statusCode); + } else if (statusCode >= 300 && statusCode <= 400) { + logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown")); + } else if (statusCode == 403 || statusCode == 401) { + logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode); + } + return null; + } + try (Reader reader = new InputStreamReader(response.body())) { + return Launcher.gsonManager.gson.fromJson(reader, clazz); + } + } catch (Exception e) { + return null; + } + } + + @Override + public User getUserByUsername(String username) { + return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class); + } + + @Override + public User getUserByLogin(String login) { + if (getUserByLoginUrl != null) { + return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class); + } + return super.getUserByLogin(login); + } + + @Override + public User getUserByUUID(UUID uuid) { + return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class); + } + + @Override + public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired { + if (getUserSessionByOAuthAccessTokenUrl == null) { + return null; + } + JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class); + if (response == null) return null; + if (!response.expired) throw new OAuthAccessTokenExpired(); + return response.session; + } + + @Override + public List getDetails(Client client) { + if (getAuthDetailsUrl != null) { + JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class); + if (response == null) return super.getDetails(client); + return response.details; + } + return super.getDetails(client); + } + + @Override + public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) { + JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class); + return response == null ? null : response.toAuthReport(); + } + + @Override + public void verifyAuth(AuthResponse.AuthContext context) throws AuthException { + + } + + @Override + public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) { + JsonUser jsonUser = (JsonUser) user; + if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) { + if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) { + return PasswordVerifyReport.OK; + } else { + return PasswordVerifyReport.FAILED; + } + } + if (user == null) { + return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class); + } + return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class); + } + + @Override + public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException { + JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class); + if (response == null) return null; + if (response.error != null) throw new AuthException(response.error); + JsonUser user1 = (JsonUser) user; + user1.accessToken = response.minecraftAccessToken; + return response.toAuthReport(); + } + + @Override + public void init(LaunchServer server) { + client = HttpClient.newBuilder().build(); + } + + @Override + protected boolean updateServerID(User user, String serverID) throws IOException { + JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class); + if (successResponse == null) return false; + return successResponse.success; + } + + @Override + public void close() throws IOException { + + } + + public R jsonRequest(T request, String url, Class clazz) { + return jsonRequest(request, url, bearerToken, clazz, client); + } + public static class JsonGetUserByUsername { public String username; @@ -142,99 +276,6 @@ public static class JsonGetDetailsResponse { public List details; } - @Override - public User getUserByUsername(String username) { - return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class); - } - - @Override - public User getUserByLogin(String login) { - if (getUserByLoginUrl != null) { - return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class); - } - return super.getUserByLogin(login); - } - - @Override - public User getUserByUUID(UUID uuid) { - return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class); - } - - @Override - public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired { - if (getUserSessionByOAuthAccessTokenUrl == null) { - return null; - } - JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class); - if (response == null) return null; - if (!response.expired) throw new OAuthAccessTokenExpired(); - return response.session; - } - - @Override - public List getDetails(Client client) { - if (getAuthDetailsUrl != null) { - JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class); - if (response == null) return super.getDetails(client); - return response.details; - } - return super.getDetails(client); - } - - @Override - public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) { - JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class); - return response == null ? null : response.toAuthReport(); - } - - @Override - public void verifyAuth(AuthResponse.AuthContext context) throws AuthException { - - } - - @Override - public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) { - JsonUser jsonUser = (JsonUser) user; - if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) { - if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) { - return PasswordVerifyReport.OK; - } else { - return PasswordVerifyReport.FAILED; - } - } - if (user == null) { - return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class); - } - return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class); - } - - @Override - public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException { - JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class); - if (response == null) return null; - if (response.error != null) throw new AuthException(response.error); - JsonUser user1 = (JsonUser) user; - user1.accessToken = response.minecraftAccessToken; - return response.toAuthReport(); - } - - @Override - public void init(LaunchServer server) { - client = HttpClient.newBuilder().build(); - } - - @Override - protected boolean updateServerID(User user, String serverID) throws IOException { - JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class); - if (successResponse == null) return false; - return successResponse.success; - } - - @Override - public void close() throws IOException { - - } - public static class JsonUser implements User { private String username; private UUID uuid; @@ -319,45 +360,4 @@ public String toString() { '}'; } } - - public R jsonRequest(T request, String url, Class clazz) { - return jsonRequest(request, url, bearerToken, clazz, client); - } - - public static R jsonRequest(T request, String url, String bearerToken, Class clazz, HttpClient client) { - HttpRequest.BodyPublisher publisher; - if (request != null) { - publisher = HttpRequest.BodyPublishers.ofString(request.toString()); - } else { - publisher = HttpRequest.BodyPublishers.noBody(); - } - try { - HttpRequest.Builder request1 = HttpRequest.newBuilder() - .method("POST", publisher) - .uri(new URI(url)) - .header("Content-Type", "application/json; charset=UTF-8") - .header("Accept", "application/json") - .timeout(Duration.ofMillis(10000)); - if (bearerToken != null) { - request1.header("Authentication", "Bearer ".concat(bearerToken)); - } - HttpResponse response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream()); - int statusCode = response.statusCode(); - if (200 > statusCode || statusCode > 300) { - if (statusCode >= 500) { - logger.error("JsonCoreProvider: {} return {}", url, statusCode); - } else if (statusCode >= 300 && statusCode <= 400) { - logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown")); - } else if (statusCode == 403 || statusCode == 401) { - logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode); - } - return null; - } - try (Reader reader = new InputStreamReader(response.body())) { - return Launcher.gsonManager.gson.fromJson(reader, clazz); - } - } catch (Exception e) { - return null; - } - } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java index 638dc91f..4d53b5cc 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java @@ -41,6 +41,13 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa public String tableHWID = "hwids"; public String tableHWIDLog = "hwidLog"; + public PasswordVerifier passwordVerifier; + public double criticalCompareLevel = 1.0; + public String customQueryByUUIDSQL; + public String customQueryByUsernameSQL; + public String customQueryByLoginSQL; + public String customUpdateAuthSQL; + public String customUpdateServerIdSQL; private transient String sqlFindHardwareByPublicKey; private transient String sqlFindHardwareByData; private transient String sqlFindHardwareById; @@ -50,10 +57,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa private transient String sqlUpdateHardwareBanned; private transient String sqlUpdateUsers; private transient String sqlUsersByHwidId; - - public PasswordVerifier passwordVerifier; - public double criticalCompareLevel = 1.0; - // Prepared SQL queries private transient String queryByUUIDSQL; private transient String queryByUsernameSQL; @@ -61,12 +64,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa private transient String updateAuthSQL; private transient String updateServerIDSQL; - public String customQueryByUUIDSQL; - public String customQueryByUsernameSQL; - public String customQueryByLoginSQL; - public String customUpdateAuthSQL; - public String customUpdateServerIdSQL; - @Override public User getUserByUsername(String username) { try { @@ -154,16 +151,20 @@ public void init(LaunchServer server) { updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1", table, serverIDColumn, uuidColumn); String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey"; - if(sqlFindHardwareByPublicKey == null) sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID); - if(sqlFindHardwareById == null) sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID); - if(sqlUsersByHwidId == null) sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn); + if (sqlFindHardwareByPublicKey == null) + sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID); + if (sqlFindHardwareById == null) + sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID); + if (sqlUsersByHwidId == null) + sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn); if (sqlFindHardwareByData == null) sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID); if (sqlCreateHardware == null) sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID); if (sqlCreateHWIDLog == null) sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog); - if(sqlUpdateHardwarePublicKey == null) sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID); + if (sqlUpdateHardwarePublicKey == null) + sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID); sqlUpdateHardwareBanned = String.format("UPDATE %s SET `banned` = ? WHERE `id` = ?", tableHWID); sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn); } @@ -405,6 +406,50 @@ public void unbanHardware(UserHardware hardware) { } } + public static class MySQLUserHardware implements UserHardware { + private final HardwareReportRequest.HardwareInfo hardwareInfo; + private final long id; + private byte[] publicKey; + private boolean banned; + + public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) { + this.hardwareInfo = hardwareInfo; + this.publicKey = publicKey; + this.id = id; + this.banned = banned; + } + + @Override + public HardwareReportRequest.HardwareInfo getHardwareInfo() { + return hardwareInfo; + } + + @Override + public byte[] getPublicKey() { + return publicKey; + } + + @Override + public String getId() { + return String.valueOf(id); + } + + @Override + public boolean isBanned() { + return banned; + } + + @Override + public String toString() { + return "MySQLUserHardware{" + + "hardwareInfo=" + hardwareInfo + + ", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) + + ", id=" + id + + ", banned=" + banned + + '}'; + } + } + public class MySQLUser implements User, UserSupportHardware { protected UUID uuid; protected String username; @@ -468,48 +513,4 @@ public String toString() { '}'; } } - - public static class MySQLUserHardware implements UserHardware { - private final HardwareReportRequest.HardwareInfo hardwareInfo; - private byte[] publicKey; - private final long id; - private boolean banned; - - public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) { - this.hardwareInfo = hardwareInfo; - this.publicKey = publicKey; - this.id = id; - this.banned = banned; - } - - @Override - public HardwareReportRequest.HardwareInfo getHardwareInfo() { - return hardwareInfo; - } - - @Override - public byte[] getPublicKey() { - return publicKey; - } - - @Override - public String getId() { - return String.valueOf(id); - } - - @Override - public boolean isBanned() { - return banned; - } - - @Override - public String toString() { - return "MySQLUserHardware{" + - "hardwareInfo=" + hardwareInfo + - ", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) + - ", id=" + id + - ", banned=" + banned + - '}'; - } - } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/user/UserSupportBanInfo.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/user/UserSupportBanInfo.java index 60f4ad36..77899389 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/user/UserSupportBanInfo.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/user/UserSupportBanInfo.java @@ -3,6 +3,8 @@ import java.time.LocalDateTime; public interface UserSupportBanInfo { + UserBanInfo getBanInfo(); + interface UserBanInfo { String getId(); @@ -22,6 +24,4 @@ default LocalDateTime getEndDate() { return null; } } - - UserBanInfo getBanInfo(); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DigestPasswordVerifier.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DigestPasswordVerifier.java index a5546763..1fe50c32 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DigestPasswordVerifier.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DigestPasswordVerifier.java @@ -2,9 +2,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.SecurityHelper; -import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -15,7 +15,7 @@ public class DigestPasswordVerifier extends PasswordVerifier { private byte[] digest(String text) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance(algo); - return digest.digest(text.getBytes(StandardCharsets.UTF_8)); + return digest.digest(IOHelper.encode(text)); } @Override diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DoubleDigestPasswordVerifier.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DoubleDigestPasswordVerifier.java index 7f72e773..c715a4af 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DoubleDigestPasswordVerifier.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/DoubleDigestPasswordVerifier.java @@ -2,9 +2,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.SecurityHelper; -import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -16,8 +16,8 @@ public class DoubleDigestPasswordVerifier extends PasswordVerifier { private byte[] digest(String text) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance(algo); - byte[] firstDigest = digest.digest(text.getBytes(StandardCharsets.UTF_8)); - return toHexMode ? digest.digest(SecurityHelper.toHex(firstDigest).getBytes(StandardCharsets.UTF_8)) : digest.digest(firstDigest); + byte[] firstDigest = digest.digest(IOHelper.encode(text)); + return toHexMode ? digest.digest(IOHelper.encode(SecurityHelper.toHex(firstDigest))) : digest.digest(firstDigest); } @Override diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/JsonPasswordVerifier.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/JsonPasswordVerifier.java index 35aa8624..d712fd10 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/JsonPasswordVerifier.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/password/JsonPasswordVerifier.java @@ -5,9 +5,18 @@ import java.net.http.HttpClient; public class JsonPasswordVerifier extends PasswordVerifier { + private transient final HttpClient client = HttpClient.newBuilder().build(); public String url; public String bearerToken; - private transient final HttpClient client = HttpClient.newBuilder().build(); + + @Override + public boolean check(String encryptedPassword, String password) { + JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client); + if (response != null) { + return response.success; + } + return false; + } public static class JsonPasswordRequest { public String encryptedPassword; @@ -22,13 +31,4 @@ public JsonPasswordRequest(String encryptedPassword, String password) { public static class JsonPasswordResponse { public boolean success; } - - @Override - public boolean check(String encryptedPassword, String password) { - JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client); - if (response != null) { - return response.success; - } - return false; - } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/BuildContext.java b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/BuildContext.java index 69b042ab..cbe7228f 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/binary/BuildContext.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/binary/BuildContext.java @@ -14,6 +14,7 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -37,7 +38,6 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; -import static pro.gravit.utils.helper.IOHelper.UNICODE_CHARSET; import static pro.gravit.utils.helper.IOHelper.newZipEntry; public class BuildContext { @@ -72,8 +72,14 @@ public void pushFile(String filename, StreamObject object) throws IOException { } public void pushFile(String filename, Object object, Type type) throws IOException { - String bytes = Launcher.gsonManager.gson.toJson(object, type); - pushBytes(filename, bytes.getBytes(UNICODE_CHARSET)); + ZipEntry zip = IOHelper.newZipEntry(filename); + output.putNextEntry(zip); + try (BufferedWriter w = IOHelper.newWriter(IOHelper.nonClosing(output))) { + Launcher.gsonManager.gson.toJson(object, type); + } + output.closeEntry(); + fileList.add(filename); + pushBytes(filename, IOHelper.encode(Launcher.gsonManager.gson.toJson(object, type))); } public void pushDir(Path dir, String targetDir, Map hashMap, boolean hidden) throws IOException { @@ -211,7 +217,7 @@ private EncryptedRuntimeDirVisitor(ZipOutputStream output, String aesKey, Map 2) pair = server.config.getAuthProviderPair(args[2]); else pair = server.config.getAuthProviderPair(); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); - if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); + if (pair.isUseCore()) + throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); String login = args[0]; String password = args[1]; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UUIDToUsernameCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UUIDToUsernameCommand.java index 76eee274..3e210f82 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UUIDToUsernameCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UUIDToUsernameCommand.java @@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException { if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]); else pair = server.config.getAuthProviderPair(); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); - if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); + if (pair.isUseCore()) + throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); UUID uuid = parseUUID(args[0]); // Get UUID by username diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UsernameToUUIDCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UsernameToUUIDCommand.java index ac9b1517..4d16f54f 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UsernameToUUIDCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/auth/UsernameToUUIDCommand.java @@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException { if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]); else pair = server.config.getAuthProviderPair(); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); - if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); + if (pair.isUseCore()) + throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); String username = parseUsername(args[0]); // Get UUID by username diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java index 218b597b..47455d21 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java @@ -78,7 +78,7 @@ public void invoke(String... args) { } else { printCheckResult(String.format("auth.%s.handler", name), "", true); } - if(!pair.isUseCore()) { + if (!pair.isUseCore()) { printCheckResult(String.format("auth.%s", name), "AuthProvider/AuthHandler may be removed in future release", null); } }); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/WhitelistComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/WhitelistComponent.java index 7d7ca533..20d69a21 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/WhitelistComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/WhitelistComponent.java @@ -16,11 +16,11 @@ import java.util.Map; public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable { - private transient LaunchServer server; private transient final Logger logger = LogManager.getLogger(); public String message = "auth.message.techwork"; public boolean enabled = true; public List whitelist = new ArrayList<>(); + private transient LaunchServer server; @Override public void init(LaunchServer launchServer) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/helper/MakeProfileHelper.java b/LaunchServer/src/main/java/pro/gravit/launchserver/helper/MakeProfileHelper.java index 7464ebff..bfd05f6a 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/helper/MakeProfileHelper.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/helper/MakeProfileHelper.java @@ -182,6 +182,14 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP return options.toArray(new MakeProfileOption[0]); } + private static Path findFirstDir(Path path) throws IOException { + return Files.list(path).findFirst().orElse(null); + } + + private static Path findFirstMavenFile(Path path) throws IOException { + return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow(); + } + public interface MakeProfileOption { } @@ -192,11 +200,6 @@ public static class MakeProfileOptionForge implements MakeProfileOption { public String minecraftVersion; public String mcpVersion; - public List makeClientArgs() { - if (launchTarget == null) return List.of(); - return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion); - } - public MakeProfileOptionForge() { } @@ -230,14 +233,11 @@ public MakeProfileOptionForge(Path clientDir) throws IOException { String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-"); mcpVersion = minecraftFullVersion[1]; } - } - private static Path findFirstDir(Path path) throws IOException { - return Files.list(path).findFirst().orElse(null); - } - - private static Path findFirstMavenFile(Path path) throws IOException { - return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow(); + public List makeClientArgs() { + if (launchTarget == null) return List.of(); + return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion); + } } public static class MakeProfileOptionLaunchWrapper implements MakeProfileOption { @@ -248,11 +248,6 @@ public static class MakeProfileOptionFabric implements MakeProfileOption { public String jimfsPath; public String guavaPath; - public List getAltClassPath() { - if (jimfsPath == null || guavaPath == null) return List.of(); - return List.of(jimfsPath, guavaPath); - } - public MakeProfileOptionFabric() { } @@ -267,6 +262,11 @@ public MakeProfileOptionFabric(Path clientDir) throws IOException { guavaPath = clientDir.relativize(findFirstMavenFile(clientDir.resolve("libraries/com/google/guava/guava/"))).toString(); } } + + public List getAltClassPath() { + if (jimfsPath == null || guavaPath == null) return List.of(); + return List.of(jimfsPath, guavaPath); + } } public static class MakeProfileOptionLiteLoader implements MakeProfileOption { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java index 11e4b684..81eece80 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java @@ -210,26 +210,6 @@ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, Auth } } - public static class CheckServerReport { - public UUID uuid; - public User user; - public PlayerProfile playerProfile; - - public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) { - this.uuid = uuid; - this.user = user; - this.playerProfile = playerProfile; - } - - public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) { - return new CheckServerReport(user.getUUID(), user, playerProfile); - } - - public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) { - return new CheckServerReport(uuid, null, playerProfile); - } - } - public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException { if (client.auth == null) return null; if (client.auth.isUseCore()) { @@ -397,6 +377,26 @@ private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.Au return password; } + public static class CheckServerReport { + public UUID uuid; + public User user; + public PlayerProfile playerProfile; + + public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) { + this.uuid = uuid; + this.user = user; + this.playerProfile = playerProfile; + } + + public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) { + return new CheckServerReport(user.getUUID(), user, playerProfile); + } + + public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) { + return new CheckServerReport(uuid, null, playerProfile); + } + } + public static class AuthReport { public final String minecraftAccessToken; public final String oauthAccessToken; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java index e811c094..13aede51 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java @@ -6,8 +6,8 @@ import pro.gravit.launchserver.auth.RequiredDAO; import pro.gravit.launchserver.socket.Client; import pro.gravit.utils.HookSet; +import pro.gravit.utils.helper.IOHelper; -import java.nio.charset.StandardCharsets; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -46,11 +46,11 @@ public void clear() { } private byte[] compressClient(Client client) { - return Launcher.gsonManager.gson.toJson(client).getBytes(StandardCharsets.UTF_8); //Compress using later + return IOHelper.encode(Launcher.gsonManager.gson.toJson(client)); //Compress using later } private Client decompressClient(byte[] client) { - return Launcher.gsonManager.gson.fromJson(new String(client, StandardCharsets.UTF_8), Client.class); //Compress using later + return Launcher.gsonManager.gson.fromJson(IOHelper.decode(client), Client.class); //Compress using later } @SuppressWarnings("deprecation") diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/UpdatesManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/UpdatesManager.java index 052c5601..47e9f4f6 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/UpdatesManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/UpdatesManager.java @@ -19,8 +19,8 @@ public class UpdatesManager { private final LaunchServer server; private final Logger logger = LogManager.getLogger(); - private volatile Map updatesDirMap; private final Path cacheFile; + private volatile Map updatesDirMap; public UpdatesManager(LaunchServer server) { this.server = server; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/handlers/NettyWebAPIHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/handlers/NettyWebAPIHandler.java index 2c0a9513..33f49a64 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/handlers/NettyWebAPIHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/handlers/NettyWebAPIHandler.java @@ -9,6 +9,7 @@ import org.apache.logging.log4j.Logger; import pro.gravit.launcher.Launcher; import pro.gravit.launchserver.socket.NettyConnectContext; +import pro.gravit.utils.helper.IOHelper; import java.net.URLDecoder; import java.nio.charset.Charset; @@ -21,6 +22,12 @@ public class NettyWebAPIHandler extends SimpleChannelInboundHandler { private static final TreeSet severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length())); + private static final DefaultFullHttpResponse ERROR_500 = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(IOHelper.encode("Internal Server Error 500"))); + + static { + ERROR_500.retain(); + } + private final NettyConnectContext context; private transient final Logger logger = LogManager.getLogger(); @@ -54,7 +61,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro pair.callback.handle(ctx, msg, context); } catch (Throwable e) { logger.error("WebAPI Error", e); - ctx.writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer("Internal Server Error 500".getBytes())), ctx.voidPromise()); + ctx.writeAndFlush(ERROR_500, ctx.voidPromise()); } isNext = false; break; @@ -92,11 +99,11 @@ default Map getParamsFromUri(String uri) { } default FullHttpResponse simpleResponse(HttpResponseStatus status, String body) { - return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(body.getBytes()) : Unpooled.buffer()); + return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(body)) : Unpooled.buffer()); } default FullHttpResponse simpleJsonResponse(HttpResponseStatus status, Object body) { - DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(Launcher.gsonManager.gson.toJson(body).getBytes()) : Unpooled.buffer()); + DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(Launcher.gsonManager.gson.toJson(body))) : Unpooled.buffer()); httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON); return httpResponse; } diff --git a/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java b/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java index 325412c7..4421bc4f 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java +++ b/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java @@ -17,16 +17,14 @@ public boolean eventHandle(T event) { SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event; if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) { LauncherEngine.exitLauncher(80); - } - else if(event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) { + } else if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) { try { Request.restore(); } catch (Exception e) { LogHelper.error(e); } } - } - else if (event instanceof ExtendedTokenRequestEvent) { + } else if (event instanceof ExtendedTokenRequestEvent) { ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event; String token = event1.getExtendedToken(); if (token != null) { diff --git a/Launcher/src/main/java/pro/gravit/launcher/JSApplication.java b/Launcher/src/main/java/pro/gravit/launcher/JSApplication.java deleted file mode 100644 index 1ba6bca8..00000000 --- a/Launcher/src/main/java/pro/gravit/launcher/JSApplication.java +++ /dev/null @@ -1,19 +0,0 @@ -package pro.gravit.launcher; - -import javafx.application.Application; - -import java.util.concurrent.atomic.AtomicReference; - -@Deprecated -public abstract class JSApplication extends Application { - private static final AtomicReference INSTANCE = new AtomicReference<>(); - - - public JSApplication() { - INSTANCE.set(this); - } - - public static JSApplication getInstance() { - return INSTANCE.get(); - } -} diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 95b3d793..07ae298b 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicBoolean; public class LauncherEngine { - public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false); public static ClientLauncherProcess.ClientParams clientParams; public static LauncherGuardInterface guard; public static ClientModuleManager modulesManager; @@ -133,14 +132,6 @@ public static void verifyNoAgent() { throw new SecurityException("JavaAgent found"); } - public ECPublicKey getClientPublicKey() { - return publicKey; - } - - public byte[] sign(byte[] bytes) { - return SecurityHelper.sign(bytes, privateKey); - } - public static LauncherGuardInterface tryGetStdGuard() { switch (Launcher.getConfig().guardType) { case "no": @@ -159,6 +150,14 @@ public static LauncherEngine newInstance(boolean clientInstance) { return new LauncherEngine(clientInstance); } + public ECPublicKey getClientPublicKey() { + return publicKey; + } + + public byte[] sign(byte[] bytes) { + return SecurityHelper.sign(bytes, privateKey); + } + public void readKeys() throws IOException, InvalidKeySpecException { if (privateKey != null || publicKey != null) return; Path dir = DirBridge.dir; diff --git a/Launcher/src/main/java/pro/gravit/launcher/api/DialogService.java b/Launcher/src/main/java/pro/gravit/launcher/api/DialogService.java index 387c1b9a..edb79984 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/api/DialogService.java +++ b/Launcher/src/main/java/pro/gravit/launcher/api/DialogService.java @@ -12,20 +12,6 @@ private DialogService() { throw new UnsupportedOperationException(); } - public interface DialogServiceImplementation { - void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback); - - void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback); - - void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback); - - void showTextDialog(String header, Consumer onApplyCallback, Runnable onCloseCallback); - } - - public interface DialogServiceNotificationImplementation { - void createNotification(NotificationEvent.NotificationType type, String head, String message); - } - public static void setDialogImpl(DialogServiceImplementation impl) { DialogService.dialogImpl = impl; } @@ -74,4 +60,18 @@ public static void showTextDialog(String header, Consumer onApplyCallbac checkIfAvailable(); dialogImpl.showTextDialog(header, onApplyCallback, onCloseCallback); } + + public interface DialogServiceImplementation { + void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback); + + void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback); + + void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback); + + void showTextDialog(String header, Consumer onApplyCallback, Runnable onCloseCallback); + } + + public interface DialogServiceNotificationImplementation { + void createNotification(NotificationEvent.NotificationType type, String head, String message); + } } diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index 0646f59f..a4101444 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -49,7 +49,7 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre socket.connect(address); try (HInput input = new HInput(socket.getInputStream())) { byte[] serialized = input.readByteArray(0); - ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(new String(serialized, IOHelper.UNICODE_CHARSET), ClientLauncherProcess.ClientParams.class); + ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(IOHelper.decode(serialized), ClientLauncherProcess.ClientParams.class); params.clientHDir = new HashedDir(input); params.assetHDir = new HashedDir(input); boolean isNeedReadJavaDir = input.readBoolean(); @@ -61,7 +61,6 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre } public static void main(String[] args) throws Throwable { - LauncherEngine.IS_CLIENT.set(true); LauncherEngine engine = LauncherEngine.clientInstance(); JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true); EnvHelper.checkDangerousParams(); diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java index ac25b06e..1dbe37ab 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java @@ -221,7 +221,7 @@ public void runWriteParams(SocketAddress address) throws IOException { } Socket socket = serverSocket.accept(); try (HOutput output = new HOutput(socket.getOutputStream())) { - byte[] serializedMainParams = Launcher.gsonManager.gson.toJson(params).getBytes(IOHelper.UNICODE_CHARSET); + byte[] serializedMainParams = IOHelper.encode(Launcher.gsonManager.gson.toJson(params)); output.writeByteArray(serializedMainParams, 0); params.clientHDir.write(output); params.assetHDir.write(output); diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/modules/LauncherModule.java b/LauncherAPI/src/main/java/pro/gravit/launcher/modules/LauncherModule.java index 3e327dd4..20e6b883 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/modules/LauncherModule.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/modules/LauncherModule.java @@ -14,6 +14,7 @@ public abstract class LauncherModule { protected InitStatus initStatus = InitStatus.CREATED; private LauncherModulesContext context; private LauncherTrustManager.CheckClassResult checkResult; + protected LauncherModule() { moduleInfo = new LauncherModuleInfo("UnknownModule"); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java index 0e7cb119..f47d334d 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/optional/triggers/OptionalTrigger.java @@ -6,6 +6,8 @@ public abstract class OptionalTrigger { public static ProviderMap providers = new ProviderMap<>("OptionalTriggers"); private static boolean isRegisteredProviders = false; + public boolean required; + public boolean inverted; public static void registerProviders() { if (!isRegisteredProviders) { @@ -15,9 +17,6 @@ public static void registerProviders() { } } - public boolean required; - public boolean inverted; - protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context); public boolean check(OptionalFile optional, OptionalTriggerContext context) { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java index f059c99f..4eb13f47 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java @@ -17,14 +17,14 @@ import java.util.function.BiConsumer; public abstract class Request implements WebSocketRequest { + private static final List extendedTokenCallbacks = new ArrayList<>(4); + private static final List> oauthChangeHandlers = new ArrayList<>(4); public static StdWebSocketService service; private static UUID session = UUID.randomUUID(); private static AuthRequestEvent.OAuthRequestEvent oauth; private static Map extendedTokens; private static String authId; private static long tokenExpiredTime; - private static final List extendedTokenCallbacks = new ArrayList<>(4); - private static final List> oauthChangeHandlers = new ArrayList<>(4); @LauncherNetworkAPI public final UUID requestUUID = UUID.randomUUID(); private transient final AtomicBoolean started = new AtomicBoolean(false); diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/AsyncDownloader.java b/LauncherCore/src/main/java/pro/gravit/launcher/AsyncDownloader.java index 6b02b960..f7ff77fa 100644 --- a/LauncherCore/src/main/java/pro/gravit/launcher/AsyncDownloader.java +++ b/LauncherCore/src/main/java/pro/gravit/launcher/AsyncDownloader.java @@ -42,6 +42,20 @@ public AsyncDownloader() { callback = IGNORE; } + public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException { + if (sslSocketFactory != null) return sslSocketFactory; + SSLContext sslContext = makeSSLContext(); + sslSocketFactory = sslContext.getSocketFactory(); + return sslSocketFactory; + } + + public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException { + if (sslContext != null) return sslContext; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom()); + return sslContext; + } + public void downloadFile(URL url, Path target, long size) throws IOException { if (isClosed) throw new IOException("Download interrupted"); URLConnection connection = url.openConnection(); @@ -73,20 +87,6 @@ public void downloadFile(URL url, Path target) throws IOException { } } - public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException { - if (sslSocketFactory != null) return sslSocketFactory; - SSLContext sslContext = makeSSLContext(); - sslSocketFactory = sslContext.getSocketFactory(); - return sslSocketFactory; - } - - public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException { - if (sslContext != null) return sslContext; - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom()); - return sslContext; - } - public void downloadListInOneThread(List files, String baseURL, Path targetDir) throws URISyntaxException, IOException { URI baseUri = new URI(baseURL); String scheme = baseUri.getScheme(); diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Downloader.java b/LauncherCore/src/main/java/pro/gravit/utils/Downloader.java index 5bfa4e13..b36da07f 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Downloader.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Downloader.java @@ -10,32 +10,13 @@ import java.util.concurrent.Executors; public class Downloader { - public interface DownloadCallback { - void apply(long fullDiff); - - void onComplete(Path path); - } - private final CompletableFuture future; private final AsyncDownloader asyncDownloader; - private Downloader(CompletableFuture future, AsyncDownloader downloader) { this.future = future; this.asyncDownloader = downloader; } - public CompletableFuture getFuture() { - return future; - } - - public void cancel() { - this.asyncDownloader.isClosed = true; - } - - public boolean isCanceled() { - return this.asyncDownloader.isClosed; - } - public static Downloader downloadList(List files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { final boolean closeExecutor; LogHelper.info("Download with legacy mode"); @@ -60,4 +41,22 @@ public static Downloader downloadList(List files, Str } }), asyncDownloader); } + + public CompletableFuture getFuture() { + return future; + } + + public void cancel() { + this.asyncDownloader.isClosed = true; + } + + public boolean isCanceled() { + return this.asyncDownloader.isClosed; + } + + public interface DownloadCallback { + void apply(long fullDiff); + + void onComplete(Path path); + } } diff --git a/LauncherCore/src/main/java/pro/gravit/utils/helper/IOHelper.java b/LauncherCore/src/main/java/pro/gravit/utils/helper/IOHelper.java index b465b44d..313945d3 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/helper/IOHelper.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/helper/IOHelper.java @@ -589,6 +589,29 @@ public static void write(Path file, byte[] bytes) throws IOException { Files.write(file, bytes, WRITE_OPTIONS); } + public static InputStream nonClosing(InputStream in) { + return new FilterInputStream(in) { + @Override + public void close() { + // ignore + } + }; + } + + public static OutputStream nonClosing(OutputStream out) { + return new FilterOutputStream(out) { + @Override + public void write(byte[] b, int offset, int len) throws IOException { + super.out.write(b, offset, len); + } + + @Override + public void close() { + // ignore + } + }; + } + private static class MoveFileVisitor implements FileVisitor { private final Path from, to; diff --git a/LauncherCore/src/main/java11/pro/gravit/utils/Downloader.java b/LauncherCore/src/main/java11/pro/gravit/utils/Downloader.java index 91137902..44dcc17a 100644 --- a/LauncherCore/src/main/java11/pro/gravit/utils/Downloader.java +++ b/LauncherCore/src/main/java11/pro/gravit/utils/Downloader.java @@ -26,41 +26,15 @@ public class Downloader { private static boolean isCertificatePinning; @LauncherInject("launcher.noHttp2") private static boolean isNoHttp2; - - public interface DownloadCallback { - void apply(long fullDiff); - - void onComplete(Path path); - } - protected final HttpClient client; protected final ExecutorService executor; - protected CompletableFuture future; protected final LinkedList tasks = new LinkedList<>(); - + protected CompletableFuture future; protected Downloader(HttpClient client, ExecutorService executor) { this.client = client; this.executor = executor; } - public void cancel() { - for (DownloadTask task : tasks) { - if (!task.isCompleted()) { - task.cancel(); - } - } - tasks.clear(); - executor.shutdownNow(); - } - - public boolean isCanceled() { - return executor.isTerminated(); - } - - public CompletableFuture getFuture() { - return future; - } - public static Downloader downloadList(List files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { boolean closeExecutor = false; LogHelper.info("Download with Java 11+ HttpClient"); @@ -96,8 +70,22 @@ public static Downloader newDownloader(ExecutorService executor) { return new Downloader(client, executor); } - private static class ConsumerObject { - Consumer> next = null; + public void cancel() { + for (DownloadTask task : tasks) { + if (!task.isCompleted()) { + task.cancel(); + } + } + tasks.clear(); + executor.shutdownNow(); + } + + public boolean isCanceled() { + return executor.isTerminated(); + } + + public CompletableFuture getFuture() { + return future; } public CompletableFuture downloadFiles(List files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { @@ -136,24 +124,6 @@ public CompletableFuture downloadFiles(List fil return future; } - public static class DownloadTask { - public final ProgressTrackingBodyHandler bodyHandler; - public final CompletableFuture> completableFuture; - - public DownloadTask(ProgressTrackingBodyHandler bodyHandler, CompletableFuture> completableFuture) { - this.bodyHandler = bodyHandler; - this.completableFuture = completableFuture; - } - - public boolean isCompleted() { - return completableFuture.isDone() | completableFuture.isCompletedExceptionally(); - } - - public void cancel() { - bodyHandler.cancel(); - } - } - protected DownloadTask sendAsync(AsyncDownloader.SizedFile file, URI baseUri, Path targetDir, DownloadCallback callback) throws Exception { IOHelper.createParentDirs(targetDir.resolve(file.filePath)); ProgressTrackingBodyHandler bodyHandler = makeBodyHandler(targetDir.resolve(file.filePath), callback); @@ -187,6 +157,34 @@ protected ProgressTrackingBodyHandler makeBodyHandler(Path file, DownloadC return new ProgressTrackingBodyHandler<>(HttpResponse.BodyHandlers.ofFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE), callback); } + public interface DownloadCallback { + void apply(long fullDiff); + + void onComplete(Path path); + } + + private static class ConsumerObject { + Consumer> next = null; + } + + public static class DownloadTask { + public final ProgressTrackingBodyHandler bodyHandler; + public final CompletableFuture> completableFuture; + + public DownloadTask(ProgressTrackingBodyHandler bodyHandler, CompletableFuture> completableFuture) { + this.bodyHandler = bodyHandler; + this.completableFuture = completableFuture; + } + + public boolean isCompleted() { + return completableFuture.isDone() | completableFuture.isCompletedExceptionally(); + } + + public void cancel() { + bodyHandler.cancel(); + } + } + public static class ProgressTrackingBodyHandler implements HttpResponse.BodyHandler { private final HttpResponse.BodyHandler delegate; private final DownloadCallback callback; diff --git a/README.md b/README.md index 57408216..28b1ee3f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Modification of the launcher sashok724's v3 from Gravit [![Build Status](https://travis-ci.com/GravitLauncher/Launcher.svg?branch=master)](https://travis-ci.com/GravitLauncher/Launcher) + * [Discord channel](https://discord.gg/b9QG4ygY75) * [See license](LICENSE)