Merge branch 'release/5.2.3'

This commit is contained in:
Gravita 2021-10-13 21:43:41 +07:00
commit b48059998f
109 changed files with 807 additions and 3303 deletions

View file

@ -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/*

View file

@ -12,8 +12,8 @@
}
}
sourceCompatibility = '11'
targetCompatibility = '11'
sourceCompatibility = '17'
targetCompatibility = '17'
configurations {
compileOnlyA

View file

@ -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);

View file

@ -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();

View file

@ -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();
}
}

View file

@ -1,5 +0,0 @@
package pro.gravit.launchserver.auth;
@Deprecated
public interface RequiredDAO {
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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() {
}
}

View file

@ -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;
}
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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() {
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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");
}
}

View file

@ -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() {
}
}

View file

@ -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;
}
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -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);
}

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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());
}
}));
}

View file

@ -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

View file

@ -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());
}
}
}

View file

@ -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);
}
}

View file

@ -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) {
}
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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();
}
}

View file

@ -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();
}
}
}

View file

@ -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"));
{

View file

@ -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);

View file

@ -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);

View file

@ -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));

View file

@ -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())));
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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)) {

View file

@ -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())));
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)));
}

View file

@ -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;

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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;
}
}
}

View file

@ -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;

View file

@ -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
}
}
}

View file

@ -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);

View file

@ -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),

View file

@ -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);
}
}

View file

@ -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);

View file

@ -5,7 +5,4 @@
public class OptionalDepend {
@LauncherNetworkAPI
public String name;
@Deprecated
@LauncherNetworkAPI
public OptionalType type;
}

View file

@ -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));
}
}

View file

@ -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
}
}

View file

@ -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
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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"));
}
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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<>();

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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));
}
}

View file

@ -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