diff --git a/.gitmodules b/.gitmodules index f70ed106..8d20570a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "modules"] path = modules url = git@github.com:GravitLauncher/LauncherModules.git +[submodule "Radon"] + path = Radon + url = git@github.com:GravitLauncher/Radon.git diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 0f2209c1..b9527cca 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -3,10 +3,10 @@ repositories { maven { - url "http://maven.geomajas.org/" + url "https://oss.sonatype.org/content/repositories/snapshots" } maven { - url "https://oss.sonatype.org/content/repositories/snapshots" + url "http://maven.geomajas.org/" } } @@ -14,6 +14,7 @@ targetCompatibility = '1.8' configurations { + compileOnlyA bundleOnly bundle hikari @@ -38,8 +39,7 @@ dependencies { pack project(':libLauncher') - bundle 'org.ow2.asm:asm-commons:7.0' - bundle 'org.ow2.asm:asm-util:7.0' + bundle project(':Radon') bundle 'mysql:mysql-connector-java:8.0.13' bundle 'jline:jline:2.14.6' bundle 'net.sf.proguard:proguard-base:6.0.3' @@ -48,7 +48,6 @@ pack project(':libLauncher') bundle 'commons-codec:commons-codec:1.11' bundle 'org.javassist:javassist:3.24.1-GA' bundle 'io.netty:netty-all:4.1.32.Final' - bundle 'org.kohsuke:github-api:1.95' bundle 'org.slf4j:slf4j-simple:1.7.25' bundle 'org.slf4j:slf4j-api:1.7.25' @@ -71,6 +70,9 @@ pack project(':libLauncher') launch4jCJ('net.sf.launch4j:launch4j:3.12:workdir-linux') { exclude group: '*' } + + compileOnlyA 'com.google.guava:guava:26.0-jre' + compileOnlyA 'org.apache.logging.log4j:log4j-core:2.11.2' } task hikari(type: Copy) { @@ -105,7 +107,7 @@ task launch4jA(type: Copy) { } else { fcp.exclude() } - } + } } task dumpLibs(type: Copy) { @@ -114,13 +116,25 @@ task dumpLibs(type: Copy) { from configurations.bundleOnly } +task dumpCompileOnlyLibs(type: Copy) { + into "$buildDir/libs/launcher-libraries-compile" + from configurations.compileOnlyA +} + task bundle(type: Zip) { - dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.jar + dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.jar archiveName 'LaunchServer.zip' destinationDir file("$buildDir") from(tasks.dumpLibs.destinationDir) { into 'libraries' } + from(tasks.dumpCompileOnlyLibs.destinationDir) { into 'launcher-libraries-compile' } from tasks.jar.archivePath from(parent.childProjects.Launcher.tasks.dumpLibs) { into 'launcher-libraries' } } -build.dependsOn tasks.dumpLibs, tasks.bundle +task dumpClientLibs(type: Copy) { + dependsOn parent.childProjects.Launcher.tasks.build + into "$buildDir/libs/launcher-libraries" + from parent.childProjects.Launcher.tasks.dumpLibs.destinationDir +} + +build.dependsOn tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.dumpClientLibs, tasks.bundle diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java index da369875..5c79bffd 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java @@ -10,6 +10,9 @@ import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launchserver.auth.AuthLimiter; import ru.gravit.launchserver.auth.AuthProviderPair; +import ru.gravit.launchserver.auth.protect.NoProtectHandler; +import ru.gravit.launchserver.auth.protect.ProtectHandler; +import ru.gravit.launchserver.components.AuthLimiterComponent; import ru.gravit.launchserver.auth.handler.AuthHandler; import ru.gravit.launchserver.auth.handler.MemoryAuthHandler; import ru.gravit.launchserver.auth.hwid.AcceptHWIDHandler; @@ -19,6 +22,7 @@ import ru.gravit.launchserver.auth.provider.AuthProvider; import ru.gravit.launchserver.auth.provider.RejectAuthProvider; import ru.gravit.launchserver.binary.*; +import ru.gravit.launchserver.components.Component; import ru.gravit.utils.command.CommandHandler; import ru.gravit.utils.command.JLineCommandHandler; import ru.gravit.utils.command.StdCommandHandler; @@ -96,6 +100,9 @@ public AuthProviderPair getAuthProviderPair(String name) } return null; } + public ProtectHandler protectHandler; + + public PermissionsHandler permissionsHandler; public AuthProviderPair getAuthProviderPair() { @@ -115,6 +122,8 @@ public AuthProviderPair getAuthProviderPair() public HWIDHandler hwidHandler; + public HashMap components; + // Misc options public int threadCount; @@ -126,14 +135,6 @@ public AuthProviderPair getAuthProviderPair() public boolean compress; - public int authRateLimit; - - public int authRateLimitMilis; - - public String[] authLimitExclusions; - - public String authRejectString; - public String whitelistRejectString; public boolean genMappings; @@ -142,14 +143,13 @@ public AuthProviderPair getAuthProviderPair() public boolean isWarningMissArchJava; public boolean enabledProGuard; + public boolean enabledRadon; public boolean stripLineNumbers; public boolean deleteTempFiles; public boolean enableRcon; public String startScript; - public boolean updatesNotify = true; // Defaultly to true - public String getAddress() { return address; } @@ -195,6 +195,9 @@ public void verify() { isOneDefault = true; break; } + if(protectHandler == null) + { + throw new NullPointerException("ProtectHandler must not be null"); } if(!isOneDefault) { @@ -294,7 +297,8 @@ public static void main(String... args) throws Throwable { // Start LaunchServer long startTime = System.currentTimeMillis(); try { - LaunchServer launchserver = new LaunchServer(IOHelper.WORKING_DIR, args); + @SuppressWarnings("resource") + LaunchServer launchserver = new LaunchServer(IOHelper.WORKING_DIR, args); if(args.length == 0) launchserver.run(); else { //Обработка команды launchserver.commandHandler.eval(args,false); @@ -313,6 +317,8 @@ public static void main(String... args) throws Throwable { public final Path launcherLibraries; + public final Path launcherLibrariesCompile; + public final List args; public final Path configFile; @@ -341,8 +347,6 @@ public static void main(String... args) throws Throwable { public final LauncherBinary launcherEXEBinary; // HWID ban + anti-brutforce - public final AuthLimiter limiter; - public final SessionManager sessionManager; public final SocketHookManager socketHookManager; @@ -377,7 +381,6 @@ public static void main(String... args) throws Throwable { public volatile Map> updatesDirMap; public final Timer taskPool; - public final Updater updater; public static Gson gson; public static GsonBuilder gsonBuilder; @@ -386,10 +389,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE this.dir = dir; taskPool = new Timer("Timered task worker thread", true); launcherLibraries = dir.resolve("launcher-libraries"); - if (!Files.isDirectory(launcherLibraries)) { - Files.deleteIfExists(launcherLibraries); - Files.createDirectory(launcherLibraries); - } + launcherLibrariesCompile = dir.resolve("launcher-libraries-compile"); this.args = Arrays.asList(args); configFile = dir.resolve("LaunchServer.conf"); publicKeyFile = dir.resolve("public.key"); @@ -404,6 +404,8 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE HWIDHandler.registerHandlers(); PermissionsHandler.registerHandlers(); Response.registerResponses(); + Component.registerComponents(); + ProtectHandler.registerHandlers(); LaunchServer.server = this; // Set command handler @@ -462,10 +464,23 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE for (AuthProviderPair provider : config.auth) { provider.init(); } + if(config.protectHandler != null) + { + config.protectHandler.checkLaunchServerLicense(); + } + config.authHandler.init(); + if(config.components != null) + { + LogHelper.debug("PreInit components"); + config.components.forEach((k,v) -> { + LogHelper.subDebug("PreInit component %s", k); + v.preInit(this); + }); + LogHelper.debug("PreInit components successful"); + } // build hooks, anti-brutforce and other buildHookManager = new BuildHookManager(); - limiter = new AuthLimiter(this); proguardConf = new ProguardConf(this); sessionManager = new SessionManager(); mirrorManager = new MirrorManager(); @@ -474,7 +489,6 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE socketHookManager = new SocketHookManager(); authHookManager = new AuthHookManager(); GarbageManager.registerNeedGC(sessionManager); - GarbageManager.registerNeedGC(limiter); reloadManager.registerReloadable("launchServer", this); if (config.permissionsHandler instanceof Reloadable) reloadManager.registerReloadable("permissionsHandler", (Reloadable) config.permissionsHandler); @@ -506,6 +520,15 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE // init modules modulesManager.initModules(); + if(config.components != null) + { + LogHelper.debug("Init components"); + config.components.forEach((k,v) -> { + LogHelper.subDebug("Init component %s", k); + v.init(this); + }); + LogHelper.debug("Init components successful"); + } // Set launcher EXE binary launcherBinary = new JARLauncherBinary(this); @@ -531,8 +554,16 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE // post init modules modulesManager.postInitModules(); + if(config.components != null) + { + LogHelper.debug("PostInit components"); + config.components.forEach((k,v) -> { + LogHelper.subDebug("PostInit component %s", k); + v.postInit(this); + }); + LogHelper.debug("PostInit components successful"); + } // start updater - this.updater = new Updater(this); if(config.netty != null) nettyServerSocketHandler = new NettyServerSocketHandler(this); else @@ -547,6 +578,8 @@ public static void initGson() { Launcher.gsonBuilder.registerTypeAdapter(AuthHandler.class, new AuthHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); + Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); + Launcher.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter()); Launcher.gson = Launcher.gsonBuilder.create(); //Human readable @@ -557,6 +590,8 @@ public static void initGson() { LaunchServer.gsonBuilder.registerTypeAdapter(AuthHandler.class, new AuthHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); + LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); + LaunchServer.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter()); LaunchServer.gson = LaunchServer.gsonBuilder.create(); } @@ -611,10 +646,10 @@ private void generateConfigIfNotExists() throws IOException { new MemoryAuthHandler(), new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png") , "std") }; + newConfig.protectHandler = new NoProtectHandler(); newConfig.permissionsHandler = new JsonFilePermissionsHandler(); newConfig.port = 7240; newConfig.bindAddress = "0.0.0.0"; - newConfig.authRejectString = "Превышен лимит авторизаций"; newConfig.binaryName = "Launcher"; newConfig.whitelistRejectString = "Вас нет в белом списке"; @@ -626,11 +661,19 @@ private void generateConfigIfNotExists() throws IOException { newConfig.threadCoreCount = 0; // on your own newConfig.threadCount = JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() >= 4 ? JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() / 2 : JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors(); + newConfig.enabledRadon = true; newConfig.enabledProGuard = true; newConfig.stripLineNumbers = true; newConfig.deleteTempFiles = true; newConfig.isWarningMissArchJava = true; + newConfig.components = new HashMap<>(); + AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent(); + authLimiterComponent.rateLimit = 3; + authLimiterComponent.rateLimitMilis = 8000; + authLimiterComponent.message = "Превышен лимит авторизаций"; + newConfig.components.put("authLimiter", authLimiterComponent); + // Set server address System.out.println("LaunchServer address: "); newConfig.setAddress(commandHandler.readLine()); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/Updater.java b/LaunchServer/src/main/java/ru/gravit/launchserver/Updater.java deleted file mode 100644 index a6d57254..00000000 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/Updater.java +++ /dev/null @@ -1,92 +0,0 @@ -package ru.gravit.launchserver; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.Locale; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.kohsuke.github.GHRelease; -import org.kohsuke.github.GHRepository; -import org.kohsuke.github.GitHub; - -import ru.gravit.launcher.Launcher; -import ru.gravit.utils.Version; -import ru.gravit.utils.Version.Type; -import ru.gravit.utils.helper.LogHelper; - -public class Updater extends TimerTask { - private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss", Locale.US); - private static final long period = 1000*3600; - private static final Version VERSION = Launcher.getVersion(); - private final GHRepository gravitLauncher; - private Version parent = VERSION; - - public Updater(LaunchServer srv) { - - GHRepository gravitLauncherTmp = null; - try { - gravitLauncherTmp = GitHub.connectAnonymously().getOrganization("GravitLauncher").getRepository("Launcher"); - } catch (Throwable e) { - LogHelper.error(e); - } - this.gravitLauncher = gravitLauncherTmp; - run(); - if (srv.config.updatesNotify) srv.taskPool.schedule(this, new Date(System.currentTimeMillis()+period), period); - } - - @Override - public void run() { - try { - GHRelease rel = gravitLauncher.getLatestRelease(); - Version relV = parseVer(rel.getTagName()); - if (relV == null) { - LogHelper.debug("Updater: parsing version error."); - return; - } - if (!parent.equals(relV)) parent = relV; - if (VERSION.major >= relV.major && VERSION.minor >= relV.minor - && VERSION.patch >= relV.patch && VERSION.build >= relV.build) return; - if (relV.release.equals(Type.STABLE) || relV.release.equals(Type.LTS)) { - LogHelper.warning("New %s release: %s", relV.getReleaseStatus(), relV.getVersionString()); - LogHelper.warning("You can download it: " + rel.getHtmlUrl().toString()); - LogHelper.warning("It`s published at: " + DATE_TIME_FORMATTER.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(rel.getPublished_at().getTime()), ZoneId.systemDefault()))); - } else { - LogHelper.debug("New %s release: %s", relV.getReleaseStatus(), relV.getVersionString()); - LogHelper.debug("You can download it: " + rel.getHtmlUrl()); - LogHelper.debug("It`s published at: " + DATE_TIME_FORMATTER.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(rel.getPublished_at().getTime()), ZoneId.systemDefault()))); - } - } catch (Throwable e) { - LogHelper.error(e); - } - } - - private static final Pattern startingVerPattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.?\\d*"); - private static final Pattern pointPatternSpltitter = Pattern.compile("\\."); - - private static Version parseVer(String relS) { - Matcher verMatcher = startingVerPattern.matcher(relS); - if (!verMatcher.find()) return VERSION; - String[] ver = pointPatternSpltitter.split(relS.substring(verMatcher.start(), verMatcher.end())); - if (ver.length < 3) return VERSION; - return new Version(Integer.parseInt(ver[0]), Integer.parseInt(ver[1]), - Integer.parseInt(ver[2]), ver.length > 3 ? Integer.parseInt(ver[3]) : 0, findRelType(relS.substring(verMatcher.end()))); - } - - private static Type findRelType(String substring) { - if (substring.isEmpty()) return Type.UNKNOWN; - String tS = substring; - if (tS.startsWith("-")) tS = tS.substring(1); - final String wrk = tS.toLowerCase(Locale.ENGLISH); - final AtomicReference t = new AtomicReference(Type.UNKNOWN); - Type.unModTypes.forEach((s, type) -> { - if (wrk.startsWith(s)) t.set(type); - }); - return t.get(); - } -} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/MySQLAuthHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/MySQLAuthHandler.java index a98811e3..345bd489 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/MySQLAuthHandler.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/handler/MySQLAuthHandler.java @@ -4,6 +4,7 @@ import ru.gravit.utils.helper.LogHelper; import java.io.IOException; +import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -64,8 +65,8 @@ protected Entry fetchEntry(UUID uuid) throws IOException { } private Entry query(String sql, String value) throws IOException { - try { - PreparedStatement s = mySQLHolder.getConnection().prepareStatement(sql); + try(Connection c = mySQLHolder.getConnection()) { + PreparedStatement s = c.prepareStatement(sql); s.setString(1, value); s.setQueryTimeout(MySQLSourceConfig.TIMEOUT); try (ResultSet set = s.executeQuery()) { @@ -78,8 +79,8 @@ private Entry query(String sql, String value) throws IOException { @Override protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException { - try { - PreparedStatement s = mySQLHolder.getConnection().prepareStatement(updateAuthSQL); + try(Connection c = mySQLHolder.getConnection()) { + PreparedStatement s = c.prepareStatement(updateAuthSQL); s.setString(1, username); // Username case s.setString(2, accessToken); s.setString(3, uuid.toString()); @@ -92,8 +93,8 @@ protected boolean updateAuth(UUID uuid, String username, String accessToken) thr @Override protected boolean updateServerID(UUID uuid, String serverID) throws IOException { - try { - PreparedStatement s = mySQLHolder.getConnection().prepareStatement(updateServerIDSQL); + try(Connection c = mySQLHolder.getConnection()) { + PreparedStatement s = c.prepareStatement(updateServerIDSQL); s.setString(1, serverID); s.setString(2, uuid.toString()); s.setQueryTimeout(MySQLSourceConfig.TIMEOUT); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/hwid/MysqlHWIDHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/hwid/MysqlHWIDHandler.java index 8eb46a41..1201815b 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/hwid/MysqlHWIDHandler.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/hwid/MysqlHWIDHandler.java @@ -63,8 +63,7 @@ public class MysqlHWIDHandler extends HWIDHandler { public void check0(HWID hwid, String username) throws HWIDException { if (hwid instanceof OshiHWID) { OshiHWID oshiHWID = (OshiHWID) hwid; - try { - Connection c = mySQLHolder.getConnection(); + try(Connection c = mySQLHolder.getConnection()) { PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin)); @@ -178,22 +177,21 @@ public void setIsBanned(HWID hwid, boolean isBanned) { LogHelper.debug("%s Request HWID: %s", isBanned ? "Ban" : "UnBan", hwid.toString()); if (hwid instanceof OshiHWID) { OshiHWID oshiHWID = (OshiHWID) hwid; - Connection c = null; - try { - c = mySQLHolder.getConnection(); - } catch (SQLException e) { - e.printStackTrace(); - } - try (PreparedStatement a = c.prepareStatement(queryBan)) { - String[] replaceParamsUpd = {"totalMemory", String.valueOf(oshiHWID.totalMemory), "serialNumber", oshiHWID.serialNumber, "HWDiskSerial", oshiHWID.HWDiskSerial, "processorID", oshiHWID.processorID, "isBanned", isBanned ? "1" : "0"}; - for (int i = 0; i < paramsBan.length; i++) { - a.setString(i + 1, CommonHelper.replace(paramsBan[i], replaceParamsUpd)); + try(Connection c = mySQLHolder.getConnection()) { + try (PreparedStatement a = c.prepareStatement(queryBan)) { + String[] replaceParamsUpd = {"totalMemory", String.valueOf(oshiHWID.totalMemory), "serialNumber", oshiHWID.serialNumber, "HWDiskSerial", oshiHWID.HWDiskSerial, "processorID", oshiHWID.processorID, "isBanned", isBanned ? "1" : "0"}; + for (int i = 0; i < paramsBan.length; i++) { + a.setString(i + 1, CommonHelper.replace(paramsBan[i], replaceParamsUpd)); + } + a.setQueryTimeout(MySQLSourceConfig.TIMEOUT); + a.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); } - a.setQueryTimeout(MySQLSourceConfig.TIMEOUT); - a.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } + } } @@ -214,9 +212,8 @@ public void unban(List list) { @Override public List getHwid(String username) { ArrayList list = new ArrayList<>(); - try { + try(Connection c = mySQLHolder.getConnection()) { LogHelper.debug("Try find HWID from username %s", username); - Connection c = mySQLHolder.getConnection(); PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin)); s.setString(1, username); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java new file mode 100644 index 00000000..400c9a3e --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/NoProtectHandler.java @@ -0,0 +1,16 @@ +package ru.gravit.launchserver.auth.protect; + +import ru.gravit.launchserver.response.auth.AuthResponse; +import ru.gravit.utils.helper.SecurityHelper; + +public class NoProtectHandler extends ProtectHandler { + @Override + public String generateSecureToken(AuthResponse.AuthContext context) { + return SecurityHelper.randomStringToken(); + } + + @Override + public void checkLaunchServerLicense() { + // None + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java new file mode 100644 index 00000000..9145df79 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/protect/ProtectHandler.java @@ -0,0 +1,46 @@ +package ru.gravit.launchserver.auth.protect; + +import ru.gravit.launchserver.auth.AuthException; +import ru.gravit.launchserver.auth.handler.AuthHandler; +import ru.gravit.launchserver.response.auth.AuthResponse; +import ru.gravit.utils.helper.VerifyHelper; + +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class ProtectHandler { + private static final Map> PROTECT_HANDLERS = new ConcurrentHashMap<>(4); + private static boolean registredHandl = false; + + + public static void registerHandler(String name, Class adapter) { + VerifyHelper.verifyIDName(name); + VerifyHelper.putIfAbsent(PROTECT_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"), + String.format("Protect handler has been already registered: '%s'", name)); + } + + public static Class getHandlerClass(String name) { + return PROTECT_HANDLERS.get(name); + } + + public static String getHandlerName(Class clazz) { + for (Map.Entry> e : PROTECT_HANDLERS.entrySet()) { + if (e.getValue().equals(clazz)) return e.getKey(); + } + return null; + } + + public static void registerHandlers() { + if (!registredHandl) { + registerHandler("none", NoProtectHandler.class); + registredHandl = true; + } + } + + public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface + + public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии + //public abstract +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/provider/MySQLAuthProvider.java b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/provider/MySQLAuthProvider.java index 3a3c5cfa..0f578583 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/provider/MySQLAuthProvider.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/auth/provider/MySQLAuthProvider.java @@ -8,6 +8,7 @@ import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.SecurityHelper; +import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -28,16 +29,20 @@ public void init() { @Override public AuthProviderResult auth(String login, String password, String ip) throws SQLException, AuthException { - PreparedStatement s = mySQLHolder.getConnection().prepareStatement(query); - String[] replaceParams = {"login", login, "password", password, "ip", ip}; - for (int i = 0; i < queryParams.length; i++) - s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams)); + try(Connection c = mySQLHolder.getConnection()) + { + PreparedStatement s = c.prepareStatement(query); + String[] replaceParams = {"login", login, "password", password, "ip", ip}; + for (int i = 0; i < queryParams.length; i++) + s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams)); - // Execute SQL query - s.setQueryTimeout(MySQLSourceConfig.TIMEOUT); - try (ResultSet set = s.executeQuery()) { - return set.next() ? new AuthProviderResult(set.getString(1), SecurityHelper.randomStringToken(), usePermission ? new ClientPermissions(set.getLong(2)) : LaunchServer.server.config.permissionsHandler.getPermissions(set.getString(1))) : authError(message); + // Execute SQL query + s.setQueryTimeout(MySQLSourceConfig.TIMEOUT); + try (ResultSet set = s.executeQuery()) { + return set.next() ? new AuthProviderResult(set.getString(1), SecurityHelper.randomStringToken(), usePermission ? new ClientPermissions(set.getLong(2)) : LaunchServer.server.config.permissionsHandler.getPermissions(set.getString(1))) : authError(message); + } } + } @Override diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java index 5a113e71..b5c79351 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java @@ -21,6 +21,7 @@ public final class JARLauncherBinary extends LauncherBinary { public final Path buildDir; public List tasks; public List coreLibs; + public List addonLibs; public JARLauncherBinary(LaunchServer server) throws IOException { super(server); @@ -31,6 +32,7 @@ public JARLauncherBinary(LaunchServer server) throws IOException { buildDir = server.dir.resolve("build"); tasks = new ArrayList<>(); coreLibs = new ArrayList<>(); + addonLibs = new ArrayList<>(); if (!Files.isDirectory(buildDir)) { Files.deleteIfExists(buildDir); Files.createDirectory(buildDir); @@ -42,8 +44,9 @@ public void init() { tasks.add(new PrepareBuildTask(server)); tasks.add(new MainBuildTask(server)); tasks.add(new ProGuardBuildTask(server)); - tasks.add(new AttachJarsTask(server)); tasks.add(new AdditionalFixesApplyTask(server)); + tasks.add(new RadonBuildTask(server)); + tasks.add(new AttachJarsTask(server)); } @Override diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/ProguardConf.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/ProguardConf.java index 6853ee48..365f55a4 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/ProguardConf.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/ProguardConf.java @@ -4,6 +4,7 @@ import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.SecurityHelper; +import ru.gravit.utils.helper.UnpackHelper; import java.io.*; import java.nio.file.Files; @@ -13,7 +14,6 @@ import java.util.List; public class ProguardConf { - private static final String charsFirst = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"; private static final String chars = "1aAbBcC2dDeEfF3gGhHiI4jJkKl5mMnNoO6pPqQrR7sStT8uUvV9wWxX0yYzZ"; private static String generateString(SecureRandom rand, String lowString, String upString, int il) { @@ -50,6 +50,9 @@ public String[] buildConfig(Path inputJar, Path outputJar) { srv.launcherBinary.coreLibs.stream() .map(e -> "-libraryjars \'" + e.toAbsolutePath().toString() + "\'") .forEach(confStrs::add); + srv.launcherBinary.addonLibs.stream() + .map(e -> "-libraryjars \'" + e.toAbsolutePath().toString() + "\'") + .forEach(confStrs::add); confStrs.add("-classobfuscationdictionary \'" + words.toFile().getName() + "\'"); confStrs.add(readConf()); return confStrs.toArray(new String[0]); @@ -58,9 +61,7 @@ public String[] buildConfig(Path inputJar, Path outputJar) { private void genConfig(boolean force) throws IOException { if (IOHelper.exists(config) && !force) return; Files.deleteIfExists(config); - try (OutputStream out = IOHelper.newOutput(config); InputStream in = IOHelper.newInput(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/proguard.cfg"))) { - IOHelper.transfer(in, out); - } + UnpackHelper.unpack(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/proguard.cfg"), config); } public void genWords(boolean force) throws IOException { diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/PrepareBuildTask.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/PrepareBuildTask.java index dc08fe0b..6e9cb621 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/PrepareBuildTask.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/PrepareBuildTask.java @@ -30,7 +30,9 @@ public String getName() { @Override public Path process(Path inputFile) throws IOException { server.launcherBinary.coreLibs.clear(); + server.launcherBinary.addonLibs.clear(); IOHelper.walk(server.launcherLibraries, new ListFileVisitor(server.launcherBinary.coreLibs), true); + IOHelper.walk(server.launcherLibrariesCompile, new ListFileVisitor(server.launcherBinary.addonLibs), true); UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), result); tryUnpack(); return result; diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/ProGuardBuildTask.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/ProGuardBuildTask.java index ce086579..efeae198 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/ProGuardBuildTask.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/ProGuardBuildTask.java @@ -25,8 +25,8 @@ public String getName() { @Override public Path process(Path inputFile) throws IOException { + Path outputJar = server.launcherBinary.nextLowerPath(this); if (server.config.enabledProGuard) { - Path outputJar = server.launcherBinary.nextLowerPath(this); Configuration proguard_cfg = new Configuration(); ConfigurationParser parser = new ConfigurationParser(server.proguardConf.buildConfig(inputFile, outputJar), server.proguardConf.proguard.toFile(), System.getProperties()); @@ -37,12 +37,9 @@ public Path process(Path inputFile) throws IOException { } catch (ParseException e) { LogHelper.error(e); } - return outputJar; - } else { - Path outputJar = server.launcherBinary.nextPath("non-obf"); + } else IOHelper.copy(inputFile, outputJar); - return outputJar; - } + return outputJar; } @Override diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/RadonBuildTask.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/RadonBuildTask.java new file mode 100644 index 00000000..c7ab1468 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/RadonBuildTask.java @@ -0,0 +1,55 @@ +package ru.gravit.launchserver.binary.tasks; + +import ru.gravit.launchserver.LaunchServer; +import ru.gravit.utils.helper.IOHelper; +import ru.gravit.utils.helper.UnpackHelper; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; + +import me.itzsomebody.radon.Radon; +import me.itzsomebody.radon.SessionInfo; +import me.itzsomebody.radon.config.ConfigurationParser; + +public class RadonBuildTask implements LauncherBuildTask { + private final LaunchServer srv; + public final Path config; + + public RadonBuildTask(LaunchServer srv) { + this.srv = srv; + config = this.srv.dir.resolve("radon.yml"); + System.setProperty("radon.useJVMCP", "true"); + } + + @Override + public String getName() { + return "Radon"; + } + + @Override + public Path process(Path inputFile) throws IOException { + Path outputFile = srv.launcherBinary.nextLowerPath(this); + if (srv.config.enabledRadon) { + if (!IOHelper.isFile(config)) UnpackHelper.unpack(IOHelper.getResourceURL("ru/gravit/launchserver/defaults/radon.cfg"), config); + ConfigurationParser p = new ConfigurationParser(IOHelper.newInput(config)); + SessionInfo info = p.createSessionFromConfig(); + info.setInput(inputFile.toFile()); + info.setOutput(outputFile.toFile()); + List libs = srv.launcherBinary.coreLibs.stream().map(e -> e.toFile()).collect(Collectors.toList()); + libs.addAll(srv.launcherBinary.addonLibs.stream().map(e -> e.toFile()).collect(Collectors.toList())); + info.setLibraries(libs); + Radon r = new Radon(info); + r.run(); + } else + IOHelper.copy(inputFile, outputFile); + return outputFile; + } + + @Override + public boolean allowDelete() { + return true; + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/AuthLimiter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/components/AuthLimiterComponent.java similarity index 65% rename from LaunchServer/src/main/java/ru/gravit/launchserver/auth/AuthLimiter.java rename to LaunchServer/src/main/java/ru/gravit/launchserver/components/AuthLimiterComponent.java index 40122c15..907817e3 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/auth/AuthLimiter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/components/AuthLimiterComponent.java @@ -1,14 +1,42 @@ -package ru.gravit.launchserver.auth; +package ru.gravit.launchserver.components; import ru.gravit.launcher.NeedGarbageCollection; import ru.gravit.launchserver.LaunchServer; +import ru.gravit.launchserver.auth.AuthException; +import ru.gravit.launchserver.auth.provider.AuthProvider; +import ru.gravit.launchserver.components.Component; +import ru.gravit.launchserver.response.auth.AuthResponse; +import ru.gravit.launchserver.socket.Client; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; -public class AuthLimiter implements NeedGarbageCollection { +public class AuthLimiterComponent extends Component implements NeedGarbageCollection { + private LaunchServer server; + @Override + public void preInit(LaunchServer launchServer) { + + } + + @Override + public void init(LaunchServer launchServer) { + server = launchServer; + launchServer.authHookManager.registerPreHook(this::preAuthHook); + } + + @Override + public void postInit(LaunchServer launchServer) { + + } + public void preAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException { + if(isLimit(context.ip)) + { + AuthProvider.authError(message); + } + } + static class AuthEntry { public int value; @@ -50,20 +78,12 @@ public String toString() { public static final long TIMEOUT = 10 * 60 * 1000; //10 минут - public final int rateLimit; - public final int rateLimitMilis; + public int rateLimit; + public int rateLimitMilis; + public String message; - private final HashMap map; - private final List excludeIps; - - public AuthLimiter(LaunchServer srv) { - map = new HashMap<>(); - excludeIps = new ArrayList<>(); - if (srv.config.authLimitExclusions != null) - excludeIps.addAll(Arrays.asList(srv.config.authLimitExclusions)); - rateLimit = srv.config.authRateLimit; - rateLimitMilis = srv.config.authRateLimitMilis; - } + public transient HashMap map = new HashMap<>(); + public List excludeIps = new ArrayList<>(); @Override public void garbageCollection() { diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/components/Component.java b/LaunchServer/src/main/java/ru/gravit/launchserver/components/Component.java new file mode 100644 index 00000000..4cd718ac --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/components/Component.java @@ -0,0 +1,40 @@ +package ru.gravit.launchserver.components; + +import ru.gravit.launchserver.LaunchServer; +import ru.gravit.utils.helper.VerifyHelper; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class Component { + private static final Map> COMPONENTS = new ConcurrentHashMap<>(4); + private static boolean registredComp = false; + + public static void registerComponent(String name, Class adapter) { + VerifyHelper.verifyIDName(name); + VerifyHelper.putIfAbsent(COMPONENTS, name, Objects.requireNonNull(adapter, "adapter"), + String.format("Auth handler has been already registered: '%s'", name)); + } + + public static Class getComponentClass(String name) { + return COMPONENTS.get(name); + } + + public static String getComponentName(Class clazz) { + for (Map.Entry> e : COMPONENTS.entrySet()) { + if (e.getValue().equals(clazz)) return e.getKey(); + } + return null; + } + + public static void registerComponents() { + if (!registredComp) { + registerComponent("authLimiter", AuthLimiterComponent.class); + registredComp = true; + } + } + public abstract void preInit(LaunchServer launchServer); + public abstract void init(LaunchServer launchServer); + public abstract void postInit(LaunchServer launchServer); +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthHandlerAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthHandlerAdapter.java index 608b36ae..f796e921 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthHandlerAdapter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthHandlerAdapter.java @@ -2,6 +2,7 @@ import com.google.gson.*; import ru.gravit.launchserver.auth.handler.AuthHandler; +import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; @@ -12,6 +13,11 @@ public class AuthHandlerAdapter implements JsonSerializer, JsonDese public AuthHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); Class cls = AuthHandler.getHandlerClass(typename); + if(cls == null) + { + LogHelper.error("AuthHandler %s not found", typename); + return null; + } return (AuthHandler) context.deserialize(json, cls); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthProviderAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthProviderAdapter.java index a45c6e92..f4e74c95 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthProviderAdapter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/AuthProviderAdapter.java @@ -2,6 +2,7 @@ import com.google.gson.*; import ru.gravit.launchserver.auth.provider.AuthProvider; +import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; @@ -12,6 +13,11 @@ public class AuthProviderAdapter implements JsonSerializer, JsonDe public AuthProvider deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); Class cls = AuthProvider.getProviderClass(typename); + if(cls == null) + { + LogHelper.error("AuthProvider %s not found", typename); + return null; + } return (AuthProvider) context.deserialize(json, cls); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/ComponentAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ComponentAdapter.java new file mode 100644 index 00000000..65c8f7da --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ComponentAdapter.java @@ -0,0 +1,36 @@ +package ru.gravit.launchserver.config; + +import com.google.gson.*; +import ru.gravit.launchserver.components.Component; +import ru.gravit.utils.helper.LogHelper; + +import java.lang.reflect.Type; + +public class ComponentAdapter implements JsonSerializer, JsonDeserializer { + private static final String PROP_NAME = "component"; + + @Override + public Component deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); + Class cls = Component.getComponentClass(typename); + if(cls == null) + { + LogHelper.error("Component %s not found", typename); + return null; + } + + + return (Component) context.deserialize(json, cls); + } + + @Override + public JsonElement serialize(Component src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jo = context.serialize(src).getAsJsonObject(); + + @SuppressWarnings("unchecked") + String classPath = Component.getComponentName((Class) src.getClass()); + jo.add(PROP_NAME, new JsonPrimitive(classPath)); + + return jo; + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/HWIDHandlerAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/HWIDHandlerAdapter.java index bcc887b7..3a2d994c 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/config/HWIDHandlerAdapter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/HWIDHandlerAdapter.java @@ -2,6 +2,7 @@ import com.google.gson.*; import ru.gravit.launchserver.auth.hwid.HWIDHandler; +import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; @@ -12,6 +13,11 @@ public class HWIDHandlerAdapter implements JsonSerializer, JsonDese public HWIDHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); Class cls = HWIDHandler.getHandlerClass(typename); + if(cls == null) + { + LogHelper.error("HWIDHandler %s not found", typename); + return null; + } return (HWIDHandler) context.deserialize(json, cls); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/PermissionsHandlerAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/PermissionsHandlerAdapter.java index 83dd21e9..bc2e21ae 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/config/PermissionsHandlerAdapter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/PermissionsHandlerAdapter.java @@ -2,6 +2,7 @@ import com.google.gson.*; import ru.gravit.launchserver.auth.permissions.PermissionsHandler; +import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; @@ -12,6 +13,11 @@ public class PermissionsHandlerAdapter implements JsonSerializer cls = PermissionsHandler.getHandlerClass(typename); + if(cls == null) + { + LogHelper.error("PermissionsHandler %s not found", typename); + return null; + } return (PermissionsHandler) context.deserialize(json, cls); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java new file mode 100644 index 00000000..6e6fcd19 --- /dev/null +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/ProtectHandlerAdapter.java @@ -0,0 +1,37 @@ +package ru.gravit.launchserver.config; + +import com.google.gson.*; +import ru.gravit.launchserver.auth.handler.AuthHandler; +import ru.gravit.launchserver.auth.protect.ProtectHandler; +import ru.gravit.utils.helper.LogHelper; + +import java.lang.reflect.Type; + +public class ProtectHandlerAdapter implements JsonSerializer, JsonDeserializer { + private static final String PROP_NAME = "type"; + + @Override + public ProtectHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); + Class cls = ProtectHandler.getHandlerClass(typename); + if(cls == null) + { + LogHelper.error("ProtectHandler %s not found", typename); + return null; + } + + + return (ProtectHandler) context.deserialize(json, cls); + } + + @Override + public JsonElement serialize(ProtectHandler src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jo = context.serialize(src).getAsJsonObject(); + + @SuppressWarnings("unchecked") + String classPath = ProtectHandler.getHandlerName((Class) src.getClass()); + jo.add(PROP_NAME, new JsonPrimitive(classPath)); + + return jo; + } +} diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/config/TextureProviderAdapter.java b/LaunchServer/src/main/java/ru/gravit/launchserver/config/TextureProviderAdapter.java index e79041c8..75aba651 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/config/TextureProviderAdapter.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/config/TextureProviderAdapter.java @@ -2,6 +2,7 @@ import com.google.gson.*; import ru.gravit.launchserver.texture.TextureProvider; +import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; @@ -12,6 +13,11 @@ public class TextureProviderAdapter implements JsonSerializer, public TextureProvider deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); Class cls = TextureProvider.getProviderClass(typename); + if(cls == null) + { + LogHelper.error("TextureProvider %s not found", typename); + return null; + } return (TextureProvider) context.deserialize(json, cls); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/hook/AuthHookManager.java b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/hook/AuthHookManager.java index f60b9f78..2f3a4ed2 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/hook/AuthHookManager.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/manangers/hook/AuthHookManager.java @@ -1,5 +1,7 @@ package ru.gravit.launchserver.manangers.hook; +import ru.gravit.launcher.request.RequestException; +import ru.gravit.launchserver.auth.AuthException; import ru.gravit.launchserver.response.auth.AuthResponse; import ru.gravit.launchserver.socket.Client; @@ -14,22 +16,22 @@ public class AuthHookManager { @FunctionalInterface public interface AuthPreHook { - void preAuthHook(AuthResponse.AuthContext context, Client client); + void preAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException; } @FunctionalInterface public interface AuthPostHook { - void postAuthHook(AuthResponse.AuthContext context, Client client); + void postAuthHook(AuthResponse.AuthContext context, Client client) throws AuthException; } @FunctionalInterface public interface CheckServerHook { - void checkServerHook(String username, String serverID); + void checkServerHook(String username, String serverID) throws AuthException; } @FunctionalInterface public interface JoinServerHook { - void joinServerHook(String username, String accessToken, String serverID); + void joinServerHook(String username, String accessToken, String serverID) throws AuthException; } public void registerPostHook(AuthPostHook hook) { @@ -48,25 +50,25 @@ public void registerPreHook(AuthPreHook hook) { PRE_HOOKS.add(hook); } - public void preHook(AuthResponse.AuthContext context, Client client) { + public void preHook(AuthResponse.AuthContext context, Client client) throws AuthException { for (AuthPreHook preHook : PRE_HOOKS) { preHook.preAuthHook(context, client); } } - public void checkServerHook(String username, String serverID) { + public void checkServerHook(String username, String serverID) throws AuthException { for (CheckServerHook hook : CHECKSERVER_HOOKS) { hook.checkServerHook(username, serverID); } } - public void joinServerHook(String username, String accessToken, String serverID) { + public void joinServerHook(String username, String accessToken, String serverID) throws AuthException { for (JoinServerHook hook : JOINSERVER_HOOKS) { hook.joinServerHook(username, accessToken, serverID); } } - public void postHook(AuthResponse.AuthContext context, Client client) { + public void postHook(AuthResponse.AuthContext context, Client client) throws AuthException { for (AuthPostHook postHook : POST_HOOKS) { postHook.postAuthHook(context, client); } 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 f115ee28..69028ae8 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 @@ -37,13 +37,14 @@ public AuthResponse(LaunchServer server, long session, HInput input, HOutput out } public static class AuthContext { - public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, boolean isServerAuth) { + public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) { this.session = session; this.login = login; this.password_lenght = password_lenght; this.customText = customText; this.client = client; this.hwid = hwid; + this.ip = ip; this.isServerAuth = isServerAuth; } @@ -53,6 +54,7 @@ public AuthContext(long session, String login, int password_lenght, String custo public String client; public String hwid; public String customText; + public String ip; public boolean isServerAuth; } @@ -86,13 +88,9 @@ public void reply() throws Exception { if(pair == null) requestError("Auth type not found"); AuthProvider provider = pair.provider; clientData.type = Client.Type.USER; - AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, false); + AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, ip, false); try { server.authHookManager.preHook(context, clientData); - if (server.limiter.isLimit(ip)) { - AuthProvider.authError(server.config.authRejectString); - return; - } if (!clientData.checkSign) { throw new AuthException("You must using checkLauncher"); } @@ -145,10 +143,12 @@ public void reply() throws Exception { requestError("Internal auth handler error"); return; } + String protectToken = server.config.protectHandler.generateSecureToken(context); writeNoError(output); // Write profile and UUID ProfileByUUIDResponse.getProfile(server, uuid, result.username, client, clientData.auth.textureProvider).write(output); output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH); clientData.permissions.write(output); + output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT); } } 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 index 87cf5efd..48fd0332 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/response/auth/AuthServerResponse.java @@ -57,10 +57,6 @@ public void reply() throws Exception { if(pair == null) requestError("Auth type not found"); AuthProvider provider = pair.provider; 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)); diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/socket/websocket/json/auth/AuthResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/socket/websocket/json/auth/AuthResponse.java index 01ed5b1c..e36a47aa 100644 --- a/LaunchServer/src/main/java/ru/gravit/launchserver/socket/websocket/json/auth/AuthResponse.java +++ b/LaunchServer/src/main/java/ru/gravit/launchserver/socket/websocket/json/auth/AuthResponse.java @@ -57,10 +57,6 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client try { AuthRequestEvent result = new AuthRequestEvent(); String ip = IOHelper.getIP(ctx.channel().remoteAddress()); - if (LaunchServer.server.limiter.isLimit(ip)) { - AuthProvider.authError(LaunchServer.server.config.authRejectString); - return; - } if ((authType == null || authType == ConnectTypes.CLIENT) &&!clientData.checkSign) { AuthProvider.authError("Don't skip Launcher Update"); return; @@ -86,7 +82,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client AuthProviderPair pair; if(auth_id.isEmpty()) pair = LaunchServer.server.config.getAuthProviderPair(); else pair = LaunchServer.server.config.getAuthProviderPair(auth_id); - ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(),customText, client, null, false); + ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(),customText, client, ip, null, false); AuthProvider provider = pair.provider; LaunchServer.server.authHookManager.preHook(context, clientData); provider.preAuth(login,password,customText,ip); diff --git a/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/radon.cfg b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/radon.cfg new file mode 100644 index 00000000..539eb775 --- /dev/null +++ b/LaunchServer/src/main/resources/ru/gravit/launchserver/defaults/radon.cfg @@ -0,0 +1,21 @@ +StringEncryption: + Enabled: true + Mode: Normal + StringPool: false +InvokeDynamic: None +NumberObfuscation: Normal +FlowObfuscation: Normal +HideCode: false +Shuffler: true +Crasher: false +Optimizer: + Enabled: true + InlineGotoGoto: true + InlineGotoReturn: true + RemoveNopInstructions: true +Watermarker: + Enabled: false + Message: "This copy belongs to GravitLauncher" + Key: "SuperSecureKey" +Dictionary: Spaces +TrashClasses: 500 \ No newline at end of file diff --git a/Launcher/runtime/dialog/dialog.js b/Launcher/runtime/dialog/dialog.js index dfa26435..712b3fcb 100644 --- a/Launcher/runtime/dialog/dialog.js +++ b/Launcher/runtime/dialog/dialog.js @@ -215,6 +215,7 @@ function doAuth(login, rsaPassword) { overlay.show(processing.overlay, function (event) { FunctionalBridge.getHWID.join(); makeAuthRequest(login, rsaPassword, function (result) { + FunctionalBridge.setAuthParams(result); loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions}; overlay.hide(0, function () { diff --git a/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java b/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java index 7c1dfcbe..79455c5e 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java +++ b/Launcher/src/main/java/ru/gravit/launcher/client/ClientLauncher.java @@ -302,7 +302,7 @@ public static Process launch( // Write params file (instead of CLI; Mustdie32 API can't handle command line > 32767 chars) LogHelper.debug("Writing ClientLauncher params"); ClientLauncherContext context = new ClientLauncherContext(); - CommonHelper.newThread("Client params writter", false, () -> + CommonHelper.newThread("Client params writter", true, () -> { try { try (ServerSocket socket = new ServerSocket()) { @@ -356,8 +356,6 @@ public static Process launch( context.args.add(JVMHelper.jvmProperty("os.name", "Windows 10")); context.args.add(JVMHelper.jvmProperty("os.version", "10.0")); } - context.args.add(JVMHelper.systemToJvmProperty("avn32")); - context.args.add(JVMHelper.systemToJvmProperty("avn64")); } // Add classpath and main class String pathLauncher = IOHelper.getCodeSource(ClientLauncher.class).toString(); @@ -388,6 +386,7 @@ public static Process launch( } // Let's rock! process = builder.start(); + if(!LogHelper.isDebugEnabled()) Thread.sleep(1000); //даем время потоку записи return process; } diff --git a/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java b/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java index f055ebda..d001f8da 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java +++ b/Launcher/src/main/java/ru/gravit/launcher/client/FunctionalBridge.java @@ -3,6 +3,7 @@ import javafx.concurrent.Task; import ru.gravit.launcher.HWID; import ru.gravit.launcher.LauncherAPI; +import ru.gravit.launcher.events.request.AuthRequestEvent; import ru.gravit.launcher.guard.LauncherGuardManager; import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.HashedDir; @@ -103,6 +104,12 @@ public static HasherStore getDefaultHasherStore() { return HasherManager.getDefaultStore(); } + @LauncherAPI + public static void setAuthParams(AuthRequestEvent event) + { + LauncherGuardManager.guard.setProtectToken(event.protectToken); + } + @FunctionalInterface public interface HashedDirRunnable { SignedObjectHolder run() throws Exception; diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java index fb6e8fdd..be71089c 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardInterface.java @@ -11,4 +11,5 @@ public interface LauncherGuardInterface { void init(boolean clientInstance); void addCustomParams(ClientLauncherContext context); void addCustomEnv(ClientLauncherContext context); + void setProtectToken(String token); } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java index 77c4606a..3d637628 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherJavaGuard.java @@ -43,4 +43,9 @@ public void addCustomParams(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) { } + + @Override + public void setProtectToken(String token) { + //Skip + } } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java index 9bd1923c..4ae7b35e 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherNoGuard.java @@ -40,4 +40,9 @@ public void addCustomParams(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) { } + + @Override + public void setProtectToken(String token) { + //Skip + } } diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java index bd97ebbb..91df7434 100644 --- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java +++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherWrapperGuard.java @@ -13,6 +13,9 @@ import java.util.Map; public class LauncherWrapperGuard implements LauncherGuardInterface { + + public String protectToken; + @Override public String getName() { return "wrapper"; @@ -62,6 +65,7 @@ public void addCustomEnv(ClientLauncherContext context) { env.put("GUARD_USERNAME", context.playerProfile.username); env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16)); env.put("GUARD_PROJECTNAME", config.projectname); + env.put("GUARD_TOKEN", protectToken); if(config.guardLicenseName != null) env.put("GUARD_LICENSE_NAME", config.guardLicenseName); if(config.guardLicenseKey != null) @@ -69,4 +73,9 @@ public void addCustomEnv(ClientLauncherContext context) { env.put("GUARD_LICENSE_KEY", config.guardLicenseKey); } } + + @Override + public void setProtectToken(String token) { + protectToken = token; + } } diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java index 59606788..f3e8398f 100644 --- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/auth/AuthRequest.java @@ -109,7 +109,8 @@ protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOExce PlayerProfile pp = new PlayerProfile(input); String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH); ClientPermissions permissions = new ClientPermissions(input); - return new AuthRequestEvent(pp, accessToken, permissions); + String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT); + return new AuthRequestEvent(permissions, pp, accessToken, protectToken); } @Override diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java index 80352243..96c01bc4 100644 --- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java +++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java @@ -303,9 +303,16 @@ public Integer getLegacyType() { } @Override - protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException { + public UpdateRequestEvent request() throws Exception { Files.createDirectories(dir); localDir = new HashedDir(dir, matcher, false, digest); + + // Start request + return super.request(); + } + + @Override + protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException { // Write update dir name output.writeString(dirName, 255); output.flush(); diff --git a/Radon b/Radon new file mode 160000 index 00000000..e1f7548f --- /dev/null +++ b/Radon @@ -0,0 +1 @@ +Subproject commit e1f7548f97132fa29b01f68bd57ffab32de7b6e7 diff --git a/build.gradle b/build.gradle index 3d42a735..02d6daae 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,11 @@ -configure(subprojects.findAll {it.name != 'modules'}) { +configure(subprojects.findAll { it.name != 'modules' && it.name != 'Radon' }) { apply plugin: 'idea' apply plugin: 'eclipse' apply plugin: 'java' repositories { mavenCentral() + maven { url 'http://oss.sonatype.org/content/groups/public' } maven { url "http://clojars.org/repo/" } diff --git a/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java b/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java index a61a0a18..aab137be 100644 --- a/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java +++ b/libLauncher/src/main/java/ru/gravit/launcher/events/request/AuthRequestEvent.java @@ -20,6 +20,8 @@ public AuthRequestEvent() { public PlayerProfile playerProfile; @LauncherNetworkAPI public String accessToken; + @LauncherNetworkAPI + public String protectToken; public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) { this.playerProfile = pp; @@ -27,6 +29,13 @@ public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions this.permissions = permissions; } + public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken) { + this.permissions = permissions; + this.playerProfile = playerProfile; + this.accessToken = accessToken; + this.protectToken = protectToken; + } + @Override public UUID getUUID() { return uuid; diff --git a/settings.gradle b/settings.gradle index 3fc709d9..234a8355 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,7 @@ rootProject.name = 'GravitLauncher' include 'Launcher' +include 'Radon' include 'libLauncher' include 'LauncherAPI' include 'ServerWrapper'