From 9841ef315751797febfd450043f073b3f3795b24 Mon Sep 17 00:00:00 2001 From: Gravita Date: Tue, 12 Oct 2021 16:55:32 +0700 Subject: [PATCH] [FEATURE] Permissions --- .../pro/gravit/launchserver/LaunchServer.java | 3 + .../launchserver/auth/AuthProviderPair.java | 14 ++++ .../auth/protect/AdvancedProtectHandler.java | 4 +- .../auth/protect/StdProtectHandler.java | 38 ++++++++--- .../launchserver/manangers/AuthManager.java | 3 + .../gravit/launcher/ClientPermissions.java | 67 ++++++++++++++++--- .../launcher/profiles/ClientProfile.java | 6 ++ .../pro/gravit/launcher/PermissionTest.java | 50 ++++++++++++++ .../launcher/managers/GarbageManager.java | 1 + .../main/java/pro/gravit/utils/Version.java | 2 +- .../gravit/utils/command/basic/GCCommand.java | 1 - 11 files changed, 166 insertions(+), 23 deletions(-) create mode 100644 LauncherAPI/src/test/java/pro/gravit/launcher/PermissionTest.java diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index 58bbec6a..0c501f62 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -121,6 +121,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab // Updates and profiles private volatile Set profilesList; + @SuppressWarnings("deprecation") public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException { this.dir = directories.dir; this.tmpDir = directories.tmpDir; @@ -405,6 +406,7 @@ public void restart() { } } + @SuppressWarnings("deprecation") public void registerObject(String name, Object object) { if (object instanceof Reconfigurable) { reconfigurableManager.registerReconfigurable(name, (Reconfigurable) object); @@ -414,6 +416,7 @@ public void registerObject(String name, Object object) { } } + @SuppressWarnings("deprecation") public void unregisterObject(String name, Object object) { if (object instanceof Reconfigurable) { reconfigurableManager.unregisterReconfigurable(name); 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 44eced04..28afb86c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/AuthProviderPair.java @@ -1,8 +1,11 @@ package pro.gravit.launchserver.auth; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.core.AuthSocialProvider; +import pro.gravit.launchserver.auth.core.MySQLCoreProvider; import pro.gravit.launchserver.auth.texture.TextureProvider; import java.io.IOException; @@ -11,6 +14,7 @@ import java.util.Set; public final class AuthProviderPair { + private transient final Logger logger = LogManager.getLogger(); public boolean isDefault = true; public AuthCoreProvider core; public AuthSocialProvider social; @@ -19,6 +23,7 @@ public final class AuthProviderPair { public transient String name; public transient Set features; public String displayName; + private transient boolean warnOAuthShow = false; public AuthProviderPair(AuthCoreProvider core, TextureProvider textureProvider) { this.core = core; @@ -42,6 +47,15 @@ public static Set getFeatures(Class clazz) { return list; } + public void internalShowOAuthWarnMessage() { + if(!warnOAuthShow) { + if(!(core instanceof MySQLCoreProvider)) { // MySQL upgraded later + logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName()); + } + warnOAuthShow = true; + } + } + public static void getFeatures(Class clazz, Set list) { Features features = clazz.getAnnotation(Features.class); if (features != null) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java index 2f92fff6..a440e330 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java @@ -141,8 +141,10 @@ public boolean onJoinServer(String serverID, String username, Client client) { @Override public void init(LaunchServer server) { - if (provider != null) + if (provider != null) { provider.init(server); + logger.warn("HWIDProvider deprecated. Please use 'AuthSupportHardware' in AuthCoreProvider"); + } this.server = server; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/StdProtectHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/StdProtectHandler.java index 38983477..d2bf0799 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/StdProtectHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/StdProtectHandler.java @@ -1,16 +1,17 @@ package pro.gravit.launchserver.auth.protect; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import pro.gravit.launcher.profiles.ClientProfile; +import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.auth.protect.interfaces.ProfilesProtectHandler; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.auth.AuthResponse; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class StdProtectHandler extends ProtectHandler implements ProfilesProtectHandler { + private transient final Logger logger = LogManager.getLogger(); public Map> profileWhitelist = new HashMap<>(); public List allowUpdates = new ArrayList<>(); @@ -24,14 +25,21 @@ public void checkLaunchServerLicense() { } + @Override + public void init(LaunchServer server) { + if(profileWhitelist != null && profileWhitelist.size() > 0) { + logger.warn("profileWhitelist deprecated. Please use permission 'launchserver.profile.PROFILE_UUID.show' and 'launchserver.profile.PROFILE_UUID.enter'"); + } + } + @Override public boolean canGetProfile(ClientProfile profile, Client client) { - return canChangeProfile(profile, client); + return client.isAuth && client.username != null && (!profile.isLimited() || isWhitelisted("launchserver.profile.%s.show", profile, client) ); } @Override public boolean canChangeProfile(ClientProfile profile, Client client) { - return client.isAuth && client.username != null && isWhitelisted(profile.getTitle(), client.username); + return client.isAuth && client.username != null && (!profile.isLimited() || isWhitelisted("launchserver.profile.%s.enter", profile, client) ); } @Override @@ -39,9 +47,19 @@ public boolean canGetUpdates(String updatesDirName, Client client) { return client.profile != null && (client.profile.getDir().equals(updatesDirName) || client.profile.getAssetDir().equals(updatesDirName) || allowUpdates.contains(updatesDirName)); } - public boolean isWhitelisted(String profileTitle, String username) { - List allowedUsername = profileWhitelist.get(profileTitle); - if (allowedUsername == null) return true; - return allowedUsername.contains(username); + private boolean isWhitelisted(String property, ClientProfile profile, Client client) { + if(client.permissions != null) { + String permByUUID = String.format(property, profile.getUUID()); + if(client.permissions.hasAction(permByUUID)) { + return true; + } + String permByTitle = String.format(property, profile.getTitle().toLowerCase(Locale.ROOT)); + if(client.permissions.hasAction(permByTitle)) { + return true; + } + } + List allowedUsername = profileWhitelist.get(profile.getTitle()); + if (allowedUsername != null && allowedUsername.contains(client.username)) return true; + return false; } } 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 63529b75..e3a7e6ed 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/AuthManager.java @@ -205,6 +205,9 @@ public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswor * Writing authorization information to the Client object */ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, AuthProviderPair pair, String username, UUID uuid, ClientPermissions permissions, boolean oauth) { + if(!oauth) { + pair.internalShowOAuthWarnMessage(); + } client.isAuth = true; client.permissions = permissions; client.auth_id = pair.name; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/ClientPermissions.java b/LauncherAPI/src/main/java/pro/gravit/launcher/ClientPermissions.java index 3a10075a..b7772452 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/ClientPermissions.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/ClientPermissions.java @@ -3,10 +3,7 @@ import pro.gravit.launcher.serialize.HInput; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; +import java.util.*; public class ClientPermissions { public static final ClientPermissions DEFAULT = new ClientPermissions(); @@ -21,7 +18,7 @@ public class ClientPermissions { @LauncherNetworkAPI private List actions; - private transient List available; + private transient List available; public ClientPermissions(HInput input) throws IOException { this(input.readLong()); @@ -61,12 +58,12 @@ public synchronized void compile() { } available = new ArrayList<>(actions.size()); for (String a : actions) { - available.add(Pattern.compile(a)); + available.add(new PermissionPattern(a)); } if (permissions != 0) { if (isPermission(PermissionConsts.ADMIN)) { roles.add("ADMIN"); - available.add(Pattern.compile(".*")); + available.add(new PermissionPattern("*")); } } } @@ -75,8 +72,8 @@ public boolean hasAction(String action) { if (available == null) { compile(); } - for (Pattern p : available) { - if (p.matcher(action).matches()) { + for (PermissionPattern p : available) { + if (p.match(action)) { return true; } } @@ -98,7 +95,7 @@ public void addAction(String action) { if(available == null) { available = new ArrayList<>(1); } - available.add(Pattern.compile(action)); + available.add(new PermissionPattern(action)); } public List getRoles() { @@ -186,4 +183,54 @@ public enum FlagConsts { this.mask = mask; } } + + public static class PermissionPattern { + private final String[] parts; + private final int priority; + + public PermissionPattern(String pattern) { + List prepare = new ArrayList<>(); + for(int i=0;true;) { + int pos = pattern.indexOf("*", i); + if(pos >= 0) { + prepare.add(pattern.substring(i, pos)); + i = pos+1; + } else { + prepare.add(pattern.substring(i)); + break; + } + } + priority = prepare.size() - 1; + parts = prepare.toArray(new String[0]); + } + + public int getPriority() { + return priority; + } + + public boolean match(String str) { + if(parts.length == 0) { + return true; + } + if(parts.length == 1) { + return parts[0].equals(str); + } + int offset = 0; + if(!str.startsWith(parts[0])) { + return false; + } + if(!str.endsWith(parts[parts.length-1])) { + return false; + } + for(int i=1;i= 0) { + offset = pos+1; + } else { + return false; + } + } + return true; + } + } } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/ClientProfile.java b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/ClientProfile.java index 903eb757..816dc942 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/ClientProfile.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/profiles/ClientProfile.java @@ -77,6 +77,8 @@ public final class ClientProfile implements Comparable { private ProfileDefaultSettings settings = new ProfileDefaultSettings(); @LauncherNetworkAPI private boolean updateFastCheck; + @LauncherNetworkAPI + private boolean limited; // Client launcher @LauncherNetworkAPI private String mainClass; @@ -441,6 +443,10 @@ public void setRuntimeInClientConfig(RuntimeInClientConfig runtimeInClientConfig this.runtimeInClientConfig = runtimeInClientConfig; } + public boolean isLimited() { + return limited; + } + public enum Version { MC125("1.2.5", 29), MC147("1.4.7", 51), diff --git a/LauncherAPI/src/test/java/pro/gravit/launcher/PermissionTest.java b/LauncherAPI/src/test/java/pro/gravit/launcher/PermissionTest.java new file mode 100644 index 00000000..048a0cfd --- /dev/null +++ b/LauncherAPI/src/test/java/pro/gravit/launcher/PermissionTest.java @@ -0,0 +1,50 @@ +package pro.gravit.launcher; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class PermissionTest { + @Test + public void testPermission() { + { + ClientPermissions permissions = new ClientPermissions(); + permissions.addAction("*"); + Assertions.assertTrue(permissions.hasAction("abcd")); + Assertions.assertTrue(permissions.hasAction("t.a.c.d.f.*")); + Assertions.assertTrue(permissions.hasAction("*")); + } + { + ClientPermissions permissions = new ClientPermissions(); + permissions.addAction("launchserver.*"); + Assertions.assertTrue(permissions.hasAction("launchserver.*")); + Assertions.assertTrue(permissions.hasAction("launchserver.abcd")); + Assertions.assertFalse(permissions.hasAction("default.abcd")); + Assertions.assertFalse(permissions.hasAction("nolaunchserver.abcd")); + } + { + ClientPermissions permissions = new ClientPermissions(); + permissions.addAction("launchserver.*.prop"); + Assertions.assertTrue(permissions.hasAction("launchserver.ii.prop")); + Assertions.assertTrue(permissions.hasAction("launchserver.ia.prop")); + Assertions.assertFalse(permissions.hasAction("default.abcd")); + Assertions.assertFalse(permissions.hasAction("launchserver.ia")); + Assertions.assertFalse(permissions.hasAction("launchserver.ia.prop2")); + } + { + ClientPermissions permissions = new ClientPermissions(); + permissions.addAction("launchserver.*.def.*.prop"); + Assertions.assertTrue(permissions.hasAction("launchserver.1.def.2.prop")); + Assertions.assertTrue(permissions.hasAction("launchserver.none.def.none.prop")); + Assertions.assertTrue(permissions.hasAction("launchserver.def.def.def.prop")); + Assertions.assertFalse(permissions.hasAction("launchserver.*.*.prop")); + Assertions.assertFalse(permissions.hasAction("launchserver.*.undef.*.prop")); + } + { + ClientPermissions permissions = new ClientPermissions(); + permissions.addAction("launchserver.*.e.*.i.*.prop"); + Assertions.assertTrue(permissions.hasAction("launchserver.2.e.3.i.4.prop")); + Assertions.assertTrue(permissions.hasAction("launchserver.12212.e.233455.i.2356436346346345345345345.prop")); + Assertions.assertFalse(permissions.hasAction("launchserver.prop")); + } + } +} diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java b/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java index 5a654d9a..9726d81d 100644 --- a/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java +++ b/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java @@ -7,6 +7,7 @@ import java.util.Timer; import java.util.TimerTask; +@Deprecated public class GarbageManager { private static final Timer timer = new Timer("GarbageTimer"); private static final Set NEED_GARBARE_COLLECTION = new HashSet<>(); diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Version.java b/LauncherCore/src/main/java/pro/gravit/utils/Version.java index 76893ac5..6ec24411 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Version.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Version.java @@ -8,7 +8,7 @@ public final class Version implements Comparable { public static final int MINOR = 2; public static final int PATCH = 3; public static final int BUILD = 1; - public static final Version.Type RELEASE = Type.DEV; + public static final Version.Type RELEASE = Type.BETA; public final int major; public final int minor; public final int patch; diff --git a/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java b/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java index 81da6add..bb00782e 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java @@ -20,7 +20,6 @@ public String getUsageDescription() { public void invoke(String... args) { LogHelper.subInfo("Performing full GC"); JVMHelper.fullGC(); - GarbageManager.gc(); // Print memory usage long max = JVMHelper.RUNTIME.maxMemory() >> 20; long free = JVMHelper.RUNTIME.freeMemory() >> 20;