mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-02-22 19:49:46 +03:00
Merge branch 'release/5.2.3'
This commit is contained in:
commit
b48059998f
109 changed files with 807 additions and 3303 deletions
29
.github/workflows/push.yml
vendored
29
.github/workflows/push.yml
vendored
|
@ -16,10 +16,10 @@ jobs:
|
|||
path: ~/.gradle/caches
|
||||
key: gravit-${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}-launcher
|
||||
|
||||
- name: Set up JDK 11
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
java-version: 17
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
@ -30,16 +30,13 @@ jobs:
|
|||
- name: Create artifacts
|
||||
run: |
|
||||
mkdir -p artifacts/modules
|
||||
cd LaunchServer/build/libs/
|
||||
cd LaunchServer/build/libs
|
||||
zip -r -9 ../../../artifacts/libraries.zip * -x "LaunchServer.jar" -x "LaunchServer-clean.jar"
|
||||
cp LaunchServer.jar ../../../artifacts/LaunchServer.jar
|
||||
cd ../../../ServerWrapper/build/libs
|
||||
cp ServerWrapper.jar ../../../artifacts/ServerWrapper.jar
|
||||
cd ../../../LauncherAuthlib/build/libs
|
||||
cp LauncherAuthlib.jar ../../../artifacts/LauncherAuthlib.jar
|
||||
cd ../../../
|
||||
cd ../../..
|
||||
cp ServerWrapper/build/libs/ServerWrapper.jar artifacts/ServerWrapper.jar
|
||||
cp LauncherAuthlib/build/libs/LauncherAuthlib.jar artifacts/LauncherAuthlib.jar
|
||||
cp modules/*_module/build/libs/*.jar artifacts/modules || true
|
||||
cp modules/*_swmodule/build/libs/*.jar artifacts/modules || true
|
||||
cp modules/*_lmodule/build/libs/*.jar artifacts/modules || true
|
||||
|
||||
- name: Upload artifacts
|
||||
|
@ -56,10 +53,11 @@ jobs:
|
|||
if: startsWith(github.event.ref, 'refs/tags')
|
||||
run: |
|
||||
cd artifacts
|
||||
zip -9 LauncherBase.zip libraries.zip LaunchServer.jar
|
||||
zip -r -9 Release.zip *
|
||||
zip -j -9 LaunchServerModules.zip ../modules/*_module/build/libs/*.jar
|
||||
zip -j -9 LauncherModules.zip ../modules/*_lmodule/build/libs/*.jar
|
||||
zip -j -9 ServerWrapperModules.zip ../modules/*_swmodule/build/libs/*.jar
|
||||
cd ../LaunchServer/build/libs
|
||||
zip -r -9 ../../../artifacts/LauncherBase.zip * -x "LaunchServer-clean.jar"
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
|
@ -74,11 +72,4 @@ jobs:
|
|||
draft: false
|
||||
prerelease: false
|
||||
files: |
|
||||
libraries.zip
|
||||
LaunchServer.jar
|
||||
ServerWrapper.jar
|
||||
LauncherAuthlib.jar
|
||||
LauncherModules.zip
|
||||
LaunchServerModules.zip
|
||||
ServerWrapperModules.zip
|
||||
LauncherBase.zip
|
||||
artifacts/*
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
sourceCompatibility = '11'
|
||||
targetCompatibility = '11'
|
||||
sourceCompatibility = '17'
|
||||
targetCompatibility = '17'
|
||||
|
||||
configurations {
|
||||
compileOnlyA
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launcher.hasher.HashedDir;
|
||||
import pro.gravit.launcher.managers.ConfigManager;
|
||||
import pro.gravit.launcher.managers.GarbageManager;
|
||||
import pro.gravit.launcher.modules.events.ClosePhase;
|
||||
|
@ -40,10 +39,7 @@
|
|||
import java.lang.invoke.MethodType;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.security.interfaces.ECPrivateKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
@ -89,10 +85,6 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
|||
* This object contains runtime configuration
|
||||
*/
|
||||
public final LaunchServerRuntimeConfig runtime;
|
||||
@Deprecated
|
||||
public final ECPublicKey publicKey;
|
||||
@Deprecated
|
||||
public final ECPrivateKey privateKey;
|
||||
/**
|
||||
* Pipeline for building JAR
|
||||
*/
|
||||
|
@ -121,18 +113,15 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
|||
// Server
|
||||
public final CommandHandler commandHandler;
|
||||
public final NettyServerSocketHandler nettyServerSocketHandler;
|
||||
@Deprecated
|
||||
public final Timer taskPool;
|
||||
public final ScheduledExecutorService service;
|
||||
public final AtomicBoolean started = new AtomicBoolean(false);
|
||||
public final LauncherModuleLoader launcherModuleLoader;
|
||||
private final Logger logger = LogManager.getLogger();
|
||||
public LaunchServerConfig config;
|
||||
@Deprecated
|
||||
public volatile Map<String, HashedDir> updatesDirMap;
|
||||
// Updates and profiles
|
||||
private volatile Set<ClientProfile> 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;
|
||||
|
@ -143,13 +132,10 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
|||
this.profilesDir = directories.profilesDir;
|
||||
this.updatesDir = directories.updatesDir;
|
||||
this.keyAgreementManager = keyAgreementManager;
|
||||
this.publicKey = keyAgreementManager.ecdsaPublicKey;
|
||||
this.privateKey = keyAgreementManager.ecdsaPrivateKey;
|
||||
this.commandHandler = commandHandler;
|
||||
this.runtime = runtimeConfig;
|
||||
this.certificateManager = certificateManager;
|
||||
this.service = Executors.newScheduledThreadPool(config.netty.performance.schedulerThread);
|
||||
taskPool = new Timer("Timered task worker thread", true);
|
||||
launcherLibraries = directories.launcherLibrariesDir;
|
||||
launcherLibrariesCompile = directories.launcherLibrariesCompileDir;
|
||||
|
||||
|
@ -247,18 +233,10 @@ public void invoke(String... args) throws Exception {
|
|||
return;
|
||||
}
|
||||
switch (args[0]) {
|
||||
case "full":
|
||||
reload(ReloadType.FULL);
|
||||
break;
|
||||
case "no_auth":
|
||||
reload(ReloadType.NO_AUTH);
|
||||
break;
|
||||
case "no_components":
|
||||
reload(ReloadType.NO_COMPONENTS);
|
||||
break;
|
||||
default:
|
||||
reload(ReloadType.FULL);
|
||||
break;
|
||||
case "full" -> reload(ReloadType.FULL);
|
||||
case "no_auth" -> reload(ReloadType.NO_AUTH);
|
||||
case "no_components" -> reload(ReloadType.NO_COMPONENTS);
|
||||
default -> reload(ReloadType.FULL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -282,14 +260,7 @@ public void invoke(String... args) throws Exception {
|
|||
logger.error("Pair not found");
|
||||
return;
|
||||
}
|
||||
if (pair.isUseCore()) {
|
||||
pair.core.close();
|
||||
} else {
|
||||
pair.provider.close();
|
||||
pair.handler.close();
|
||||
pair.handler = null;
|
||||
pair.provider = null;
|
||||
}
|
||||
pair.core.close();
|
||||
pair.core = new RejectAuthCoreProvider();
|
||||
pair.core.init(instance);
|
||||
}
|
||||
|
@ -341,16 +312,6 @@ public void setProfiles(Set<ClientProfile> profilesList) {
|
|||
this.profilesList = Collections.unmodifiableSet(profilesList);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public HashedDir getUpdateDir(String name) {
|
||||
return updatesDirMap.get(name);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Set<Entry<String, HashedDir>> getUpdateDirs() {
|
||||
return updatesDirMap.entrySet();
|
||||
}
|
||||
|
||||
public void rebindNettyServerSocket() {
|
||||
nettyServerSocketHandler.close();
|
||||
CommonHelper.newThread("Netty Server Socket Thread", false, nettyServerSocketHandler).start();
|
||||
|
@ -445,6 +406,7 @@ public void restart() {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void registerObject(String name, Object object) {
|
||||
if (object instanceof Reconfigurable) {
|
||||
reconfigurableManager.registerReconfigurable(name, (Reconfigurable) object);
|
||||
|
@ -454,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);
|
||||
|
|
|
@ -11,17 +11,14 @@
|
|||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.session.SessionStorage;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
import pro.gravit.launchserver.components.Component;
|
||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||
import pro.gravit.launchserver.manangers.CertificateManager;
|
||||
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
|
||||
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
||||
|
@ -85,9 +82,6 @@ public static void main(String[] args) throws Exception {
|
|||
logger.warn("LaunchServer signed incorrectly. Status: {}", result.type.name());
|
||||
}
|
||||
}
|
||||
if (JVMHelper.getVersion() < 17) {
|
||||
logger.warn("LaunchServer will end Java {} support in next release. Please install Java 17 or above", JVMHelper.getVersion());
|
||||
}
|
||||
|
||||
LaunchServerRuntimeConfig runtimeConfig;
|
||||
LaunchServerConfig config;
|
||||
|
@ -204,13 +198,10 @@ public static void initGson(LaunchServerModulesManager modulesManager) {
|
|||
public static void registerAll() {
|
||||
AuthCoreProvider.registerProviders();
|
||||
PasswordVerifier.registerProviders();
|
||||
AuthHandler.registerHandlers();
|
||||
AuthProvider.registerProviders();
|
||||
TextureProvider.registerProviders();
|
||||
Component.registerComponents();
|
||||
ProtectHandler.registerHandlers();
|
||||
WebSocketService.registerResponses();
|
||||
DaoProvider.registerProviders();
|
||||
AuthRequest.registerProviders();
|
||||
GetAvailabilityAuthRequest.registerProviders();
|
||||
HWIDProvider.registerProviders();
|
||||
|
|
|
@ -1,10 +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.handler.AuthHandler;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.core.MySQLCoreProvider;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -13,22 +14,16 @@
|
|||
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;
|
||||
public AuthProvider provider;
|
||||
public AuthHandler handler;
|
||||
public TextureProvider textureProvider;
|
||||
public Map<String, String> links;
|
||||
public transient String name;
|
||||
public transient Set<String> features;
|
||||
public String displayName;
|
||||
|
||||
public AuthProviderPair(AuthProvider provider, AuthHandler handler, TextureProvider textureProvider) {
|
||||
this.provider = provider;
|
||||
this.handler = handler;
|
||||
this.textureProvider = textureProvider;
|
||||
}
|
||||
private transient boolean warnOAuthShow = false;
|
||||
|
||||
public AuthProviderPair(AuthCoreProvider core, TextureProvider textureProvider) {
|
||||
this.core = core;
|
||||
|
@ -52,6 +47,15 @@ public static Set<String> 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<String> list) {
|
||||
Features features = clazz.getAnnotation(Features.class);
|
||||
if (features != null) {
|
||||
|
@ -80,23 +84,12 @@ public final <T> T isSupport(Class<T> clazz) {
|
|||
public final void init(LaunchServer srv, String name) {
|
||||
this.name = name;
|
||||
if (links != null) link(srv);
|
||||
if (core == null) {
|
||||
if (provider == null) throw new NullPointerException(String.format("Auth %s provider null", name));
|
||||
if (handler == null) throw new NullPointerException(String.format("Auth %s handler null", name));
|
||||
if (social != null)
|
||||
throw new IllegalArgumentException(String.format("Auth %s social can't be used in provider/handler method", name));
|
||||
provider.init(srv);
|
||||
handler.init(srv);
|
||||
} else {
|
||||
if (provider != null) throw new IllegalArgumentException(String.format("Auth %s provider not null", name));
|
||||
if (handler != null) throw new IllegalArgumentException(String.format("Auth %s handler not null", name));
|
||||
core.init(srv);
|
||||
features = new HashSet<>();
|
||||
getFeatures(core.getClass(), features);
|
||||
if (social != null) {
|
||||
social.init(srv, core);
|
||||
getFeatures(social.getClass(), features);
|
||||
}
|
||||
core.init(srv);
|
||||
features = new HashSet<>();
|
||||
getFeatures(core.getClass(), features);
|
||||
if (social != null) {
|
||||
social.init(srv, core);
|
||||
getFeatures(social.getClass(), features);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,19 +99,7 @@ public final void link(LaunchServer srv) {
|
|||
if (pair == null) {
|
||||
throw new NullPointerException(String.format("Auth %s link failed. Pair %s not found", name, v));
|
||||
}
|
||||
if ("provider".equals(k)) {
|
||||
if (pair.provider == null)
|
||||
throw new NullPointerException(String.format("Auth %s link failed. %s.provider is null", name, v));
|
||||
provider = pair.provider;
|
||||
} else if ("handler".equals(k)) {
|
||||
if (pair.handler == null)
|
||||
throw new NullPointerException(String.format("Auth %s link failed. %s.handler is null", name, v));
|
||||
handler = pair.handler;
|
||||
} else if ("textureProvider".equals(k)) {
|
||||
if (pair.textureProvider == null)
|
||||
throw new NullPointerException(String.format("Auth %s link failed. %s.textureProvider is null", name, v));
|
||||
textureProvider = pair.textureProvider;
|
||||
} else if ("core".equals(k)) {
|
||||
if ("core".equals(k)) {
|
||||
if (pair.core == null)
|
||||
throw new NullPointerException(String.format("Auth %s link failed. %s.core is null", name, v));
|
||||
core = pair.core;
|
||||
|
@ -130,26 +111,13 @@ public final void close() throws IOException {
|
|||
if (social != null) {
|
||||
social.close();
|
||||
}
|
||||
if (core == null) {
|
||||
provider.close();
|
||||
handler.close();
|
||||
} else {
|
||||
core.close();
|
||||
}
|
||||
core.close();
|
||||
if (textureProvider != null) {
|
||||
textureProvider.close();
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isUseCore() {
|
||||
return core != null;
|
||||
}
|
||||
|
||||
public final boolean isUseSocial() {
|
||||
return core != null && social != null;
|
||||
}
|
||||
|
||||
public final boolean isUseProviderAndHandler() {
|
||||
return !isUseCore();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package pro.gravit.launchserver.auth;
|
||||
|
||||
@Deprecated
|
||||
public interface RequiredDAO {
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package pro.gravit.launchserver.auth.core;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
|
@ -14,6 +15,7 @@
|
|||
import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportGetAllUsers;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRegistration;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||
import pro.gravit.launchserver.manangers.AuthManager;
|
||||
|
@ -25,6 +27,7 @@
|
|||
import pro.gravit.utils.command.SubCommand;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -93,7 +96,7 @@ public void invoke(String... args) throws Exception {
|
|||
if (report.success) {
|
||||
logger.info("Password correct");
|
||||
} else {
|
||||
if (report.needMoreFactor) {
|
||||
if (report.needMoreFactors) {
|
||||
if (report.factors.size() == 1 && report.factors.get(0) == -1) {
|
||||
logger.info("Password not correct: Required 2FA");
|
||||
} else {
|
||||
|
@ -145,13 +148,13 @@ public void invoke(String... args) throws Exception {
|
|||
return;
|
||||
}
|
||||
if (report.isUsingOAuth()) {
|
||||
logger.info("OAuth: AccessToken: {} RefreshToken: {} MinecraftAccessToken: {}", report.oauthAccessToken, report.oauthRefreshToken, report.minecraftAccessToken);
|
||||
if (report.session != null) {
|
||||
logger.info("UserSession: id {} expire {} user {}", report.session.getID(), report.session.getExpireIn(), report.session.getUser() == null ? "null" : "found");
|
||||
logger.info(report.session.toString());
|
||||
logger.info("OAuth: AccessToken: {} RefreshToken: {} MinecraftAccessToken: {}", report.oauthAccessToken(), report.oauthRefreshToken(), report.minecraftAccessToken());
|
||||
if (report.session() != null) {
|
||||
logger.info("UserSession: id {} expire {} user {}", report.session().getID(), report.session().getExpireIn(), report.session().getUser() == null ? "null" : "found");
|
||||
logger.info(report.session().toString());
|
||||
}
|
||||
} else {
|
||||
logger.info("Basic: MinecraftAccessToken: {}", report.minecraftAccessToken);
|
||||
logger.info("Basic: MinecraftAccessToken: {}", report.minecraftAccessToken());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -281,6 +284,33 @@ public void invoke(String... args) throws Exception {
|
|||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
var instance = isSupport(AuthSupportRegistration.class);
|
||||
if (instance != null) {
|
||||
map.put("register", new SubCommand("[username] [email] [plain or json password] (json args)", "Register new user") {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 2);
|
||||
Map<String, String> map = null;
|
||||
String username = args[0];
|
||||
String email = args[1];
|
||||
String plainPassword = args[2];
|
||||
if (args.length > 3) {
|
||||
Type typeOfMap = new TypeToken<Map<String, String>>() {
|
||||
}.getType();
|
||||
map = Launcher.gsonManager.gson.fromJson(args[2], typeOfMap);
|
||||
}
|
||||
AuthRequest.AuthPasswordInterface password;
|
||||
if (plainPassword.startsWith("{")) {
|
||||
password = Launcher.gsonManager.gson.fromJson(plainPassword, AuthRequest.AuthPasswordInterface.class);
|
||||
} else {
|
||||
password = new AuthPlainPassword(plainPassword);
|
||||
}
|
||||
instance.registration(username, email, password, map);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -315,30 +345,30 @@ public static class PasswordVerifyReport {
|
|||
public static final PasswordVerifyReport FAILED = new PasswordVerifyReport(false);
|
||||
public static final PasswordVerifyReport OK = new PasswordVerifyReport(true);
|
||||
public final boolean success;
|
||||
public final boolean needMoreFactor;
|
||||
public final boolean needMoreFactors;
|
||||
public final List<Integer> factors;
|
||||
|
||||
public PasswordVerifyReport(boolean success) {
|
||||
this.success = success;
|
||||
this.needMoreFactor = false;
|
||||
this.needMoreFactors = false;
|
||||
this.factors = List.of();
|
||||
}
|
||||
|
||||
public PasswordVerifyReport(int nextFactor) {
|
||||
this.success = false;
|
||||
this.needMoreFactor = true;
|
||||
this.needMoreFactors = true;
|
||||
this.factors = List.of(nextFactor);
|
||||
}
|
||||
|
||||
public PasswordVerifyReport(List<Integer> factors) {
|
||||
this.success = false;
|
||||
this.needMoreFactor = false;
|
||||
this.needMoreFactors = false;
|
||||
this.factors = Collections.unmodifiableList(factors);
|
||||
}
|
||||
|
||||
private PasswordVerifyReport(boolean success, boolean needMoreFactor, List<Integer> factors) {
|
||||
private PasswordVerifyReport(boolean success, boolean needMoreFactors, List<Integer> factors) {
|
||||
this.success = success;
|
||||
this.needMoreFactor = needMoreFactor;
|
||||
this.needMoreFactors = needMoreFactors;
|
||||
this.factors = factors;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
public abstract class AuthHandler implements AutoCloseable {
|
||||
public static final ProviderMap<AuthHandler> providers = new ProviderMap<>("AuthHandler");
|
||||
private static boolean registredHandl = false;
|
||||
protected transient LaunchServer srv;
|
||||
|
||||
public static UUID authError(String message) throws AuthException {
|
||||
throw new AuthException(message);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void registerHandlers() {
|
||||
if (!registredHandl) {
|
||||
providers.register("null", NullAuthHandler.class);
|
||||
providers.register("json", JsonAuthHandler.class);
|
||||
providers.register("memory", MemoryAuthHandler.class);
|
||||
providers.register("mysql", MySQLAuthHandler.class);
|
||||
providers.register("postgresql", PostgreSQLAuthHandler.class);
|
||||
providers.register("request", RequestAuthHandler.class);
|
||||
providers.register("hibernate", HibernateAuthHandler.class);
|
||||
registredHandl = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UUID associated with the account
|
||||
*
|
||||
* @param authResult {@link pro.gravit.launchserver.auth.provider.AuthProvider} result
|
||||
* @return User UUID
|
||||
* @throws IOException Internal Script Error
|
||||
*/
|
||||
public abstract UUID auth(AuthProviderResult authResult) throws IOException;
|
||||
|
||||
/**
|
||||
* Validates serverID
|
||||
*
|
||||
* @param username user name
|
||||
* @param serverID serverID to check
|
||||
* @return user UUID
|
||||
* @throws IOException Internal Script Error
|
||||
*/
|
||||
public abstract UUID checkServer(String username, String serverID) throws IOException;
|
||||
|
||||
@Override
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Checks assessToken for validity and saves serverID if successful
|
||||
*
|
||||
* @param username user name
|
||||
* @param accessToken assessToken to check
|
||||
* @param serverID serverID to save
|
||||
* @return true - allow, false - deny
|
||||
* @throws IOException Internal Script Error
|
||||
*/
|
||||
public abstract boolean joinServer(String username, String accessToken, String serverID) throws IOException;
|
||||
|
||||
|
||||
public abstract UUID usernameToUUID(String username) throws IOException;
|
||||
|
||||
|
||||
public abstract String uuidToUsername(UUID uuid) throws IOException;
|
||||
|
||||
public void init(LaunchServer srv) {
|
||||
this.srv = srv;
|
||||
}
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launchserver.Reconfigurable;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.utils.command.Command;
|
||||
import pro.gravit.utils.command.SubCommand;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class CachedAuthHandler extends AuthHandler implements NeedGarbageCollection, Reconfigurable {
|
||||
private transient final Map<UUID, Entry> entryCache = new HashMap<>(1024);
|
||||
private transient final Map<String, UUID> usernamesCache = new HashMap<>(1024);
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
|
||||
@Override
|
||||
public Map<String, Command> getCommands() {
|
||||
Map<String, Command> commands = new HashMap<>();
|
||||
commands.put("clear", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) {
|
||||
long entryCacheSize = entryCache.size();
|
||||
long usernamesCacheSize = usernamesCache.size();
|
||||
entryCache.clear();
|
||||
usernamesCache.clear();
|
||||
logger.info("Cleared cache: {} Entry {} Usernames", entryCacheSize, usernamesCacheSize);
|
||||
}
|
||||
});
|
||||
commands.put("load", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 2);
|
||||
|
||||
logger.info("CachedAuthHandler read from {}", args[0]);
|
||||
int size_entry;
|
||||
int size_username;
|
||||
try (Reader reader = IOHelper.newReader(Paths.get(args[1]))) {
|
||||
EntryAndUsername entryAndUsername = Launcher.gsonManager.configGson.fromJson(reader, EntryAndUsername.class);
|
||||
size_entry = entryAndUsername.entryCache.size();
|
||||
size_username = entryAndUsername.usernameCache.size();
|
||||
loadEntryCache(entryAndUsername.entryCache);
|
||||
loadUsernameCache(entryAndUsername.usernameCache);
|
||||
|
||||
}
|
||||
logger.info("Read {} entryCache {} usernameCache", size_entry, size_username);
|
||||
}
|
||||
});
|
||||
commands.put("unload", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 2);
|
||||
|
||||
logger.info("CachedAuthHandler write to {}", args[1]);
|
||||
Map<UUID, CachedAuthHandler.Entry> entryCache = getEntryCache();
|
||||
Map<String, UUID> usernamesCache = getUsernamesCache();
|
||||
EntryAndUsername serializable = new EntryAndUsername();
|
||||
serializable.entryCache = entryCache;
|
||||
serializable.usernameCache = usernamesCache;
|
||||
try (Writer writer = IOHelper.newWriter(Paths.get(args[1]))) {
|
||||
Launcher.gsonManager.configGson.toJson(serializable, writer);
|
||||
}
|
||||
logger.info("Write {} entryCache, {} usernameCache", entryCache.size(), usernamesCache.size());
|
||||
}
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
|
||||
protected void addEntry(Entry entry) {
|
||||
Entry previous = entryCache.put(entry.uuid, entry);
|
||||
if (previous != null)
|
||||
usernamesCache.remove(CommonHelper.low(previous.username));
|
||||
usernamesCache.put(CommonHelper.low(entry.username), entry.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized UUID auth(AuthProviderResult result) throws IOException {
|
||||
Entry entry = getEntry(result.username);
|
||||
if (entry == null || !updateAuth(entry.uuid, entry.username, result.accessToken))
|
||||
return authError(String.format("UUID is null for username '%s'", result.username));
|
||||
|
||||
// Update cached access token (and username case)
|
||||
entry.username = result.username;
|
||||
entry.accessToken = result.accessToken;
|
||||
entry.serverID = null;
|
||||
return entry.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized UUID checkServer(String username, String serverID) throws IOException {
|
||||
Entry entry = getEntry(username);
|
||||
return entry != null && username.equals(entry.username) &&
|
||||
serverID.equals(entry.serverID) ? entry.uuid : null;
|
||||
}
|
||||
|
||||
protected abstract Entry fetchEntry(String username) throws IOException;
|
||||
|
||||
protected abstract Entry fetchEntry(UUID uuid) throws IOException;
|
||||
|
||||
private Entry getEntry(String username) throws IOException {
|
||||
UUID uuid = usernamesCache.get(CommonHelper.low(username));
|
||||
if (uuid != null)
|
||||
return getEntry(uuid);
|
||||
|
||||
// Fetch entry by username
|
||||
Entry entry = fetchEntry(username);
|
||||
if (entry != null)
|
||||
addEntry(entry);
|
||||
|
||||
// Return what we got
|
||||
return entry;
|
||||
}
|
||||
|
||||
private Entry getEntry(UUID uuid) throws IOException {
|
||||
Entry entry = entryCache.get(uuid);
|
||||
if (entry == null) {
|
||||
entry = fetchEntry(uuid);
|
||||
if (entry != null)
|
||||
addEntry(entry);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean joinServer(String username, String accessToken, String serverID) throws IOException {
|
||||
Entry entry = getEntry(username);
|
||||
if (entry == null || !username.equals(entry.username) || !accessToken.equals(entry.accessToken) ||
|
||||
!updateServerID(entry.uuid, serverID))
|
||||
return false; // Account doesn't exist or invalid access token
|
||||
|
||||
// Update cached server ID
|
||||
entry.serverID = serverID;
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void garbageCollection() {
|
||||
entryCache.clear();
|
||||
usernamesCache.clear();
|
||||
}
|
||||
|
||||
public Map<UUID, Entry> getEntryCache() {
|
||||
return entryCache;
|
||||
}
|
||||
|
||||
public Map<String, UUID> getUsernamesCache() {
|
||||
return usernamesCache;
|
||||
}
|
||||
|
||||
public void loadEntryCache(Map<UUID, Entry> map) {
|
||||
entryCache.putAll(map);
|
||||
}
|
||||
|
||||
public void loadUsernameCache(Map<String, UUID> map) {
|
||||
usernamesCache.putAll(map);
|
||||
}
|
||||
|
||||
protected abstract boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException;
|
||||
|
||||
protected abstract boolean updateServerID(UUID uuid, String serverID) throws IOException;
|
||||
|
||||
@Override
|
||||
public final synchronized UUID usernameToUUID(String username) throws IOException {
|
||||
Entry entry = getEntry(username);
|
||||
return entry == null ? null : entry.uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized String uuidToUsername(UUID uuid) throws IOException {
|
||||
Entry entry = getEntry(uuid);
|
||||
return entry == null ? null : entry.username;
|
||||
}
|
||||
|
||||
public static final class Entry {
|
||||
|
||||
public final UUID uuid;
|
||||
private String username;
|
||||
private String accessToken;
|
||||
private String serverID;
|
||||
|
||||
|
||||
public Entry(UUID uuid, String username, String accessToken, String serverID) {
|
||||
this.uuid = Objects.requireNonNull(uuid, "uuid");
|
||||
this.username = Objects.requireNonNull(username, "username");
|
||||
this.accessToken = accessToken == null ? null : SecurityHelper.verifyToken(accessToken);
|
||||
this.serverID = serverID == null ? null : VerifyHelper.verifyServerID(serverID);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class EntryAndUsername {
|
||||
public Map<UUID, CachedAuthHandler.Entry> entryCache;
|
||||
public Map<String, UUID> usernameCache;
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import pro.gravit.launchserver.auth.RequiredDAO;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
public class HibernateAuthHandler extends CachedAuthHandler implements RequiredDAO {
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) {
|
||||
User user = srv.config.dao.userDAO.findByUsername(username);
|
||||
if (user == null) return null;
|
||||
return new Entry(user.getUuid(), user.getUsername(), user.getAccessToken(), user.getServerID());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) {
|
||||
User user = srv.config.dao.userDAO.findByUUID(uuid);
|
||||
if (user == null) return null;
|
||||
return new Entry(user.getUuid(), user.getUsername(), user.getAccessToken(), user.getServerID());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) {
|
||||
User user = srv.config.dao.userDAO.findByUUID(uuid);
|
||||
user.setAccessToken(accessToken);
|
||||
srv.config.dao.userDAO.update(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) {
|
||||
User user = srv.config.dao.userDAO.findByUUID(uuid);
|
||||
user.setServerID(serverID);
|
||||
srv.config.dao.userDAO.update(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import pro.gravit.launcher.HTTPRequest;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public class JsonAuthHandler extends CachedAuthHandler {
|
||||
public URL getUrl;
|
||||
public URL updateAuthUrl;
|
||||
public URL updateServerIdUrl;
|
||||
public String apiKey;
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) throws IOException {
|
||||
return Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new EntryRequestByUsername(username, apiKey)), getUrl), Entry.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) throws IOException {
|
||||
return Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new EntryRequestByUUID(uuid, apiKey)), getUrl), Entry.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||
return Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new UpdateAuthRequest(uuid, username, accessToken, apiKey)), updateAuthUrl), SuccessResponse.class).success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||
return Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new UpdateServerIDRequest(uuid, serverID, apiKey)), updateServerIdUrl), SuccessResponse.class).success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
public static class EntryRequestByUsername {
|
||||
public final String username;
|
||||
public final String apiKey;
|
||||
|
||||
public EntryRequestByUsername(String username, String apiKey) {
|
||||
this.username = username;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntryRequestByUUID {
|
||||
public final UUID uuid;
|
||||
public final String apiKey;
|
||||
|
||||
public EntryRequestByUUID(UUID uuid, String apiKey) {
|
||||
this.uuid = uuid;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateAuthRequest {
|
||||
public final UUID uuid;
|
||||
public final String username;
|
||||
public final String accessToken;
|
||||
public final String apiKey;
|
||||
|
||||
public UpdateAuthRequest(UUID uuid, String username, String accessToken, String apiKey) {
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static class UpdateServerIDRequest {
|
||||
public final UUID uuid;
|
||||
public final String serverID;
|
||||
public final String apiKey;
|
||||
|
||||
public UpdateServerIDRequest(UUID uuid, String serverID, String apiKey) {
|
||||
this.uuid = uuid;
|
||||
this.serverID = serverID;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SuccessResponse {
|
||||
public boolean success;
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MemoryAuthHandler extends CachedAuthHandler {
|
||||
private static String toUsername(UUID uuid) {
|
||||
byte[] bytes = ByteBuffer.allocate(16).
|
||||
putLong(uuid.getMostSignificantBits()).
|
||||
putLong(uuid.getLeastSignificantBits()).array();
|
||||
|
||||
// Find username end
|
||||
int length = 0;
|
||||
while (length < bytes.length && bytes[length] != 0)
|
||||
length++;
|
||||
|
||||
// Decode and verify
|
||||
return VerifyHelper.verifyUsername(new String(bytes, 0, length, IOHelper.ASCII_CHARSET));
|
||||
}
|
||||
|
||||
private static UUID toUUID(String username) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(Arrays.copyOf(IOHelper.encodeASCII(username), 16));
|
||||
return new UUID(buffer.getLong(), buffer.getLong()); // MOST, LEAST
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) {
|
||||
return new Entry(toUUID(username), username, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) {
|
||||
return new Entry(uuid, toUsername(uuid), null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) {
|
||||
return true; // Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) {
|
||||
return true; // Do nothing
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MySQLAuthHandler extends CachedAuthHandler {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
private MySQLSourceConfig mySQLHolder;
|
||||
private String uuidColumn;
|
||||
private String usernameColumn;
|
||||
private String accessTokenColumn;
|
||||
private String serverIDColumn;
|
||||
private String table;
|
||||
|
||||
// Prepared SQL queries
|
||||
private transient String queryByUUIDSQL;
|
||||
private transient String queryByUsernameSQL;
|
||||
private transient String updateAuthSQL;
|
||||
private transient String updateServerIDSQL;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer srv) {
|
||||
super.init(srv);
|
||||
//Verify
|
||||
if (mySQLHolder == null) logger.error("mySQLHolder cannot be null");
|
||||
if (uuidColumn == null) logger.error("uuidColumn cannot be null");
|
||||
if (usernameColumn == null) logger.error("usernameColumn cannot be null");
|
||||
if (accessTokenColumn == null) logger.error("accessTokenColumn cannot be null");
|
||||
if (serverIDColumn == null) logger.error("serverIDColumn cannot be null");
|
||||
if (table == null) logger.error("table cannot be null");
|
||||
// Prepare SQL queries
|
||||
queryByUUIDSQL = String.format("SELECT %s, %s, %s, %s FROM %s WHERE %s=? LIMIT 1",
|
||||
uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, table, uuidColumn);
|
||||
queryByUsernameSQL = String.format("SELECT %s, %s, %s, %s FROM %s WHERE %s=? LIMIT 1",
|
||||
uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, table, usernameColumn);
|
||||
updateAuthSQL = String.format("UPDATE %s SET %s=?, %s=?, %s=NULL WHERE %s=? LIMIT 1",
|
||||
table, usernameColumn, accessTokenColumn, serverIDColumn, uuidColumn);
|
||||
updateServerIDSQL = String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
|
||||
table, serverIDColumn, uuidColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mySQLHolder.close();
|
||||
}
|
||||
|
||||
private Entry constructEntry(ResultSet set) throws SQLException {
|
||||
return set.next() ? new Entry(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
|
||||
set.getString(accessTokenColumn), set.getString(serverIDColumn)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) throws IOException {
|
||||
return query(queryByUsernameSQL, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) throws IOException {
|
||||
return query(queryByUUIDSQL, uuid.toString());
|
||||
}
|
||||
|
||||
private Entry query(String sql, String value) throws IOException {
|
||||
try (Connection c = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = c.prepareStatement(sql);
|
||||
s.setString(1, value);
|
||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||
try (ResultSet set = s.executeQuery()) {
|
||||
return constructEntry(set);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||
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());
|
||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||
return s.executeUpdate() > 0;
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||
try (Connection c = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = c.prepareStatement(updateServerIDSQL);
|
||||
s.setString(1, serverID);
|
||||
s.setString(2, uuid.toString());
|
||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||
return s.executeUpdate() > 0;
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class NullAuthHandler extends AuthHandler {
|
||||
private volatile AuthHandler handler;
|
||||
|
||||
@Override
|
||||
public UUID auth(AuthProviderResult authResult) throws IOException {
|
||||
return getHandler().auth(authResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID checkServer(String username, String serverID) throws IOException {
|
||||
return getHandler().checkServer(username, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
AuthHandler handler = this.handler;
|
||||
if (handler != null)
|
||||
handler.close();
|
||||
}
|
||||
|
||||
private AuthHandler getHandler() {
|
||||
return VerifyHelper.verify(handler, Objects::nonNull, "Backend auth handler wasn't set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinServer(String username, String accessToken, String serverID) throws IOException {
|
||||
return getHandler().joinServer(username, accessToken, serverID);
|
||||
}
|
||||
|
||||
|
||||
public void setBackend(AuthHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID usernameToUUID(String username) throws IOException {
|
||||
return getHandler().usernameToUUID(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uuidToUsername(UUID uuid) throws IOException {
|
||||
return getHandler().uuidToUsername(uuid);
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import org.postgresql.util.PGobject;
|
||||
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PostgreSQLAuthHandler extends CachedAuthHandler {
|
||||
private PostgreSQLSourceConfig postgreSQLHolder;
|
||||
private String uuidColumn;
|
||||
private String usernameColumn;
|
||||
private String accessTokenColumn;
|
||||
private String serverIDColumn;
|
||||
|
||||
|
||||
private String queryByUUIDSQL;
|
||||
private String queryByUsernameSQL;
|
||||
private String updateAuthSQL;
|
||||
private String updateServerIDSQL;
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
postgreSQLHolder.close();
|
||||
}
|
||||
|
||||
private Entry constructEntry(ResultSet set) throws SQLException {
|
||||
return set.next() ? new Entry(UUID.fromString(set.getString(uuidColumn)),
|
||||
set.getString(usernameColumn), set.getString(accessTokenColumn), set.getString(serverIDColumn)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) throws IOException {
|
||||
return query(queryByUsernameSQL, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) throws IOException {
|
||||
return query(queryByUUIDSQL, uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||
try (Connection c = postgreSQLHolder.getConnection();
|
||||
PreparedStatement s = c.prepareStatement(updateAuthSQL)) {
|
||||
s.setString(1, username); // Username case
|
||||
s.setString(2, accessToken);
|
||||
|
||||
PGobject uuidObject = new PGobject();
|
||||
uuidObject.setType("uuid");
|
||||
uuidObject.setValue(uuid.toString());
|
||||
s.setObject(3, uuidObject);
|
||||
|
||||
// Execute update
|
||||
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||
return s.executeUpdate() > 0;
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||
try (Connection c = postgreSQLHolder.getConnection();
|
||||
PreparedStatement s = c.prepareStatement(updateServerIDSQL)) {
|
||||
s.setString(1, serverID);
|
||||
|
||||
PGobject uuidObject = new PGobject();
|
||||
uuidObject.setType("uuid");
|
||||
uuidObject.setValue(uuid.toString());
|
||||
s.setObject(2, uuidObject);
|
||||
|
||||
// Execute update
|
||||
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||
return s.executeUpdate() > 0;
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Entry query(String sql, String value) throws IOException {
|
||||
try (Connection c = postgreSQLHolder.getConnection();
|
||||
PreparedStatement s = c.prepareStatement(sql)) {
|
||||
s.setString(1, value);
|
||||
|
||||
// Execute query
|
||||
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||
try (ResultSet set = s.executeQuery()) {
|
||||
return constructEntry(set);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Entry query(String sql, UUID value) throws IOException {
|
||||
try (Connection c = postgreSQLHolder.getConnection();
|
||||
PreparedStatement s = c.prepareStatement(sql)) {
|
||||
PGobject uuidObject = new PGobject();
|
||||
uuidObject.setType("uuid");
|
||||
uuidObject.setValue(value.toString());
|
||||
|
||||
s.setObject(1, uuidObject);
|
||||
|
||||
// Execute query
|
||||
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||
try (ResultSet set = s.executeQuery()) {
|
||||
return constructEntry(set);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.handler;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class RequestAuthHandler extends CachedAuthHandler {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
private final String splitSymbol = ":";
|
||||
private final String goodResponse = "OK";
|
||||
private String usernameFetch;
|
||||
private String uuidFetch;
|
||||
private String updateAuth;
|
||||
private String updateServerID;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer srv) {
|
||||
super.init(srv);
|
||||
if (usernameFetch == null)
|
||||
logger.error("usernameFetch cannot be null");
|
||||
if (uuidFetch == null)
|
||||
logger.error("uuidFetch cannot be null");
|
||||
if (updateAuth == null)
|
||||
logger.error("updateAuth cannot be null");
|
||||
if (updateServerID == null)
|
||||
logger.error("updateServerID cannot be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(UUID uuid) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(uuidFetch, "uuid", IOHelper.urlEncode(uuid.toString()))));
|
||||
String[] parts = response.split(splitSymbol);
|
||||
String username = parts[0];
|
||||
String accessToken = parts[1];
|
||||
String serverID = parts[2];
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[AuthHandler] Got username: " + username);
|
||||
logger.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
logger.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
logger.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
}
|
||||
return new Entry(uuid, username, accessToken, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(usernameFetch, "user", IOHelper.urlEncode(username))));
|
||||
String[] parts = response.split(splitSymbol);
|
||||
UUID uuid = UUID.fromString(parts[0]);
|
||||
String accessToken = parts[1];
|
||||
String serverID = parts[2];
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[AuthHandler] Got username: " + username);
|
||||
logger.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
logger.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
logger.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
}
|
||||
return new Entry(uuid, username, accessToken, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "user", IOHelper.urlEncode(username), "uuid", IOHelper.urlEncode(uuid.toString()), "token", IOHelper.urlEncode(accessToken))));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[AuthHandler] Set accessToken: " + accessToken);
|
||||
logger.debug("[AuthHandler] Set UUID: " + uuid);
|
||||
logger.debug("[AuthHandler] For this username: " + username);
|
||||
}
|
||||
return goodResponse.equals(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "serverid", IOHelper.urlEncode(serverID), "uuid", IOHelper.urlEncode(uuid.toString()))));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("[AuthHandler] Set serverID: " + serverID);
|
||||
logger.debug("[AuthHandler] For this UUID: " + uuid);
|
||||
}
|
||||
return goodResponse.equals(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String, List<String>> profileWhitelist = new HashMap<>();
|
||||
public List<String> 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 !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 !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<String> 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.hasPerm(permByUUID)) {
|
||||
return true;
|
||||
}
|
||||
String permByTitle = String.format(property, profile.getTitle().toLowerCase(Locale.ROOT));
|
||||
if(client.permissions.hasPerm(permByTitle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
List<String> allowedUsername = profileWhitelist.get(profile.getTitle());
|
||||
if (allowedUsername != null && allowedUsername.contains(client.username)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public final class AcceptAuthProvider extends AuthProvider {
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) {
|
||||
return new AuthProviderResult(login, SecurityHelper.randomStringToken(), ClientPermissions.DEFAULT); // Same as login
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.details.AuthPasswordDetails;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AuthProvider implements AutoCloseable {
|
||||
public static final ProviderMap<AuthProvider> providers = new ProviderMap<>("AuthProvider");
|
||||
private static boolean registredProv = false;
|
||||
protected transient LaunchServer srv = null;
|
||||
|
||||
public static AuthProviderResult authError(String message) throws AuthException {
|
||||
throw new AuthException(message);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void registerProviders() {
|
||||
if (!registredProv) {
|
||||
providers.register("null", NullAuthProvider.class);
|
||||
providers.register("accept", AcceptAuthProvider.class);
|
||||
providers.register("reject", RejectAuthProvider.class);
|
||||
providers.register("mysql", MySQLAuthProvider.class);
|
||||
providers.register("postgresql", PostgreSQLAuthProvider.class);
|
||||
providers.register("request", RequestAuthProvider.class);
|
||||
providers.register("json", JsonAuthProvider.class);
|
||||
providers.register("hibernate", HibernateAuthProvider.class);
|
||||
registredProv = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public GetAvailabilityAuthRequestEvent.AuthAvailability.AuthType getFirstAuthType() {
|
||||
return GetAvailabilityAuthRequestEvent.AuthAvailability.AuthType.PASSWORD;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public GetAvailabilityAuthRequestEvent.AuthAvailability.AuthType getSecondAuthType() {
|
||||
return GetAvailabilityAuthRequestEvent.AuthAvailability.AuthType.NONE;
|
||||
}
|
||||
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||
return List.of(new AuthPasswordDetails());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the username and password
|
||||
*
|
||||
* @param login user login
|
||||
* @param password user password
|
||||
* @param ip user ip
|
||||
* @return player privileges, effective username and authorization token
|
||||
* @throws Exception Throws an exception {@link AuthException} {@link pro.gravit.utils.HookException} if the verification script returned a meaningful error
|
||||
* In other cases, throwing an exception indicates a serious error
|
||||
*/
|
||||
public abstract AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception;
|
||||
|
||||
public void preAuth(String login, AuthRequest.AuthPasswordInterface password, String ip) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
public void init(LaunchServer srv) {
|
||||
this.srv = srv;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
|
||||
@Deprecated
|
||||
public class AuthProviderDAOResult extends AuthProviderResult {
|
||||
public User daoObject;
|
||||
|
||||
public AuthProviderDAOResult(String username, String accessToken) {
|
||||
super(username, accessToken);
|
||||
}
|
||||
|
||||
public AuthProviderDAOResult(String username, String accessToken, ClientPermissions permissions) {
|
||||
super(username, accessToken, permissions);
|
||||
}
|
||||
|
||||
public AuthProviderDAOResult(String username, String accessToken, ClientPermissions permissions, User daoObject) {
|
||||
super(username, accessToken, permissions);
|
||||
this.daoObject = daoObject;
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
|
||||
|
||||
public class AuthProviderResult {
|
||||
public final String username;
|
||||
public final String accessToken;
|
||||
public final ClientPermissions permissions;
|
||||
|
||||
public AuthProviderResult(String username, String accessToken) {
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
permissions = ClientPermissions.DEFAULT;
|
||||
}
|
||||
|
||||
public AuthProviderResult(String username, String accessToken, ClientPermissions permissions) {
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper.DigestAlgorithm;
|
||||
|
||||
public abstract class DigestAuthProvider extends AuthProvider {
|
||||
private DigestAlgorithm digest;
|
||||
|
||||
|
||||
protected final void verifyDigest(String validDigest, String password) throws AuthException {
|
||||
boolean valid;
|
||||
if (digest == DigestAlgorithm.PLAIN)
|
||||
valid = password.equals(validDigest);
|
||||
else if (validDigest == null)
|
||||
valid = false;
|
||||
else {
|
||||
byte[] actualDigest = SecurityHelper.digest(digest, password);
|
||||
valid = SecurityHelper.toHex(actualDigest).equals(validDigest);
|
||||
}
|
||||
|
||||
// Verify is valid
|
||||
if (!valid)
|
||||
authError("Incorrect username or password");
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.RequiredDAO;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
@Deprecated
|
||||
public class HibernateAuthProvider extends AuthProvider implements RequiredDAO {
|
||||
public boolean autoReg;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
User user = srv.config.dao.userDAO.findByUsername(login);
|
||||
if (user == null && autoReg) {
|
||||
AuthHookManager.RegContext context = new AuthHookManager.RegContext(login, ((AuthPlainPassword) password).password, ip, false);
|
||||
if (srv.authHookManager.registraion.hook(context)) {
|
||||
//user = srv.config.dao.userService.registerNewUser(login, ((AuthPlainPassword) password).password); //TODO: FIX
|
||||
} else {
|
||||
throw new AuthException("Registration canceled. Try again later");
|
||||
}
|
||||
}
|
||||
if (user == null || !user.verifyPassword(((AuthPlainPassword) password).password)) {
|
||||
if (user == null) throw new AuthException("Username incorrect");
|
||||
else throw new AuthException("Username or password incorrect");
|
||||
}
|
||||
return new AuthProviderDAOResult(user.getUsername(), SecurityHelper.randomStringToken(), user.getPermissions(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.HTTPRequest;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.Auth2FAPassword;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launcher.request.auth.password.AuthTOTPPassword;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class JsonAuthProvider extends AuthProvider {
|
||||
public URL url;
|
||||
public boolean enable2FA;
|
||||
public String apiKey;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException {
|
||||
String firstPassword;
|
||||
String secondPassword;
|
||||
if (!enable2FA) {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
firstPassword = ((AuthPlainPassword) password).password;
|
||||
secondPassword = null;
|
||||
} else {
|
||||
if (password instanceof AuthPlainPassword) {
|
||||
firstPassword = ((AuthPlainPassword) password).password;
|
||||
secondPassword = null;
|
||||
} else if (password instanceof Auth2FAPassword) {
|
||||
if (!(((Auth2FAPassword) password).firstPassword instanceof AuthPlainPassword))
|
||||
throw new AuthException("This password type not supported");
|
||||
firstPassword = ((AuthPlainPassword) ((Auth2FAPassword) password).firstPassword).password;
|
||||
if (!(((Auth2FAPassword) password).secondPassword instanceof AuthTOTPPassword))
|
||||
throw new AuthException("This password type not supported");
|
||||
secondPassword = ((AuthTOTPPassword) ((Auth2FAPassword) password).secondPassword).totp;
|
||||
} else {
|
||||
throw new AuthException("This password type not supported");
|
||||
}
|
||||
}
|
||||
|
||||
JsonElement content = HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new authRequest(login, firstPassword, secondPassword, ip, apiKey)), url);
|
||||
if (!content.isJsonObject())
|
||||
return authError("Authentication server response is malformed");
|
||||
authResult result = Launcher.gsonManager.gson.fromJson(content, authResult.class);
|
||||
if (result.username != null)
|
||||
return new AuthProviderResult(result.username, SecurityHelper.randomStringToken(), new ClientPermissions(result.permissions, result.flags));
|
||||
else return authError(Objects.requireNonNullElse(result.error, "Authentication server response is malformed"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// pass
|
||||
}
|
||||
|
||||
public static class authResult {
|
||||
String username;
|
||||
String error;
|
||||
long permissions;
|
||||
long flags;
|
||||
}
|
||||
|
||||
public static class authRequest {
|
||||
final String username;
|
||||
final String password;
|
||||
final String secondPassword;
|
||||
final String ip;
|
||||
String apiKey;
|
||||
|
||||
public authRequest(String username, String password, String ip) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.secondPassword = null;
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public authRequest(String username, String password, String secondPassword, String ip, String apiKey) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.secondPassword = secondPassword;
|
||||
this.ip = ip;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public final class MySQLAuthProvider extends AuthProvider {
|
||||
private MySQLSourceConfig mySQLHolder;
|
||||
private String query;
|
||||
private String message;
|
||||
private String[] queryParams;
|
||||
private boolean flagsEnabled;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer srv) {
|
||||
super.init(srv);
|
||||
if (mySQLHolder == null) throw new RuntimeException("[Verify][AuthProvider] mySQLHolder cannot be null");
|
||||
if (query == null) throw new RuntimeException("[Verify][AuthProvider] query cannot be null");
|
||||
if (message == null) throw new RuntimeException("[Verify][AuthProvider] message cannot be null");
|
||||
if (queryParams == null) throw new RuntimeException("[Verify][AuthProvider] queryParams cannot be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws SQLException, AuthException {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
try (Connection c = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = c.prepareStatement(query);
|
||||
String[] replaceParams = {"login", login, "password", ((AuthPlainPassword) 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(), new ClientPermissions(
|
||||
set.getLong(2), flagsEnabled ? set.getLong(3) : 0)) : authError(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mySQLHolder.close();
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class NullAuthProvider extends AuthProvider {
|
||||
private volatile AuthProvider provider;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception {
|
||||
return getProvider().auth(login, password, ip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
AuthProvider provider = this.provider;
|
||||
if (provider != null)
|
||||
provider.close();
|
||||
}
|
||||
|
||||
private AuthProvider getProvider() {
|
||||
return VerifyHelper.verify(provider, Objects::nonNull, "Backend auth provider wasn't set");
|
||||
}
|
||||
|
||||
|
||||
public void setBackend(AuthProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public final class PostgreSQLAuthProvider extends AuthProvider {
|
||||
private PostgreSQLSourceConfig postgreSQLHolder;
|
||||
private String query;
|
||||
private String message;
|
||||
private String[] queryParams;
|
||||
private boolean flagsEnabled;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws SQLException, AuthException {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
try (Connection c = postgreSQLHolder.getConnection(); PreparedStatement s = c.prepareStatement(query)) {
|
||||
String[] replaceParams = {"login", login, "password", ((AuthPlainPassword) 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(PostgreSQLSourceConfig.TIMEOUT);
|
||||
try (ResultSet set = s.executeQuery()) {
|
||||
return set.next() ? new AuthProviderResult(set.getString(1), SecurityHelper.randomStringToken(), new ClientPermissions(
|
||||
set.getLong(2), flagsEnabled ? set.getLong(3) : 0)) : authError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
postgreSQLHolder.close();
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launchserver.Reconfigurable;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.utils.command.Command;
|
||||
import pro.gravit.utils.command.SubCommand;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class RejectAuthProvider extends AuthProvider implements Reconfigurable {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
public String message;
|
||||
public ArrayList<String> whitelist = new ArrayList<>();
|
||||
|
||||
public RejectAuthProvider() {
|
||||
}
|
||||
|
||||
public RejectAuthProvider(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws AuthException {
|
||||
if (whitelist != null) {
|
||||
for (String username : whitelist) {
|
||||
if (login.equals(username)) {
|
||||
return new AuthProviderResult(login, SecurityHelper.randomStringToken(), ClientPermissions.DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return authError(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Command> getCommands() {
|
||||
Map<String, Command> commands = new HashMap<>();
|
||||
commands.put("message", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
message = args[0];
|
||||
logger.info("New reject message: {}", message);
|
||||
}
|
||||
});
|
||||
commands.put("whitelist.add", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
whitelist.add(args[0]);
|
||||
logger.info("{} added to whitelist", args[0]);
|
||||
}
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class RequestAuthProvider extends AuthProvider {
|
||||
private transient final HttpClient client = HttpClient.newBuilder()
|
||||
.build();
|
||||
public String url;
|
||||
public transient Pattern pattern;
|
||||
public String response;
|
||||
public boolean flagsEnabled;
|
||||
public boolean usePermission = true;
|
||||
public int timeout = 5000;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer srv) {
|
||||
super.init(srv);
|
||||
if (url == null) throw new RuntimeException("[Verify][AuthProvider] url cannot be null");
|
||||
if (response == null) throw new RuntimeException("[Verify][AuthProvider] response cannot be null");
|
||||
pattern = Pattern.compile(response);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException, URISyntaxException, InterruptedException {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
HttpResponse<String> response = client.send(HttpRequest.newBuilder()
|
||||
.uri(new URI(getFormattedURL(login, ((AuthPlainPassword) password).password, ip)))
|
||||
.header("User-Agent", IOHelper.USER_AGENT)
|
||||
.timeout(Duration.ofMillis(timeout))
|
||||
.GET()
|
||||
.build(), HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
// Match username
|
||||
String currentResponse = response.body();
|
||||
Matcher matcher = pattern.matcher(currentResponse);
|
||||
return matcher.matches() && matcher.groupCount() >= 1 ?
|
||||
new AuthProviderResult(matcher.group("username"), SecurityHelper.randomStringToken(), new ClientPermissions(
|
||||
usePermission ? Long.parseLong(matcher.group("permissions")) : 0, flagsEnabled ? Long.parseLong(matcher.group("flags")) : 0)) :
|
||||
authError(currentResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private String getFormattedURL(String login, String password, String ip) {
|
||||
return CommonHelper.replace(url, "login", IOHelper.urlEncode(login), "password", IOHelper.urlEncode(password), "ip", IOHelper.urlEncode(ip));
|
||||
}
|
||||
}
|
|
@ -30,7 +30,6 @@
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
@ -98,36 +97,6 @@ public void pushBytes(String filename, byte[] bytes) throws IOException {
|
|||
fileList.add(filename);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushJarFile(ZipInputStream input) throws IOException {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
if (fileList.contains(e.getName())) {
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
output.putNextEntry(IOHelper.newZipEntry(e));
|
||||
IOHelper.transfer(input, output);
|
||||
fileList.add(e.getName());
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushJarFile(ZipInputStream input, Set<String> blacklist) throws IOException {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
if (fileList.contains(e.getName()) || blacklist.contains(e.getName())) {
|
||||
e = input.getNextEntry();
|
||||
continue;
|
||||
}
|
||||
output.putNextEntry(IOHelper.newZipEntry(e));
|
||||
IOHelper.transfer(input, output);
|
||||
fileList.add(e.getName());
|
||||
e = input.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public void pushJarFile(Path jarfile, Predicate<ZipEntry> filter, Predicate<String> needTransform) throws IOException {
|
||||
pushJarFile(jarfile.toUri().toURL(), filter, needTransform);
|
||||
}
|
||||
|
|
|
@ -134,8 +134,7 @@ public byte[] transformClass(byte[] bytes, String classname, BuildContext contex
|
|||
ClassWriter writer;
|
||||
ClassNode cn = null;
|
||||
for (Transformer t : transformers) {
|
||||
if (t instanceof ASMTransformer) {
|
||||
ASMTransformer asmTransformer = (ASMTransformer) t;
|
||||
if (t instanceof ASMTransformer asmTransformer) {
|
||||
if (cn == null) {
|
||||
ClassReader cr = new ClassReader(result);
|
||||
cn = new ClassNode();
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package pro.gravit.launchserver.command.auth;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class AuthCommand extends Command {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
|
||||
public AuthCommand(LaunchServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "<login> <password> <auth_id>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageDescription() {
|
||||
return "Try to auth with specified login and password";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 2);
|
||||
AuthProviderPair pair;
|
||||
if (args.length > 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));
|
||||
String login = args[0];
|
||||
String password = args[1];
|
||||
|
||||
// Authenticate
|
||||
AuthProvider provider = pair.provider;
|
||||
AuthProviderResult result = provider.auth(login, new AuthPlainPassword(password), "127.0.0.1");
|
||||
UUID uuid = pair.handler.auth(result);
|
||||
|
||||
// Print auth successful message
|
||||
logger.info("UUID: {}, Username: '{}', Access Token: '{}'", uuid, result.username, result.accessToken);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package pro.gravit.launchserver.command.auth;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.command.CommandException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class UUIDToUsernameCommand extends Command {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
|
||||
public UUIDToUsernameCommand(LaunchServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "<uuid> <auth_id>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageDescription() {
|
||||
return "Convert player UUID to username";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String... args) throws CommandException, IOException {
|
||||
verifyArgs(args, 1);
|
||||
AuthProviderPair pair;
|
||||
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));
|
||||
UUID uuid = parseUUID(args[0]);
|
||||
|
||||
// Get UUID by username
|
||||
String username = pair.handler.uuidToUsername(uuid);
|
||||
if (username == null)
|
||||
throw new CommandException("Unknown UUID: " + uuid);
|
||||
|
||||
// Print username
|
||||
logger.info("Username of player {}: '{}'", uuid, username);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package pro.gravit.launchserver.command.auth;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.command.CommandException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class UsernameToUUIDCommand extends Command {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
|
||||
public UsernameToUUIDCommand(LaunchServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "<username> <auth_id>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageDescription() {
|
||||
return "Convert player username to UUID";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String... args) throws CommandException, IOException {
|
||||
verifyArgs(args, 1);
|
||||
AuthProviderPair pair;
|
||||
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));
|
||||
String username = parseUsername(args[0]);
|
||||
|
||||
// Get UUID by username
|
||||
UUID uuid = pair.handler.usernameToUUID(username);
|
||||
if (uuid == null)
|
||||
throw new CommandException(String.format("Unknown username: '%s'", username));
|
||||
|
||||
// Print UUID
|
||||
logger.info("UUID of player '{}': {}", username, uuid);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package pro.gravit.launchserver.command.handler;
|
||||
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.command.auth.AuthCommand;
|
||||
import pro.gravit.launchserver.command.auth.UUIDToUsernameCommand;
|
||||
import pro.gravit.launchserver.command.auth.UsernameToUUIDCommand;
|
||||
import pro.gravit.launchserver.command.basic.BuildCommand;
|
||||
import pro.gravit.launchserver.command.basic.RestartCommand;
|
||||
import pro.gravit.launchserver.command.basic.StopCommand;
|
||||
|
@ -50,14 +47,6 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
|
|||
Category updatesCategory = new Category(updates, "updates", "Update and Sync Management");
|
||||
handler.registerCategory(updatesCategory);
|
||||
|
||||
// Register auth commands
|
||||
BaseCommandCategory auth = new BaseCommandCategory();
|
||||
auth.registerCommand("auth", new AuthCommand(server));
|
||||
auth.registerCommand("usernameToUUID", new UsernameToUUIDCommand(server));
|
||||
auth.registerCommand("uuidToUsername", new UUIDToUsernameCommand(server));
|
||||
Category authCategory = new Category(auth, "auth", "User Management");
|
||||
handler.registerCategory(authCategory);
|
||||
|
||||
//Register service commands
|
||||
BaseCommandCategory service = new BaseCommandCategory();
|
||||
service.registerCommand("config", new ConfigCommand(server));
|
||||
|
@ -69,6 +58,7 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
|
|||
service.registerCommand("signDir", new SignDirCommand(server));
|
||||
service.registerCommand("pingServers", new PingServersCommand(server));
|
||||
service.registerCommand("securitycheck", new SecurityCheckCommand(server));
|
||||
service.registerCommand("token", new TokenCommand(server));
|
||||
Category serviceCategory = new Category(service, "service", "Managing LaunchServer Components");
|
||||
handler.registerCategory(serviceCategory);
|
||||
}
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalFile;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalTrigger;
|
||||
import pro.gravit.launcher.profiles.optional.actions.*;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
@ -16,9 +13,6 @@
|
|||
import java.io.Writer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SaveProfilesCommand extends Command {
|
||||
|
@ -28,7 +22,6 @@ public SaveProfilesCommand(LaunchServer server) {
|
|||
super(server);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void saveProfile(ClientProfile profile, Path path) throws IOException {
|
||||
if (profile.getUUID() == null) profile.setUUID(UUID.randomUUID());
|
||||
if (profile.getServers().size() == 0) {
|
||||
|
@ -39,41 +32,6 @@ public static void saveProfile(ClientProfile profile, Path path) throws IOExcept
|
|||
serverProfile.serverPort = profile.getServerPort();
|
||||
profile.getServers().add(serverProfile);
|
||||
}
|
||||
for (OptionalFile file : profile.getOptional()) {
|
||||
if (file.list != null) {
|
||||
String[] list = file.list;
|
||||
file.list = null;
|
||||
if (file.actions == null) file.actions = new ArrayList<>(2);
|
||||
OptionalAction action;
|
||||
switch (file.type) {
|
||||
case FILE:
|
||||
OptionalActionFile result = new OptionalActionFile(new HashMap<>());
|
||||
for (String s : list) result.files.put(s, "");
|
||||
action = result;
|
||||
break;
|
||||
case CLASSPATH:
|
||||
action = new OptionalActionClassPath(list);
|
||||
break;
|
||||
case JVMARGS:
|
||||
action = new OptionalActionJvmArgs(Arrays.asList(list));
|
||||
break;
|
||||
case CLIENTARGS:
|
||||
action = new OptionalActionClientArgs(Arrays.asList(list));
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
file.actions.add(action);
|
||||
}
|
||||
if (file.triggers != null) {
|
||||
file.triggersList = new ArrayList<>(file.triggers.length);
|
||||
for (OptionalTrigger trigger : file.triggers) {
|
||||
pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger newTrigger = trigger.toTrigger();
|
||||
if (newTrigger != null) file.triggersList.add(newTrigger);
|
||||
}
|
||||
file.triggers = null;
|
||||
}
|
||||
}
|
||||
try (Writer w = IOHelper.newWriter(path)) {
|
||||
Launcher.gsonManager.configGson.toJson(profile, w);
|
||||
}
|
||||
|
|
|
@ -47,10 +47,12 @@ public void invoke(String... args) {
|
|||
logger.info("OAuth {} | session {}", client.useOAuth, client.sessionObject == null ? "null" : client.sessionObject);
|
||||
logger.info("Data: checkSign {} | auth_id {}", client.checkSign ? "true" : "false",
|
||||
client.auth_id);
|
||||
if (client.trustLevel != null) {
|
||||
logger.info("trustLevel | key {} | pubkey {}", client.trustLevel.keyChecked ? "checked" : "unchecked", client.trustLevel.publicKey == null ? "null" : new String(Base64.getEncoder().encode(client.trustLevel.publicKey)));
|
||||
}
|
||||
logger.info("Permissions: {} (permissions {} | flags {})", client.permissions == null ? "null" : client.permissions.toString(), client.permissions == null ? 0 : client.permissions.permissions, client.permissions == null ? 0 : client.permissions.flags);
|
||||
}
|
||||
if (client.trustLevel != null) {
|
||||
logger.info("trustLevel | key {} | pubkey {}", client.trustLevel.keyChecked ? "checked" : "unchecked", client.trustLevel.publicKey == null ? "null" : new String(Base64.getEncoder().encode(client.trustLevel.publicKey)));
|
||||
}
|
||||
if (client.permissions != null) {
|
||||
logger.info("Permissions: {}", client.permissions.toString());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -4,18 +4,15 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
||||
import pro.gravit.launchserver.auth.protect.AdvancedProtectHandler;
|
||||
import pro.gravit.launchserver.auth.protect.NoProtectHandler;
|
||||
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
|
||||
import pro.gravit.launchserver.auth.provider.AcceptAuthProvider;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.launchserver.components.ProGuardComponent;
|
||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||
import pro.gravit.launchserver.helper.SignHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -49,11 +46,6 @@ public static void printCheckResult(String module, String comment, Boolean statu
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void printCheckResult(LogHelper.Level level, String module, String comment, Boolean status) {
|
||||
printCheckResult(module, comment, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "[]";
|
||||
|
@ -68,19 +60,6 @@ public String getUsageDescription() {
|
|||
public void invoke(String... args) {
|
||||
LaunchServerConfig config = server.config;
|
||||
config.auth.forEach((name, pair) -> {
|
||||
if (pair.provider instanceof AcceptAuthProvider) {
|
||||
printCheckResult(String.format("auth.%s.provider", name), "Accept auth provider", false);
|
||||
} else {
|
||||
printCheckResult(String.format("auth.%s.provider", name), "", true);
|
||||
}
|
||||
if (pair.handler instanceof MemoryAuthHandler) {
|
||||
printCheckResult(String.format("auth.%s.handler", name), "MemoryAuthHandler test-only", false);
|
||||
} else {
|
||||
printCheckResult(String.format("auth.%s.handler", name), "", true);
|
||||
}
|
||||
if (!pair.isUseCore()) {
|
||||
printCheckResult(String.format("auth.%s", name), "AuthProvider/AuthHandler may be removed in future release", null);
|
||||
}
|
||||
});
|
||||
if (config.protectHandler instanceof NoProtectHandler) {
|
||||
printCheckResult("protectHandler", "protectHandler none", false);
|
||||
|
@ -171,19 +150,10 @@ public void invoke(String... args) {
|
|||
}
|
||||
|
||||
switch (config.env) {
|
||||
|
||||
case DEV:
|
||||
printCheckResult("env", "found env DEV", false);
|
||||
break;
|
||||
case DEBUG:
|
||||
printCheckResult("env", "found env DEBUG", false);
|
||||
break;
|
||||
case STD:
|
||||
printCheckResult("env", "you can improve security by using env PROD", null);
|
||||
break;
|
||||
case PROD:
|
||||
printCheckResult("env", "", true);
|
||||
break;
|
||||
case DEV -> printCheckResult("env", "found env DEV", false);
|
||||
case DEBUG -> printCheckResult("env", "found env DEBUG", false);
|
||||
case STD -> printCheckResult("env", "you can improve security by using env PROD", null);
|
||||
case PROD -> printCheckResult("env", "", true);
|
||||
}
|
||||
|
||||
//Profiles
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.auth.handler.CachedAuthHandler;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.command.CommandHandler;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
|
@ -43,9 +42,6 @@ public void invoke(String... args) {
|
|||
}
|
||||
logger.info("Commands: {}({} categories)", commands, server.commandHandler.getCategories().size() + 1);
|
||||
for (AuthProviderPair pair : server.config.auth.values()) {
|
||||
if (pair.handler instanceof CachedAuthHandler) {
|
||||
logger.info("AuthHandler {}: EntryCache: {} | usernameCache: {}", pair.name, ((CachedAuthHandler) pair.handler).getEntryCache().size(), ((CachedAuthHandler) pair.handler).getUsernamesCache().size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package pro.gravit.launchserver.command.service;
|
||||
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.command.SubCommand;
|
||||
|
||||
public class TokenCommand extends Command {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
public TokenCommand(LaunchServer server) {
|
||||
super(server);
|
||||
this.childCommands.put("info", new SubCommand("[token]", "print token info") {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
var parser = Jwts.parserBuilder().setSigningKey(server.keyAgreementManager.ecdsaPublicKey).build();
|
||||
var claims = parser.parseClaimsJws(args[0]);
|
||||
logger.info("Token: {}", claims.getBody());
|
||||
}
|
||||
});
|
||||
this.childCommands.put("server", new SubCommand("[serverName] (authId)", "generate new server token") {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
String token = server.authManager.newCheckServerToken(args[0], args.length > 1 ? args[1] : server.config.getAuthProviderPair().name);
|
||||
logger.info("Token: {}", token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "[new/info/token name] [args]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageDescription() {
|
||||
return "jwt management";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
invokeSubcommands(args);
|
||||
}
|
||||
}
|
|
@ -19,19 +19,9 @@ public static void registerComponents() {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void preInit(LaunchServer launchServer) {
|
||||
|
||||
}
|
||||
|
||||
public abstract void init(LaunchServer launchServer);
|
||||
|
||||
public final void setComponentName(String s) {
|
||||
this.componentName = s;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void postInit(LaunchServer launchServer) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import pro.gravit.launchserver.components.Component;
|
||||
import pro.gravit.launchserver.components.ProGuardComponent;
|
||||
import pro.gravit.launchserver.components.RegLimiterComponent;
|
||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||
import pro.gravit.utils.Version;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
|
||||
|
@ -37,8 +36,6 @@ public final class LaunchServerConfig {
|
|||
public boolean cacheUpdates = true;
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
public Map<String, AuthProviderPair> auth;
|
||||
@Deprecated
|
||||
public DaoProvider dao;
|
||||
public SessionStorage sessions;
|
||||
// Handlers & Providers
|
||||
public ProtectHandler protectHandler;
|
||||
|
@ -154,10 +151,6 @@ public void verify() {
|
|||
throw new NullPointerException("AuthProviderPair`s count should be at least one");
|
||||
}
|
||||
|
||||
if (dao != null) {
|
||||
logger.warn("DAO deprecated and may be remove in future release");
|
||||
}
|
||||
|
||||
boolean isOneDefault = false;
|
||||
for (AuthProviderPair pair : auth.values()) {
|
||||
if (pair.isDefault) {
|
||||
|
@ -183,13 +176,6 @@ public void init(LaunchServer.ReloadType type) {
|
|||
Launcher.applyLauncherEnv(env);
|
||||
for (Map.Entry<String, AuthProviderPair> provider : auth.entrySet()) {
|
||||
provider.getValue().init(server, provider.getKey());
|
||||
if (!provider.getValue().isUseCore()) {
|
||||
logger.warn("Deprecated auth {}: legacy provider/handler auth may be removed in future release", provider.getKey());
|
||||
}
|
||||
}
|
||||
if (dao != null) {
|
||||
server.registerObject("dao", dao);
|
||||
dao.init(server);
|
||||
}
|
||||
if (protectHandler != null) {
|
||||
server.registerObject("protectHandler", protectHandler);
|
||||
|
@ -205,8 +191,6 @@ public void init(LaunchServer.ReloadType type) {
|
|||
}
|
||||
if (!type.equals(LaunchServer.ReloadType.NO_AUTH)) {
|
||||
for (AuthProviderPair pair : auth.values()) {
|
||||
server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".core"), pair.core);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".social"), pair.social);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
|
@ -219,8 +203,6 @@ public void close(LaunchServer.ReloadType type) {
|
|||
try {
|
||||
if (!type.equals(LaunchServer.ReloadType.NO_AUTH)) {
|
||||
for (AuthProviderPair pair : auth.values()) {
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".social"), pair.social);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".core"), pair.core);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
|
@ -256,16 +238,6 @@ public void close(LaunchServer.ReloadType type) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dao != null) {
|
||||
server.unregisterObject("dao", dao);
|
||||
if (dao instanceof AutoCloseable) {
|
||||
try {
|
||||
((AutoCloseable) dao).close();
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExeConf {
|
||||
|
@ -307,8 +279,6 @@ public static class NettyUpdatesBind {
|
|||
public static class LauncherConf {
|
||||
public String guardType;
|
||||
public boolean compress;
|
||||
@Deprecated
|
||||
public boolean warningMissArchJava;
|
||||
public boolean stripLineNumbers;
|
||||
public boolean deleteTempFiles;
|
||||
public boolean certificatePinning;
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package pro.gravit.launchserver.dao;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
public interface User {
|
||||
String getUsername();
|
||||
|
||||
ClientPermissions getPermissions();
|
||||
|
||||
void setPermissions(ClientPermissions permissions);
|
||||
|
||||
boolean verifyPassword(String password);
|
||||
|
||||
void setPassword(String password);
|
||||
|
||||
String getAccessToken();
|
||||
|
||||
void setAccessToken(String accessToken);
|
||||
|
||||
String getServerID();
|
||||
|
||||
void setServerID(String serverID);
|
||||
|
||||
UUID getUuid();
|
||||
|
||||
void setUuid(UUID uuid);
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package pro.gravit.launchserver.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Deprecated
|
||||
public interface UserDAO {
|
||||
User findById(int id);
|
||||
|
||||
User findByUsername(String username);
|
||||
|
||||
User findByUUID(UUID uuid);
|
||||
|
||||
void save(User user);
|
||||
|
||||
void update(User user);
|
||||
|
||||
void delete(User user);
|
||||
|
||||
List<User> findAll();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package pro.gravit.launchserver.dao.provider;
|
||||
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.dao.UserDAO;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
@Deprecated
|
||||
public abstract class DaoProvider {
|
||||
public static final ProviderMap<DaoProvider> providers = new ProviderMap<>("DaoProvider");
|
||||
public transient UserDAO userDAO;
|
||||
|
||||
public static void registerProviders() {
|
||||
// None
|
||||
}
|
||||
|
||||
public abstract void init(LaunchServer server);
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
package pro.gravit.launchserver.dao.provider;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.Reconfigurable;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.dao.UserDAO;
|
||||
import pro.gravit.utils.command.Command;
|
||||
import pro.gravit.utils.command.SubCommand;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Deprecated from 5.2.0
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class HibernateDaoProvider extends DaoProvider implements Reconfigurable, AutoCloseable {
|
||||
public String driver;
|
||||
public String url;
|
||||
public String username;
|
||||
public String password;
|
||||
public String dialect;
|
||||
public String pool_size;
|
||||
public String hibernateConfig;
|
||||
public boolean parallelHibernateInit;
|
||||
protected transient SessionFactory sessionFactory;
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
Runnable init = () -> {
|
||||
Configuration cfg = new Configuration()
|
||||
//.addAnnotatedClass(UserHibernateImpl.class)
|
||||
.setProperty("hibernate.connection.driver_class", driver)
|
||||
.setProperty("hibernate.connection.url", url)
|
||||
.setProperty("hibernate.connection.username", username)
|
||||
.setProperty("hibernate.connection.password", password)
|
||||
.setProperty("hibernate.connection.pool_size", pool_size);
|
||||
if (dialect != null)
|
||||
cfg.setProperty("hibernate.dialect", dialect);
|
||||
if (hibernateConfig != null)
|
||||
cfg.configure(Paths.get(hibernateConfig).toFile());
|
||||
onConfigure(cfg);
|
||||
sessionFactory = cfg.buildSessionFactory();
|
||||
userDAO = newUserDAO();
|
||||
};
|
||||
if (parallelHibernateInit)
|
||||
CommonHelper.newThread("Hibernate Thread", true, init);
|
||||
else
|
||||
init.run();
|
||||
}
|
||||
|
||||
protected abstract void onConfigure(Configuration configuration);
|
||||
|
||||
protected abstract UserDAO newUserDAO();
|
||||
|
||||
@Override
|
||||
public Map<String, Command> getCommands() {
|
||||
Map<String, Command> commands = new HashMap<>();
|
||||
commands.put("getallusers", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) {
|
||||
int count = 0;
|
||||
for (User user : userDAO.findAll()) {
|
||||
LogHelper.subInfo("[%s] UUID: %s", user.getUsername(), user.getUuid().toString());
|
||||
count++;
|
||||
}
|
||||
LogHelper.info("Print %d users", count);
|
||||
}
|
||||
});
|
||||
commands.put("getuser", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
User user = userDAO.findByUsername(args[0]);
|
||||
if (user == null) {
|
||||
LogHelper.error("User %s not found", args[0]);
|
||||
return;
|
||||
}
|
||||
LogHelper.info("[%s] UUID: %s | permissions %s", user.getUsername(), user.getUuid().toString(), user.getPermissions() == null ? "null" : user.getPermissions().toString());
|
||||
}
|
||||
});
|
||||
commands.put("givepermission", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 3);
|
||||
User user = userDAO.findByUsername(args[0]);
|
||||
if (user == null) {
|
||||
LogHelper.error("User %s not found", args[0]);
|
||||
return;
|
||||
}
|
||||
ClientPermissions permissions = user.getPermissions();
|
||||
long perm = Long.parseLong(args[1]);
|
||||
boolean value = Boolean.parseBoolean(args[2]);
|
||||
permissions.setPermission(perm, value);
|
||||
user.setPermissions(permissions);
|
||||
userDAO.update(user);
|
||||
}
|
||||
});
|
||||
commands.put("giveflag", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 3);
|
||||
User user = userDAO.findByUsername(args[0]);
|
||||
if (user == null) {
|
||||
LogHelper.error("User %s not found", args[0]);
|
||||
return;
|
||||
}
|
||||
ClientPermissions permissions = user.getPermissions();
|
||||
long perm = Long.parseLong(args[1]);
|
||||
boolean value = Boolean.parseBoolean(args[2]);
|
||||
permissions.setFlag(perm, value);
|
||||
user.setPermissions(permissions);
|
||||
userDAO.update(user);
|
||||
}
|
||||
});
|
||||
return commands;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package pro.gravit.launchserver.helper;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.request.RequestException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class HttpHelper {
|
||||
private static transient final Logger logger = LogManager.getLogger();
|
||||
private HttpHelper() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static class HttpOptional<T,E> {
|
||||
protected final T result;
|
||||
protected final E error;
|
||||
protected final int statusCode;
|
||||
|
||||
public HttpOptional(T result, E error, int statusCode) {
|
||||
this.result = result;
|
||||
this.error = error;
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
public T result() {
|
||||
return result;
|
||||
}
|
||||
public E error() {
|
||||
return error;
|
||||
}
|
||||
public int statusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
public boolean isSuccessful() {
|
||||
return statusCode >= 200 && statusCode < 300;
|
||||
}
|
||||
public T getOrThrow() throws RequestException {
|
||||
if(isSuccessful()) {
|
||||
return result;
|
||||
} else {
|
||||
throw new RequestException(error == null ? String.format("statusCode %d", statusCode) : error.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface HttpErrorHandler<T, E> {
|
||||
HttpOptional<T,E> apply(HttpResponse<InputStream> response);
|
||||
}
|
||||
|
||||
public interface HttpJsonErrorHandler<T, E> extends HttpErrorHandler<T,E> {
|
||||
HttpOptional<T,E> applyJson(JsonElement response, int statusCode);
|
||||
default HttpOptional<T,E> apply(HttpResponse<InputStream> response) {
|
||||
try(Reader reader = new InputStreamReader(response.body())) {
|
||||
var element = Launcher.gsonManager.gson.fromJson(reader, JsonElement.class);
|
||||
return applyJson(element, response.statusCode());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BasicJsonHttpErrorHandler<T> implements HttpJsonErrorHandler<T, Void> {
|
||||
private final Class<T> type;
|
||||
|
||||
public BasicJsonHttpErrorHandler(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpOptional<T, Void> applyJson(JsonElement response, int statusCode) {
|
||||
return new HttpOptional<>(Launcher.gsonManager.gson.fromJson(response, type), null, statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static<T,E> HttpOptional<T,E> send(HttpClient client, HttpRequest request, HttpErrorHandler<T,E> handler) throws IOException {
|
||||
try {
|
||||
var response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
|
||||
return handler.apply(response);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static<T,E> CompletableFuture<HttpOptional<T,E>> sendAsync(HttpClient client, HttpRequest request, HttpErrorHandler<T,E> handler) throws IOException {
|
||||
return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(handler::apply);
|
||||
}
|
||||
|
||||
public static<T> HttpResponse.BodyHandler<T> ofJsonResult(Class<T> type) {
|
||||
return ofJsonResult((Type) type);
|
||||
}
|
||||
|
||||
public static<T> HttpResponse.BodyHandler<T> ofJsonResult(Type type) {
|
||||
return new JsonBodyHandler<>(HttpResponse.BodyHandlers.ofInputStream(), (input) -> {
|
||||
try(Reader reader = new InputStreamReader(input)) {
|
||||
return Launcher.gsonManager.gson.fromJson(reader, type);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static<T> HttpRequest.BodyPublisher jsonBodyPublisher(T obj) {
|
||||
return HttpRequest.BodyPublishers.ofString(Launcher.gsonManager.gson.toJson(obj));
|
||||
}
|
||||
|
||||
private static class JsonBodyHandler<T> implements HttpResponse.BodyHandler<T> {
|
||||
private final HttpResponse.BodyHandler<InputStream> delegate;
|
||||
private final Function<InputStream, T> func;
|
||||
|
||||
private JsonBodyHandler(HttpResponse.BodyHandler<InputStream> delegate, Function<InputStream, T> func) {
|
||||
this.delegate = delegate;
|
||||
this.func = func;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse.BodySubscriber<T> apply(HttpResponse.ResponseInfo responseInfo) {
|
||||
return new JsonBodySubscriber<>(delegate.apply(responseInfo), func);
|
||||
}
|
||||
}
|
||||
|
||||
private static class JsonBodySubscriber<T> implements HttpResponse.BodySubscriber<T> {
|
||||
private final HttpResponse.BodySubscriber<InputStream> delegate;
|
||||
private final Function<InputStream, T> func;
|
||||
|
||||
private JsonBodySubscriber(HttpResponse.BodySubscriber<InputStream> delegate, Function<InputStream, T> func) {
|
||||
this.delegate = delegate;
|
||||
this.func = func;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<T> getBody() {
|
||||
return delegate.getBody().thenApply(func);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Flow.Subscription subscription) {
|
||||
delegate.onSubscribe(subscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(List<ByteBuffer> item) {
|
||||
delegate.onNext(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
delegate.onError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
delegate.onComplete();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
|||
builder.setTitle(title);
|
||||
builder.setUuid(UUID.randomUUID());
|
||||
builder.setMainClass(getMainClassByVersion(version, options));
|
||||
builder.setServers(List.of(new ClientProfile.ServerProfile(title, "localhost", 25535)));
|
||||
builder.setServers(List.of(new ClientProfile.ServerProfile(title, "localhost", 25565)));
|
||||
// ------------
|
||||
builder.setUpdateVerify(List.of("libraries", "natives", "mods", "minecraft.jar", "forge.jar", "liteloader.jar"));
|
||||
{
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package pro.gravit.launchserver.manangers;
|
||||
|
||||
import io.jsonwebtoken.JwtParser;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
|
@ -16,12 +18,10 @@
|
|||
import pro.gravit.launchserver.auth.core.User;
|
||||
import pro.gravit.launchserver.auth.core.UserSession;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderDAOResult;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
|
@ -36,9 +36,59 @@
|
|||
public class AuthManager {
|
||||
private transient final LaunchServer server;
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
private transient final JwtParser checkServerTokenParser;
|
||||
|
||||
public AuthManager(LaunchServer server) {
|
||||
this.server = server;
|
||||
this.checkServerTokenParser = Jwts.parserBuilder()
|
||||
.requireIssuer("LaunchServer")
|
||||
.require("tokenType", "checkServer")
|
||||
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
||||
.build();
|
||||
}
|
||||
|
||||
public String newCheckServerToken(String serverName, String authId) {
|
||||
return Jwts.builder()
|
||||
.setIssuer("LaunchServer")
|
||||
.claim("serverName", serverName)
|
||||
.claim("authId", authId)
|
||||
.claim("tokenType", "checkServer")
|
||||
.signWith(server.keyAgreementManager.ecdsaPrivateKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public record CheckServerTokenInfo(String serverName, String authId) {
|
||||
}
|
||||
|
||||
public CheckServerTokenInfo parseCheckServerToken(String token) {
|
||||
try {
|
||||
var jwt = checkServerTokenParser.parseClaimsJws(token).getBody();
|
||||
return new CheckServerTokenInfo(jwt.get("serverName", String.class), jwt.get("authId", String.class));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CheckServerVerifier implements RestoreResponse.ExtendedTokenProvider {
|
||||
private final LaunchServer server;
|
||||
|
||||
public CheckServerVerifier(LaunchServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Client client, AuthProviderPair pair, String extendedToken) {
|
||||
var info = server.authManager.parseCheckServerToken(extendedToken);
|
||||
if(info == null) {
|
||||
return false;
|
||||
}
|
||||
client.auth_id = info.authId;
|
||||
client.auth = server.config.getAuthProviderPair(info.authId);
|
||||
if(client.permissions == null) client.permissions = new ClientPermissions();
|
||||
client.permissions.addPerm("launchserver.checkserver");
|
||||
client.permissions.addPerm(String.format("launchserver.profiles.%s.show", info.serverName));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,12 +111,10 @@ public AuthResponse.AuthContext makeAuthContext(Client client, AuthResponse.Conn
|
|||
*/
|
||||
public void check(AuthResponse.AuthContext context) throws AuthException {
|
||||
if (context.authType == AuthResponse.ConnectTypes.CLIENT && !context.client.checkSign) {
|
||||
AuthProvider.authError("Don't skip Launcher Update");
|
||||
return;
|
||||
throw new AuthException("Don't skip Launcher Update");
|
||||
}
|
||||
if (context.client.isAuth) {
|
||||
AuthProvider.authError("You are already logged in");
|
||||
return;
|
||||
throw new AuthException("You are already logged in");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,47 +126,9 @@ public void check(AuthResponse.AuthContext context) throws AuthException {
|
|||
* @return Access token
|
||||
*/
|
||||
public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
|
||||
AuthProviderPair pair = context.pair;
|
||||
AuthReport report;
|
||||
if (pair.core == null) {
|
||||
try {
|
||||
report = AuthReport.ofMinecraftAccessToken(authWithProviderAndHandler(context, password));
|
||||
} catch (Exception e) {
|
||||
if (e instanceof AuthException) throw (AuthException) e;
|
||||
throw new AuthException("Internal Auth Error. Please contact administrator");
|
||||
}
|
||||
} else {
|
||||
report = authWithCore(context, password);
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private String authWithProviderAndHandler(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws Exception {
|
||||
String accessToken;
|
||||
context.pair.provider.preAuth(context.login, password, context.ip);
|
||||
AuthProviderResult aresult = context.pair.provider.auth(context.login, password, context.ip);
|
||||
UUID uuid;
|
||||
String username = aresult.username != null ? aresult.username : context.login;
|
||||
if (aresult instanceof AuthProviderDAOResult) {
|
||||
context.client.daoObject = ((AuthProviderDAOResult) aresult).daoObject;
|
||||
}
|
||||
if (context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||
uuid = context.pair.handler.auth(aresult);
|
||||
accessToken = aresult.accessToken;
|
||||
} else {
|
||||
uuid = context.pair.handler.usernameToUUID(aresult.username);
|
||||
accessToken = null;
|
||||
}
|
||||
internalAuth(context.client, context.authType, context.pair, username, uuid, aresult.permissions, false);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
private AuthReport authWithCore(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
|
||||
AuthCoreProvider provider = context.pair.core;
|
||||
provider.verifyAuth(context);
|
||||
if (password instanceof AuthOAuthPassword) {
|
||||
AuthOAuthPassword password1 = (AuthOAuthPassword) password;
|
||||
if (password instanceof AuthOAuthPassword password1) {
|
||||
UserSession session;
|
||||
try {
|
||||
session = provider.getUserSessionByOAuthAccessToken(password1.accessToken);
|
||||
|
@ -180,7 +190,7 @@ private AuthReport authWithCore(AuthResponse.AuthContext context, AuthRequest.Au
|
|||
internalAuth(context.client, context.authType, context.pair, user.getUsername(), user.getUUID(), user.getPermissions(), result.isUsingOAuth());
|
||||
return result;
|
||||
} else {
|
||||
if (report.needMoreFactor) {
|
||||
if (report.needMoreFactors) {
|
||||
if (report.factors.size() == 1 && report.factors.get(0) == -1) {
|
||||
throw new AuthException(AuthRequestEvent.TWO_FACTOR_NEED_ERROR_MESSAGE);
|
||||
}
|
||||
|
@ -196,6 +206,9 @@ private AuthReport authWithCore(AuthResponse.AuthContext context, AuthRequest.Au
|
|||
* 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;
|
||||
|
@ -204,30 +217,19 @@ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, Auth
|
|||
client.type = authType;
|
||||
client.uuid = uuid;
|
||||
client.useOAuth = oauth;
|
||||
if (pair.isUseCore() && client.coreObject == null) {
|
||||
client.coreObject = pair.core.getUserByUUID(uuid);
|
||||
}
|
||||
client.coreObject = pair.core.getUserByUUID(uuid);
|
||||
}
|
||||
|
||||
public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException {
|
||||
if (client.auth == null) return null;
|
||||
if (client.auth.isUseCore()) {
|
||||
User user = client.auth.core.checkServer(client, username, serverID);
|
||||
if (user == null) return null;
|
||||
else return CheckServerReport.ofUser(user, getPlayerProfile(client.auth, user));
|
||||
} else {
|
||||
UUID uuid = client.auth.handler.checkServer(username, serverID);
|
||||
return uuid == null ? null : CheckServerReport.ofUUID(uuid, getPlayerProfile(client.auth, uuid));
|
||||
}
|
||||
User user = client.auth.core.checkServer(client, username, serverID);
|
||||
if (user == null) return null;
|
||||
else return CheckServerReport.ofUser(user, getPlayerProfile(client.auth, user));
|
||||
}
|
||||
|
||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
||||
if (client.auth == null) return false;
|
||||
if (client.auth.isUseCore()) {
|
||||
return client.auth.core.joinServer(client, username, accessToken, serverID);
|
||||
} else {
|
||||
return client.auth.handler.joinServer(username, accessToken, serverID);
|
||||
}
|
||||
return client.auth.core.joinServer(client, username, accessToken, serverID);
|
||||
}
|
||||
|
||||
public PlayerProfile getPlayerProfile(Client client) {
|
||||
|
@ -253,22 +255,14 @@ public PlayerProfile getPlayerProfile(AuthProviderPair pair, String username) {
|
|||
}
|
||||
|
||||
public PlayerProfile getPlayerProfile(AuthProviderPair pair, String username, ClientProfile profile) {
|
||||
UUID uuid = null;
|
||||
if (pair.isUseCore()) {
|
||||
User user = pair.core.getUserByUsername(username);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
PlayerProfile playerProfile = getPlayerProfile(pair, user);
|
||||
uuid = user.getUUID();
|
||||
if (playerProfile != null) return playerProfile;
|
||||
} else {
|
||||
try {
|
||||
uuid = pair.handler.usernameToUUID(username);
|
||||
} catch (IOException e) {
|
||||
logger.error("UsernameToUUID failed", e);
|
||||
}
|
||||
UUID uuid;
|
||||
User user = pair.core.getUserByUsername(username);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
PlayerProfile playerProfile = getPlayerProfile(pair, user);
|
||||
uuid = user.getUUID();
|
||||
if (playerProfile != null) return playerProfile;
|
||||
if (uuid == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -283,22 +277,14 @@ public PlayerProfile getPlayerProfile(AuthProviderPair pair, UUID uuid) {
|
|||
}
|
||||
|
||||
public PlayerProfile getPlayerProfile(AuthProviderPair pair, UUID uuid, ClientProfile profile) {
|
||||
String username = null;
|
||||
if (pair.isUseCore()) {
|
||||
User user = pair.core.getUserByUUID(uuid);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
PlayerProfile playerProfile = getPlayerProfile(pair, user);
|
||||
username = user.getUsername();
|
||||
if (playerProfile != null) return playerProfile;
|
||||
} else {
|
||||
try {
|
||||
username = pair.handler.uuidToUsername(uuid);
|
||||
} catch (IOException e) {
|
||||
logger.error("UUIDToUsername failed", e);
|
||||
}
|
||||
String username;
|
||||
User user = pair.core.getUserByUUID(uuid);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
PlayerProfile playerProfile = getPlayerProfile(pair, user);
|
||||
username = user.getUsername();
|
||||
if (playerProfile != null) return playerProfile;
|
||||
if (username == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -327,12 +313,10 @@ private PlayerProfile getPlayerProfile(UUID uuid, String username, String client
|
|||
}
|
||||
|
||||
public AuthRequest.AuthPasswordInterface decryptPassword(AuthRequest.AuthPasswordInterface password) throws AuthException {
|
||||
if (password instanceof Auth2FAPassword) {
|
||||
Auth2FAPassword auth2FAPassword = (Auth2FAPassword) password;
|
||||
if (password instanceof Auth2FAPassword auth2FAPassword) {
|
||||
auth2FAPassword.firstPassword = tryDecryptPasswordPlain(auth2FAPassword.firstPassword);
|
||||
auth2FAPassword.secondPassword = tryDecryptPasswordPlain(auth2FAPassword.secondPassword);
|
||||
} else if (password instanceof AuthMultiPassword) {
|
||||
AuthMultiPassword multiPassword = (AuthMultiPassword) password;
|
||||
} else if (password instanceof AuthMultiPassword multiPassword) {
|
||||
List<AuthRequest.AuthPasswordInterface> list = new ArrayList<>(multiPassword.list.size());
|
||||
for (AuthRequest.AuthPasswordInterface p : multiPassword.list) {
|
||||
list.add(tryDecryptPasswordPlain(p));
|
||||
|
@ -344,16 +328,7 @@ public AuthRequest.AuthPasswordInterface decryptPassword(AuthRequest.AuthPasswor
|
|||
return password;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.AuthPasswordInterface password) throws AuthException {
|
||||
if (password instanceof AuthECPassword) {
|
||||
try {
|
||||
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
|
||||
, ((AuthECPassword) password).password)));
|
||||
} catch (Exception ignored) {
|
||||
throw new AuthException("Password decryption error");
|
||||
}
|
||||
}
|
||||
if (password instanceof AuthAESPassword) {
|
||||
try {
|
||||
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
|
||||
|
@ -395,20 +370,9 @@ public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AuthReport {
|
||||
public final String minecraftAccessToken;
|
||||
public final String oauthAccessToken;
|
||||
public final String oauthRefreshToken;
|
||||
public final long oauthExpire;
|
||||
public final UserSession session;
|
||||
|
||||
public AuthReport(String minecraftAccessToken, String oauthAccessToken, String oauthRefreshToken, long oauthExpire, UserSession session) {
|
||||
this.minecraftAccessToken = minecraftAccessToken;
|
||||
this.oauthAccessToken = oauthAccessToken;
|
||||
this.oauthRefreshToken = oauthRefreshToken;
|
||||
this.oauthExpire = oauthExpire;
|
||||
this.session = session;
|
||||
}
|
||||
public record AuthReport(String minecraftAccessToken, String oauthAccessToken,
|
||||
String oauthRefreshToken, long oauthExpire,
|
||||
UserSession session) {
|
||||
|
||||
public static AuthReport ofOAuth(String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
|
||||
return new AuthReport(null, oauthAccessToken, oauthRefreshToken, oauthExpire, null);
|
||||
|
|
|
@ -4,118 +4,31 @@
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||||
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
import org.bouncycastle.operator.bc.BcECContentSignerBuilder;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.util.io.pem.PemObject;
|
||||
import org.bouncycastle.util.io.pem.PemReader;
|
||||
import org.bouncycastle.util.io.pem.PemWriter;
|
||||
import pro.gravit.launcher.LauncherTrustManager;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.security.*;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class CertificateManager {
|
||||
@Deprecated
|
||||
public final int validDays = 60;
|
||||
@Deprecated
|
||||
public final int minusHours = 6;
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
@Deprecated
|
||||
public X509CertificateHolder ca;
|
||||
@Deprecated
|
||||
public AsymmetricKeyParameter caKey;
|
||||
@Deprecated
|
||||
public X509CertificateHolder server;
|
||||
@Deprecated
|
||||
public AsymmetricKeyParameter serverKey;
|
||||
public LauncherTrustManager trustManager;
|
||||
@Deprecated
|
||||
public String orgName;
|
||||
|
||||
@Deprecated
|
||||
public X509CertificateHolder generateCertificate(String subjectName, PublicKey subjectPublicKey) throws OperatorCreationException {
|
||||
SubjectPublicKeyInfo subjectPubKeyInfo = SubjectPublicKeyInfo.getInstance(subjectPublicKey.getEncoded());
|
||||
BigInteger serial = BigInteger.valueOf(SecurityHelper.newRandom().nextLong());
|
||||
Date startDate = Date.from(Instant.now().minus(minusHours, ChronoUnit.HOURS));
|
||||
Date endDate = Date.from(startDate.toInstant().plus(validDays, ChronoUnit.DAYS));
|
||||
|
||||
X500NameBuilder subject = new X500NameBuilder();
|
||||
subject.addRDN(BCStyle.CN, subjectName);
|
||||
subject.addRDN(BCStyle.O, orgName);
|
||||
X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(ca.getSubject(), serial,
|
||||
startDate, endDate, subject.build(), subjectPubKeyInfo);
|
||||
|
||||
AlgorithmIdentifier sigAlgId = ca.getSignatureAlgorithm();
|
||||
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
|
||||
ContentSigner sigGen = new BcECContentSignerBuilder(sigAlgId, digAlgId).build(caKey);
|
||||
|
||||
return v3CertGen.build(sigGen);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void generateCA() throws NoSuchAlgorithmException, IOException, OperatorCreationException, InvalidAlgorithmParameterException {
|
||||
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp384k1");
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
|
||||
generator.initialize(ecGenSpec, SecurityHelper.newRandom());
|
||||
KeyPair pair = generator.generateKeyPair();
|
||||
LocalDateTime startDate = LocalDate.now().atStartOfDay();
|
||||
|
||||
X500NameBuilder subject = new X500NameBuilder();
|
||||
subject.addRDN(BCStyle.CN, orgName.concat(" CA"));
|
||||
subject.addRDN(BCStyle.O, orgName);
|
||||
|
||||
X509v3CertificateBuilder builder = new X509v3CertificateBuilder(
|
||||
subject.build(),
|
||||
new BigInteger("0"),
|
||||
Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()),
|
||||
Date.from(startDate.plusDays(3650).atZone(ZoneId.systemDefault()).toInstant()),
|
||||
new X500Name("CN=ca"),
|
||||
SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded()));
|
||||
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256WITHECDSA");
|
||||
ContentSigner signer = csBuilder.build(pair.getPrivate());
|
||||
ca = builder.build(signer);
|
||||
caKey = PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public KeyPair generateKeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
||||
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp384k1");
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
|
||||
generator.initialize(ecGenSpec, SecurityHelper.newRandom());
|
||||
return generator.generateKeyPair();
|
||||
}
|
||||
|
||||
public void writePrivateKey(Path file, PrivateKey privateKey) throws IOException {
|
||||
writePrivateKey(IOHelper.newWriter(file), privateKey);
|
||||
|
@ -214,24 +127,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
|||
trustManager = new LauncherTrustManager(certificates.toArray(new X509Certificate[0]));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void checkClass(Class<?> clazz, LauncherTrustManager.CheckMode mode) throws SecurityException {
|
||||
if (trustManager == null) return;
|
||||
X509Certificate[] certificates = JVMHelper.getCertificates(clazz);
|
||||
if (certificates == null) {
|
||||
if (mode == LauncherTrustManager.CheckMode.EXCEPTION_IN_NOT_SIGNED)
|
||||
throw new SecurityException(String.format("Class %s not signed", clazz.getName()));
|
||||
else if (mode == LauncherTrustManager.CheckMode.WARN_IN_NOT_SIGNED)
|
||||
logger.warn("Class {} not signed", clazz.getName());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
trustManager.checkCertificatesSuccess(certificates, trustManager::stdCertificateChecker);
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public LauncherTrustManager.CheckClassResult checkClass(Class<?> clazz) {
|
||||
X509Certificate[] certificates = JVMHelper.getCertificates(clazz);
|
||||
return trustManager.checkCertificates(certificates, trustManager::stdCertificateChecker);
|
||||
|
|
|
@ -11,15 +11,12 @@
|
|||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.session.SessionStorage;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
import pro.gravit.launchserver.components.Component;
|
||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
||||
import pro.gravit.launchserver.socket.WebSocketService;
|
||||
import pro.gravit.launchserver.socket.response.UnknownResponse;
|
||||
|
@ -34,17 +31,13 @@ public LaunchServerGsonManager(LaunchServerModulesManager modulesManager) {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void registerAdapters(GsonBuilder builder) {
|
||||
super.registerAdapters(builder);
|
||||
builder.registerTypeAdapter(AuthProvider.class, new UniversalJsonAdapter<>(AuthProvider.providers));
|
||||
builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers));
|
||||
builder.registerTypeAdapter(AuthHandler.class, new UniversalJsonAdapter<>(AuthHandler.providers));
|
||||
builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers));
|
||||
builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers));
|
||||
builder.registerTypeAdapter(Component.class, new UniversalJsonAdapter<>(Component.providers));
|
||||
builder.registerTypeAdapter(ProtectHandler.class, new UniversalJsonAdapter<>(ProtectHandler.providers));
|
||||
builder.registerTypeAdapter(DaoProvider.class, new UniversalJsonAdapter<>(DaoProvider.providers));
|
||||
builder.registerTypeAdapter(WebSocketServerResponse.class, new UniversalJsonAdapter<>(WebSocketService.providers, UnknownResponse.class));
|
||||
builder.registerTypeAdapter(WebSocketEvent.class, new JsonResultSerializeAdapter());
|
||||
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
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.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -36,11 +34,6 @@ public boolean removeByUUID(UUID uuid) {
|
|||
return server.config.sessions.deleteSessionsByUserUUID(uuid);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Set<UUID> getSavedUUIDs() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
server.config.sessions.clear();
|
||||
}
|
||||
|
@ -53,18 +46,11 @@ private Client decompressClient(byte[] client) {
|
|||
return Launcher.gsonManager.gson.fromJson(IOHelper.decode(client), Client.class); //Compress using later
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private Client restoreFromString(byte[] data) {
|
||||
Client result = decompressClient(data);
|
||||
result.updateAuth(server);
|
||||
if (result.auth != null && (result.username != null)) {
|
||||
if (result.auth.isUseCore()) {
|
||||
result.coreObject = result.auth.core.getUserByUUID(result.uuid);
|
||||
} else {
|
||||
if (result.auth.handler instanceof RequiredDAO || result.auth.provider instanceof RequiredDAO || result.auth.textureProvider instanceof RequiredDAO) {
|
||||
result.daoObject = server.config.dao.userDAO.findByUsername(result.username);
|
||||
}
|
||||
}
|
||||
result.coreObject = result.auth.core.getUserByUUID(result.uuid);
|
||||
}
|
||||
if (result.refCount == null) result.refCount = new AtomicInteger(1);
|
||||
clientRestoreHook.hook(result);
|
||||
|
@ -92,25 +78,4 @@ public Client getOrNewClient(UUID session) {
|
|||
public boolean remove(UUID session) {
|
||||
return server.config.sessions.deleteSession(session);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void removeClient(UUID session) {
|
||||
remove(session);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void updateClient(UUID session) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Set<Client> getSessions() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void loadSessions(Set<Client> set) {
|
||||
throw new UnsupportedOperationException();
|
||||
//clientSet.putAll(set.stream().collect(Collectors.toMap(c -> c.session, Function.identity())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
import pro.gravit.launcher.LauncherTrustManager;
|
||||
import pro.gravit.launcher.modules.LauncherModule;
|
||||
import pro.gravit.launcher.modules.LauncherModuleInfo;
|
||||
import pro.gravit.launcher.modules.impl.SimpleModuleManager;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -26,23 +22,6 @@ public void fullInitializedLaunchServer(LaunchServer server) {
|
|||
initContext = new LaunchServerInitContext(server);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void printModulesInfo() {
|
||||
for (LauncherModule module : modules) {
|
||||
LauncherModuleInfo info = module.getModuleInfo();
|
||||
LauncherTrustManager.CheckClassResult checkStatus = module.getCheckResult();
|
||||
LogHelper.info("[MODULE] %s v: %s p: %d deps: %s sig: %s", info.name, info.version.getVersionString(), info.priority, Arrays.toString(info.dependencies), checkStatus == null ? "null" : checkStatus.type);
|
||||
if (checkStatus != null && checkStatus.endCertificate != null) {
|
||||
X509Certificate cert = checkStatus.endCertificate;
|
||||
LogHelper.info("[MODULE CERT] Module signer: %s", cert.getSubjectDN().getName());
|
||||
}
|
||||
if (checkStatus != null && checkStatus.rootCertificate != null) {
|
||||
X509Certificate cert = checkStatus.rootCertificate;
|
||||
LogHelper.info("[MODULE CERT] Module signer CA: %s", cert.getSubjectDN().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<LauncherModule> getModules() {
|
||||
return Collections.unmodifiableList(modules);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -29,9 +28,6 @@ public class Client {
|
|||
|
||||
public transient AuthProviderPair auth;
|
||||
|
||||
@Deprecated
|
||||
public transient User daoObject;
|
||||
|
||||
public transient pro.gravit.launchserver.auth.core.User coreObject;
|
||||
|
||||
public transient pro.gravit.launchserver.auth.core.UserSession sessionObject;
|
||||
|
@ -86,18 +82,12 @@ public void setSerializableProperty(String name, String value) {
|
|||
|
||||
public pro.gravit.launchserver.auth.core.User getUser() {
|
||||
if (coreObject != null) return coreObject;
|
||||
if (auth != null && uuid != null && auth.isUseCore()) {
|
||||
if (auth != null && uuid != null) {
|
||||
coreObject = auth.core.getUserByUUID(uuid);
|
||||
}
|
||||
return coreObject;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum Type {
|
||||
SERVER,
|
||||
USER
|
||||
}
|
||||
|
||||
public static class TrustLevel {
|
||||
public byte[] verifySecureKey;
|
||||
public boolean keyChecked;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
import pro.gravit.launcher.events.request.ExitRequestEvent;
|
||||
import pro.gravit.launcher.request.WebSocketEvent;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
||||
|
@ -43,7 +42,6 @@
|
|||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class WebSocketService {
|
||||
public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
||||
|
@ -155,8 +153,7 @@ void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client
|
|||
if (hook.hook(context, ctx)) {
|
||||
return;
|
||||
}
|
||||
if (response instanceof SimpleResponse) {
|
||||
SimpleResponse simpleResponse = (SimpleResponse) response;
|
||||
if (response instanceof SimpleResponse simpleResponse) {
|
||||
simpleResponse.server = server;
|
||||
simpleResponse.service = this;
|
||||
simpleResponse.ctx = ctx;
|
||||
|
@ -223,19 +220,6 @@ public void sendObjectToUUID(UUID userUuid, Object obj, Type type) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void updateDaoObject(UUID userUuid, User daoObject, Consumer<Channel> callback) {
|
||||
for (Channel ch : channels) {
|
||||
if (ch == null || ch.pipeline() == null) continue;
|
||||
WebSocketFrameHandler wsHandler = ch.pipeline().get(WebSocketFrameHandler.class);
|
||||
if (wsHandler == null) continue;
|
||||
Client client = wsHandler.getClient();
|
||||
if (client == null || client.daoObject == null || !userUuid.equals(client.uuid)) continue;
|
||||
client.daoObject = daoObject;
|
||||
if (callback != null) callback.accept(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public Channel getChannelFromConnectUUID(UUID connectUuid) {
|
||||
for (Channel ch : channels) {
|
||||
if (ch == null || ch.pipeline() == null) continue;
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
||||
private transient final LaunchServer server;
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
@Deprecated
|
||||
public volatile boolean logConnections = Boolean.getBoolean("launcher.logConnections");
|
||||
public LauncherNettyServer nettyServer;
|
||||
private SSLServerSocketFactory ssf;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AdditionalDataResponse extends SimpleResponse {
|
||||
public String username;
|
||||
public UUID uuid;
|
||||
|
@ -23,7 +24,7 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
if (!client.isAuth || !client.auth.isUseCore()) {
|
||||
if (!client.isAuth) {
|
||||
sendError("Access denied");
|
||||
return;
|
||||
}
|
||||
|
@ -31,8 +32,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
if (username == null && uuid == null) {
|
||||
Map<String, String> properties;
|
||||
User user = client.getUser();
|
||||
if (user instanceof UserSupportAdditionalData) {
|
||||
UserSupportAdditionalData userSupport = (UserSupportAdditionalData) user;
|
||||
if (user instanceof UserSupportAdditionalData userSupport) {
|
||||
if (user.getPermissions().isPermission(ClientPermissions.PermissionConsts.ADMIN)) {
|
||||
properties = userSupport.getPropertiesMap();
|
||||
} else {
|
||||
|
@ -50,11 +50,10 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
} else {
|
||||
user = pair.core.getUserByUUID(uuid);
|
||||
}
|
||||
if (!(user instanceof UserSupportAdditionalData)) {
|
||||
if (!(user instanceof UserSupportAdditionalData userSupport)) {
|
||||
sendResult(new AdditionalDataRequestEvent(Map.of()));
|
||||
return;
|
||||
}
|
||||
UserSupportAdditionalData userSupport = (UserSupportAdditionalData) user;
|
||||
Map<String, String> properties;
|
||||
if (client.permissions.isPermission(ClientPermissions.PermissionConsts.ADMIN)) {
|
||||
properties = userSupport.getPropertiesMap();
|
||||
|
|
|
@ -48,7 +48,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
context.report = server.authManager.auth(context, password);
|
||||
server.authHookManager.postHook.hook(context, clientData);
|
||||
if (context.report.isUsingOAuth()) {
|
||||
result.oauth = new AuthRequestEvent.OAuthRequestEvent(context.report.oauthAccessToken, context.report.oauthRefreshToken, context.report.oauthExpire);
|
||||
result.oauth = new AuthRequestEvent.OAuthRequestEvent(context.report.oauthAccessToken(), context.report.oauthRefreshToken(), context.report.oauthExpire());
|
||||
} else if (getSession) {
|
||||
if (clientData.session == null) {
|
||||
clientData.session = UUID.randomUUID();
|
||||
|
@ -56,8 +56,8 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
}
|
||||
result.session = clientData.session;
|
||||
}
|
||||
if (context.report.minecraftAccessToken != null) {
|
||||
result.accessToken = context.report.minecraftAccessToken;
|
||||
if (context.report.minecraftAccessToken() != null) {
|
||||
result.accessToken = context.report.minecraftAccessToken();
|
||||
}
|
||||
result.playerProfile = server.authManager.getPlayerProfile(clientData);
|
||||
sendResult(result);
|
||||
|
@ -67,8 +67,6 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
}
|
||||
|
||||
public enum ConnectTypes {
|
||||
@Deprecated
|
||||
SERVER,
|
||||
CLIENT,
|
||||
API
|
||||
}
|
||||
|
@ -81,8 +79,6 @@ public static class AuthContext {
|
|||
public final Client client;
|
||||
public final AuthProviderPair pair;
|
||||
public AuthManager.AuthReport report;
|
||||
@Deprecated
|
||||
public int password_length; //Use AuthProvider for get password
|
||||
|
||||
public AuthContext(Client client, String login, String profileName, String ip, ConnectTypes authType, AuthProviderPair pair) {
|
||||
this.client = client;
|
||||
|
|
|
@ -23,7 +23,7 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client pClient) {
|
||||
if (!pClient.isAuth || pClient.type == AuthResponse.ConnectTypes.CLIENT) {
|
||||
if (pClient.permissions == null || !pClient.permissions.hasPerm("launchserver.checkserver")) {
|
||||
sendError("Permissions denied");
|
||||
return;
|
||||
}
|
||||
|
@ -46,5 +46,4 @@ public void execute(ChannelHandlerContext ctx, Client pClient) {
|
|||
}
|
||||
sendResult(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,24 +5,10 @@
|
|||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CurrentUserResponse extends SimpleResponse {
|
||||
@Deprecated
|
||||
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(Client client) throws IOException {
|
||||
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
||||
if (client.auth != null && client.isAuth && client.username != null) {
|
||||
UUID uuid = client.uuid != null ? client.uuid : client.auth.handler.usernameToUUID(client.username);
|
||||
if (uuid != null) {
|
||||
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, client.username, client.profile == null ? null : client.profile.getTitle(), client.auth.textureProvider);
|
||||
}
|
||||
}
|
||||
result.permissions = client.permissions;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(LaunchServer server, Client client) throws IOException {
|
||||
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
import pro.gravit.launcher.events.request.ExitRequestEvent;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
|
@ -35,7 +34,7 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
if (username != null && (!client.isAuth || client.permissions == null || !client.permissions.isPermission(ClientPermissions.PermissionConsts.ADMIN))) {
|
||||
if (username != null && (!client.isAuth || client.permissions == null || !client.permissions.hasPerm("launchserver\\.management\\.kick"))) {
|
||||
sendError("Permissions denied");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ public String getType() {
|
|||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>();
|
||||
for (AuthProviderPair pair : server.config.auth.values()) {
|
||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName, pair.isUseCore() ? (pair.isUseSocial() ? pair.social.getDetails(client) : pair.core.getDetails(client)) : pair.provider.getDetails(client)));
|
||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
|
||||
pair.isUseSocial() ? pair.social.getDetails(client) : pair.core.getDetails(client)));
|
||||
}
|
||||
sendResult(new GetAvailabilityAuthRequestEvent(list));
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
|
||||
List<ClientProfile> profileList;
|
||||
Set<ClientProfile> serverProfiles = server.getProfiles();
|
||||
if (server.config.protectHandler instanceof ProfilesProtectHandler) {
|
||||
ProfilesProtectHandler protectHandler = (ProfilesProtectHandler) server.config.protectHandler;
|
||||
if (server.config.protectHandler instanceof ProfilesProtectHandler protectHandler) {
|
||||
profileList = new ArrayList<>(4);
|
||||
for (ClientProfile profile : serverProfiles) {
|
||||
if (protectHandler.canGetProfile(profile, client)) {
|
||||
|
|
|
@ -33,7 +33,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
} else {
|
||||
pair = client.auth;
|
||||
}
|
||||
if (pair == null || !pair.isUseCore()) {
|
||||
if (pair == null) {
|
||||
sendError("Invalid request");
|
||||
return;
|
||||
}
|
||||
|
@ -42,6 +42,6 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
sendError("Invalid RefreshToken");
|
||||
return;
|
||||
}
|
||||
sendResult(new RefreshTokenRequestEvent(new AuthRequestEvent.OAuthRequestEvent(report.oauthAccessToken, report.oauthRefreshToken, report.oauthExpire)));
|
||||
sendResult(new RefreshTokenRequestEvent(new AuthRequestEvent.OAuthRequestEvent(report.oauthAccessToken(), report.oauthRefreshToken(), report.oauthExpire())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import pro.gravit.launchserver.auth.core.User;
|
||||
import pro.gravit.launchserver.auth.core.UserSession;
|
||||
import pro.gravit.launchserver.auth.protect.AdvancedProtectHandler;
|
||||
import pro.gravit.launchserver.manangers.AuthManager;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
||||
|
@ -32,6 +33,7 @@ public static void registerProviders(LaunchServer server) {
|
|||
providers.put(LauncherRequestEvent.LAUNCHER_EXTENDED_TOKEN_NAME, new LauncherResponse.LauncherTokenVerifier(server));
|
||||
providers.put("publicKey", new AdvancedProtectHandler.PublicKeyTokenVerifier(server));
|
||||
providers.put("hardware", new AdvancedProtectHandler.HardwareInfoTokenVerifier(server));
|
||||
providers.put("checkServer", new AuthManager.CheckServerVerifier(server));
|
||||
registeredProviders = true;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +59,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
} else {
|
||||
pair = client.auth;
|
||||
}
|
||||
if (pair == null || !pair.isUseCore()) {
|
||||
if (pair == null) {
|
||||
sendError("Invalid authId");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package pro.gravit.launchserver.socket.response.management;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.request.PingServerReportRequestEvent;
|
||||
import pro.gravit.launcher.request.management.PingServerReportRequest;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
|
@ -18,7 +17,7 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
if (!client.isAuth || client.permissions == null || !client.permissions.isPermission(ClientPermissions.PermissionConsts.MANAGEMENT)) {
|
||||
if (!client.isAuth || client.permissions == null || !client.permissions.hasPerm("launchserver\\.management\\.pingserver")) {
|
||||
sendError("Access denied");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2,43 +2,17 @@
|
|||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
import pro.gravit.launcher.profiles.Texture;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.auth.core.User;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ProfileByUUIDResponse extends SimpleResponse {
|
||||
public UUID uuid;
|
||||
public String client;
|
||||
|
||||
@Deprecated
|
||||
public static PlayerProfile getProfile(UUID uuid, String username, String client, TextureProvider textureProvider) {
|
||||
// Get skin texture
|
||||
Texture skin;
|
||||
try {
|
||||
skin = textureProvider.getSkinTexture(uuid, username, client);
|
||||
} catch (IOException e) {
|
||||
skin = null;
|
||||
}
|
||||
|
||||
// Get cloak texture
|
||||
Texture cloak;
|
||||
try {
|
||||
cloak = textureProvider.getCloakTexture(uuid, username, client);
|
||||
} catch (IOException e) {
|
||||
cloak = null;
|
||||
}
|
||||
|
||||
// Return combined profile
|
||||
return new PlayerProfile(uuid, username, skin, cloak);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "profileByUUID";
|
||||
|
@ -46,7 +20,6 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
String username;
|
||||
AuthProviderPair pair;
|
||||
if (client.auth == null) {
|
||||
pair = server.config.getAuthProviderPair();
|
||||
|
@ -57,18 +30,10 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
sendError("ProfileByUUIDResponse: AuthProviderPair is null");
|
||||
return;
|
||||
}
|
||||
if (pair.isUseCore()) {
|
||||
User user = pair.core.getUserByUUID(uuid);
|
||||
if (user == null) {
|
||||
sendError("User not found");
|
||||
return;
|
||||
} else username = user.getUsername();
|
||||
} else {
|
||||
username = pair.handler.uuidToUsername(uuid);
|
||||
if (username == null) {
|
||||
sendError(String.format("ProfileByUUIDResponse: User with uuid %s not found or AuthProvider#uuidToUsername returned null", uuid));
|
||||
return;
|
||||
}
|
||||
User user = pair.core.getUserByUUID(uuid);
|
||||
if (user == null) {
|
||||
sendError("User not found");
|
||||
return;
|
||||
}
|
||||
sendResult(new ProfileByUUIDRequestEvent(server.authManager.getPlayerProfile(pair, uuid)));
|
||||
}
|
||||
|
|
|
@ -14,13 +14,12 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
if (!(server.config.protectHandler instanceof SecureProtectHandler)) {
|
||||
if (!(server.config.protectHandler instanceof SecureProtectHandler secureProtectHandler)) {
|
||||
GetSecureLevelInfoRequestEvent response = new GetSecureLevelInfoRequestEvent(null);
|
||||
response.enabled = false;
|
||||
sendResult(response);
|
||||
return;
|
||||
}
|
||||
SecureProtectHandler secureProtectHandler = (SecureProtectHandler) server.config.protectHandler;
|
||||
if (!secureProtectHandler.allowGetSecureLevelInfo(client)) {
|
||||
sendError("Access denied");
|
||||
return;
|
||||
|
|
|
@ -19,11 +19,10 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
if (!(server.config.protectHandler instanceof SecureProtectHandler) || client.trustLevel == null || client.trustLevel.verifySecureKey == null) {
|
||||
if (!(server.config.protectHandler instanceof SecureProtectHandler secureProtectHandler) || client.trustLevel == null || client.trustLevel.verifySecureKey == null) {
|
||||
sendError("This method not allowed");
|
||||
return;
|
||||
}
|
||||
SecureProtectHandler secureProtectHandler = (SecureProtectHandler) server.config.protectHandler;
|
||||
try {
|
||||
secureProtectHandler.verifySecureLevelKey(publicKey, client.trustLevel.verifySecureKey, signature);
|
||||
} catch (InvalidKeySpecException e) {
|
||||
|
|
|
@ -2,18 +2,8 @@
|
|||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import pro.gravit.launchserver.auth.texture.NullTextureProvider;
|
||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||
import pro.gravit.launchserver.impl.TestLaunchServerConfigManager;
|
||||
|
@ -21,9 +11,7 @@
|
|||
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
|
||||
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
||||
import pro.gravit.utils.command.StdCommandHandler;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.Security;
|
||||
|
||||
|
@ -57,26 +45,4 @@ public static void prepare() throws Throwable {
|
|||
.setCommandHandler(new StdCommandHandler(false));
|
||||
launchServer = builder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadTest() throws Exception {
|
||||
AuthProvider provider = new AuthProvider() {
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws Exception {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new UnsupportedOperationException();
|
||||
if (login.equals("test") && ((AuthPlainPassword) password).password.equals("test")) {
|
||||
return new AuthProviderResult(login, SecurityHelper.randomStringToken(), new ClientPermissions());
|
||||
}
|
||||
throw new AuthException("Incorrect password");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
};
|
||||
AuthProviderPair pair = new AuthProviderPair(provider, new MemoryAuthHandler(), new NullTextureProvider());
|
||||
launchServerConfigManager.config.auth.put("std", pair);
|
||||
launchServer.reload(LaunchServer.ReloadType.FULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class AuthService {
|
|||
public static UUID uuid;
|
||||
public static ClientProfile profile;
|
||||
|
||||
public static boolean isAdmin() {
|
||||
return permissions.isPermission(ClientPermissions.PermissionConsts.ADMIN);
|
||||
public static boolean hasPermission(String permission) {
|
||||
return permissions.hasPerm(permission);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,6 +163,9 @@ private Result modernPing(HInput input, HOutput output) throws IOException {
|
|||
|
||||
// Parse JSON response
|
||||
JsonObject object = JsonParser.parseString(response).getAsJsonObject();
|
||||
if(object.has("error")) {
|
||||
throw new IOException(object.get("error").getAsString());
|
||||
}
|
||||
JsonObject playersObject = object.get("players").getAsJsonObject();
|
||||
int online = playersObject.get("online").getAsInt();
|
||||
int max = playersObject.get("max").getAsInt();
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
package pro.gravit.launcher;
|
||||
|
||||
import pro.gravit.launcher.serialize.HInput;
|
||||
import pro.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class ClientPermissions {
|
||||
public static final ClientPermissions DEFAULT = new ClientPermissions();
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public long permissions;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public long flags;
|
||||
@LauncherNetworkAPI
|
||||
private List<String> roles;
|
||||
@LauncherNetworkAPI
|
||||
private List<String> perms;
|
||||
|
||||
private transient List<PermissionPattern> available;
|
||||
|
||||
public ClientPermissions(HInput input) throws IOException {
|
||||
this(input.readLong());
|
||||
|
@ -32,6 +40,7 @@ public ClientPermissions(long permissions, long flags) {
|
|||
public static ClientPermissions getSuperuserAccount() {
|
||||
ClientPermissions perm = new ClientPermissions();
|
||||
perm.setPermission(PermissionConsts.ADMIN, true);
|
||||
perm.addPerm("*");
|
||||
return perm;
|
||||
}
|
||||
|
||||
|
@ -39,44 +48,116 @@ public long toLong() {
|
|||
return permissions;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void write(HOutput output) throws IOException {
|
||||
output.writeLong(toLong());
|
||||
public boolean hasRole(String role) {
|
||||
return roles != null && roles.contains(role);
|
||||
}
|
||||
|
||||
public synchronized void compile() {
|
||||
if (available != null) {
|
||||
return;
|
||||
}
|
||||
available = new ArrayList<>(perms.size());
|
||||
for (String a : perms) {
|
||||
available.add(new PermissionPattern(a));
|
||||
}
|
||||
if (permissions != 0) {
|
||||
if (isPermission(PermissionConsts.ADMIN)) {
|
||||
roles.add("ADMIN");
|
||||
available.add(new PermissionPattern("*"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPerm(String action) {
|
||||
if (available == null) {
|
||||
compile();
|
||||
}
|
||||
for (PermissionPattern p : available) {
|
||||
if (p.match(action)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addRole(String role) {
|
||||
if (roles == null) {
|
||||
roles = new ArrayList<>(1);
|
||||
}
|
||||
roles.add(role);
|
||||
}
|
||||
|
||||
public void addPerm(String perm) {
|
||||
if (perms == null) {
|
||||
perms = new ArrayList<>(1);
|
||||
}
|
||||
perms.add(perm);
|
||||
if(available == null) {
|
||||
available = new ArrayList<>(1);
|
||||
}
|
||||
available.add(new PermissionPattern(perm));
|
||||
}
|
||||
|
||||
public void removePerm(String action) {
|
||||
if (perms == null) {
|
||||
return;
|
||||
}
|
||||
if(available == null) {
|
||||
return;
|
||||
}
|
||||
perms.remove(action);
|
||||
available.remove(new PermissionPattern(action));
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public List<String> getPerms() {
|
||||
return perms;
|
||||
}
|
||||
|
||||
//Read methods
|
||||
@Deprecated
|
||||
public final boolean isPermission(PermissionConsts con) {
|
||||
return (permissions & con.mask) != 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final boolean isPermission(long mask) {
|
||||
return (permissions & mask) != 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final boolean isFlag(FlagConsts con) {
|
||||
return (flags & con.mask) != 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final boolean isFlag(long mask) {
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
//Write methods
|
||||
@Deprecated
|
||||
public final void setPermission(PermissionConsts con, boolean value) {
|
||||
if (value) this.permissions |= con.mask;
|
||||
else this.permissions &= ~con.mask;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setPermission(long mask, boolean value) {
|
||||
if (value) this.permissions |= mask;
|
||||
else this.permissions &= ~mask;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setFlag(FlagConsts con, boolean value) {
|
||||
if (value) this.flags |= con.mask;
|
||||
else this.flags &= ~con.mask;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setFlag(long mask, boolean value) {
|
||||
if (value) this.flags |= mask;
|
||||
else this.flags &= ~mask;
|
||||
|
@ -85,11 +166,12 @@ public final void setFlag(long mask, boolean value) {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "ClientPermissions{" +
|
||||
"permissions=" + permissions +
|
||||
", flags=" + flags +
|
||||
"roles=" + String.join(", ", roles == null ? Collections.emptyList() : roles) +
|
||||
", actions=" + String.join(", ", perms == null ? Collections.emptyList() : perms) +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum PermissionConsts {
|
||||
ADMIN(0x01),
|
||||
MANAGEMENT(0x02);
|
||||
|
@ -100,7 +182,7 @@ public enum PermissionConsts {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
public enum FlagConsts {
|
||||
SYSTEM(0x01),
|
||||
BANNED(0x02),
|
||||
|
@ -112,4 +194,69 @@ public enum FlagConsts {
|
|||
this.mask = mask;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PermissionPattern {
|
||||
private final String[] parts;
|
||||
private final int priority;
|
||||
|
||||
public PermissionPattern(String pattern) {
|
||||
List<String> 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<parts.length-1;++i) {
|
||||
int pos = str.indexOf(parts[i], offset);
|
||||
if(pos >= 0) {
|
||||
offset = pos+1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PermissionPattern that = (PermissionPattern) o;
|
||||
return priority == that.priority && Arrays.equals(parts, that.parts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hash(priority);
|
||||
result = 31 * result + Arrays.hashCode(parts);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@ public final class LauncherConfig extends StreamObject {
|
|||
public final ECPublicKey ecdsaPublicKey;
|
||||
public final RSAPublicKey rsaPublicKey;
|
||||
public final Map<String, byte[]> runtime;
|
||||
@Deprecated
|
||||
public final boolean isWarningMissArchJava;
|
||||
@LauncherInject("launcher.guardType")
|
||||
public final String guardType;
|
||||
@LauncherInject("runtimeconfig.secureCheckHash")
|
||||
|
@ -46,8 +44,6 @@ public final class LauncherConfig extends StreamObject {
|
|||
public final String runtimeEncryptKey;
|
||||
@LauncherInject("launcher.address")
|
||||
public final String address;
|
||||
@Deprecated
|
||||
public ECPublicKey publicKey = null;
|
||||
@LauncherInject("runtimeconfig.secretKeyClient")
|
||||
public String secretKeyClient;
|
||||
@LauncherInject("runtimeconfig.oemUnlockKey")
|
||||
|
@ -60,7 +56,6 @@ public final class LauncherConfig extends StreamObject {
|
|||
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
||||
ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||
rsaPublicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||
publicKey = ecdsaPublicKey;
|
||||
secureCheckHash = null;
|
||||
secureCheckSalt = null;
|
||||
passwordEncryptKey = null;
|
||||
|
@ -74,8 +69,6 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
|||
} catch (CertificateException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
isWarningMissArchJava = false;
|
||||
guardType = null;
|
||||
address = null;
|
||||
environment = LauncherEnvironment.STD;
|
||||
|
@ -92,25 +85,6 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
|||
runtime = Collections.unmodifiableMap(localResources);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public LauncherConfig(String address, ECPublicKey publicKey, Map<String, byte[]> runtime, String projectName) {
|
||||
this.address = address;
|
||||
this.publicKey = publicKey;
|
||||
this.ecdsaPublicKey = this.publicKey;
|
||||
this.rsaPublicKey = null;
|
||||
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||
this.projectName = projectName;
|
||||
this.clientPort = 32148;
|
||||
guardType = "no";
|
||||
isWarningMissArchJava = true;
|
||||
environment = LauncherEnvironment.STD;
|
||||
secureCheckSalt = null;
|
||||
secureCheckHash = null;
|
||||
passwordEncryptKey = null;
|
||||
runtimeEncryptKey = null;
|
||||
trustManager = null;
|
||||
}
|
||||
|
||||
public LauncherConfig(String address, ECPublicKey ecdsaPublicKey, RSAPublicKey rsaPublicKey, Map<String, byte[]> runtime, String projectName) {
|
||||
this.address = address;
|
||||
this.ecdsaPublicKey = ecdsaPublicKey;
|
||||
|
@ -119,7 +93,6 @@ public LauncherConfig(String address, ECPublicKey ecdsaPublicKey, RSAPublicKey r
|
|||
this.projectName = projectName;
|
||||
this.clientPort = 32148;
|
||||
guardType = "no";
|
||||
isWarningMissArchJava = true;
|
||||
environment = LauncherEnvironment.STD;
|
||||
secureCheckSalt = null;
|
||||
secureCheckHash = null;
|
||||
|
@ -138,7 +111,6 @@ public LauncherConfig(String address, Map<String, byte[]> runtime, String projec
|
|||
this.ecdsaPublicKey = null;
|
||||
environment = env;
|
||||
guardType = "no";
|
||||
isWarningMissArchJava = true;
|
||||
secureCheckSalt = null;
|
||||
secureCheckHash = null;
|
||||
passwordEncryptKey = null;
|
||||
|
|
|
@ -45,42 +45,11 @@ public static class AuthAvailability {
|
|||
public String name;
|
||||
@LauncherNetworkAPI
|
||||
public String displayName;
|
||||
@Deprecated
|
||||
@LauncherNetworkAPI
|
||||
public AuthType firstType;
|
||||
@Deprecated
|
||||
@LauncherNetworkAPI
|
||||
public AuthType secondType;
|
||||
|
||||
@Deprecated
|
||||
public AuthAvailability(String name, String displayName, AuthType firstType, AuthType secondType) {
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
this.firstType = firstType;
|
||||
this.secondType = secondType;
|
||||
this.details = null;
|
||||
}
|
||||
|
||||
public AuthAvailability(String name, String displayName, List<AuthAvailabilityDetails> details) {
|
||||
this.name = name;
|
||||
this.displayName = displayName;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum AuthType {
|
||||
@LauncherNetworkAPI
|
||||
PASSWORD,
|
||||
@LauncherNetworkAPI
|
||||
KEY,
|
||||
@LauncherNetworkAPI
|
||||
TOTP,
|
||||
@LauncherNetworkAPI
|
||||
OAUTH,
|
||||
@LauncherNetworkAPI
|
||||
NONE,
|
||||
@LauncherNetworkAPI
|
||||
OTHER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ public class SimpleModuleManager implements LauncherModulesManager {
|
|||
protected final LauncherTrustManager trustManager;
|
||||
protected final PublicURLClassLoader classLoader = new PublicURLClassLoader(new URL[]{});
|
||||
protected LauncherInitContext initContext;
|
||||
@Deprecated
|
||||
protected LauncherTrustManager.CheckMode checkMode = LauncherTrustManager.CheckMode.WARN_IN_NOT_SIGNED;
|
||||
|
||||
public SimpleModuleManager(Path modulesDir, Path configDir) {
|
||||
modulesConfigManager = new SimpleModulesConfigManager(configDir);
|
||||
|
@ -172,24 +170,6 @@ public LauncherModule loadModule(Path file) throws IOException {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void checkModuleClass(Class<? extends LauncherModule> clazz, LauncherTrustManager.CheckMode mode) throws SecurityException {
|
||||
if (trustManager == null) return;
|
||||
X509Certificate[] certificates = getCertificates(clazz);
|
||||
if (certificates == null) {
|
||||
if (mode == LauncherTrustManager.CheckMode.EXCEPTION_IN_NOT_SIGNED)
|
||||
throw new SecurityException(String.format("Class %s not signed", clazz.getName()));
|
||||
else if (mode == LauncherTrustManager.CheckMode.WARN_IN_NOT_SIGNED)
|
||||
LogHelper.warning("Class %s not signed", clazz.getName());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
trustManager.checkCertificatesSuccess(certificates, trustManager::stdCertificateChecker);
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public LauncherTrustManager.CheckClassResult checkModuleClass(Class<? extends LauncherModule> clazz) {
|
||||
if (trustManager == null) return null;
|
||||
X509Certificate[] certificates = getCertificates(clazz);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import pro.gravit.launcher.hasher.FileNameMatcher;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalDepend;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalFile;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalType;
|
||||
import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
@ -78,6 +77,8 @@ public final class ClientProfile implements Comparable<ClientProfile> {
|
|||
private ProfileDefaultSettings settings = new ProfileDefaultSettings();
|
||||
@LauncherNetworkAPI
|
||||
private boolean updateFastCheck;
|
||||
@LauncherNetworkAPI
|
||||
private boolean limited;
|
||||
// Client launcher
|
||||
@LauncherNetworkAPI
|
||||
private String mainClass;
|
||||
|
@ -257,13 +258,6 @@ public void updateOptionalGraph() {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public OptionalFile getOptionalFile(String file, OptionalType type) {
|
||||
for (OptionalFile f : updateOptional)
|
||||
if (f.type.equals(type) && f.name.equals(file)) return f;
|
||||
return null;
|
||||
}
|
||||
|
||||
public OptionalFile getOptionalFile(String file) {
|
||||
for (OptionalFile f : updateOptional)
|
||||
if (f.name.equals(file)) return f;
|
||||
|
@ -279,11 +273,6 @@ public int getServerPort() {
|
|||
return profile == null ? 25565 : profile.serverPort;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public InetSocketAddress getServerSocketAddress() {
|
||||
return InetSocketAddress.createUnresolved(getServerAddress(), getServerPort());
|
||||
}
|
||||
|
||||
public int getSortIndex() {
|
||||
return sortIndex;
|
||||
}
|
||||
|
@ -454,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),
|
||||
|
|
|
@ -1,31 +1,18 @@
|
|||
package pro.gravit.launcher.profiles;
|
||||
|
||||
import pro.gravit.launcher.serialize.HInput;
|
||||
import pro.gravit.launcher.serialize.HOutput;
|
||||
import pro.gravit.launcher.serialize.stream.StreamObject;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PlayerProfile extends StreamObject {
|
||||
public final class PlayerProfile {
|
||||
|
||||
public final UUID uuid;
|
||||
public final String username;
|
||||
public final Texture skin, cloak;
|
||||
|
||||
|
||||
@Deprecated
|
||||
public PlayerProfile(HInput input) throws IOException {
|
||||
uuid = input.readUUID();
|
||||
username = VerifyHelper.verifyUsername(input.readString(64));
|
||||
skin = input.readBoolean() ? new Texture(input) : null;
|
||||
cloak = input.readBoolean() ? new Texture(input) : null;
|
||||
}
|
||||
|
||||
|
||||
public PlayerProfile(UUID uuid, String username, Texture skin, Texture cloak) {
|
||||
this.uuid = Objects.requireNonNull(uuid, "uuid");
|
||||
this.username = VerifyHelper.verifyUsername(username);
|
||||
|
@ -41,19 +28,4 @@ public static UUID offlineUUID(String username) {
|
|||
return UUID.nameUUIDFromBytes(IOHelper.encodeASCII("OfflinePlayer:" + username));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void write(HOutput output) throws IOException {
|
||||
output.writeUUID(uuid);
|
||||
output.writeString(username, 64);
|
||||
|
||||
// Write textures
|
||||
output.writeBoolean(skin != null);
|
||||
if (skin != null)
|
||||
skin.write(output);
|
||||
output.writeBoolean(cloak != null);
|
||||
if (cloak != null)
|
||||
cloak.write(output);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package pro.gravit.launcher.profiles;
|
||||
|
||||
import pro.gravit.launcher.serialize.HInput;
|
||||
import pro.gravit.launcher.serialize.HOutput;
|
||||
import pro.gravit.launcher.serialize.stream.StreamObject;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
@ -25,14 +24,6 @@ public final class Texture extends StreamObject {
|
|||
|
||||
public final Map<String, String> metadata;
|
||||
|
||||
|
||||
@Deprecated
|
||||
public Texture(HInput input) throws IOException {
|
||||
url = IOHelper.verifyURL(input.readASCII(2048));
|
||||
digest = input.readByteArray(-DIGEST_ALGO.bytes);
|
||||
metadata = null;
|
||||
}
|
||||
|
||||
public Texture(String url, boolean cloak) throws IOException {
|
||||
this.url = IOHelper.verifyURL(url);
|
||||
|
||||
|
|
|
@ -5,7 +5,4 @@
|
|||
public class OptionalDepend {
|
||||
@LauncherNetworkAPI
|
||||
public String name;
|
||||
@Deprecated
|
||||
@LauncherNetworkAPI
|
||||
public OptionalType type;
|
||||
}
|
||||
|
|
|
@ -2,28 +2,11 @@
|
|||
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.serialize.HInput;
|
||||
import pro.gravit.launcher.serialize.HOutput;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class OptionalFile {
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public long permissions = 0L;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public String[] list;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public OptionalType type;
|
||||
@LauncherNetworkAPI
|
||||
public List<OptionalAction> actions;
|
||||
@LauncherNetworkAPI
|
||||
|
@ -37,9 +20,6 @@ public class OptionalFile {
|
|||
@LauncherNetworkAPI
|
||||
public List<pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger> triggersList;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public OptionalTrigger[] triggers;
|
||||
@LauncherNetworkAPI
|
||||
public OptionalDepend[] dependenciesFile;
|
||||
@LauncherNetworkAPI
|
||||
public OptionalDepend[] conflictFile;
|
||||
|
@ -51,35 +31,8 @@ public class OptionalFile {
|
|||
public int subTreeLevel = 1;
|
||||
@LauncherNetworkAPI
|
||||
public boolean isPreset;
|
||||
@Deprecated
|
||||
public transient Set<OptionalFile> dependenciesCount;
|
||||
@Deprecated
|
||||
private volatile transient Collection<BiConsumer<OptionalFile, Boolean>> watchList = null;
|
||||
|
||||
@Deprecated
|
||||
public static OptionalType readType(HInput input) throws IOException {
|
||||
int t = input.readInt();
|
||||
OptionalType type;
|
||||
switch (t) {
|
||||
case 1:
|
||||
type = OptionalType.FILE;
|
||||
break;
|
||||
case 2:
|
||||
type = OptionalType.CLASSPATH;
|
||||
break;
|
||||
case 3:
|
||||
type = OptionalType.JVMARGS;
|
||||
break;
|
||||
case 4:
|
||||
type = OptionalType.CLIENTARGS;
|
||||
break;
|
||||
default:
|
||||
LogHelper.error("readType failed. Read int %d", t);
|
||||
type = OptionalType.FILE;
|
||||
break;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@LauncherNetworkAPI
|
||||
public boolean limited;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
@ -93,11 +46,6 @@ public int hashCode() {
|
|||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public OptionalType getType() {
|
||||
return OptionalType.FILE;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -109,54 +57,4 @@ public boolean isVisible() {
|
|||
public boolean isMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void writeType(HOutput output) throws IOException {
|
||||
switch (type) {
|
||||
|
||||
case FILE:
|
||||
output.writeInt(1);
|
||||
break;
|
||||
case CLASSPATH:
|
||||
output.writeInt(2);
|
||||
break;
|
||||
case JVMARGS:
|
||||
output.writeInt(3);
|
||||
break;
|
||||
case CLIENTARGS:
|
||||
output.writeInt(4);
|
||||
break;
|
||||
default:
|
||||
output.writeInt(5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void registerWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
||||
if (watchList == null) watchList = ConcurrentHashMap.newKeySet();
|
||||
watchList.add(watcher);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void removeWatcher(BiConsumer<OptionalFile, Boolean> watcher) {
|
||||
if (watchList == null) return;
|
||||
watchList.remove(watcher);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void clearAllWatchers() {
|
||||
if (watchList == null) return;
|
||||
watchList.clear();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void watchEvent(boolean isMark) {
|
||||
if (watchList == null) return;
|
||||
watchList.forEach((e) -> e.accept(this, isMark));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
package pro.gravit.launcher.profiles.optional;
|
||||
|
||||
import pro.gravit.launcher.profiles.optional.triggers.JavaTrigger;
|
||||
import pro.gravit.launcher.profiles.optional.triggers.OSTrigger;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
|
||||
@Deprecated
|
||||
public class OptionalTrigger {
|
||||
public TriggerType type;
|
||||
public boolean need = true;
|
||||
public long value;
|
||||
public long compareMode = 0;
|
||||
|
||||
public OptionalTrigger() {
|
||||
}
|
||||
|
||||
public OptionalTrigger(TriggerType type, long value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public OptionalTrigger(TriggerType type, boolean need, long value, long compareMode) {
|
||||
this.type = type;
|
||||
this.need = need;
|
||||
this.value = value;
|
||||
this.compareMode = compareMode;
|
||||
}
|
||||
|
||||
public boolean isTriggered() {
|
||||
long test;
|
||||
switch (type) {
|
||||
|
||||
case JAVA_VERSION:
|
||||
test = JVMHelper.JVM_VERSION;
|
||||
break;
|
||||
case JAVA_BITS:
|
||||
test = JVMHelper.JVM_BITS;
|
||||
break;
|
||||
case OS_BITS:
|
||||
test = JVMHelper.OS_BITS;
|
||||
break;
|
||||
case OS_TYPE:
|
||||
switch (JVMHelper.OS_TYPE) {
|
||||
|
||||
case MUSTDIE:
|
||||
test = 0;
|
||||
break;
|
||||
case LINUX:
|
||||
test = 1;
|
||||
break;
|
||||
case MACOSX:
|
||||
test = 2;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (compareMode == 0) return test == value;
|
||||
else if (compareMode < 0) return test < value;
|
||||
else return test > value;
|
||||
}
|
||||
|
||||
public pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger toTrigger() {
|
||||
switch (type) {
|
||||
case JAVA_VERSION: {
|
||||
JavaTrigger trigger = new JavaTrigger((int) value, (int) value);
|
||||
trigger.required = need;
|
||||
if (compareMode > 0) {
|
||||
trigger.maxVersion = 999;
|
||||
} else if (compareMode < 0) {
|
||||
trigger.minVersion = 0;
|
||||
}
|
||||
return trigger;
|
||||
}
|
||||
case JAVA_BITS:
|
||||
case OS_BITS:
|
||||
return null;
|
||||
case OS_TYPE: {
|
||||
JVMHelper.OS os;
|
||||
if (value == 0) os = JVMHelper.OS.MUSTDIE;
|
||||
else if (value == 1) os = JVMHelper.OS.LINUX;
|
||||
else if (value == 2) os = JVMHelper.OS.MUSTDIE;
|
||||
else throw new IllegalArgumentException(String.format("Os version %d unknown", value));
|
||||
OSTrigger trigger = new OSTrigger(os);
|
||||
trigger.required = need;
|
||||
if (compareMode != 0) trigger.inverted = true;
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum TriggerType {
|
||||
JAVA_VERSION, JAVA_BITS, OS_BITS, OS_TYPE
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package pro.gravit.launcher.profiles.optional;
|
||||
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
|
||||
@Deprecated
|
||||
public enum OptionalType {
|
||||
@LauncherNetworkAPI
|
||||
FILE,
|
||||
@LauncherNetworkAPI
|
||||
CLASSPATH,
|
||||
@LauncherNetworkAPI
|
||||
JVMARGS,
|
||||
@LauncherNetworkAPI
|
||||
CLIENTARGS
|
||||
}
|
|
@ -11,21 +11,18 @@
|
|||
|
||||
public class OptionalView {
|
||||
public Set<OptionalFile> enabled = new HashSet<>();
|
||||
@Deprecated
|
||||
public Map<OptionalFile, Set<OptionalFile>> dependenciesCountMap = new HashMap<>();
|
||||
public Map<OptionalFile, OptionalFileInstallInfo> installInfo = new HashMap<>();
|
||||
public Set<OptionalFile> all;
|
||||
|
||||
public OptionalView(ClientProfile profile) {
|
||||
this.all = profile.getOptional();
|
||||
for (OptionalFile f : this.all) {
|
||||
if (f.mark) enable(f);
|
||||
if (f.mark) enable(f, true, null);
|
||||
}
|
||||
}
|
||||
|
||||
public OptionalView(OptionalView view) {
|
||||
this.enabled = new HashSet<>(view.enabled);
|
||||
this.dependenciesCountMap = new HashMap<>(view.dependenciesCountMap);
|
||||
this.installInfo = new HashMap<>(view.installInfo);
|
||||
this.all = view.all;
|
||||
}
|
||||
|
@ -66,51 +63,6 @@ public Set<OptionalAction> getDisabledActions() {
|
|||
return results;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void enable(OptionalFile file) {
|
||||
if (enabled.contains(file)) return;
|
||||
enabled.add(file);
|
||||
file.watchEvent(true);
|
||||
if (file.dependencies != null) {
|
||||
for (OptionalFile dep : file.dependencies) {
|
||||
Set<OptionalFile> dependenciesCount = dependenciesCountMap.computeIfAbsent(dep, k -> new HashSet<>());
|
||||
dependenciesCount.add(file);
|
||||
enable(dep);
|
||||
}
|
||||
}
|
||||
if (file.conflict != null) {
|
||||
for (OptionalFile conflict : file.conflict) {
|
||||
disable(conflict);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void disable(OptionalFile file) {
|
||||
if (!enabled.remove(file)) return;
|
||||
file.watchEvent(false);
|
||||
Set<OptionalFile> dependenciesCount = dependenciesCountMap.get(file);
|
||||
if (dependenciesCount != null) {
|
||||
for (OptionalFile f : dependenciesCount) {
|
||||
if (f.isPreset) continue;
|
||||
disable(f);
|
||||
}
|
||||
dependenciesCount.clear();
|
||||
}
|
||||
if (file.dependencies != null) {
|
||||
for (OptionalFile f : file.dependencies) {
|
||||
if (!enabled.contains(f)) continue;
|
||||
dependenciesCount = dependenciesCountMap.get(f);
|
||||
if (dependenciesCount == null) {
|
||||
disable(f);
|
||||
} else if (dependenciesCount.size() <= 1) {
|
||||
dependenciesCount.clear();
|
||||
disable(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void enable(OptionalFile file, boolean manual, BiConsumer<OptionalFile, Boolean> callback) {
|
||||
if (enabled.contains(file)) return;
|
||||
enabled.add(file);
|
||||
|
@ -128,7 +80,7 @@ public void enable(OptionalFile file, boolean manual, BiConsumer<OptionalFile, B
|
|||
}
|
||||
if (file.conflict != null) {
|
||||
for (OptionalFile conflict : file.conflict) {
|
||||
disable(conflict);
|
||||
disable(conflict, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public abstract class Request<R extends WebSocketEvent> implements WebSocketRequ
|
|||
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
|
||||
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
|
||||
public static StdWebSocketService service;
|
||||
private static UUID session = UUID.randomUUID();
|
||||
private static UUID session;
|
||||
private static AuthRequestEvent.OAuthRequestEvent oauth;
|
||||
private static Map<String, String> extendedTokens;
|
||||
private static String authId;
|
||||
|
@ -110,20 +110,44 @@ public static String getRefreshToken() {
|
|||
return oauth == null ? null : oauth.refreshToken;
|
||||
}
|
||||
|
||||
public static void reconnect() throws Exception {
|
||||
public static RequestRestoreReport reconnect() throws Exception {
|
||||
service.open();
|
||||
restore();
|
||||
return restore();
|
||||
}
|
||||
|
||||
public static void restore() throws Exception {
|
||||
if (oauth != null) {
|
||||
if (isTokenExpired() || oauth.accessToken == null) {
|
||||
RefreshTokenRequest request = new RefreshTokenRequest(authId, oauth.refreshToken);
|
||||
RefreshTokenRequestEvent event = request.request();
|
||||
setOAuth(authId, event.oauth);
|
||||
public static class RequestRestoreReport {
|
||||
public final boolean legacySession;
|
||||
public final boolean refreshed;
|
||||
public final List<String> invalidExtendedTokens;
|
||||
|
||||
public RequestRestoreReport(boolean legacySession, boolean refreshed, List<String> invalidExtendedTokens) {
|
||||
this.legacySession = legacySession;
|
||||
this.refreshed = refreshed;
|
||||
this.invalidExtendedTokens = invalidExtendedTokens;
|
||||
}
|
||||
}
|
||||
|
||||
public static RequestRestoreReport restore() throws Exception {
|
||||
if (session != null) {
|
||||
RestoreSessionRequest request = new RestoreSessionRequest(session);
|
||||
request.request();
|
||||
return new RequestRestoreReport(true, false, null);
|
||||
} else {
|
||||
boolean refreshed = false;
|
||||
RestoreRequest request;
|
||||
if(oauth != null) {
|
||||
if (isTokenExpired() || oauth.accessToken == null) {
|
||||
RefreshTokenRequest refreshRequest = new RefreshTokenRequest(authId, oauth.refreshToken);
|
||||
RefreshTokenRequestEvent event = refreshRequest.request();
|
||||
setOAuth(authId, event.oauth);
|
||||
refreshed = true;
|
||||
}
|
||||
request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, false);
|
||||
} else {
|
||||
request = new RestoreRequest(authId, null, extendedTokens, false);
|
||||
}
|
||||
RestoreRequest request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, false);
|
||||
RestoreRequestEvent event = request.request();
|
||||
List<String> invalidTokens = null;
|
||||
if (event.invalidTokens != null && event.invalidTokens.size() > 0) {
|
||||
boolean needRequest = false;
|
||||
Map<String, String> tokens = new HashMap<>();
|
||||
|
@ -144,10 +168,9 @@ public static void restore() throws Exception {
|
|||
LogHelper.warning("Tokens %s not restored", String.join(",", event.invalidTokens));
|
||||
}
|
||||
}
|
||||
invalidTokens = event.invalidTokens;
|
||||
}
|
||||
} else if (session != null) {
|
||||
RestoreSessionRequest request = new RestoreSessionRequest(session);
|
||||
request.request();
|
||||
return new RequestRestoreReport(false, refreshed, invalidTokens);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import pro.gravit.launcher.request.auth.password.*;
|
||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public final class AuthRequest extends Request<AuthRequestEvent> implements WebSocketRequest {
|
||||
public static final ProviderMap<AuthPasswordInterface> providers = new ProviderMap<>();
|
||||
|
@ -22,33 +21,6 @@ public final class AuthRequest extends Request<AuthRequestEvent> implements WebS
|
|||
@LauncherNetworkAPI
|
||||
private final ConnectTypes authType;
|
||||
|
||||
@Deprecated
|
||||
public AuthRequest(String login, byte[] password) {
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
this.password = new AuthECPassword(password.clone());
|
||||
auth_id = "";
|
||||
getSession = true;
|
||||
authType = ConnectTypes.CLIENT;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public AuthRequest(String login, byte[] password, String auth_id) {
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
this.password = new AuthECPassword(password.clone());
|
||||
this.auth_id = auth_id;
|
||||
getSession = true;
|
||||
authType = ConnectTypes.CLIENT;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public AuthRequest(String login, byte[] encryptedPassword, String auth_id, ConnectTypes authType) {
|
||||
this.login = login;
|
||||
this.password = new AuthECPassword(encryptedPassword.clone());
|
||||
this.auth_id = auth_id;
|
||||
this.authType = authType;
|
||||
this.getSession = false;
|
||||
}
|
||||
|
||||
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
|
||||
this.login = login;
|
||||
this.password = new AuthPlainPassword(password);
|
||||
|
@ -65,12 +37,10 @@ public AuthRequest(String login, AuthPasswordInterface password, String auth_id,
|
|||
this.authType = authType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void registerProviders() {
|
||||
if (!registerProviders) {
|
||||
providers.register("plain", AuthPlainPassword.class);
|
||||
providers.register("rsa2", AuthRSAPassword.class);
|
||||
providers.register("rsa", AuthECPassword.class);
|
||||
providers.register("aes", AuthAESPassword.class);
|
||||
providers.register("2fa", Auth2FAPassword.class);
|
||||
providers.register("multi", AuthMultiPassword.class);
|
||||
|
@ -88,9 +58,6 @@ public String getType() {
|
|||
}
|
||||
|
||||
public enum ConnectTypes {
|
||||
@Deprecated
|
||||
@LauncherNetworkAPI
|
||||
SERVER,
|
||||
@LauncherNetworkAPI
|
||||
CLIENT,
|
||||
@LauncherNetworkAPI
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package pro.gravit.launcher.request.auth.password;
|
||||
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
|
||||
@Deprecated
|
||||
public class AuthECPassword implements AuthRequest.AuthPasswordInterface {
|
||||
@LauncherNetworkAPI
|
||||
public final byte[] password;
|
||||
|
||||
public AuthECPassword(byte[] password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -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.addPerm("*");
|
||||
Assertions.assertTrue(permissions.hasPerm("abcd"));
|
||||
Assertions.assertTrue(permissions.hasPerm("t.a.c.d.f.*"));
|
||||
Assertions.assertTrue(permissions.hasPerm("*"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addPerm("launchserver.*");
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.*"));
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.abcd"));
|
||||
Assertions.assertFalse(permissions.hasPerm("default.abcd"));
|
||||
Assertions.assertFalse(permissions.hasPerm("nolaunchserver.abcd"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addPerm("launchserver.*.prop");
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.ii.prop"));
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.ia.prop"));
|
||||
Assertions.assertFalse(permissions.hasPerm("default.abcd"));
|
||||
Assertions.assertFalse(permissions.hasPerm("launchserver.ia"));
|
||||
Assertions.assertFalse(permissions.hasPerm("launchserver.ia.prop2"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addPerm("launchserver.*.def.*.prop");
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.1.def.2.prop"));
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.none.def.none.prop"));
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.def.def.def.prop"));
|
||||
Assertions.assertFalse(permissions.hasPerm("launchserver.*.*.prop"));
|
||||
Assertions.assertFalse(permissions.hasPerm("launchserver.*.undef.*.prop"));
|
||||
}
|
||||
{
|
||||
ClientPermissions permissions = new ClientPermissions();
|
||||
permissions.addPerm("launchserver.*.e.*.i.*.prop");
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.2.e.3.i.4.prop"));
|
||||
Assertions.assertTrue(permissions.hasPerm("launchserver.12212.e.233455.i.2356436346346345345345345.prop"));
|
||||
Assertions.assertFalse(permissions.hasPerm("launchserver.prop"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,10 +5,6 @@
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -87,30 +83,6 @@ public void checkCertificatesSuccess(X509Certificate[] certs, CertificateChecker
|
|||
throw new SecurityException(result.type.name());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void checkCertificate(X509Certificate[] certs, CertificateChecker checker) throws CertificateException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
|
||||
if (certs == null) throw new SecurityException("Object not signed");
|
||||
for (int i = 0; i < certs.length; ++i) {
|
||||
X509Certificate cert = certs[i];
|
||||
if (trustCache.contains(cert)) {
|
||||
//Добавляем в кеш все проверенные сертификаты
|
||||
trustCache.addAll(Arrays.asList(certs).subList(0, i));
|
||||
return;
|
||||
}
|
||||
X509Certificate signer = (i + 1 < certs.length) ? certs[i + 1] : null;
|
||||
cert.checkValidity();
|
||||
if (signer != null) {
|
||||
cert.verify(signer.getPublicKey());
|
||||
} else {
|
||||
if (!isTrusted(cert)) {
|
||||
throw new CertificateException(String.format("Certificate %s is not signed by a trusted signer", cert.getSubjectDN().getName()));
|
||||
}
|
||||
}
|
||||
checker.check(cert, signer, i);
|
||||
}
|
||||
Collections.addAll(trustCache, certs);
|
||||
}
|
||||
|
||||
public boolean isTrusted(X509Certificate certificate) throws CertificateEncodingException {
|
||||
//Java API не дает возможности вызвать getFingerprint
|
||||
//Oracle использует хак с кастом к sun.security.x509.X509CertImpl для проверки равенства сертификатов
|
||||
|
@ -167,11 +139,6 @@ public enum CheckClassResultType {
|
|||
UNCOMPAT
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public enum CheckMode {
|
||||
EXCEPTION_IN_NOT_SIGNED, WARN_IN_NOT_SIGNED, NONE_IN_NOT_SIGNED
|
||||
}
|
||||
|
||||
public interface CertificateChecker {
|
||||
void check(X509Certificate cert, X509Certificate signer, int number) throws SecurityException;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import pro.gravit.launcher.serialize.HOutput;
|
||||
import pro.gravit.launcher.serialize.stream.EnumSerializer;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
import pro.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -68,40 +67,6 @@ public void remove(String name) {
|
|||
map.remove(name);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void removeR(String name) {
|
||||
LinkedList<String> dirs = new LinkedList<>();
|
||||
StringTokenizer t = new StringTokenizer(name, "/");
|
||||
while (t.hasMoreTokens()) {
|
||||
dirs.add(t.nextToken());
|
||||
}
|
||||
Map<String, HashedEntry> current = map;
|
||||
for (String s : dirs) {
|
||||
HashedEntry e = current.get(s);
|
||||
if (e == null) {
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("Null %s", s);
|
||||
}
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
for (String x : current.keySet()) LogHelper.debug("Contains %s", x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (e.getType() == Type.DIR) {
|
||||
current = ((HashedDir) e).map;
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("Found dir %s", s);
|
||||
}
|
||||
} else {
|
||||
current.remove(s);
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("Found filename %s", s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void moveTo(String elementName, HashedDir target, String targetElementName) {
|
||||
HashedEntry entry = map.remove(elementName);
|
||||
target.map.put(targetElementName, entry);
|
||||
|
|
|
@ -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<Entry> NEED_GARBARE_COLLECTION = new HashSet<>();
|
||||
|
|
|
@ -6,7 +6,7 @@ public final class Version implements Comparable<Version> {
|
|||
|
||||
public static final int MAJOR = 5;
|
||||
public static final int MINOR = 2;
|
||||
public static final int PATCH = 2;
|
||||
public static final int PATCH = 3;
|
||||
public static final int BUILD = 1;
|
||||
public static final Version.Type RELEASE = Type.STABLE;
|
||||
public final int major;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -151,6 +151,15 @@ public static JavaVersionAndBuild getJavaVersion(String version) {
|
|||
result.version = Integer.parseInt(version.substring(0, dot));
|
||||
dot = version.lastIndexOf(".");
|
||||
result.build = Integer.parseInt(version.substring(dot + 1));
|
||||
} else {
|
||||
try {
|
||||
if(version.endsWith("-ea")) {
|
||||
version = version.substring(0, version.length()-3);
|
||||
}
|
||||
result.version = Integer.parseInt(version);
|
||||
result.build = 0;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -10,10 +10,7 @@
|
|||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
@ -135,11 +132,6 @@ public static void setDevEnabled(boolean stacktraceEnabled) {
|
|||
impl.setDevEnabled(stacktraceEnabled);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String getDataTime() {
|
||||
return DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss", Locale.US).format(LocalDateTime.now());
|
||||
}
|
||||
|
||||
public static void log(Level level, String message, boolean sub) {
|
||||
impl.log(level, message, sub);
|
||||
}
|
||||
|
@ -205,9 +197,6 @@ public enum OutputTypes {
|
|||
PLAIN,
|
||||
@LauncherNetworkAPI
|
||||
JANSI,
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
HTML
|
||||
}
|
||||
|
||||
public enum Level {
|
||||
|
|
|
@ -83,11 +83,6 @@ public static byte[] digest(DigestAlgorithm algo, URL url) throws IOException {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static KeyPair genECKeyPair(SecureRandom random) {
|
||||
return genECDSAKeyPair(random);
|
||||
}
|
||||
|
||||
public static KeyPair genECDSAKeyPair(SecureRandom random) {
|
||||
try {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance(EC_ALGO);
|
||||
|
@ -409,16 +404,6 @@ public static String toHex(byte[] bytes) {
|
|||
return new String(hex);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ECPublicKey toPublicECKey(byte[] bytes) throws InvalidKeySpecException {
|
||||
return toPublicECDSAKey(bytes);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static ECPrivateKey toPrivateECKey(byte[] bytes) throws InvalidKeySpecException {
|
||||
return toPrivateECDSAKey(bytes);
|
||||
}
|
||||
|
||||
public static ECPublicKey toPublicECDSAKey(byte[] bytes) throws InvalidKeySpecException {
|
||||
return (ECPublicKey) newECDSAKeyFactory().generatePublic(new X509EncodedKeySpec(bytes));
|
||||
}
|
||||
|
|
|
@ -15,12 +15,14 @@
|
|||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
||||
import pro.gravit.launcher.request.auth.RestoreRequest;
|
||||
import pro.gravit.launcher.request.update.ProfilesRequest;
|
||||
import pro.gravit.launcher.server.setup.ServerWrapperSetup;
|
||||
import pro.gravit.utils.PublicURLClassLoader;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
@ -28,16 +30,11 @@
|
|||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> {
|
||||
public static final Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules"));
|
||||
public static final Path modulesConfigDir = Paths.get(System.getProperty("serverwrapper.modulesConfigDir", "modules-config"));
|
||||
public static final Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapperConfig.json"));
|
||||
public static final boolean disableSetup = Boolean.parseBoolean(System.getProperty("serverwrapper.disableSetup", "false"));
|
||||
public static ServerWrapperModulesManager modulesManager;
|
||||
public static ServerWrapper wrapper;
|
||||
public Config config;
|
||||
public PublicURLClassLoader ucp;
|
||||
|
@ -51,77 +48,53 @@ public ServerWrapper(Type type, Path configPath) {
|
|||
super(type, configPath);
|
||||
}
|
||||
|
||||
public static void initGson(ServerWrapperModulesManager modulesManager) {
|
||||
Launcher.gsonManager = new ServerWrapperGsonManager(modulesManager);
|
||||
public static void initGson() {
|
||||
Launcher.gsonManager = new ServerWrapperGsonManager();
|
||||
Launcher.gsonManager.initGson();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
LogHelper.printVersion("ServerWrapper");
|
||||
LogHelper.printLicense("ServerWrapper");
|
||||
modulesManager = new ServerWrapperModulesManager(modulesDir, modulesConfigDir);
|
||||
modulesManager.autoload();
|
||||
modulesManager.initModules(null);
|
||||
ServerWrapper.wrapper = new ServerWrapper(ServerWrapper.Config.class, configFile);
|
||||
ServerWrapper.wrapper.run(args);
|
||||
}
|
||||
|
||||
public boolean auth() {
|
||||
try {
|
||||
Launcher.getConfig();
|
||||
AuthRequest request = new AuthRequest(config.login, config.password, config.auth_id, AuthRequest.ConnectTypes.API);
|
||||
AuthRequestEvent authResult = request.request();
|
||||
if (config.saveSession) {
|
||||
if (authResult.oauth != null) {
|
||||
Request.setOAuth(config.auth_id, authResult.oauth);
|
||||
config.oauth = authResult.oauth;
|
||||
config.oauthExpireTime = Request.getTokenExpiredTime();
|
||||
} else {
|
||||
Request.setSession(authResult.session);
|
||||
}
|
||||
saveConfig();
|
||||
}
|
||||
permissions = authResult.permissions;
|
||||
playerProfile = authResult.playerProfile;
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
LogHelper.error(e);
|
||||
if (config.stopOnError) System.exit(-1);
|
||||
return false;
|
||||
public void restore() throws Exception {
|
||||
if(config.oauth != null) {
|
||||
Request.setOAuth(config.authId, config.oauth, config.oauthExpireTime);
|
||||
}
|
||||
if(config.extendedTokens != null) {
|
||||
Request.addAllExtendedToken(config.extendedTokens);
|
||||
}
|
||||
Request.restore();
|
||||
}
|
||||
|
||||
public ProfilesRequestEvent getProfiles() {
|
||||
try {
|
||||
ProfilesRequestEvent result = new ProfilesRequest().request();
|
||||
for (ClientProfile p : result.profiles) {
|
||||
LogHelper.debug("Get profile: %s", p.getTitle());
|
||||
boolean isFound = false;
|
||||
for (ClientProfile.ServerProfile srv : p.getServers()) {
|
||||
if (srv != null && srv.name.equals(config.serverName)) {
|
||||
this.serverProfile = srv;
|
||||
this.profile = p;
|
||||
Launcher.profile = p;
|
||||
LogHelper.debug("Found profile: %s", Launcher.profile.getTitle());
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
public ProfilesRequestEvent getProfiles() throws Exception {
|
||||
ProfilesRequestEvent result = new ProfilesRequest().request();
|
||||
for (ClientProfile p : result.profiles) {
|
||||
LogHelper.debug("Get profile: %s", p.getTitle());
|
||||
boolean isFound = false;
|
||||
for (ClientProfile.ServerProfile srv : p.getServers()) {
|
||||
if (srv != null && srv.name.equals(config.serverName)) {
|
||||
this.serverProfile = srv;
|
||||
this.profile = p;
|
||||
Launcher.profile = p;
|
||||
LogHelper.debug("Found profile: %s", Launcher.profile.getTitle());
|
||||
isFound = true;
|
||||
break;
|
||||
}
|
||||
if (isFound) break;
|
||||
}
|
||||
if (profile == null) {
|
||||
LogHelper.warning("Not connected to ServerProfile. May be serverName incorrect?");
|
||||
}
|
||||
return result;
|
||||
} catch (Throwable e) {
|
||||
LogHelper.error(e);
|
||||
if (config.stopOnError) System.exit(-1);
|
||||
return null;
|
||||
if (isFound) break;
|
||||
}
|
||||
if (profile == null) {
|
||||
LogHelper.warning("Not connected to ServerProfile. May be serverName incorrect?");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void run(String... args) throws Throwable {
|
||||
initGson(modulesManager);
|
||||
initGson();
|
||||
AuthRequest.registerProviders();
|
||||
GetAvailabilityAuthRequest.registerProviders();
|
||||
OptionalAction.registerProviders();
|
||||
|
@ -133,7 +106,6 @@ public void run(String... args) throws Throwable {
|
|||
setup.run();
|
||||
System.exit(0);
|
||||
}
|
||||
modulesManager.invokeEvent(new PreConfigPhase());
|
||||
LogHelper.debug("Read ServerWrapperConfig.json");
|
||||
loadConfig();
|
||||
updateLauncherConfig();
|
||||
|
@ -141,49 +113,29 @@ public void run(String... args) throws Throwable {
|
|||
else Launcher.applyLauncherEnv(LauncherConfig.LauncherEnvironment.STD);
|
||||
if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true));
|
||||
{
|
||||
if (config.saveSession) {
|
||||
boolean needRestore = false;
|
||||
if (config.oauth != null) {
|
||||
Request.setOAuth(config.auth_id, config.oauth, config.oauthExpireTime);
|
||||
needRestore = true;
|
||||
} else if (config.session != null) {
|
||||
Request.setSession(config.session);
|
||||
needRestore = true;
|
||||
} else {
|
||||
auth();
|
||||
}
|
||||
try {
|
||||
if (needRestore)
|
||||
Request.restore();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
auth();
|
||||
}
|
||||
} else {
|
||||
auth();
|
||||
}
|
||||
restore();
|
||||
getProfiles();
|
||||
}
|
||||
modulesManager.invokeEvent(new ServerWrapperInitPhase(this));
|
||||
String classname = (config.mainclass == null || config.mainclass.isEmpty()) ? args[0] : config.mainclass;
|
||||
if (classname.length() == 0) {
|
||||
LogHelper.error("MainClass not found. Please set MainClass for ServerWrapper.cfg or first commandline argument");
|
||||
if (config.stopOnError) System.exit(-1);
|
||||
LogHelper.error("MainClass not found. Please set MainClass for ServerWrapper.json or first commandline argument");
|
||||
System.exit(-1);
|
||||
}
|
||||
if(config.oauth == null && ( config.extendedTokens == null || config.extendedTokens.isEmpty())) {
|
||||
LogHelper.error("Auth not configured. Please use 'java -jar ServerWrapper.jar setup'");
|
||||
System.exit(-1);
|
||||
}
|
||||
Class<?> mainClass;
|
||||
if (config.customClassPath) {
|
||||
if (config.classpath == null)
|
||||
throw new UnsupportedOperationException("classpath is null, customClassPath not available");
|
||||
String[] cp = config.classpath.split(":");
|
||||
if (config.classpath != null && !config.classpath.isEmpty()) {
|
||||
if (!ServerAgent.isAgentStarted()) {
|
||||
LogHelper.warning("JavaAgent not found. Using URLClassLoader");
|
||||
URL[] urls = Arrays.stream(cp).map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
||||
URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
||||
ucp = new PublicURLClassLoader(urls);
|
||||
Thread.currentThread().setContextClassLoader(ucp);
|
||||
loader = ucp;
|
||||
} else {
|
||||
LogHelper.info("Found %d custom classpath elements", cp.length);
|
||||
for (String c : cp)
|
||||
LogHelper.info("Found %d custom classpath elements", config.classpath.size());
|
||||
for (String c : config.classpath)
|
||||
ServerAgent.addJVMClassPath(c);
|
||||
}
|
||||
}
|
||||
|
@ -200,20 +152,15 @@ public void run(String... args) throws Throwable {
|
|||
if (loader != null) mainClass = Class.forName(classname, true, loader);
|
||||
else mainClass = Class.forName(classname);
|
||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||
modulesManager.invokeEvent(new PostInitPhase());
|
||||
Request.service.reconnectCallback = () ->
|
||||
{
|
||||
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||
if (config.saveSession) {
|
||||
try {
|
||||
Request.restore();
|
||||
} catch (Exception e) {
|
||||
auth();
|
||||
}
|
||||
} else {
|
||||
auth();
|
||||
try {
|
||||
Request.reconnect();
|
||||
getProfiles();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
getProfiles();
|
||||
};
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
|
||||
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||
|
@ -226,9 +173,9 @@ public void run(String... args) throws Throwable {
|
|||
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
||||
} else real_args = args;
|
||||
|
||||
mainMethod.invoke(real_args);
|
||||
mainMethod.invoke((Object) real_args);
|
||||
} else {
|
||||
mainMethod.invoke(config.args);
|
||||
mainMethod.invoke((Object) config.args.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,43 +200,29 @@ public Config getDefaultConfig() {
|
|||
Config newConfig = new Config();
|
||||
newConfig.serverName = "your server name";
|
||||
newConfig.projectname = "MineCraft";
|
||||
newConfig.login = "login";
|
||||
newConfig.password = "password";
|
||||
newConfig.mainclass = "";
|
||||
newConfig.syncAuth = true;
|
||||
newConfig.stopOnError = true;
|
||||
newConfig.saveSession = true;
|
||||
newConfig.reconnectCount = 10;
|
||||
newConfig.reconnectSleep = 1000;
|
||||
newConfig.extendedTokens = new HashMap<>();
|
||||
newConfig.args = new ArrayList<>();
|
||||
newConfig.classpath = new ArrayList<>();
|
||||
newConfig.address = "ws://localhost:9274/api";
|
||||
newConfig.env = LauncherConfig.LauncherEnvironment.STD;
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
public static final class Config {
|
||||
@Deprecated
|
||||
public String title;
|
||||
public String projectname;
|
||||
public String address;
|
||||
public String serverName;
|
||||
public int reconnectCount;
|
||||
public int reconnectSleep;
|
||||
public boolean customClassPath;
|
||||
public boolean autoloadLibraries;
|
||||
public boolean stopOnError;
|
||||
public boolean syncAuth;
|
||||
public String logFile;
|
||||
public String classpath;
|
||||
public List<String> classpath;
|
||||
public String librariesDir;
|
||||
public String mainclass;
|
||||
public String login;
|
||||
public String[] args;
|
||||
public String password;
|
||||
public String auth_id = "";
|
||||
public boolean saveSession;
|
||||
public List<String> args;
|
||||
public String authId;
|
||||
public AuthRequestEvent.OAuthRequestEvent oauth;
|
||||
public long oauthExpireTime;
|
||||
public UUID session;
|
||||
public Map<String, String> extendedTokens;
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,13 @@
|
|||
import pro.gravit.launcher.request.websockets.ClientWebSocketService;
|
||||
|
||||
public class ServerWrapperGsonManager extends GsonManager {
|
||||
private final ServerWrapperModulesManager modulesManager;
|
||||
|
||||
public ServerWrapperGsonManager(ServerWrapperModulesManager modulesManager) {
|
||||
this.modulesManager = modulesManager;
|
||||
public ServerWrapperGsonManager() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAdapters(GsonBuilder builder) {
|
||||
super.registerAdapters(builder);
|
||||
ClientWebSocketService.appendTypeAdapters(builder);
|
||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
package pro.gravit.launcher.server;
|
||||
|
||||
import pro.gravit.launcher.modules.LauncherInitContext;
|
||||
|
||||
public class ServerWrapperInitContext implements LauncherInitContext {
|
||||
public final ServerWrapper serverWrapper;
|
||||
|
||||
public ServerWrapperInitContext(ServerWrapper serverWrapper) {
|
||||
this.serverWrapper = serverWrapper;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue