mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-01-09 00:59:44 +03:00
Merge branch 'release/5.1.8' into master
This commit is contained in:
commit
90f360c565
125 changed files with 1796 additions and 680 deletions
|
@ -12,8 +12,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
sourceCompatibility = '1.8'
|
||||
targetCompatibility = '1.8'
|
||||
sourceCompatibility = '11'
|
||||
targetCompatibility = '11'
|
||||
|
||||
configurations {
|
||||
compileOnlyA
|
||||
|
@ -33,6 +33,7 @@
|
|||
from(parent.childProjects.Launcher.tasks.genRuntimeJS)
|
||||
manifest.attributes("Main-Class": mainClassName,
|
||||
"Premain-Class": mainAgentName,
|
||||
"Multi-Release": "true",
|
||||
"Can-Redefine-Classes": "true",
|
||||
"Can-Retransform-Classes": "true",
|
||||
"Can-Set-Native-Method-Prefix": "true"
|
||||
|
@ -80,6 +81,7 @@ pack project(':LauncherAPI')
|
|||
bundle group: 'org.slf4j', name: 'slf4j-simple', version: rootProject['verSlf4j']
|
||||
bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j']
|
||||
bundle group: 'org.hibernate', name: 'hibernate-core', version: rootProject['verHibernate']
|
||||
bundle group: 'org.hibernate', name: 'hibernate-hikaricp', version: rootProject['verHibernate']
|
||||
bundle group: 'mysql', name: 'mysql-connector-java', version: rootProject['verMySQLConn']
|
||||
bundle group: 'org.postgresql', name: 'postgresql', version: rootProject['verPostgreSQLConn']
|
||||
bundle group: 'net.sf.proguard', name: 'proguard-base', version: rootProject['verProguard']
|
||||
|
@ -184,6 +186,18 @@ task dumpClientLibs(type: Copy) {
|
|||
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'gravita'
|
||||
name = 'Gravita'
|
||||
email = 'gravita@gravit.pro'
|
||||
}
|
||||
developer {
|
||||
id = 'zaxar163'
|
||||
name = 'Zaxar163'
|
||||
email = 'zahar.vcherachny@yandex.ru'
|
||||
}
|
||||
}
|
||||
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||
|
|
|
@ -388,7 +388,7 @@ public void syncProfilesDir() throws IOException {
|
|||
// Sort and set new profiles
|
||||
newProfies.sort(Comparator.comparing(a -> a));
|
||||
profilesList = Collections.unmodifiableList(newProfies);
|
||||
if(pingServerManager != null)
|
||||
if (pingServerManager != null)
|
||||
pingServerManager.syncServers();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.LauncherTrustManager;
|
||||
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||
|
@ -213,6 +214,7 @@ public static void registerAll() {
|
|||
DaoProvider.registerProviders();
|
||||
AuthRequest.registerProviders();
|
||||
HWIDProvider.registerProviders();
|
||||
OptionalAction.registerProviders();
|
||||
}
|
||||
|
||||
public static void generateConfigIfNotExists(Path configFile, CommandHandler commandHandler, LaunchServer.LaunchServerEnv env) throws IOException {
|
||||
|
|
|
@ -21,7 +21,7 @@ public static boolean isAgentStarted() {
|
|||
|
||||
public static void premain(String agentArgument, Instrumentation inst) {
|
||||
StarterAgent.inst = inst;
|
||||
libraries = Paths.get(Optional.ofNullable(agentArgument).map(e -> e.trim()).filter(e -> !e.isEmpty()).orElse("libraries"));
|
||||
libraries = Paths.get(Optional.ofNullable(agentArgument).map(String::trim).filter(e -> !e.isEmpty()).orElse("libraries"));
|
||||
isStarted = true;
|
||||
try {
|
||||
Files.walkFileTree(libraries, Collections.singleton(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new StarterVisitor());
|
||||
|
@ -40,11 +40,10 @@ private static final class StarterVisitor extends SimpleFileVisitor<Path> {
|
|||
DPERMS = Collections.unmodifiableSet(perms);
|
||||
}
|
||||
|
||||
private final Path filef;
|
||||
private final boolean fixLib;
|
||||
|
||||
private StarterVisitor() {
|
||||
this.filef = StarterAgent.libraries.resolve(".libraries_chmoded");
|
||||
Path filef = StarterAgent.libraries.resolve(".libraries_chmoded");
|
||||
this.fixLib = !Files.exists(filef) && !Boolean.getBoolean("launcher.noLibrariesPosixPermsFix");
|
||||
if (fixLib) {
|
||||
try {
|
||||
|
|
|
@ -79,7 +79,7 @@ private static void visit(ClassNode classNode, Map<String, Object> values) {
|
|||
return;
|
||||
}
|
||||
field.invisibleAnnotations.remove(valueAnnotation);
|
||||
AtomicReference<String> valueName = new AtomicReference<String>(null);
|
||||
AtomicReference<String> valueName = new AtomicReference<>(null);
|
||||
valueAnnotation.accept(new AnnotationVisitor(Opcodes.ASM7) {
|
||||
@Override
|
||||
public void visit(final String name, final Object value) {
|
||||
|
@ -142,15 +142,11 @@ public void visit(final String name, final Object value) {
|
|||
}
|
||||
|
||||
private static Serializer<?> serializerClass(int opcode) {
|
||||
return new Serializer<Number>() {
|
||||
@Override
|
||||
public InsnList serialize(Number value) {
|
||||
InsnList ret = new InsnList();
|
||||
ret.add(NodeUtils.push(value.intValue()));
|
||||
ret.add(new InsnNode(opcode));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (Serializer<Number>) value -> {
|
||||
InsnList ret = new InsnList();
|
||||
ret.add(NodeUtils.push(value.intValue()));
|
||||
ret.add(new InsnNode(opcode));
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -175,9 +171,8 @@ private static InsnList serializeValue(Object value) {
|
|||
value.getClass()));
|
||||
}
|
||||
|
||||
public static boolean isSerializableValue(Object value)
|
||||
{
|
||||
if(value == null) return true;
|
||||
public static boolean isSerializableValue(Object value) {
|
||||
if (value == null) return true;
|
||||
if (primitiveLDCClasses.contains(value.getClass())) return true;
|
||||
for (Map.Entry<Class<?>, Serializer<?>> serializerEntry : serializers.entrySet()) {
|
||||
if (serializerEntry.getKey().isInstance(value)) {
|
||||
|
|
|
@ -42,6 +42,21 @@ public MySQLSourceConfig(String poolName) {
|
|||
this.poolName = poolName;
|
||||
}
|
||||
|
||||
public MySQLSourceConfig(String poolName, String address, int port, String username, String password, String database) {
|
||||
this.poolName = poolName;
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public MySQLSourceConfig(String poolName, DataSource source, boolean hikari) {
|
||||
this.poolName = poolName;
|
||||
this.source = source;
|
||||
this.hikari = hikari;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
if (hikari)
|
||||
|
|
|
@ -9,7 +9,7 @@ public class HibernateAuthHandler extends CachedAuthHandler {
|
|||
protected Entry fetchEntry(String username) {
|
||||
User user = srv.config.dao.userDAO.findByUsername(username);
|
||||
if (user == null) return null;
|
||||
return new Entry(user.getUuid(), username, user.getAccessToken(), user.getServerID());
|
||||
return new Entry(user.getUuid(), user.getUsername(), user.getAccessToken(), user.getServerID());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,25 +11,26 @@ 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.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new EntryRequestByUsername(username)), getUrl), Entry.class);
|
||||
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.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new EntryRequestByUUID(uuid)), getUrl), Entry.class);
|
||||
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.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new UpdateAuthRequest(uuid, username, accessToken)), updateAuthUrl), SuccessResponse.class).success;
|
||||
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.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new UpdateServerIDRequest(uuid, serverID)), updateServerIdUrl), SuccessResponse.class).success;
|
||||
return Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new UpdateServerIDRequest(uuid, serverID, apiKey)), updateServerIdUrl), SuccessResponse.class).success;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,17 +40,21 @@ public void close() {
|
|||
|
||||
public static class EntryRequestByUsername {
|
||||
public final String username;
|
||||
public final String apiKey;
|
||||
|
||||
public EntryRequestByUsername(String username) {
|
||||
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) {
|
||||
public EntryRequestByUUID(UUID uuid, String apiKey) {
|
||||
this.uuid = uuid;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,21 +62,25 @@ 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) {
|
||||
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) {
|
||||
public UpdateServerIDRequest(UUID uuid, String serverID, String apiKey) {
|
||||
this.uuid = uuid;
|
||||
this.serverID = serverID;
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import pro.gravit.launcher.events.request.GetSecureLevelInfoRequestEvent;
|
||||
import pro.gravit.launcher.events.request.HardwareReportRequestEvent;
|
||||
import pro.gravit.launcher.events.request.VerifySecureLevelKeyRequestEvent;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.Reconfigurable;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDException;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||
|
@ -21,6 +22,7 @@
|
|||
public class AdvancedProtectHandler extends StdProtectHandler implements SecureProtectHandler, HardwareProtectHandler, JoinServerProtectHandler, Reconfigurable {
|
||||
public boolean enableHardwareFeature;
|
||||
public HWIDProvider provider;
|
||||
private transient LaunchServer server;
|
||||
|
||||
@Override
|
||||
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||
|
@ -44,14 +46,12 @@ public boolean allowGetSecureLevelInfo(Client client) {
|
|||
|
||||
@Override
|
||||
public void onHardwareReport(HardwareReportResponse response, Client client) {
|
||||
if(!enableHardwareFeature)
|
||||
{
|
||||
if (!enableHardwareFeature) {
|
||||
response.sendResult(new HardwareReportRequestEvent());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if(!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null)
|
||||
{
|
||||
if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) {
|
||||
response.sendError("Access denied");
|
||||
return;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
|
|||
LogHelper.debug("[HardwareInfo] HardwareInfo received");
|
||||
boolean needCreate = !provider.addPublicKeyToHardwareInfo(response.hardware, client.trustLevel.publicKey, client);
|
||||
LogHelper.debug("[HardwareInfo] HardwareInfo needCreate: %s", needCreate ? "true" : "false");
|
||||
if(needCreate)
|
||||
if (needCreate)
|
||||
provider.createHardwareInfo(response.hardware, client.trustLevel.publicKey, client);
|
||||
client.trustLevel.hardwareInfo = response.hardware;
|
||||
} catch (HWIDException e) {
|
||||
|
@ -70,17 +70,13 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
|
|||
|
||||
@Override
|
||||
public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
|
||||
if(enableHardwareFeature)
|
||||
{
|
||||
if(provider == null)
|
||||
{
|
||||
if (enableHardwareFeature) {
|
||||
if (provider == null) {
|
||||
LogHelper.warning("HWIDProvider null. HardwareInfo not checked!");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
client.trustLevel.hardwareInfo = provider.findHardwareInfoByPublicKey(client.trustLevel.publicKey, client);
|
||||
if(client.trustLevel.hardwareInfo == null) //HWID not found?
|
||||
if (client.trustLevel.hardwareInfo == null) //HWID not found?
|
||||
return new VerifySecureLevelKeyRequestEvent(true);
|
||||
} catch (HWIDException e) {
|
||||
throw new SecurityException(e.getMessage()); //Show banned message
|
||||
|
@ -94,8 +90,7 @@ public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
|
|||
@Override
|
||||
public Map<String, Command> getCommands() {
|
||||
Map<String, Command> commands = new HashMap<>();
|
||||
if(provider instanceof Reconfigurable)
|
||||
{
|
||||
if (provider instanceof Reconfigurable) {
|
||||
commands.putAll(((Reconfigurable) provider).getCommands());
|
||||
}
|
||||
return commands;
|
||||
|
@ -107,14 +102,14 @@ public boolean onJoinServer(String serverID, String username, Client client) {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
if(provider != null)
|
||||
provider.init();
|
||||
public void init(LaunchServer server) {
|
||||
if (provider != null)
|
||||
provider.init(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if(provider != null)
|
||||
if (provider != null)
|
||||
provider.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package pro.gravit.launchserver.auth.protect;
|
||||
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
|
@ -21,13 +22,11 @@ public static void registerHandlers() {
|
|||
|
||||
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
|
||||
|
||||
public void init()
|
||||
{
|
||||
public void init(LaunchServer server) {
|
||||
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
public void close() {
|
||||
|
||||
}
|
||||
//public abstract
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pro.gravit.launchserver.auth.protect.hwid;
|
||||
|
||||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.helper.DamerauHelper;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
@ -12,107 +13,102 @@
|
|||
public abstract class HWIDProvider {
|
||||
public static final ProviderMap<HWIDProvider> providers = new ProviderMap<>("HWIDProvider");
|
||||
private static boolean registredProv = false;
|
||||
|
||||
public static void registerProviders() {
|
||||
if(!registredProv)
|
||||
{
|
||||
if (!registredProv) {
|
||||
providers.register("memory", MemoryHWIDProvider.class);
|
||||
providers.register("mysql", MysqlHWIDProvider.class);
|
||||
providers.register("json", JsonHWIDProvider.class);
|
||||
registredProv = true;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException;
|
||||
|
||||
public abstract void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException;
|
||||
|
||||
public abstract boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException;
|
||||
|
||||
public void normalizeHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo)
|
||||
{
|
||||
if(hardwareInfo.baseboardSerialNumber != null) hardwareInfo.baseboardSerialNumber = hardwareInfo.baseboardSerialNumber.trim();
|
||||
if(hardwareInfo.hwDiskId != null) hardwareInfo.hwDiskId = hardwareInfo.hwDiskId.trim();
|
||||
public void normalizeHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo) {
|
||||
if (hardwareInfo.baseboardSerialNumber != null)
|
||||
hardwareInfo.baseboardSerialNumber = hardwareInfo.baseboardSerialNumber.trim();
|
||||
if (hardwareInfo.hwDiskId != null) hardwareInfo.hwDiskId = hardwareInfo.hwDiskId.trim();
|
||||
}
|
||||
public static class HardwareInfoCompareResult
|
||||
{
|
||||
|
||||
public static class HardwareInfoCompareResult {
|
||||
public double firstSpoofingLevel = 0.0;
|
||||
public double secondSpoofingLevel = 0.0;
|
||||
public double compareLevel;
|
||||
}
|
||||
|
||||
//Required normalize HardwareInfo
|
||||
public HardwareInfoCompareResult compareHardwareInfo(HardwareReportRequest.HardwareInfo first, HardwareReportRequest.HardwareInfo second)
|
||||
{
|
||||
public HardwareInfoCompareResult compareHardwareInfo(HardwareReportRequest.HardwareInfo first, HardwareReportRequest.HardwareInfo second) {
|
||||
HardwareInfoCompareResult result = new HardwareInfoCompareResult();
|
||||
if(first.hwDiskId == null || first.hwDiskId.isEmpty()) result.firstSpoofingLevel += 0.9;
|
||||
if(first.displayId == null || first.displayId.length < 4) result.firstSpoofingLevel += 0.3;
|
||||
if(first.baseboardSerialNumber == null || first.baseboardSerialNumber.trim().isEmpty()) result.firstSpoofingLevel += 0.2;
|
||||
if(second.hwDiskId == null || second.hwDiskId.trim().isEmpty()) result.secondSpoofingLevel += 0.9;
|
||||
if(second.displayId == null || second.displayId.length < 4) result.secondSpoofingLevel += 0.3;
|
||||
if(second.baseboardSerialNumber == null || second.baseboardSerialNumber.trim().isEmpty()) result.secondSpoofingLevel += 0.2;
|
||||
if(first.hwDiskId != null && second.hwDiskId != null)
|
||||
{
|
||||
if (first.hwDiskId == null || first.hwDiskId.isEmpty()) result.firstSpoofingLevel += 0.9;
|
||||
if (first.displayId == null || first.displayId.length < 4) result.firstSpoofingLevel += 0.3;
|
||||
if (first.baseboardSerialNumber == null || first.baseboardSerialNumber.trim().isEmpty())
|
||||
result.firstSpoofingLevel += 0.2;
|
||||
if (second.hwDiskId == null || second.hwDiskId.trim().isEmpty()) result.secondSpoofingLevel += 0.9;
|
||||
if (second.displayId == null || second.displayId.length < 4) result.secondSpoofingLevel += 0.3;
|
||||
if (second.baseboardSerialNumber == null || second.baseboardSerialNumber.trim().isEmpty())
|
||||
result.secondSpoofingLevel += 0.2;
|
||||
if (first.hwDiskId != null && second.hwDiskId != null) {
|
||||
int hwDIskIdRate = DamerauHelper.calculateDistance(first.hwDiskId.toLowerCase(), second.hwDiskId.toLowerCase());
|
||||
if(hwDIskIdRate == 0) // 100% compare
|
||||
if (hwDIskIdRate == 0) // 100% compare
|
||||
{
|
||||
result.compareLevel += 0.99;
|
||||
}
|
||||
else if(hwDIskIdRate < 3) //Very small change
|
||||
} else if (hwDIskIdRate < 3) //Very small change
|
||||
{
|
||||
result.compareLevel += 0.85;
|
||||
}
|
||||
else if(hwDIskIdRate < (first.hwDiskId.length()+second.hwDiskId.length()) / 4)
|
||||
{
|
||||
double addLevel = hwDIskIdRate / ( (double)(first.hwDiskId.length()+second.hwDiskId.length()) / 2.0 );
|
||||
if(addLevel > 0.0 && addLevel < 0.85) result.compareLevel += addLevel;
|
||||
} else if (hwDIskIdRate < (first.hwDiskId.length() + second.hwDiskId.length()) / 4) {
|
||||
double addLevel = hwDIskIdRate / ((double) (first.hwDiskId.length() + second.hwDiskId.length()) / 2.0);
|
||||
if (addLevel > 0.0 && addLevel < 0.85) result.compareLevel += addLevel;
|
||||
}
|
||||
}
|
||||
if(first.baseboardSerialNumber != null && second.baseboardSerialNumber != null)
|
||||
{
|
||||
if (first.baseboardSerialNumber != null && second.baseboardSerialNumber != null) {
|
||||
int baseboardSerialRate = DamerauHelper.calculateDistance(first.baseboardSerialNumber.toLowerCase(), second.baseboardSerialNumber.toLowerCase());
|
||||
if(baseboardSerialRate == 0) // 100% compare
|
||||
if (baseboardSerialRate == 0) // 100% compare
|
||||
{
|
||||
result.compareLevel += 0.3;
|
||||
}
|
||||
else if(baseboardSerialRate < 3) //Very small change
|
||||
} else if (baseboardSerialRate < 3) //Very small change
|
||||
{
|
||||
result.compareLevel += 0.15;
|
||||
}
|
||||
}
|
||||
if(first.displayId != null && second.displayId != null)
|
||||
{
|
||||
if(Arrays.equals(first.displayId, second.displayId))
|
||||
{
|
||||
if (first.displayId != null && second.displayId != null) {
|
||||
if (Arrays.equals(first.displayId, second.displayId)) {
|
||||
result.compareLevel += 0.75;
|
||||
}
|
||||
}
|
||||
//Check statistic info
|
||||
if(first.logicalProcessors == 0 || first.physicalProcessors == 0 || first.logicalProcessors < first.physicalProcessors) //WTF
|
||||
if (first.logicalProcessors == 0 || first.physicalProcessors == 0 || first.logicalProcessors < first.physicalProcessors) //WTF
|
||||
result.firstSpoofingLevel += 0.9;
|
||||
if(second.logicalProcessors == 0 || second.physicalProcessors == 0 || second.logicalProcessors < second.physicalProcessors) //WTF
|
||||
if (second.logicalProcessors == 0 || second.physicalProcessors == 0 || second.logicalProcessors < second.physicalProcessors) //WTF
|
||||
result.secondSpoofingLevel += 0.9;
|
||||
if(first.physicalProcessors == second.physicalProcessors && first.logicalProcessors == second.logicalProcessors)
|
||||
if (first.physicalProcessors == second.physicalProcessors && first.logicalProcessors == second.logicalProcessors)
|
||||
result.compareLevel += 0.05;
|
||||
if(first.battery != second.battery)
|
||||
if (first.battery != second.battery)
|
||||
result.compareLevel -= 0.05;
|
||||
if(first.processorMaxFreq == second.processorMaxFreq)
|
||||
if (first.processorMaxFreq == second.processorMaxFreq)
|
||||
result.compareLevel += 0.1;
|
||||
if(first.totalMemory == second.totalMemory)
|
||||
if (first.totalMemory == second.totalMemory)
|
||||
result.compareLevel += 0.1;
|
||||
if(Math.abs(first.totalMemory - second.totalMemory) < 32*1024)
|
||||
if (Math.abs(first.totalMemory - second.totalMemory) < 32 * 1024)
|
||||
result.compareLevel += 0.05;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void printHardwareInfo(LogHelper.Level logLevel, HardwareReportRequest.HardwareInfo info)
|
||||
{
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] Processor: logical %d | physical %d | freq %d | bitness %d", info.logicalProcessors, info.physicalProcessors, info.processorMaxFreq, info.bitness) , false);
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] Memory max: %d | battery %s", info.totalMemory, info.battery ? "true" : "false") , false);
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] HWDiskID %s | baseboardSerialNumber %s | displayId hash: %s", info.hwDiskId, info.baseboardSerialNumber, SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, info.displayId))) , false);
|
||||
protected void printHardwareInfo(LogHelper.Level logLevel, HardwareReportRequest.HardwareInfo info) {
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] Processor: logical %d | physical %d | freq %d | bitness %d", info.logicalProcessors, info.physicalProcessors, info.processorMaxFreq, info.bitness), false);
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] Memory max: %d | battery %s", info.totalMemory, info.battery ? "true" : "false"), false);
|
||||
LogHelper.log(logLevel, String.format("[HardwareInfo] HWDiskID %s | baseboardSerialNumber %s | displayId hash: %s", info.hwDiskId, info.baseboardSerialNumber, SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, info.displayId))), false);
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
public void init(LaunchServer server) {
|
||||
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
public void close() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package pro.gravit.launchserver.auth.protect.hwid;
|
||||
|
||||
import pro.gravit.launcher.HTTPRequest;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
public class JsonHWIDProvider extends HWIDProvider {
|
||||
public URL findHardwareInfoByPublicKeyRequest;
|
||||
public URL createHardwareInfoRequest;
|
||||
public URL addPublicKeyToHardwareInfoRequest;
|
||||
public String apiKey;
|
||||
|
||||
public static class RequestFind {
|
||||
public byte[] publicKey;
|
||||
public Client client;
|
||||
public String apiKey;
|
||||
}
|
||||
|
||||
public static class ResultFind {
|
||||
public String error;
|
||||
public HardwareReportRequest.HardwareInfo info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException {
|
||||
try {
|
||||
RequestFind req = new RequestFind();
|
||||
req.publicKey = publicKey;
|
||||
req.client = client;
|
||||
req.apiKey = apiKey;
|
||||
ResultFind r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), findHardwareInfoByPublicKeyRequest), ResultFind.class);
|
||||
if (r.error != null) throw new HWIDException(r.error);
|
||||
return r.info;
|
||||
} catch (HWIDException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
throw new HWIDException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RequestCreate {
|
||||
public byte[] publicKey;
|
||||
public Client client;
|
||||
public HardwareReportRequest.HardwareInfo hardwareInfo;
|
||||
public String apiKey;
|
||||
}
|
||||
|
||||
public static class ResultCreate {
|
||||
public String error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException {
|
||||
try {
|
||||
RequestCreate req = new RequestCreate();
|
||||
req.publicKey = publicKey;
|
||||
req.client = client;
|
||||
req.hardwareInfo = hardwareInfo;
|
||||
req.apiKey = apiKey;
|
||||
ResultCreate r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), createHardwareInfoRequest), ResultCreate.class);
|
||||
if (r.error != null) throw new HWIDException(r.error);
|
||||
} catch (HWIDException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
throw new HWIDException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RequestAddKey {
|
||||
public byte[] publicKey;
|
||||
public Client client;
|
||||
public HardwareReportRequest.HardwareInfo hardwareInfo;
|
||||
public String apiKey;
|
||||
}
|
||||
|
||||
public static class ResultAddKey {
|
||||
public String error;
|
||||
public boolean success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException {
|
||||
try {
|
||||
RequestAddKey req = new RequestAddKey();
|
||||
req.publicKey = publicKey;
|
||||
req.client = client;
|
||||
req.hardwareInfo = hardwareInfo;
|
||||
req.apiKey = apiKey;
|
||||
ResultAddKey r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), addPublicKeyToHardwareInfoRequest), ResultAddKey.class);
|
||||
if (r.error != null) throw new HWIDException(r.error);
|
||||
return r.success;
|
||||
} catch (HWIDException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
throw new HWIDException(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,8 +24,7 @@ public Map<String, Command> getCommands() {
|
|||
commands.put("hardwarelist", new SubCommand() {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
for(MemoryHWIDEntity e : db)
|
||||
{
|
||||
for (MemoryHWIDEntity e : db) {
|
||||
printHardwareInfo(LogHelper.Level.INFO, e.hardware);
|
||||
LogHelper.info("ID %d banned %s", e.id, e.banned ? "true" : "false");
|
||||
LogHelper.info("PublicKey Hash: %s", SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA1, e.publicKey)));
|
||||
|
@ -37,10 +36,8 @@ public void invoke(String... args) throws Exception {
|
|||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
long id = Long.parseLong(args[0]);
|
||||
for(MemoryHWIDEntity e : db)
|
||||
{
|
||||
if(e.id == id)
|
||||
{
|
||||
for (MemoryHWIDEntity e : db) {
|
||||
if (e.id == id) {
|
||||
e.banned = true;
|
||||
LogHelper.info("HardwareID %d banned", e.id);
|
||||
}
|
||||
|
@ -50,8 +47,7 @@ public void invoke(String... args) throws Exception {
|
|||
return commands;
|
||||
}
|
||||
|
||||
static class MemoryHWIDEntity
|
||||
{
|
||||
static class MemoryHWIDEntity {
|
||||
public HardwareReportRequest.HardwareInfo hardware;
|
||||
public byte[] publicKey;
|
||||
public boolean banned;
|
||||
|
@ -63,17 +59,17 @@ public MemoryHWIDEntity(HardwareReportRequest.HardwareInfo hardware, byte[] publ
|
|||
this.id = SecurityHelper.newRandom().nextLong();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MemoryHWIDEntity> db = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException {
|
||||
for(MemoryHWIDEntity e : db) {
|
||||
if(Arrays.equals(e.publicKey, publicKey))
|
||||
{
|
||||
if(e.banned) throw new HWIDException("You HWID banned");
|
||||
for (MemoryHWIDEntity e : db) {
|
||||
if (Arrays.equals(e.publicKey, publicKey)) {
|
||||
if (e.banned) throw new HWIDException("You HWID banned");
|
||||
return e.hardware;
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -85,17 +81,15 @@ public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo,
|
|||
@Override
|
||||
public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException {
|
||||
boolean isAlreadyWarning = false;
|
||||
for(MemoryHWIDEntity e : db) {
|
||||
for (MemoryHWIDEntity e : db) {
|
||||
HardwareInfoCompareResult result = compareHardwareInfo(e.hardware, hardwareInfo);
|
||||
if(warningSpoofingLevel > 0 && result.firstSpoofingLevel > warningSpoofingLevel && !isAlreadyWarning)
|
||||
{
|
||||
if (warningSpoofingLevel > 0 && result.firstSpoofingLevel > warningSpoofingLevel && !isAlreadyWarning) {
|
||||
LogHelper.warning("HardwareInfo spoofing level too high: %d", result.firstSpoofingLevel);
|
||||
isAlreadyWarning = true;
|
||||
}
|
||||
if(result.compareLevel > criticalCompareLevel)
|
||||
{
|
||||
if (result.compareLevel > criticalCompareLevel) {
|
||||
LogHelper.debug("HardwareInfo publicKey change: compareLevel %d", result.compareLevel);
|
||||
if(e.banned) throw new HWIDException("You HWID banned");
|
||||
if (e.banned) throw new HWIDException("You HWID banned");
|
||||
e.publicKey = publicKey;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pro.gravit.launchserver.auth.protect.hwid;
|
||||
|
||||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.MySQLSourceConfig;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
@ -29,37 +30,34 @@ public class MysqlHWIDProvider extends HWIDProvider {
|
|||
private String sqlUpdateUsers;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
public void init(LaunchServer server) {
|
||||
sqlFindByPublicKey = String.format("SELECT hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, banned FROM %s WHERE `publicKey` = ?", tableHWID);
|
||||
sqlFindByHardware = String.format("SELECT hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, banned FROM %s", tableHWID);
|
||||
sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID);
|
||||
sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog);
|
||||
sqlUpdateHardware = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID);
|
||||
if(tableUsers != null && usersHWIDColumn != null && usersNameColumn != null)
|
||||
{
|
||||
if (tableUsers != null && usersHWIDColumn != null && usersNameColumn != null) {
|
||||
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", tableUsers, usersHWIDColumn, usersNameColumn);
|
||||
} else {
|
||||
LogHelper.warning("[MysqlHWIDProvider] Link to users table not configured");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException {
|
||||
try(Connection connection = mySQLHolder.getConnection())
|
||||
{
|
||||
try (Connection connection = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = connection.prepareStatement(sqlFindByPublicKey);
|
||||
s.setBlob(1, new ByteArrayInputStream(publicKey));
|
||||
ResultSet set = s.executeQuery();
|
||||
if(set.next())
|
||||
{
|
||||
if(set.getBoolean(11)) //isBanned
|
||||
if (set.next()) {
|
||||
if (set.getBoolean(11)) //isBanned
|
||||
{
|
||||
throw new SecurityException("You HWID banned");
|
||||
}
|
||||
long id = set.getLong(10);
|
||||
setUserHardwareId(connection, client.username, id);
|
||||
return fetchHardwareInfo(set);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (SQLException | IOException throwables) {
|
||||
|
@ -85,8 +83,7 @@ private HardwareReportRequest.HardwareInfo fetchHardwareInfo(ResultSet set) thro
|
|||
|
||||
@Override
|
||||
public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException {
|
||||
try(Connection connection = mySQLHolder.getConnection())
|
||||
{
|
||||
try (Connection connection = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = connection.prepareStatement(sqlCreateHardware, Statement.RETURN_GENERATED_KEYS);
|
||||
s.setBlob(1, new ByteArrayInputStream(publicKey));
|
||||
s.setString(2, hardwareInfo.hwDiskId);
|
||||
|
@ -113,18 +110,15 @@ public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo,
|
|||
|
||||
@Override
|
||||
public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException {
|
||||
try(Connection connection = mySQLHolder.getConnection())
|
||||
{
|
||||
try (Connection connection = mySQLHolder.getConnection()) {
|
||||
PreparedStatement s = connection.prepareStatement(sqlFindByHardware);
|
||||
ResultSet set = s.executeQuery();
|
||||
while(set.next())
|
||||
{
|
||||
while (set.next()) {
|
||||
HardwareReportRequest.HardwareInfo hw = fetchHardwareInfo(set);
|
||||
long id = set.getLong(10);
|
||||
HardwareInfoCompareResult result = compareHardwareInfo(hw, hardwareInfo);
|
||||
if(result.compareLevel > criticalCompareLevel)
|
||||
{
|
||||
if(set.getBoolean(11)) //isBanned
|
||||
if (result.compareLevel > criticalCompareLevel) {
|
||||
if (set.getBoolean(11)) //isBanned
|
||||
{
|
||||
throw new SecurityException("You HWID banned");
|
||||
}
|
||||
|
@ -134,27 +128,29 @@ public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo har
|
|||
return true;
|
||||
}
|
||||
}
|
||||
} catch (SQLException | IOException throwables)
|
||||
{
|
||||
} catch (SQLException | IOException throwables) {
|
||||
LogHelper.error(throwables);
|
||||
throw new SecurityException("SQL error. Please try again later");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void changePublicKey(Connection connection, long id, byte[] publicKey) throws SQLException {
|
||||
PreparedStatement s = connection.prepareStatement(sqlUpdateHardware);
|
||||
s.setBlob(1, new ByteArrayInputStream(publicKey));
|
||||
s.setLong(2, id);
|
||||
s.executeUpdate();
|
||||
}
|
||||
|
||||
private void writeHwidLog(Connection connection, long hwidId, byte[] newPublicKey) throws SQLException {
|
||||
PreparedStatement s = connection.prepareStatement(sqlCreateHWIDLog);
|
||||
s.setLong(1, hwidId);
|
||||
s.setBlob(2, new ByteArrayInputStream(newPublicKey));
|
||||
s.executeUpdate();
|
||||
}
|
||||
|
||||
private void setUserHardwareId(Connection connection, String username, long hwidId) throws SQLException {
|
||||
if(sqlUpdateUsers == null || username == null) return;
|
||||
if (sqlUpdateUsers == null || username == null) return;
|
||||
PreparedStatement s = connection.prepareStatement(sqlUpdateUsers);
|
||||
s.setLong(1, hwidId);
|
||||
s.setString(2, username);
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
import pro.gravit.launchserver.socket.Client;
|
||||
|
||||
public interface JoinServerProtectHandler {
|
||||
default boolean onJoinServer(String serverID, String username, Client client)
|
||||
{
|
||||
default boolean onJoinServer(String serverID, String username, Client client) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ default void verifySecureLevelKey(byte[] publicKey, byte[] data, byte[] signatur
|
|||
default SecurityReportRequestEvent onSecurityReport(SecurityReportResponse report, Client client) {
|
||||
return new SecurityReportRequestEvent();
|
||||
}
|
||||
default VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client)
|
||||
{
|
||||
|
||||
default VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
|
||||
return new VerifySecureLevelKeyRequestEvent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface p
|
|||
if (user == null) throw new AuthException("Username incorrect");
|
||||
else throw new AuthException("Username or password incorrect");
|
||||
}
|
||||
return new AuthProviderDAOResult(login, SecurityHelper.randomStringToken(), user.getPermissions(), user);
|
||||
return new AuthProviderDAOResult(user.getUsername(), SecurityHelper.randomStringToken(), user.getPermissions(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package pro.gravit.launchserver.auth.provider;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
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.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
|
@ -11,28 +11,22 @@
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
public final class JsonAuthProvider extends AuthProvider {
|
||||
private static final Gson gson = new Gson();
|
||||
private URL url;
|
||||
private String apiKey;
|
||||
public URL url;
|
||||
public String apiKey;
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException {
|
||||
if (!(password instanceof AuthPlainPassword)) throw new AuthException("This password type not supported");
|
||||
authRequest authRequest = new authRequest(login, ((AuthPlainPassword) password).password, ip, apiKey);
|
||||
JsonElement request = gson.toJsonTree(authRequest);
|
||||
JsonElement content = HTTPRequest.jsonRequest(request, url);
|
||||
JsonElement content = HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(new authRequest(login, ((AuthPlainPassword) password).password, ip, apiKey)), url);
|
||||
if (!content.isJsonObject())
|
||||
return authError("Authentication server response is malformed");
|
||||
|
||||
authResult result = gson.fromJson(content, authResult.class);
|
||||
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 if (result.error != null)
|
||||
return authError(result.error);
|
||||
else
|
||||
return authError("Authentication server response is malformed");
|
||||
else return authError(Objects.requireNonNullElse(result.error, "Authentication server response is malformed"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
import java.util.Map;
|
||||
|
||||
public final class RejectAuthProvider extends AuthProvider implements Reconfigurable {
|
||||
private String message;
|
||||
private ArrayList<String> whitelist = new ArrayList<>();
|
||||
public String message;
|
||||
public ArrayList<String> whitelist = new ArrayList<>();
|
||||
|
||||
public RejectAuthProvider() {
|
||||
}
|
||||
|
|
|
@ -11,15 +11,24 @@
|
|||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
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 String url;
|
||||
private transient Pattern pattern;
|
||||
private String response;
|
||||
private boolean flagsEnabled;
|
||||
public String url;
|
||||
public transient Pattern pattern;
|
||||
public String response;
|
||||
public boolean flagsEnabled;
|
||||
public boolean usePermission = true;
|
||||
public int timeout = 5000;
|
||||
private final HttpClient client = HttpClient.newBuilder()
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer srv) {
|
||||
|
@ -30,15 +39,21 @@ public void init(LaunchServer srv) {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AuthProviderResult auth(String login, AuthRequest.AuthPasswordInterface password, String ip) throws IOException {
|
||||
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");
|
||||
String currentResponse = IOHelper.request(new URL(getFormattedURL(login, ((AuthPlainPassword) password).password, ip)));
|
||||
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(
|
||||
Long.parseLong(matcher.group("permissions")), flagsEnabled ? Long.parseLong(matcher.group("flags")) : 0)) :
|
||||
usePermission ? Long.parseLong(matcher.group("permissions")) : 0, flagsEnabled ? Long.parseLong(matcher.group("flags")) : 0)) :
|
||||
authError(currentResponse);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,19 +52,19 @@ public String[] buildConfig(Path inputJar, Path outputJar) {
|
|||
List<String> confStrs = new ArrayList<>();
|
||||
prepare(false);
|
||||
if (srv.config.launcher.proguardGenMappings)
|
||||
confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'");
|
||||
confStrs.add("-obfuscationdictionary \'" + words.toFile().getName() + "\'");
|
||||
confStrs.add("-injar \'" + inputJar.toAbsolutePath() + "\'");
|
||||
confStrs.add("-outjar \'" + outputJar.toAbsolutePath() + "\'");
|
||||
confStrs.add("-printmapping '" + mappings.toFile().getName() + "'");
|
||||
confStrs.add("-obfuscationdictionary '" + words.toFile().getName() + "'");
|
||||
confStrs.add("-injar '" + inputJar.toAbsolutePath() + "'");
|
||||
confStrs.add("-outjar '" + outputJar.toAbsolutePath() + "'");
|
||||
Collections.addAll(confStrs, JVMHelper.JVM_VERSION >= 9 ? JAVA9_OPTS : JAVA8_OPTS);
|
||||
srv.launcherBinary.coreLibs.stream()
|
||||
.map(e -> "-libraryjars \'" + e.toAbsolutePath().toString() + "\'")
|
||||
.map(e -> "-libraryjars '" + e.toAbsolutePath().toString() + "'")
|
||||
.forEach(confStrs::add);
|
||||
|
||||
srv.launcherBinary.addonLibs.stream()
|
||||
.map(e -> "-libraryjars \'" + e.toAbsolutePath().toString() + "\'")
|
||||
.map(e -> "-libraryjars '" + e.toAbsolutePath().toString() + "'")
|
||||
.forEach(confStrs::add);
|
||||
confStrs.add("-classobfuscationdictionary \'" + words.toFile().getName() + "\'");
|
||||
confStrs.add("-classobfuscationdictionary '" + words.toFile().getName() + "'");
|
||||
confStrs.add("@".concat(config.toFile().getName()));
|
||||
return confStrs.toArray(new String[0]);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public class CertificateAutogenTask implements LauncherBuildTask {
|
|||
public X509Certificate certificate;
|
||||
public X509CertificateHolder bcCertificate;
|
||||
public CMSSignedDataGenerator signedDataGenerator;
|
||||
private LaunchServer server;
|
||||
private final LaunchServer server;
|
||||
|
||||
public CertificateAutogenTask(LaunchServer server) {
|
||||
this.server = server;
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
public class MainBuildTask implements LauncherBuildTask {
|
||||
public final ClassMetadataReader reader;
|
||||
private final LaunchServer server;
|
||||
public Set<String> blacklist = new HashSet<>();
|
||||
public List<Transformer> transformers = new ArrayList<>();
|
||||
public IOHookSet<BuildContext> preBuildHook = new IOHookSet<>();
|
||||
public IOHookSet<BuildContext> postBuildHook = new IOHookSet<>();
|
||||
public Map<String, Object> properties = new HashMap<>();
|
||||
public final Set<String> blacklist = new HashSet<>();
|
||||
public final List<Transformer> transformers = new ArrayList<>();
|
||||
public final IOHookSet<BuildContext> preBuildHook = new IOHookSet<>();
|
||||
public final IOHookSet<BuildContext> postBuildHook = new IOHookSet<>();
|
||||
public final Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
public MainBuildTask(LaunchServer srv) {
|
||||
server = srv;
|
||||
|
@ -123,14 +123,13 @@ protected void initProps() {
|
|||
|
||||
public byte[] transformClass(byte[] bytes, String classname, BuildContext context) {
|
||||
byte[] result = bytes;
|
||||
ClassReader cr = null;
|
||||
ClassWriter writer = null;
|
||||
ClassWriter writer;
|
||||
ClassNode cn = null;
|
||||
for (Transformer t : transformers) {
|
||||
if (t instanceof ASMTransformer) {
|
||||
ASMTransformer asmTransformer = (ASMTransformer) t;
|
||||
if (cn == null) {
|
||||
cr = new ClassReader(result);
|
||||
ClassReader cr = new ClassReader(result);
|
||||
cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
}
|
||||
|
@ -144,7 +143,6 @@ public byte[] transformClass(byte[] bytes, String classname, BuildContext contex
|
|||
byte[] old_result = result;
|
||||
result = t.transform(result, classname, context);
|
||||
if (old_result != result) {
|
||||
cr = null;
|
||||
cn = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,19 +32,18 @@ public Path process(Path inputFile) throws IOException {
|
|||
Configuration proguard_cfg = new Configuration();
|
||||
ConfigurationParser parser = new ConfigurationParser(server.proguardConf.buildConfig(inputFile, outputJar),
|
||||
server.proguardConf.proguard.toFile(), System.getProperties());
|
||||
if (JVMHelper.JVM_VERSION >= 9)
|
||||
{
|
||||
if (JVMHelper.JVM_VERSION >= 9) {
|
||||
Path javaJModsPath = Paths.get(System.getProperty("java.home")).resolve("jmods");
|
||||
if(!IOHelper.exists(javaJModsPath))
|
||||
{
|
||||
if (!IOHelper.exists(javaJModsPath)) {
|
||||
LogHelper.warning("Directory %s not found. It is not good", javaJModsPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//Find javaFX libraries
|
||||
if(!IOHelper.exists(javaJModsPath.resolve("javafx.base.jmod"))) LogHelper.warning("javafx.base.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
if(!IOHelper.exists(javaJModsPath.resolve("javafx.graphics.jmod"))) LogHelper.warning("javafx.graphics.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
if(!IOHelper.exists(javaJModsPath.resolve("javafx.controls.jmod"))) LogHelper.warning("javafx.controls.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
if (!IOHelper.exists(javaJModsPath.resolve("javafx.base.jmod")))
|
||||
LogHelper.error("javafx.base.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
if (!IOHelper.exists(javaJModsPath.resolve("javafx.graphics.jmod")))
|
||||
LogHelper.error("javafx.graphics.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
if (!IOHelper.exists(javaJModsPath.resolve("javafx.controls.jmod")))
|
||||
LogHelper.error("javafx.controls.jmod not found. Launcher can be assembled incorrectly. Maybe you need to install OpenJFX?");
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package pro.gravit.launchserver.binary.tasks.exe;
|
||||
|
||||
public interface BuildExeMainTask {
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class Launch4JTask implements LauncherBuildTask {
|
||||
public class Launch4JTask implements LauncherBuildTask, BuildExeMainTask {
|
||||
public static final String DOWNLOAD_URL = "http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html"; // Oracle
|
||||
private static final String VERSION = Version.getVersion().getVersionString();
|
||||
private static final int BUILD = Version.getVersion().build;
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
import java.util.Map;
|
||||
|
||||
public abstract class Command extends pro.gravit.utils.command.Command {
|
||||
|
||||
|
||||
protected final LaunchServer server;
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
package pro.gravit.launchserver.command.basic;
|
||||
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyPair;
|
||||
|
@ -54,5 +58,28 @@ public void invoke(String... args) throws Exception {
|
|||
server.certificateManager.writePrivateKey(Paths.get(name.concat(".key")), pair.getPrivate());
|
||||
server.certificateManager.writeCertificate(Paths.get(name.concat(".crt")), cert);
|
||||
}
|
||||
if (args[0].equals("authstresser")) {
|
||||
AuthProviderPair pair = server.config.getAuthProviderPair();
|
||||
AuthPlainPassword plainPassword = new AuthPlainPassword("test");
|
||||
Runnable runnable = () -> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
for (int i = 0; i < 100000; ++i) {
|
||||
try {
|
||||
pair.provider.auth("Test", plainPassword, "127.0.0.1");
|
||||
} catch (AuthException ignored) {
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if ((i % 10000) == 0) {
|
||||
LogHelper.info("Completed %d requests", i);
|
||||
}
|
||||
}
|
||||
LogHelper.info("Completed all requests. Time %d ms", System.currentTimeMillis() - startTime);
|
||||
};
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
CommonHelper.newThread(String.format("Stresser #%d", i), true, runnable).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
|
|||
service.registerCommand("clients", new ClientsCommand(server));
|
||||
service.registerCommand("signJar", new SignJarCommand(server));
|
||||
service.registerCommand("signDir", new SignDirCommand(server));
|
||||
service.registerCommand("securitycheck", new SecurityCheckCommand(server));
|
||||
Category serviceCategory = new Category(service, "service", "Managing LaunchServer Components");
|
||||
handler.registerCategory(serviceCategory);
|
||||
}
|
||||
|
|
|
@ -63,11 +63,9 @@ public void invoke(String... args) throws IOException, CommandException {
|
|||
client.setTitle(dirName);
|
||||
client.setDir(dirName);
|
||||
client.setUUID(UUID.randomUUID());
|
||||
if(client.getServers() != null)
|
||||
{
|
||||
ClientProfile.ServerProfile serverProfile = client.getDefaultServerProfile();
|
||||
if(serverProfile != null)
|
||||
{
|
||||
if (client.getServers() != null) {
|
||||
ClientProfile.ServerProfile serverProfile = client.getDefaultServerProfile();
|
||||
if (serverProfile != null) {
|
||||
serverProfile.name = dirName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalFile;
|
||||
import pro.gravit.launcher.profiles.optional.actions.*;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.command.Command;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
|
@ -12,6 +14,9 @@
|
|||
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 {
|
||||
|
@ -19,11 +24,10 @@ public SaveProfilesCommand(LaunchServer server) {
|
|||
super(server);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecated")
|
||||
@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)
|
||||
{
|
||||
if (profile.getServers().size() == 0) {
|
||||
ClientProfile.ServerProfile serverProfile = new ClientProfile.ServerProfile();
|
||||
serverProfile.isDefault = true;
|
||||
serverProfile.name = profile.getTitle();
|
||||
|
@ -31,6 +35,34 @@ 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:
|
||||
LogHelper.warning("Not converted optional %s with type %s. Type unknown", file.name, file.type.toString());
|
||||
continue;
|
||||
}
|
||||
file.actions.add(action);
|
||||
}
|
||||
}
|
||||
try (Writer w = IOHelper.newWriter(path)) {
|
||||
Launcher.gsonManager.configGson.toJson(profile, w);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public String getUsageDescription() {
|
|||
public void invoke(String... args) throws IOException {
|
||||
server.syncProfilesDir();
|
||||
LogHelper.subInfo("Profiles successfully resynced");
|
||||
|
||||
|
||||
server.syncUpdatesDir(null);
|
||||
LogHelper.subInfo("Updates dir successfully resynced");
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public void invoke(String... args) {
|
|||
service.channels.forEach((channel -> {
|
||||
WebSocketFrameHandler frameHandler = channel.pipeline().get(WebSocketFrameHandler.class);
|
||||
Client client = frameHandler.getClient();
|
||||
String ip = IOHelper.getIP(channel.remoteAddress());
|
||||
String ip = frameHandler.context.ip != null ? frameHandler.context.ip : IOHelper.getIP(channel.remoteAddress());
|
||||
if (!client.isAuth)
|
||||
LogHelper.info("Channel %s | connectUUID %s | checkSign %s", ip, frameHandler.getConnectUUID(), client.checkSign ? "true" : "false");
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
package pro.gravit.launchserver.command.service;
|
||||
|
||||
import org.fusesource.jansi.Ansi;
|
||||
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.config.LaunchServerConfig;
|
||||
import pro.gravit.utils.helper.FormatHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class SecurityCheckCommand extends Command {
|
||||
public SecurityCheckCommand(LaunchServer server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "[]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsageDescription() {
|
||||
return "check configuration";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
LaunchServerConfig config = server.config;
|
||||
config.auth.forEach((name, pair) -> {
|
||||
if (pair.provider instanceof AcceptAuthProvider) {
|
||||
printCheckResult(LogHelper.Level.INFO, String.format("auth.%s.provider", name), "Accept auth provider", false);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, String.format("auth.%s.provider", name), "", true);
|
||||
}
|
||||
if (pair.handler instanceof MemoryAuthHandler) {
|
||||
printCheckResult(LogHelper.Level.INFO, String.format("auth.%s.handler", name), "MemoryAuthHandler test-only", false);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, String.format("auth.%s.handler", name), "", true);
|
||||
}
|
||||
});
|
||||
if (config.protectHandler instanceof NoProtectHandler) {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler", "protectHandler none", false);
|
||||
} else if (config.protectHandler instanceof AdvancedProtectHandler) {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler", "", true);
|
||||
if (!((AdvancedProtectHandler) config.protectHandler).enableHardwareFeature) {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler.hardwareId", "you can improve security by using hwid provider", null);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler.hardwareId", "", true);
|
||||
}
|
||||
} else if (config.protectHandler instanceof StdProtectHandler) {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler", "you can improve security by using advanced", null);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, "protectHandler", "unknown protectHandler", null);
|
||||
}
|
||||
if (config.netty.address.startsWith("ws://")) {
|
||||
if (config.netty.ipForwarding)
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.ipForwarding", "ipForwarding may be used to spoofing ip", null);
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.address", "websocket connection not secure", false);
|
||||
} else if (config.netty.address.startsWith("wss://")) {
|
||||
if (!config.netty.ipForwarding)
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.ipForwarding", "ipForwarding not enabled. authLimiter may be get incorrect ip", null);
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.address", "", true);
|
||||
}
|
||||
|
||||
if (config.netty.sendExceptionEnabled) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.sendExceptionEnabled", "recommend \"false\" in production", false);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.sendExceptionEnabled", "", true);
|
||||
}
|
||||
|
||||
if (config.netty.launcherURL.startsWith("http://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.launcherUrl", "launcher jar download connection not secure", false);
|
||||
} else if (config.netty.launcherURL.startsWith("https://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.launcherUrl", "", true);
|
||||
}
|
||||
|
||||
if (config.netty.launcherEXEURL.startsWith("http://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.launcherExeUrl", "launcher exe download connection not secure", false);
|
||||
} else if (config.netty.launcherEXEURL.startsWith("https://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.launcherExeUrl", "", true);
|
||||
}
|
||||
|
||||
if (config.netty.downloadURL.startsWith("http://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.downloadUrl", "assets/clients download connection not secure", false);
|
||||
} else if (config.netty.downloadURL.startsWith("https://")) {
|
||||
printCheckResult(LogHelper.Level.INFO, "netty.downloadUrl", "", true);
|
||||
}
|
||||
|
||||
if (!config.sign.enabled) {
|
||||
printCheckResult(LogHelper.Level.INFO, "sign", "it is recommended to use a signature", null);
|
||||
} else {
|
||||
/*boolean bad = false;
|
||||
KeyStore keyStore = SignHelper.getStore(new File(config.sign.keyStore).toPath(), config.sign.keyStorePass, config.sign.keyStoreType);
|
||||
X509Certificate[] certChain = (X509Certificate[]) keyStore.getCertificateChain(config.sign.keyAlias);
|
||||
X509Certificate cert = (X509Certificate) keyStore.getCertificate(config.sign.keyAlias);
|
||||
cert.checkValidity();
|
||||
if(certChain.length <= 1) {
|
||||
printCheckResult(LogHelper.Level.INFO, "sign", "certificate chain contains <2 element(recommend 2 and more)", false);
|
||||
bad = true;
|
||||
}
|
||||
if((cert.getBasicConstraints() & 1) != 0) {
|
||||
printCheckResult(LogHelper.Level.INFO, "sign", "end certificate - CA", false);
|
||||
bad = true;
|
||||
}
|
||||
for(X509Certificate certificate : certChain)
|
||||
{
|
||||
certificate.checkValidity();
|
||||
}
|
||||
if(!bad)*/
|
||||
printCheckResult(LogHelper.Level.INFO, "sign", "", true);
|
||||
}
|
||||
|
||||
if (!config.launcher.enabledProGuard) {
|
||||
printCheckResult(LogHelper.Level.INFO, "launcher.enabledProGuard", "proguard not enabled", false);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, "launcher.enabledProGuard", "", true);
|
||||
}
|
||||
if (!config.launcher.stripLineNumbers) {
|
||||
printCheckResult(LogHelper.Level.INFO, "launcher.stripLineNumbers", "stripLineNumbers not enabled", false);
|
||||
} else {
|
||||
printCheckResult(LogHelper.Level.INFO, "launcher.stripLineNumbers", "", true);
|
||||
}
|
||||
|
||||
switch (config.env) {
|
||||
|
||||
case DEV:
|
||||
printCheckResult(LogHelper.Level.INFO, "env", "found env DEV", false);
|
||||
break;
|
||||
case DEBUG:
|
||||
printCheckResult(LogHelper.Level.INFO, "env", "found env DEBUG", false);
|
||||
break;
|
||||
case STD:
|
||||
printCheckResult(LogHelper.Level.INFO, "env", "you can improve security by using env PROD", null);
|
||||
break;
|
||||
case PROD:
|
||||
printCheckResult(LogHelper.Level.INFO, "env", "", true);
|
||||
break;
|
||||
}
|
||||
|
||||
//Profiles
|
||||
for (ClientProfile profile : server.getProfiles()) {
|
||||
boolean bad = false;
|
||||
String profileModuleName = String.format("profiles.%s", profile.getTitle());
|
||||
for (String exc : profile.getUpdateExclusions()) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(exc, "/");
|
||||
if (exc.endsWith(".jar")) {
|
||||
printCheckResult(LogHelper.Level.INFO, profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
|
||||
bad = true;
|
||||
continue;
|
||||
}
|
||||
if (tokenizer.hasMoreTokens() && tokenizer.nextToken().equals("mods")) {
|
||||
String nextToken = tokenizer.nextToken();
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
printCheckResult(LogHelper.Level.INFO, profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
|
||||
bad = true;
|
||||
} else {
|
||||
if (nextToken.equals("memory_repo") || nextToken.equals(profile.getVersion().name)) {
|
||||
printCheckResult(LogHelper.Level.INFO, profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
|
||||
bad = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bad)
|
||||
printCheckResult(LogHelper.Level.INFO, profileModuleName, "", true);
|
||||
}
|
||||
LogHelper.info("Check completed");
|
||||
}
|
||||
|
||||
public static void printCheckResult(LogHelper.Level level, String module, String comment, Boolean status) {
|
||||
LogHelper.rawLog(() -> FormatHelper.rawFormat(level, LogHelper.getDataTime(), false).concat(String.format("[%s] %s - %s", module, comment, status == null ? "WARN" : (status ? "OK" : "FAIL"))),
|
||||
() -> FormatHelper.rawAnsiFormat(level, LogHelper.getDataTime(), false)
|
||||
.fgBright(Ansi.Color.WHITE)
|
||||
.a("[")
|
||||
.fgBright(Ansi.Color.BLUE)
|
||||
.a(module)
|
||||
.fgBright(Ansi.Color.WHITE)
|
||||
.a("] ".concat(comment).concat(" - "))
|
||||
.fgBright(status == null ? Ansi.Color.YELLOW : (status ? Ansi.Color.GREEN : Ansi.Color.RED))
|
||||
.a(status == null ? "WARN" : (status ? "OK" : "FAIL"))
|
||||
.reset().toString());
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ public void invoke(String... args) throws Exception {
|
|||
}
|
||||
|
||||
private class SignJarVisitor extends SimpleFileVisitor<Path> {
|
||||
private SignJarTask task;
|
||||
private final SignJarTask task;
|
||||
|
||||
public SignJarVisitor(SignJarTask task) {
|
||||
this.task = task;
|
||||
|
|
|
@ -75,6 +75,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
|||
|
||||
newConfig.netty = new NettyConfig();
|
||||
newConfig.netty.fileServerEnabled = true;
|
||||
newConfig.netty.sendExceptionEnabled = false;
|
||||
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
|
||||
newConfig.netty.performance = new NettyPerformanceConfig();
|
||||
try {
|
||||
|
@ -111,7 +112,6 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
|||
regLimiterComponent.rateLimitMillis = 1000 * 60 * 60 * 10; //Блок на 10 часов
|
||||
regLimiterComponent.message = "Превышен лимит регистраций";
|
||||
newConfig.components.put("regLimiter", regLimiterComponent);
|
||||
newConfig.netty.sendExceptionEnabled = true;
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ public void init(LaunchServer.ReloadType type) {
|
|||
}
|
||||
if (protectHandler != null) {
|
||||
server.registerObject("protectHandler", protectHandler);
|
||||
protectHandler.init();
|
||||
protectHandler.init(server);
|
||||
protectHandler.checkLaunchServerLicense();
|
||||
}
|
||||
if (components != null) {
|
||||
|
@ -296,6 +296,7 @@ public static class NettyConfig {
|
|||
public boolean fileServerEnabled;
|
||||
public boolean sendExceptionEnabled;
|
||||
public boolean ipForwarding;
|
||||
public boolean disableWebApiInterface;
|
||||
public boolean showHiddenFiles;
|
||||
public String launcherURL;
|
||||
public String downloadURL;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
public abstract class DaoProvider {
|
||||
public static final ProviderMap<DaoProvider> providers = new ProviderMap<>("DaoProvider");
|
||||
public UserDAO userDAO;
|
||||
public transient UserDAO userDAO;
|
||||
|
||||
public static void registerProviders() {
|
||||
// None
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package pro.gravit.launchserver.helper;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DamerauHelper {
|
||||
//Расстояние Дамерау — Левенштейна. GitHub https://github.com/crwohlfeil/damerau-levenshtein
|
||||
public static int calculateDistance(CharSequence source, CharSequence target) {
|
||||
|
|
|
@ -27,32 +27,7 @@
|
|||
|
||||
public class SignHelper {
|
||||
|
||||
public static final OutputStream NULL = new OutputStream() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NullOutputStream";
|
||||
}
|
||||
|
||||
/** Discards the specified byte array. */
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
}
|
||||
|
||||
/** Discards the specified byte array. */
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
}
|
||||
|
||||
/** Discards the specified byte. */
|
||||
@Override
|
||||
public void write(int b) {
|
||||
}
|
||||
|
||||
/** Never closes */
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
};
|
||||
public static final OutputStream NULL = OutputStream.nullOutputStream();
|
||||
public static final String hashFunctionName = "SHA-256";
|
||||
|
||||
private SignHelper() {
|
||||
|
|
|
@ -29,7 +29,8 @@ public class LauncherModuleLoader {
|
|||
private final LaunchServer server;
|
||||
|
||||
public LauncherModuleLoader(LaunchServer server) {
|
||||
this.server = server; modulesDir = server.dir.resolve("launcher-modules");
|
||||
this.server = server;
|
||||
modulesDir = server.dir.resolve("launcher-modules");
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
@ -140,19 +141,17 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
|||
return super.visitFile(file, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
public void addClassFieldsToProperties(Map<String, Object> propertyMap, String prefix, Object object, Class<?> classOfObject) throws IllegalAccessException {
|
||||
Field[] fields = classOfObject.getFields();
|
||||
for (Field field : fields) {
|
||||
if ((field.getModifiers() & Modifier.STATIC) != 0) continue;
|
||||
Object obj = field.get(object);
|
||||
String propertyName = prefix.concat(".").concat(field.getName().toLowerCase(Locale.US));
|
||||
if(InjectClassAcceptor.isSerializableValue(obj))
|
||||
{
|
||||
if (InjectClassAcceptor.isSerializableValue(obj)) {
|
||||
LogHelper.dev("Property name %s", propertyName);
|
||||
propertyMap.put(propertyName, obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
//Try recursive add fields
|
||||
addClassFieldsToProperties(propertyMap, propertyName, obj, obj.getClass());
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ public void readTrustStore(Path dir) throws IOException, CertificateException {
|
|||
}
|
||||
List<X509Certificate> certificates = new ArrayList<>();
|
||||
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
|
||||
IOHelper.walk(dir, new SimpleFileVisitor<Path>() {
|
||||
IOHelper.walk(dir, new SimpleFileVisitor<>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (file.toFile().getName().endsWith(".crt")) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import com.google.gson.GsonBuilder;
|
||||
import pro.gravit.launcher.managers.GsonManager;
|
||||
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
||||
import pro.gravit.launcher.request.WebSocketEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
|
@ -39,6 +40,7 @@ public void registerAdapters(GsonBuilder builder) {
|
|||
builder.registerTypeAdapter(WebSocketEvent.class, new JsonResultSerializeAdapter());
|
||||
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
||||
builder.registerTypeAdapter(HWIDProvider.class, new UniversalJsonAdapter<>(HWIDProvider.providers));
|
||||
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
|
||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||
//ClientWebSocketService.appendTypeAdapters(builder);
|
||||
}
|
||||
|
|
|
@ -8,10 +8,9 @@
|
|||
import java.util.Map;
|
||||
|
||||
public class PingServerManager {
|
||||
public static long REPORT_EXPIRED_TIME = 20*1000;
|
||||
public static final long REPORT_EXPIRED_TIME = 20 * 1000;
|
||||
|
||||
public static class ServerInfoEntry
|
||||
{
|
||||
public static class ServerInfoEntry {
|
||||
public PingServerReportRequest.PingServerReport lastReport;
|
||||
public long lastReportTime;
|
||||
public final ClientProfile profile;
|
||||
|
@ -26,37 +25,34 @@ public ServerInfoEntry(ClientProfile profile) {
|
|||
this.profile = profile;
|
||||
}
|
||||
|
||||
public boolean isExpired()
|
||||
{
|
||||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() - lastReportTime > REPORT_EXPIRED_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
public final Map<String, ServerInfoEntry> map = new HashMap<>();
|
||||
private final LaunchServer server;
|
||||
|
||||
public PingServerManager(LaunchServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
public void syncServers()
|
||||
{
|
||||
|
||||
public void syncServers() {
|
||||
server.getProfiles().forEach((p) -> {
|
||||
for(ClientProfile.ServerProfile sp : p.getServers())
|
||||
{
|
||||
for (ClientProfile.ServerProfile sp : p.getServers()) {
|
||||
ServerInfoEntry entry = map.get(sp.name);
|
||||
if(entry == null)
|
||||
{
|
||||
if (entry == null) {
|
||||
map.put(sp.name, new ServerInfoEntry(p));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public boolean updateServer(String name, PingServerReportRequest.PingServerReport report)
|
||||
{
|
||||
|
||||
public boolean updateServer(String name, PingServerReportRequest.PingServerReport report) {
|
||||
ServerInfoEntry entry = map.get(name);
|
||||
if(entry == null)
|
||||
if (entry == null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
else {
|
||||
entry.lastReportTime = System.currentTimeMillis();
|
||||
entry.lastReport = report;
|
||||
return true;
|
||||
|
|
|
@ -3,17 +3,14 @@
|
|||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SessionManager implements NeedGarbageCollection {
|
||||
|
||||
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
||||
private final Map<Long, Client> clientSet = new HashMap<>(128);
|
||||
private final Map<UUID, Client> clientSet = new HashMap<>(128);
|
||||
|
||||
|
||||
public boolean addClient(Client client) {
|
||||
|
@ -31,21 +28,21 @@ public void garbageCollection() {
|
|||
}
|
||||
|
||||
|
||||
public Client getClient(long session) {
|
||||
public Client getClient(UUID session) {
|
||||
return clientSet.get(session);
|
||||
}
|
||||
|
||||
|
||||
public Client getOrNewClient(long session) {
|
||||
public Client getOrNewClient(UUID session) {
|
||||
return clientSet.computeIfAbsent(session, Client::new);
|
||||
}
|
||||
|
||||
public Client removeClient(long session) {
|
||||
public Client removeClient(UUID session) {
|
||||
return clientSet.remove(session);
|
||||
}
|
||||
|
||||
|
||||
public void updateClient(long session) {
|
||||
public void updateClient(UUID session) {
|
||||
Client c = clientSet.get(session);
|
||||
if (c != null) {
|
||||
c.up();
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Client {
|
||||
public long session;
|
||||
public UUID session;
|
||||
public String auth_id;
|
||||
public long timestamp;
|
||||
public AuthResponse.ConnectTypes type;
|
||||
|
@ -20,13 +23,14 @@ public class Client {
|
|||
public ClientPermissions permissions;
|
||||
public String username;
|
||||
public TrustLevel trustLevel;
|
||||
public transient LogHelper.OutputEnity logOutput;
|
||||
|
||||
public transient AuthProviderPair auth;
|
||||
|
||||
public transient User daoObject;
|
||||
|
||||
public Client(long session) {
|
||||
public transient Map<String, Object> properties;
|
||||
|
||||
public Client(UUID session) {
|
||||
this.session = session;
|
||||
timestamp = System.currentTimeMillis();
|
||||
type = null;
|
||||
|
@ -58,4 +62,15 @@ public static class TrustLevel {
|
|||
public byte[] publicKey;
|
||||
public HardwareReportRequest.HardwareInfo hardwareInfo;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getProperty(String name) {
|
||||
if (properties == null) properties = new HashMap<>();
|
||||
return (T) properties.get(name);
|
||||
}
|
||||
|
||||
public <T> void setProperty(String name, T object) {
|
||||
if (properties == null) properties = new HashMap<>();
|
||||
properties.put(name, object);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||
import pro.gravit.launchserver.socket.handlers.NettyIpForwardHandler;
|
||||
import pro.gravit.launchserver.socket.handlers.NettyWebAPIHandler;
|
||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||
import pro.gravit.launchserver.socket.handlers.fileserver.FileServerHandler;
|
||||
import pro.gravit.utils.BiHookSet;
|
||||
|
@ -41,8 +42,8 @@ public LauncherNettyServer(LaunchServer server) {
|
|||
if (config.performance.usingEpoll && !Epoll.isAvailable()) {
|
||||
LogHelper.error("Epoll is not available: (netty,perfomance.usingEpoll configured wrongly)", Epoll.unavailabilityCause());
|
||||
}
|
||||
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread);
|
||||
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread);
|
||||
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread, "LauncherNettyServer.bossGroup");
|
||||
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread, "LauncherNettyServer.workerGroup");
|
||||
serverBootstrap = new ServerBootstrap();
|
||||
service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), server);
|
||||
serverBootstrap.group(bossGroup, workerGroup)
|
||||
|
@ -60,6 +61,8 @@ public void initChannel(SocketChannel ch) {
|
|||
pipeline.addLast("forward-http", new NettyIpForwardHandler(context));
|
||||
pipeline.addLast("websock-comp", new WebSocketServerCompressionHandler());
|
||||
pipeline.addLast("websock-codec", new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
||||
if (!server.config.netty.disableWebApiInterface)
|
||||
pipeline.addLast("webapi", new NettyWebAPIHandler(context));
|
||||
if (server.config.netty.fileServerEnabled)
|
||||
pipeline.addLast("fileserver", new FileServerHandler(server.updatesDir, true, config.showHiddenFiles));
|
||||
pipeline.addLast("launchserver", new WebSocketFrameHandler(context, server, service));
|
||||
|
|
|
@ -15,7 +15,7 @@ public static void setUsingEpoll(boolean value) {
|
|||
epoll = value;
|
||||
}
|
||||
|
||||
public static EventLoopGroup newEventLoopGroup(int threads) {
|
||||
public static EventLoopGroup newEventLoopGroup(int threads, String poolName) {
|
||||
if (epoll)
|
||||
return new EpollEventLoopGroup(threads);
|
||||
else
|
||||
|
@ -28,5 +28,4 @@ public static ChannelFactory<? extends ServerChannel> getServerSocketChannelFact
|
|||
else
|
||||
return NioServerSocketChannel::new;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package pro.gravit.launchserver.socket;
|
||||
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class NettyThreadFactory extends DefaultThreadFactory {
|
||||
public NettyThreadFactory(String poolName) {
|
||||
super(poolName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Thread newThread(Runnable r, String name) {
|
||||
Thread thread = super.newThread(r, name);
|
||||
thread.setUncaughtExceptionHandler((th, e) -> {
|
||||
if (LogHelper.isDebugEnabled())
|
||||
LogHelper.error(e);
|
||||
});
|
||||
return thread;
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
import pro.gravit.launcher.events.request.ErrorRequestEvent;
|
||||
import pro.gravit.launcher.request.WebSocketEvent;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
||||
import pro.gravit.launchserver.socket.response.auth.*;
|
||||
|
@ -36,6 +37,7 @@
|
|||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class WebSocketService {
|
||||
public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
||||
|
@ -45,16 +47,16 @@ public class WebSocketService {
|
|||
private final Gson gson;
|
||||
|
||||
//Statistic data
|
||||
public AtomicLong shortRequestLatency = new AtomicLong();
|
||||
public AtomicLong shortRequestCounter = new AtomicLong();
|
||||
public final AtomicLong shortRequestLatency = new AtomicLong();
|
||||
public final AtomicLong shortRequestCounter = new AtomicLong();
|
||||
|
||||
public AtomicLong middleRequestLatency = new AtomicLong();
|
||||
public AtomicLong middleRequestCounter = new AtomicLong();
|
||||
public final AtomicLong middleRequestLatency = new AtomicLong();
|
||||
public final AtomicLong middleRequestCounter = new AtomicLong();
|
||||
|
||||
public AtomicLong longRequestLatency = new AtomicLong();
|
||||
public AtomicLong longRequestCounter = new AtomicLong();
|
||||
public final AtomicLong longRequestLatency = new AtomicLong();
|
||||
public final AtomicLong longRequestCounter = new AtomicLong();
|
||||
|
||||
public AtomicLong lastRequestTime = new AtomicLong();
|
||||
public final AtomicLong lastRequestTime = new AtomicLong();
|
||||
|
||||
public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
||||
this.channels = channels;
|
||||
|
@ -65,6 +67,15 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
|||
this.gson = Launcher.gsonManager.gson;
|
||||
}
|
||||
|
||||
public void forEachActiveChannels(BiConsumer<Channel, WebSocketFrameHandler> callback) {
|
||||
channels.forEach((channel) -> {
|
||||
if (channel == null || channel.pipeline() == null) return;
|
||||
WebSocketFrameHandler wsHandler = channel.pipeline().get(WebSocketFrameHandler.class);
|
||||
if (wsHandler == null) return;
|
||||
callback.accept(channel, wsHandler);
|
||||
});
|
||||
}
|
||||
|
||||
public static void registerResponses() {
|
||||
providers.register("auth", AuthResponse.class);
|
||||
providers.register("checkServer", CheckServerResponse.class);
|
||||
|
@ -79,8 +90,6 @@ public static void registerResponses() {
|
|||
providers.register("profileByUsername", ProfileByUsername.class);
|
||||
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
||||
providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
||||
providers.register("register", RegisterResponse.class);
|
||||
providers.register("setPassword", SetPasswordResponse.class);
|
||||
providers.register("exit", ExitResponse.class);
|
||||
providers.register("getSecureLevelInfo", GetSecureLevelInfoResponse.class);
|
||||
providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class);
|
||||
|
@ -89,6 +98,7 @@ public static void registerResponses() {
|
|||
providers.register("serverStatus", ServerStatusResponse.class);
|
||||
providers.register("pingServerReport", PingServerReportResponse.class);
|
||||
providers.register("pingServer", PingServerResponse.class);
|
||||
providers.register("currentUser", CurrentUserResponse.class);
|
||||
}
|
||||
|
||||
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||
|
@ -102,32 +112,28 @@ public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client
|
|||
}
|
||||
process(ctx, response, client, ip);
|
||||
long executeTime = System.nanoTime() - startTimeNanos;
|
||||
if(executeTime > 0)
|
||||
{
|
||||
if (executeTime > 0) {
|
||||
addRequestTimeToStats(executeTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void addRequestTimeToStats(long nanos)
|
||||
{
|
||||
if(nanos < 100_000_000L) // < 100 millis
|
||||
public void addRequestTimeToStats(long nanos) {
|
||||
if (nanos < 100_000_000L) // < 100 millis
|
||||
{
|
||||
shortRequestCounter.getAndIncrement();
|
||||
shortRequestLatency.getAndAdd(nanos);
|
||||
}
|
||||
else if(nanos < 1_000_000_000L) // > 100 millis and < 1 second
|
||||
} else if (nanos < 1_000_000_000L) // > 100 millis and < 1 second
|
||||
{
|
||||
middleRequestCounter.getAndIncrement();
|
||||
middleRequestLatency.getAndAdd(nanos);
|
||||
}
|
||||
else // > 1 second
|
||||
} else // > 1 second
|
||||
{
|
||||
longRequestCounter.getAndIncrement();
|
||||
longRequestLatency.getAndAdd(nanos);
|
||||
}
|
||||
long lastTime = lastRequestTime.get();
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(currentTime - lastTime > 60*1000) //1 minute
|
||||
if (currentTime - lastTime > 60 * 1000) //1 minute
|
||||
{
|
||||
lastRequestTime.set(currentTime);
|
||||
shortRequestLatency.set(0);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package pro.gravit.launchserver.socket.handlers;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
private final NettyConnectContext context;
|
||||
|
||||
public NettyWebAPIHandler(NettyConnectContext context) {
|
||||
super();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SimpleSeverletHandler {
|
||||
void handle(ChannelHandlerContext ctx, FullHttpRequest msg, NettyConnectContext context) throws Exception;
|
||||
}
|
||||
|
||||
public static class SeverletPathPair {
|
||||
public final String key;
|
||||
public final SimpleSeverletHandler callback;
|
||||
|
||||
public SeverletPathPair(String key, SimpleSeverletHandler callback) {
|
||||
this.key = key;
|
||||
this.callback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
private static final TreeSet<SeverletPathPair> severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length()));
|
||||
|
||||
public static SeverletPathPair addNewSeverlet(String path, SimpleSeverletHandler callback) {
|
||||
SeverletPathPair pair = new SeverletPathPair("/webapi/".concat(path), callback);
|
||||
severletList.add(pair);
|
||||
return pair;
|
||||
}
|
||||
|
||||
public static SeverletPathPair addUnsafeSeverlet(String path, SimpleSeverletHandler callback) {
|
||||
SeverletPathPair pair = new SeverletPathPair(path, callback);
|
||||
severletList.add(pair);
|
||||
return pair;
|
||||
}
|
||||
|
||||
public static void removeSeverlet(SeverletPathPair pair) {
|
||||
severletList.remove(pair);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
|
||||
boolean isNext = true;
|
||||
for (SeverletPathPair pair : severletList) {
|
||||
if (msg.uri().startsWith(pair.key)) {
|
||||
pair.callback.handle(ctx, msg, context);
|
||||
isNext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNext) {
|
||||
msg.retain();
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,12 +4,12 @@
|
|||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.websocketx.*;
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||
import pro.gravit.launchserver.socket.WebSocketService;
|
||||
import pro.gravit.utils.BiHookSet;
|
||||
import pro.gravit.utils.HookSet;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
|
@ -17,15 +17,14 @@
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {
|
||||
static {
|
||||
}
|
||||
|
||||
public final LaunchServer srv;
|
||||
public final WebSocketService service;
|
||||
private final UUID connectUUID = UUID.randomUUID();
|
||||
public NettyConnectContext context;
|
||||
public BiHookSet<ChannelHandlerContext, WebSocketFrame> hooks = new BiHookSet<>();
|
||||
public final BiHookSet<ChannelHandlerContext, WebSocketFrame> hooks = new BiHookSet<>();
|
||||
private Client client;
|
||||
private ScheduledFuture<?> future;
|
||||
|
||||
public WebSocketFrameHandler(NettyConnectContext context, LaunchServer srv, WebSocketService service) {
|
||||
this.context = context;
|
||||
|
@ -50,20 +49,35 @@ public void channelActive(ChannelHandlerContext ctx) {
|
|||
if (LogHelper.isDevEnabled()) {
|
||||
LogHelper.dev("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));
|
||||
}
|
||||
client = new Client(0);
|
||||
client = new Client(null);
|
||||
Channel ch = ctx.channel();
|
||||
service.registerClient(ch);
|
||||
ctx.executor().schedule(() -> {
|
||||
ch.writeAndFlush(new PingWebSocketFrame(), ch.voidPromise());
|
||||
}, 30L, TimeUnit.SECONDS);
|
||||
future = ctx.executor().scheduleAtFixedRate(() -> ch.writeAndFlush(new PingWebSocketFrame(), ch.voidPromise()), 30L, 30L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||
// ping and pong frames already handled
|
||||
if(hooks.hook(ctx, frame)) return;
|
||||
try {
|
||||
if (hooks.hook(ctx, frame)) return;
|
||||
} catch (Throwable ex) {
|
||||
LogHelper.error(ex);
|
||||
}
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
service.process(ctx, (TextWebSocketFrame) frame, client, context.ip);
|
||||
try {
|
||||
service.process(ctx, (TextWebSocketFrame) frame, client, context.ip);
|
||||
} catch (Throwable ex) {
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.warning("Client %s send invalid request. Connection force closed.", context.ip == null ? IOHelper.getIP(ctx.channel().remoteAddress()) : context.ip);
|
||||
if (LogHelper.isDevEnabled()) {
|
||||
LogHelper.dev("Client message: %s", ((TextWebSocketFrame) frame).text());
|
||||
}
|
||||
if (LogHelper.isStacktraceEnabled()) {
|
||||
LogHelper.error(ex);
|
||||
}
|
||||
}
|
||||
ctx.channel().close();
|
||||
}
|
||||
} else if ((frame instanceof PingWebSocketFrame)) {
|
||||
frame.content().retain();
|
||||
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
|
||||
|
@ -77,4 +91,10 @@ protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
|||
LogHelper.error(new UnsupportedOperationException(message)); // prevent strange crash here.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
if (future != null) future.cancel(true);
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,17 @@
|
|||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpMethod.GET;
|
||||
|
@ -26,7 +35,7 @@
|
|||
|
||||
public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
|
||||
|
||||
public static final SimpleDateFormat dateFormatter;
|
||||
public static final DateTimeFormatter dateFormatter;
|
||||
public static final String READ = "r";
|
||||
public static final int HTTP_CACHE_SECONDS = VerifyHelper.verifyInt(Integer.parseInt(System.getProperty("launcher.fileserver.cachesec", "60")), VerifyHelper.NOT_NEGATIVE, "HttpCache seconds should be positive");
|
||||
private static final boolean OLD_ALGO = Boolean.parseBoolean(System.getProperty("launcher.fileserver.oldalgo", "true"));
|
||||
|
@ -34,8 +43,7 @@ public class FileServerHandler extends SimpleChannelInboundHandler<FullHttpReque
|
|||
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[^-\\._]?[^<>&\\\"]*");
|
||||
|
||||
static {
|
||||
dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
|
||||
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
dateFormatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US).withZone(ZoneId.of("UTC"));
|
||||
}
|
||||
|
||||
private final Path base;
|
||||
|
@ -66,7 +74,7 @@ private static void sendListing(ChannelHandlerContext ctx, File dir, String dirP
|
|||
.append("<ul>")
|
||||
.append("<li><a href=\"../\">..</a></li>\r\n");
|
||||
|
||||
for (File f : dir.listFiles()) {
|
||||
for (File f : Objects.requireNonNull(dir.listFiles())) {
|
||||
if ((f.isHidden() && !showHidden) || !f.canRead()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -128,7 +136,7 @@ private static void sendNotModified(ChannelHandlerContext ctx) {
|
|||
* @param response HTTP response
|
||||
*/
|
||||
private static void setDateHeader(FullHttpResponse response) {
|
||||
response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(new Date(System.currentTimeMillis())));
|
||||
response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(Instant.ofEpochMilli(System.currentTimeMillis())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,15 +147,14 @@ private static void setDateHeader(FullHttpResponse response) {
|
|||
*/
|
||||
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
||||
// Date header
|
||||
Calendar time = new GregorianCalendar();
|
||||
response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(time.getTime()));
|
||||
LocalDateTime time = LocalDateTime.now(Clock.systemUTC());
|
||||
response.headers().set(HttpHeaderNames.DATE, dateFormatter.format(time));
|
||||
|
||||
// Add cache headers
|
||||
time.add(Calendar.SECOND, HTTP_CACHE_SECONDS);
|
||||
response.headers().set(HttpHeaderNames.EXPIRES, dateFormatter.format(time.getTime()));
|
||||
response.headers().set(HttpHeaderNames.EXPIRES, dateFormatter.format(time.plus(HTTP_CACHE_SECONDS, ChronoUnit.SECONDS)));
|
||||
response.headers().set(HttpHeaderNames.CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
|
||||
response.headers().set(
|
||||
HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
|
||||
HttpHeaderNames.LAST_MODIFIED, dateFormatter.format(Instant.ofEpochMilli(fileToCache.lastModified())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,11 +216,11 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
|
|||
// Cache Validation
|
||||
String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE);
|
||||
if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
|
||||
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
|
||||
TemporalAccessor ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
|
||||
|
||||
// Only compare up to the second because the datetime format we send to the client
|
||||
// does not have milliseconds
|
||||
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
|
||||
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.get(ChronoField.INSTANT_SECONDS);
|
||||
long fileLastModifiedSeconds = file.lastModified() / 1000;
|
||||
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
|
||||
sendNotModified(ctx);
|
||||
|
|
|
@ -57,8 +57,15 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
throw new AuthException("Password decryption error");
|
||||
}
|
||||
}
|
||||
if (clientData.isAuth) {
|
||||
if (LogHelper.isDevEnabled()) {
|
||||
LogHelper.warning("Client %s double auth", clientData.username == null ? ip : clientData.username);
|
||||
}
|
||||
sendError("You are already logged in");
|
||||
return;
|
||||
}
|
||||
AuthProviderPair pair;
|
||||
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
||||
if (auth_id == null || auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
||||
else pair = server.config.getAuthProviderPair(auth_id);
|
||||
if (pair == null) {
|
||||
sendError("auth_id incorrect");
|
||||
|
@ -81,19 +88,18 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
clientData.permissions = aresult.permissions;
|
||||
clientData.auth_id = auth_id;
|
||||
clientData.updateAuth(server);
|
||||
if (result.playerProfile != null)
|
||||
clientData.username = result.playerProfile.username;
|
||||
if (aresult.username != null)
|
||||
clientData.username = aresult.username;
|
||||
else
|
||||
clientData.username = login;
|
||||
if(aresult instanceof AuthProviderDAOResult)
|
||||
{
|
||||
if (aresult instanceof AuthProviderDAOResult) {
|
||||
clientData.daoObject = ((AuthProviderDAOResult) aresult).daoObject;
|
||||
}
|
||||
result.accessToken = aresult.accessToken;
|
||||
result.permissions = clientData.permissions;
|
||||
if (getSession) {
|
||||
if (clientData.session == 0) {
|
||||
clientData.session = random.nextLong();
|
||||
if (clientData.session == null) {
|
||||
clientData.session = UUID.randomUUID();
|
||||
server.sessionManager.addClient(clientData);
|
||||
}
|
||||
result.session = clientData.session;
|
||||
|
@ -104,9 +110,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
uuid = pair.handler.usernameToUUID(aresult.username);
|
||||
result.accessToken = null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package pro.gravit.launchserver.socket.response.auth;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.CurrentUserRequestEvent;
|
||||
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 {
|
||||
@Override
|
||||
public String getType() {
|
||||
return "currentUser";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
sendResult(new CurrentUserRequestEvent(collectUserInfoFromClient(client)));
|
||||
}
|
||||
|
||||
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.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;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package pro.gravit.launchserver.socket.response.auth;
|
||||
|
||||
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;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
@ -24,7 +26,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
return;
|
||||
}
|
||||
if (username == null) {
|
||||
if (client.session == 0 && exitAll) {
|
||||
if (client.session == null && exitAll) {
|
||||
sendError("Session invalid");
|
||||
return;
|
||||
}
|
||||
|
@ -33,47 +35,42 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
sendError("Exit internal error");
|
||||
return;
|
||||
}
|
||||
Client newClient = new Client(0);
|
||||
Client newClient = new Client(null);
|
||||
newClient.checkSign = client.checkSign;
|
||||
handler.setClient(newClient);
|
||||
if (client.session != 0) server.sessionManager.removeClient(client.session);
|
||||
if (client.session != null) server.sessionManager.removeClient(client.session);
|
||||
if (exitAll) {
|
||||
service.channels.forEach((channel) -> {
|
||||
if (channel == null || channel.pipeline() == null) return;
|
||||
WebSocketFrameHandler wsHandler = channel.pipeline().get(WebSocketFrameHandler.class);
|
||||
if (wsHandler == null || wsHandler == handler) return;
|
||||
Client chClient = wsHandler.getClient();
|
||||
service.forEachActiveChannels(((channel, webSocketFrameHandler) -> {
|
||||
Client client1 = webSocketFrameHandler.getClient();
|
||||
if (client.isAuth && client.username != null) {
|
||||
if (!chClient.isAuth || !client.username.equals(chClient.username)) return;
|
||||
if (!client1.isAuth || !client.username.equals(client1.username)) return;
|
||||
} else {
|
||||
if (chClient.session != client.session) return;
|
||||
if (client1.session != client.session) return;
|
||||
}
|
||||
Client newCusClient = new Client(0);
|
||||
newCusClient.checkSign = chClient.checkSign;
|
||||
wsHandler.setClient(newCusClient);
|
||||
if (chClient.session != 0) server.sessionManager.removeClient(chClient.session);
|
||||
ExitRequestEvent event = new ExitRequestEvent(ExitRequestEvent.ExitReason.SERVER);
|
||||
event.requestUUID = RequestEvent.eventUUID;
|
||||
wsHandler.service.sendObject(channel, event);
|
||||
});
|
||||
exit(server, webSocketFrameHandler, channel, ExitRequestEvent.ExitReason.SERVER);
|
||||
}));
|
||||
}
|
||||
sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
|
||||
} else {
|
||||
service.channels.forEach((channel -> {
|
||||
if (channel == null || channel.pipeline() == null) return;
|
||||
WebSocketFrameHandler wsHandler = channel.pipeline().get(WebSocketFrameHandler.class);
|
||||
if (wsHandler == null) return;
|
||||
Client chClient = wsHandler.getClient();
|
||||
if (!chClient.isAuth || !username.equals(chClient.username)) return;
|
||||
Client newCusClient = new Client(0);
|
||||
newCusClient.checkSign = chClient.checkSign;
|
||||
wsHandler.setClient(newCusClient);
|
||||
if (chClient.session != 0) server.sessionManager.removeClient(chClient.session);
|
||||
ExitRequestEvent event = new ExitRequestEvent(ExitRequestEvent.ExitReason.SERVER);
|
||||
event.requestUUID = RequestEvent.eventUUID;
|
||||
wsHandler.service.sendObject(channel, event);
|
||||
service.forEachActiveChannels(((channel, webSocketFrameHandler) -> {
|
||||
Client client1 = webSocketFrameHandler.getClient();
|
||||
if (client1 != null && client.isAuth && client.username != null && client1.username.equals(username)) {
|
||||
exit(server, webSocketFrameHandler, channel, ExitRequestEvent.ExitReason.SERVER);
|
||||
}
|
||||
}));
|
||||
sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.NO_EXIT));
|
||||
}
|
||||
}
|
||||
|
||||
public static void exit(LaunchServer server, WebSocketFrameHandler wsHandler, Channel channel, ExitRequestEvent.ExitReason reason) {
|
||||
|
||||
Client chClient = wsHandler.getClient();
|
||||
Client newCusClient = new Client(null);
|
||||
newCusClient.checkSign = chClient.checkSign;
|
||||
wsHandler.setClient(newCusClient);
|
||||
if (chClient.session != null) server.sessionManager.removeClient(chClient.session);
|
||||
ExitRequestEvent event = new ExitRequestEvent(reason);
|
||||
event.requestUUID = RequestEvent.eventUUID;
|
||||
wsHandler.service.sendObject(channel, event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,14 +25,16 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
sendError("Permissions denied");
|
||||
return;
|
||||
}
|
||||
if (username == null || accessToken == null || serverID == null) {
|
||||
sendError("Invalid request");
|
||||
return;
|
||||
}
|
||||
boolean success;
|
||||
try {
|
||||
server.authHookManager.joinServerHook.hook(this, client);
|
||||
if(server.config.protectHandler instanceof JoinServerProtectHandler)
|
||||
{
|
||||
if (server.config.protectHandler instanceof JoinServerProtectHandler) {
|
||||
success = ((JoinServerProtectHandler) server.config.protectHandler).onJoinServer(serverID, username, client);
|
||||
if(!success)
|
||||
{
|
||||
if (!success) {
|
||||
sendResult(new JoinServerRequestEvent(false));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package pro.gravit.launchserver.socket.response.auth;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class RegisterResponse extends SimpleResponse {
|
||||
public String login;
|
||||
public String password;
|
||||
public String email;
|
||||
public byte[] verifyHash;
|
||||
|
||||
public static byte[] registerHash(String login, String secret) throws NoSuchAlgorithmException {
|
||||
String text = login.concat("+").concat(secret);
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
return digest.digest(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
byte[] normalHash = registerHash(login, server.runtime.registerApiKey);
|
||||
if (!(client.isAuth && client.permissions.isPermission(ClientPermissions.PermissionConsts.ADMIN)) && !Arrays.equals(normalHash, verifyHash)) {
|
||||
sendError("Hash invalid");
|
||||
return;
|
||||
}
|
||||
User checkUser = server.config.dao.userDAO.findByUsername(login);
|
||||
if (checkUser != null) {
|
||||
sendError("User already register");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "register";
|
||||
}
|
||||
}
|
|
@ -7,9 +7,12 @@
|
|||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class RestoreSessionResponse extends SimpleResponse {
|
||||
@LauncherNetworkAPI
|
||||
public long session;
|
||||
public UUID session;
|
||||
public boolean needUserInfo;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
|
@ -17,13 +20,18 @@ public String getType() {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
Client rClient = server.sessionManager.getClient(session);
|
||||
if (rClient == null) {
|
||||
sendError("Session invalid");
|
||||
return;
|
||||
}
|
||||
WebSocketFrameHandler frameHandler = ctx.pipeline().get(WebSocketFrameHandler.class);
|
||||
frameHandler.setClient(rClient);
|
||||
sendResult(new RestoreSessionRequestEvent());
|
||||
if (needUserInfo) {
|
||||
sendResult(new RestoreSessionRequestEvent(CurrentUserResponse.collectUserInfoFromClient(rClient)));
|
||||
} else {
|
||||
sendResult(new RestoreSessionRequestEvent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
package pro.gravit.launchserver.socket.response.auth;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.request.SetPasswordRequestEvent;
|
||||
import pro.gravit.launchserver.dao.User;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
||||
public class SetPasswordResponse extends SimpleResponse {
|
||||
public String oldPassword;
|
||||
public String newPassword;
|
||||
public String username;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "setPassword";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
if ((oldPassword == null && username == null) || newPassword == null) {
|
||||
sendError("Request invalid");
|
||||
return;
|
||||
}
|
||||
if (!client.isAuth) {
|
||||
sendError("You not authorized");
|
||||
return;
|
||||
}
|
||||
if (username != null && !client.permissions.isPermission(ClientPermissions.PermissionConsts.ADMIN)) {
|
||||
sendError("You not admin");
|
||||
return;
|
||||
}
|
||||
if (username != null) {
|
||||
User user = server.config.dao.userDAO.findByUsername(username);
|
||||
user.setPassword(newPassword);
|
||||
sendResult(new SetPasswordRequestEvent());
|
||||
} else {
|
||||
User user = server.config.dao.userDAO.findByUsername(client.username);
|
||||
if (user.verifyPassword(oldPassword)) {
|
||||
user.setPassword(newPassword);
|
||||
sendResult(new SetPasswordRequestEvent());
|
||||
} else {
|
||||
sendError("Old password incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
public class PingServerReportResponse extends SimpleResponse {
|
||||
public PingServerReportRequest.PingServerReport data;
|
||||
public String name;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "pingServerReport";
|
||||
|
@ -17,9 +18,9 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
if(!client.isAuth || client.permissions == null || !client.permissions.isPermission(ClientPermissions.PermissionConsts.MANAGEMENT))
|
||||
{
|
||||
if (!client.isAuth || client.permissions == null || !client.permissions.isPermission(ClientPermissions.PermissionConsts.MANAGEMENT)) {
|
||||
sendError("Access denied");
|
||||
return;
|
||||
}
|
||||
server.pingServerManager.updateServer(name, data);
|
||||
sendResult(new PingServerReportRequestEvent());
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
public class PingServerResponse extends SimpleResponse {
|
||||
public List<String> serverNames; //May be null
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "pingServer";
|
||||
|
@ -21,24 +22,18 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
Map<String, PingServerReportRequest.PingServerReport> map = new HashMap<>();
|
||||
if(serverNames == null)
|
||||
{
|
||||
if (serverNames == null) {
|
||||
server.pingServerManager.map.forEach((name, entity) -> {
|
||||
if(server.config.protectHandler instanceof ProfilesProtectHandler)
|
||||
{
|
||||
if(!((ProfilesProtectHandler) server.config.protectHandler).canGetProfile(entity.profile, client))
|
||||
{
|
||||
if (server.config.protectHandler instanceof ProfilesProtectHandler) {
|
||||
if (!((ProfilesProtectHandler) server.config.protectHandler).canGetProfile(entity.profile, client)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!entity.isExpired())
|
||||
{
|
||||
if (!entity.isExpired()) {
|
||||
map.put(name, entity.lastReport);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sendError("Not implemented");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.ServerStatusRequestEvent;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.WebSocketService;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
|
||||
|
@ -18,11 +17,11 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
ServerStatusRequestEvent event = new ServerStatusRequestEvent(server.config.projectName);
|
||||
event.totalJavaMemory = JVMHelper.RUNTIME.totalMemory();
|
||||
event.freeJavaMemory = JVMHelper.RUNTIME.freeMemory();
|
||||
event.shortLatency = ( service.shortRequestLatency.get() / service.shortRequestCounter.get() ) / 1_000_000;
|
||||
event.middleLatency = ( service.middleRequestLatency.get() / service.middleRequestCounter.get() ) / 1_000_000;
|
||||
event.longLatency = ( service.longRequestLatency.get() / service.longRequestCounter.get() ) / 1_000_000;
|
||||
event.latency = ( ( service.shortRequestLatency.get() + service.middleRequestLatency.get() + service.longRequestLatency.get() ) /
|
||||
( service.shortRequestCounter.get() + service.middleRequestCounter.get() + service.longRequestCounter.get() ) ) / 1_000_000;
|
||||
event.shortLatency = (service.shortRequestLatency.get() / service.shortRequestCounter.get()) / 1_000_000;
|
||||
event.middleLatency = (service.middleRequestLatency.get() / service.middleRequestCounter.get()) / 1_000_000;
|
||||
event.longLatency = (service.longRequestLatency.get() / service.longRequestCounter.get()) / 1_000_000;
|
||||
event.latency = ((service.shortRequestLatency.get() + service.middleRequestLatency.get() + service.longRequestLatency.get()) /
|
||||
(service.shortRequestCounter.get() + service.middleRequestCounter.get() + service.longRequestCounter.get())) / 1_000_000;
|
||||
sendResult(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.BatchProfileByUsernameRequestEvent;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -20,14 +20,19 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent();
|
||||
if (list == null) {
|
||||
sendError("Invalid request");
|
||||
return;
|
||||
}
|
||||
result.playerProfiles = new PlayerProfile[list.length];
|
||||
for (int i = 0; i < list.length; ++i) {
|
||||
UUID uuid;
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(list[i].username);
|
||||
} else uuid = client.auth.handler.usernameToUUID(list[i].username);
|
||||
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(uuid, list[i].username, list[i].client, client.auth.textureProvider);
|
||||
AuthProviderPair pair = client.auth;
|
||||
if (pair == null) {
|
||||
pair = server.config.getAuthProviderPair();
|
||||
}
|
||||
uuid = pair.handler.usernameToUUID(list[i].username);
|
||||
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(uuid, list[i].username, list[i].client, pair.textureProvider);
|
||||
}
|
||||
sendResult(result);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
String username;
|
||||
AuthProviderPair pair;
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
pair = server.config.getAuthProviderPair();
|
||||
} else {
|
||||
pair = client.auth;
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.ProfileByUsernameRequestEvent;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -20,10 +20,13 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
UUID uuid;
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(username);
|
||||
} else uuid = client.auth.handler.usernameToUUID(username);
|
||||
sendResult(new ProfileByUsernameRequestEvent(ProfileByUUIDResponse.getProfile(uuid, username, this.client, client.auth.textureProvider)));
|
||||
AuthProviderPair pair = client.auth;
|
||||
if (pair == null) pair = server.config.getAuthProviderPair();
|
||||
uuid = pair.handler.usernameToUUID(username);
|
||||
if (uuid == null) {
|
||||
sendError("User not found");
|
||||
return;
|
||||
}
|
||||
sendResult(new ProfileByUsernameRequestEvent(ProfileByUUIDResponse.getProfile(uuid, username, this.client, pair.textureProvider)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,13 @@ public String getType() {
|
|||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
if(server.config.protectHandler instanceof HardwareProtectHandler)
|
||||
{
|
||||
if (server.config.protectHandler instanceof HardwareProtectHandler) {
|
||||
try {
|
||||
((HardwareProtectHandler) server.config.protectHandler).onHardwareReport(this, client);
|
||||
} catch (SecurityException e)
|
||||
{
|
||||
} catch (SecurityException e) {
|
||||
sendError(e.getMessage());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
sendResult(new HardwareReportRequestEvent());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package pro.gravit.launchserver.socket.response.secure;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import pro.gravit.launcher.events.request.VerifySecureLevelKeyRequestEvent;
|
||||
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||
|
@ -41,8 +40,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
client.trustLevel.publicKey = publicKey;
|
||||
try {
|
||||
sendResult(secureProtectHandler.onSuccessVerify(client));
|
||||
} catch (SecurityException e)
|
||||
{
|
||||
} catch (SecurityException e) {
|
||||
sendError(e.getMessage());
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
sendError("Access denied");
|
||||
return;
|
||||
}
|
||||
if (dirName == null) {
|
||||
sendError("Invalid request");
|
||||
return;
|
||||
}
|
||||
HashedDir dir = server.updatesDirMap.get(dirName);
|
||||
if (dir == null) {
|
||||
sendError(String.format("Directory %s not found", dirName));
|
||||
|
|
|
@ -25,6 +25,7 @@ public static void prepare() throws Throwable {
|
|||
classLoader = new ASMClassLoader(ASMTransformersTest.class.getClassLoader());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void testASM() throws Throwable {
|
||||
ClassReader reader = new ClassReader(JarHelper.getClassBytes(TestClass.class));
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
manifest.attributes("Main-Class": mainClassName,
|
||||
"Premain-Class": mainAgentName,
|
||||
"Can-Redefine-Classes": "true",
|
||||
"Multi-Release": "true",
|
||||
"Can-Retransform-Classes": "true",
|
||||
"Can-Set-Native-Method-Prefix": "true",
|
||||
"Multi-Release-Jar": "true")
|
||||
|
@ -93,6 +94,18 @@ task dumpLibs(type: Copy) {
|
|||
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'gravita'
|
||||
name = 'Gravita'
|
||||
email = 'gravita@gravit.pro'
|
||||
}
|
||||
developer {
|
||||
id = 'zaxar163'
|
||||
name = 'Zaxar163'
|
||||
email = 'zahar.vcherachny@yandex.ru'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
|
||||
|
|
|
@ -22,8 +22,8 @@ public class ClientLauncherWrapper {
|
|||
public static final String NO_JAVA_CHECK_PROPERTY = "launcher.noJavaCheck";
|
||||
public static boolean noJavaCheck = Boolean.getBoolean(NO_JAVA_CHECK_PROPERTY);
|
||||
public static boolean waitProcess = Boolean.getBoolean(WAIT_PROCESS_PROPERTY);
|
||||
public static class JavaVersion
|
||||
{
|
||||
|
||||
public static class JavaVersion {
|
||||
public final Path jvmDir;
|
||||
public final int version;
|
||||
public boolean enabledJavaFX;
|
||||
|
@ -33,31 +33,29 @@ public JavaVersion(Path jvmDir, int version) {
|
|||
this.version = version;
|
||||
this.enabledJavaFX = true;
|
||||
}
|
||||
public static JavaVersion getCurrentJavaVersion()
|
||||
{
|
||||
|
||||
public static JavaVersion getCurrentJavaVersion() {
|
||||
return new JavaVersion(Paths.get(System.getProperty("java.home")), JVMHelper.getVersion());
|
||||
}
|
||||
|
||||
public static JavaVersion getByPath(Path jvmDir) throws IOException {
|
||||
Path releaseFile = jvmDir.resolve("release");
|
||||
if(!IOHelper.isFile(releaseFile)) return null;
|
||||
if (!IOHelper.isFile(releaseFile)) return null;
|
||||
Properties properties = new Properties();
|
||||
properties.load(IOHelper.newReader(releaseFile));
|
||||
int javaVersion = getJavaVersion(properties.getProperty("JAVA_VERSION").replaceAll("\"", ""));
|
||||
JavaVersion resultJavaVersion = new JavaVersion(jvmDir, javaVersion);
|
||||
if(javaVersion <= 8)
|
||||
{
|
||||
if (javaVersion <= 8) {
|
||||
resultJavaVersion.enabledJavaFX = isExistExtJavaLibrary(jvmDir, "jfxrt");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir, "javafx.base") != null;
|
||||
if(!resultJavaVersion.enabledJavaFX)
|
||||
if (!resultJavaVersion.enabledJavaFX)
|
||||
resultJavaVersion.enabledJavaFX = tryFindModule(jvmDir.resolve("jre"), "javafx.base") != null;
|
||||
}
|
||||
return resultJavaVersion;
|
||||
}
|
||||
public static boolean isExistExtJavaLibrary(Path jvmDir, String name)
|
||||
{
|
||||
|
||||
public static boolean isExistExtJavaLibrary(Path jvmDir, String name) {
|
||||
Path jrePath = jvmDir.resolve("lib").resolve("ext").resolve(name.concat(".jar"));
|
||||
Path jdkPath = jvmDir.resolve("jre").resolve("lib").resolve("ext").resolve(name.concat(".jar"));
|
||||
return IOHelper.isFile(jrePath) || IOHelper.isFile(jdkPath);
|
||||
|
@ -94,12 +92,11 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
|||
|
||||
JavaVersion javaVersion = null;
|
||||
try {
|
||||
if(!noJavaCheck) javaVersion = findJava();
|
||||
if (!noJavaCheck) javaVersion = findJava();
|
||||
} catch (Throwable e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
if (javaVersion == null)
|
||||
{
|
||||
if (javaVersion == null) {
|
||||
javaVersion = JavaVersion.getCurrentJavaVersion();
|
||||
}
|
||||
|
||||
|
@ -187,64 +184,54 @@ public static boolean tryAddModule(Path[] paths, String moduleName, StringBuilde
|
|||
return false;
|
||||
}
|
||||
|
||||
public static JavaVersion findJavaByProgramFiles(Path path)
|
||||
{
|
||||
public static JavaVersion findJavaByProgramFiles(Path path) {
|
||||
LogHelper.debug("Check Java in %s", path.toString());
|
||||
JavaVersion selectedJava = null;
|
||||
File[] candidates = path.toFile().listFiles(File::isDirectory);
|
||||
if(candidates == null) return null;
|
||||
for(File candidate : candidates)
|
||||
{
|
||||
if (candidates == null) return null;
|
||||
for (File candidate : candidates) {
|
||||
Path javaPath = candidate.toPath();
|
||||
try {
|
||||
JavaVersion javaVersion = JavaVersion.getByPath(javaPath);
|
||||
if(javaVersion == null || javaVersion.version < 8) continue;
|
||||
if (javaVersion == null || javaVersion.version < 8) continue;
|
||||
LogHelper.debug("Found Java %d in %s (javafx %s)", javaVersion.version, javaVersion.jvmDir.toString(), javaVersion.enabledJavaFX ? "true" : "false");
|
||||
if(javaVersion.enabledJavaFX && (selectedJava == null || !selectedJava.enabledJavaFX))
|
||||
{
|
||||
if (javaVersion.enabledJavaFX && (selectedJava == null || !selectedJava.enabledJavaFX)) {
|
||||
selectedJava = javaVersion;
|
||||
continue;
|
||||
}
|
||||
if(selectedJava != null && javaVersion.enabledJavaFX && javaVersion.version < selectedJava.version)
|
||||
{
|
||||
if (selectedJava != null && javaVersion.enabledJavaFX && javaVersion.version < selectedJava.version) {
|
||||
selectedJava = javaVersion;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
if(selectedJava != null)
|
||||
{
|
||||
if (selectedJava != null) {
|
||||
LogHelper.debug("Selected Java %d in %s (javafx %s)", selectedJava.version, selectedJava.jvmDir.toString(), selectedJava.enabledJavaFX ? "true" : "false");
|
||||
}
|
||||
return selectedJava;
|
||||
}
|
||||
|
||||
public static JavaVersion findJava()
|
||||
{
|
||||
if(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE)
|
||||
{
|
||||
public static JavaVersion findJava() {
|
||||
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
|
||||
JavaVersion result = null;
|
||||
Path defaultJvmContainerDir = Paths.get(System.getProperty("java.home")).getParent();
|
||||
if(defaultJvmContainerDir.getParent().getFileName().toString().contains("x86")) //Program Files (x86) ?
|
||||
if (defaultJvmContainerDir.getParent().getFileName().toString().contains("x86")) //Program Files (x86) ?
|
||||
{
|
||||
Path programFiles64 = defaultJvmContainerDir.getParent().getParent().resolve("Program Files").resolve("Java");
|
||||
if(IOHelper.isDir(programFiles64))
|
||||
{
|
||||
if (IOHelper.isDir(programFiles64)) {
|
||||
result = findJavaByProgramFiles(programFiles64);
|
||||
}
|
||||
}
|
||||
if(result == null)
|
||||
{
|
||||
if (result == null) {
|
||||
result = findJavaByProgramFiles(defaultJvmContainerDir);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getJavaVersion(String version)
|
||||
{
|
||||
public static int getJavaVersion(String version) {
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2, 3);
|
||||
} else {
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
import pro.gravit.launcher.managers.ClientGsonManager;
|
||||
import pro.gravit.launcher.managers.ConsoleManager;
|
||||
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.RequestException;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
||||
import pro.gravit.launcher.utils.NativeJVMHalt;
|
||||
|
@ -113,6 +115,8 @@ public static void main(String... args) throws Throwable {
|
|||
}
|
||||
|
||||
public static void initGson(ClientModuleManager modulesManager) {
|
||||
AuthRequest.registerProviders();
|
||||
OptionalAction.registerProviders();
|
||||
Launcher.gsonManager = new ClientGsonManager(modulesManager);
|
||||
Launcher.gsonManager.initGson();
|
||||
}
|
||||
|
|
|
@ -14,8 +14,12 @@
|
|||
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
||||
import pro.gravit.launcher.patches.FMLPatcher;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.RequestException;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||
import pro.gravit.launcher.serialize.HInput;
|
||||
import pro.gravit.launcher.utils.DirWatcher;
|
||||
|
@ -50,7 +54,9 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
|
|||
ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(new String(serialized, IOHelper.UNICODE_CHARSET), ClientLauncherProcess.ClientParams.class);
|
||||
params.clientHDir = new HashedDir(input);
|
||||
params.assetHDir = new HashedDir(input);
|
||||
params.javaHDir = new HashedDir(input);
|
||||
boolean isNeedReadJavaDir = input.readBoolean();
|
||||
if (isNeedReadJavaDir)
|
||||
params.javaHDir = new HashedDir(input);
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
@ -93,9 +99,10 @@ public static void main(String[] args) throws Throwable {
|
|||
List<URL> classpath = new LinkedList<>();
|
||||
resolveClassPathStream(clientDir, params.profile.getClassPath()).map(IOHelper::toURL).collect(Collectors.toCollection(() -> classpath));
|
||||
|
||||
params.profile.pushOptionalClassPath((opt) -> {
|
||||
resolveClassPathStream(clientDir, opt).map(IOHelper::toURL).collect(Collectors.toCollection(() -> classpath));
|
||||
});
|
||||
for (OptionalAction a : params.actions) {
|
||||
if (a instanceof OptionalActionClassPath)
|
||||
resolveClassPathStream(clientDir, ((OptionalActionClassPath) a).args).map(IOHelper::toURL).collect(Collectors.toCollection(() -> classpath));
|
||||
}
|
||||
classLoader = new ClientClassLoader(classpath.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
classLoader.nativePath = clientDir.resolve("natives").toString();
|
||||
|
@ -133,26 +140,34 @@ public static void main(String[] args) throws Throwable {
|
|||
LogHelper.debug("Starting JVM and client WatchService");
|
||||
FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher();
|
||||
FileNameMatcher clientMatcher = profile.getClientUpdateMatcher();
|
||||
Path javaDir = Paths.get(System.getProperty("java.home"));
|
||||
try (DirWatcher assetWatcher = new DirWatcher(assetDir, params.assetHDir, assetMatcher, digest);
|
||||
DirWatcher clientWatcher = new DirWatcher(clientDir, params.clientHDir, clientMatcher, digest)) {
|
||||
DirWatcher clientWatcher = new DirWatcher(clientDir, params.clientHDir, clientMatcher, digest);
|
||||
DirWatcher javaWatcher = params.javaHDir == null ? null : new DirWatcher(javaDir, params.javaHDir, null, digest)) {
|
||||
// Verify current state of all dirs
|
||||
//verifyHDir(IOHelper.JVM_DIR, jvmHDir.object, null, digest);
|
||||
//for (OptionalFile s : Launcher.profile.getOptional()) {
|
||||
// if (params.updateOptional.contains(s)) s.mark = true;
|
||||
// else hdir.removeR(s.file);
|
||||
//}
|
||||
Launcher.profile.pushOptionalFile(params.clientHDir, false);
|
||||
// Start WatchService, and only then client
|
||||
CommonHelper.newThread("Asset Directory Watcher", true, assetWatcher).start();
|
||||
CommonHelper.newThread("Client Directory Watcher", true, clientWatcher).start();
|
||||
if (javaWatcher != null)
|
||||
CommonHelper.newThread("Java Directory Watcher", true, clientWatcher).start();
|
||||
verifyHDir(assetDir, params.assetHDir, assetMatcher, digest);
|
||||
verifyHDir(clientDir, params.clientHDir, clientMatcher, digest);
|
||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessLaunchEvent(engine, params));
|
||||
if (javaWatcher != null)
|
||||
verifyHDir(javaDir, params.javaHDir, null, digest);
|
||||
if (params.javaHDir != null)
|
||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessLaunchEvent(engine, params));
|
||||
launch(profile, params);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initGson(ClientModuleManager moduleManager) {
|
||||
AuthRequest.registerProviders();
|
||||
OptionalAction.registerProviders();
|
||||
Launcher.gsonManager = new ClientGsonManager(moduleManager);
|
||||
Launcher.gsonManager.initGson();
|
||||
}
|
||||
|
@ -223,7 +238,12 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa
|
|||
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir);
|
||||
}
|
||||
Collections.addAll(args, profile.getClientArgs());
|
||||
profile.pushOptionalClientArgs(args);
|
||||
for(OptionalAction action : params.actions) {
|
||||
if(action instanceof OptionalActionClientArgs)
|
||||
{
|
||||
args.addAll(((OptionalActionClientArgs) action).args);
|
||||
}
|
||||
}
|
||||
List<String> copy = new ArrayList<>(args);
|
||||
for (int i = 0, l = copy.size(); i < l; i++) {
|
||||
String s = copy.get(i);
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
import pro.gravit.launcher.hasher.HashedDir;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
import pro.gravit.launcher.profiles.optional.OptionalView;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.serialize.HOutput;
|
||||
import pro.gravit.utils.Version;
|
||||
|
@ -34,6 +38,7 @@ public class ClientLauncherProcess {
|
|||
public Path executeFile;
|
||||
public Path workDir;
|
||||
public Path javaDir;
|
||||
public int bits;
|
||||
public boolean useLegacyJavaClassPathProperty;
|
||||
public boolean isStarted;
|
||||
private transient Process process;
|
||||
|
@ -48,17 +53,17 @@ public ClientLauncherProcess(Path executeFile, Path workDir, Path javaDir, Strin
|
|||
public ClientLauncherProcess(Path clientDir, Path assetDir, Path javaDir,
|
||||
ClientProfile profile, PlayerProfile playerProfile, String accessToken,
|
||||
HashedDir clientHDir, HashedDir assetHDir, HashedDir jvmHDir) {
|
||||
this(clientDir, assetDir, javaDir, clientDir.resolve("resourcepacks"), profile, playerProfile, accessToken, clientHDir, assetHDir, jvmHDir);
|
||||
this(clientDir, assetDir, javaDir, clientDir.resolve("resourcepacks"), profile, playerProfile, null, accessToken, clientHDir, assetHDir, jvmHDir);
|
||||
}
|
||||
|
||||
public ClientLauncherProcess(Path clientDir, Path assetDir,
|
||||
ClientProfile profile, PlayerProfile playerProfile, String accessToken,
|
||||
HashedDir clientHDir, HashedDir assetHDir, HashedDir jvmHDir) {
|
||||
this(clientDir, assetDir, Paths.get(System.getProperty("java.home")), clientDir.resolve("resourcepacks"), profile, playerProfile, accessToken, clientHDir, assetHDir, jvmHDir);
|
||||
this(clientDir, assetDir, Paths.get(System.getProperty("java.home")), clientDir.resolve("resourcepacks"), profile, playerProfile, null, accessToken, clientHDir, assetHDir, jvmHDir);
|
||||
}
|
||||
|
||||
public ClientLauncherProcess(Path clientDir, Path assetDir, Path javaDir, Path resourcePackDir,
|
||||
ClientProfile profile, PlayerProfile playerProfile, String accessToken,
|
||||
ClientProfile profile, PlayerProfile playerProfile, OptionalView view, String accessToken,
|
||||
HashedDir clientHDir, HashedDir assetHDir, HashedDir jvmHDir) {
|
||||
this.workDir = clientDir.toAbsolutePath();
|
||||
this.javaDir = javaDir;
|
||||
|
@ -73,6 +78,10 @@ public ClientLauncherProcess(Path clientDir, Path assetDir, Path javaDir, Path r
|
|||
this.params.assetHDir = assetHDir;
|
||||
this.params.clientHDir = clientHDir;
|
||||
this.params.javaHDir = jvmHDir;
|
||||
if (view != null) {
|
||||
this.params.actions = view.getEnabledActions();
|
||||
}
|
||||
this.bits = JVMHelper.JVM_BITS;
|
||||
applyClientProfile();
|
||||
}
|
||||
|
||||
|
@ -86,7 +95,11 @@ public static String getPathSeparator() {
|
|||
private void applyClientProfile() {
|
||||
this.systemClassPath.add(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toAbsolutePath().toString());
|
||||
Collections.addAll(this.jvmArgs, this.params.profile.getJvmArgs());
|
||||
this.params.profile.pushOptionalJvmArgs(this.jvmArgs);
|
||||
for (OptionalAction a : this.params.actions) {
|
||||
if (a instanceof OptionalActionJvmArgs) {
|
||||
this.jvmArgs.addAll(((OptionalActionJvmArgs) a).args);
|
||||
}
|
||||
}
|
||||
this.systemEnv.put("JAVA_HOME", javaDir.toString());
|
||||
Collections.addAll(this.systemClassPath, this.params.profile.getAlternativeClassPath());
|
||||
if (params.ram > 0) {
|
||||
|
@ -148,7 +161,12 @@ public void runWriteParams(SocketAddress address) throws IOException {
|
|||
output.writeByteArray(serializedMainParams, 0);
|
||||
params.clientHDir.write(output);
|
||||
params.assetHDir.write(output);
|
||||
params.javaHDir.write(output);
|
||||
if (params.javaHDir == null || params.javaHDir == params.assetHDir) { //TODO: OLD RUNTIME USE params.assetHDir AS NULL IN java.javaHDir
|
||||
output.writeBoolean(false);
|
||||
} else {
|
||||
output.writeBoolean(true);
|
||||
params.javaHDir.write(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderParamsWrittedEvent(this));
|
||||
|
@ -185,9 +203,11 @@ public static class ClientParams {
|
|||
|
||||
public int height;
|
||||
|
||||
public Set<OptionalAction> actions = new HashSet<>();
|
||||
|
||||
//========
|
||||
|
||||
public long session;
|
||||
public UUID session;
|
||||
|
||||
public transient HashedDir assetHDir;
|
||||
|
||||
|
@ -255,7 +275,11 @@ private void addModernClientArgs(Collection<String> args) {
|
|||
Collections.addAll(args, "--server", profile.getServerAddress());
|
||||
Collections.addAll(args, "--port", Integer.toString(profile.getServerPort()));
|
||||
}
|
||||
profile.pushOptionalClientArgs(args);
|
||||
for (OptionalAction a : actions) {
|
||||
if (a instanceof OptionalActionClientArgs) {
|
||||
args.addAll(((OptionalActionClientArgs) a).args);
|
||||
}
|
||||
}
|
||||
// Add window size args
|
||||
if (fullScreen)
|
||||
Collections.addAll(args, "--fullscreen", Boolean.toString(true));
|
||||
|
|
|
@ -36,8 +36,15 @@ public final class ServerPinger {
|
|||
private Instant cacheTime = null;
|
||||
|
||||
public ServerPinger(ClientProfile profile) {
|
||||
this.address = Objects.requireNonNull(profile.getServerSocketAddress(), "address");
|
||||
this.version = Objects.requireNonNull(profile.getVersion(), "version");
|
||||
this(profile.getDefaultServerProfile(), profile.getVersion());
|
||||
}
|
||||
|
||||
public ServerPinger(ClientProfile.ServerProfile profile, ClientProfile.Version version) {
|
||||
if (profile == null) {
|
||||
throw new NullPointerException("ServerProfile null");
|
||||
}
|
||||
this.address = profile.toSocketAddress();
|
||||
this.version = Objects.requireNonNull(version, "version");
|
||||
}
|
||||
|
||||
private static String readUTF16String(HInput input) throws IOException {
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
|
||||
public class HWIDProvider {
|
||||
public SystemInfo systemInfo;
|
||||
public OperatingSystem system;
|
||||
public HardwareAbstractionLayer hardware;
|
||||
public final SystemInfo systemInfo;
|
||||
public final OperatingSystem system;
|
||||
public final HardwareAbstractionLayer hardware;
|
||||
|
||||
public HWIDProvider() {
|
||||
systemInfo = new SystemInfo();
|
||||
|
|
|
@ -14,10 +14,29 @@ api project(':LauncherCore')
|
|||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
java11 {
|
||||
java {
|
||||
srcDirs = ['src/main/java11']
|
||||
}
|
||||
dependencies {
|
||||
java11Implementation files(sourceSets.main.output.classesDirs) { builtBy compileJava }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
into('META-INF/versions/11') {
|
||||
from sourceSets.java11.output
|
||||
}
|
||||
classifier = 'clean'
|
||||
}
|
||||
|
||||
compileJava11Java {
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from sourceSets.main.allJava
|
||||
archiveClassifier = 'sources'
|
||||
|
@ -47,6 +66,18 @@ task javadocJar(type: Jar) {
|
|||
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id = 'gravita'
|
||||
name = 'Gravita'
|
||||
email = 'gravita@gravit.pro'
|
||||
}
|
||||
developer {
|
||||
id = 'zaxar163'
|
||||
name = 'Zaxar163'
|
||||
email = 'zahar.vcherachny@yandex.ru'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
|
||||
|
|
|
@ -31,6 +31,7 @@ public ClientPermissions(long permissions, long flags) {
|
|||
|
||||
public static ClientPermissions getSuperuserAccount() {
|
||||
ClientPermissions perm = new ClientPermissions();
|
||||
perm.setPermission(PermissionConsts.ADMIN, true);
|
||||
return perm;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
import pro.gravit.launcher.events.RequestEvent;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
|
||||
public class AuthRequestEvent extends RequestEvent {
|
||||
import java.util.UUID;
|
||||
|
||||
public class AuthRequestEvent extends RequestEvent {
|
||||
public static final String TWO_FACTOR_NEED_ERROR_MESSAGE = "auth.require2fa";
|
||||
@LauncherNetworkAPI
|
||||
public ClientPermissions permissions;
|
||||
@LauncherNetworkAPI
|
||||
|
@ -16,7 +18,7 @@ public class AuthRequestEvent extends RequestEvent {
|
|||
@LauncherNetworkAPI
|
||||
public String protectToken;
|
||||
@LauncherNetworkAPI
|
||||
public long session;
|
||||
public UUID session;
|
||||
|
||||
public AuthRequestEvent() {
|
||||
}
|
||||
|
@ -34,7 +36,7 @@ public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfi
|
|||
this.protectToken = protectToken;
|
||||
}
|
||||
|
||||
public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken, long session) {
|
||||
public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken, UUID session) {
|
||||
this.permissions = permissions;
|
||||
this.playerProfile = playerProfile;
|
||||
this.accessToken = accessToken;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package pro.gravit.launcher.events.request;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||
|
||||
public class CurrentUserRequestEvent extends RequestEvent {
|
||||
public static class UserInfo {
|
||||
public ClientPermissions permissions;
|
||||
public String accessToken;
|
||||
public PlayerProfile playerProfile;
|
||||
}
|
||||
|
||||
public final UserInfo userInfo;
|
||||
|
||||
public CurrentUserRequestEvent(UserInfo userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "currentUser";
|
||||
}
|
||||
}
|
|
@ -3,6 +3,15 @@
|
|||
import pro.gravit.launcher.events.RequestEvent;
|
||||
|
||||
public class RestoreSessionRequestEvent extends RequestEvent {
|
||||
public CurrentUserRequestEvent.UserInfo userInfo;
|
||||
|
||||
public RestoreSessionRequestEvent() {
|
||||
}
|
||||
|
||||
public RestoreSessionRequestEvent(CurrentUserRequestEvent.UserInfo userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "restoreSession";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package pro.gravit.launcher.events.request;
|
||||
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
|
||||
public class ServerStatusRequestEvent extends RequestEvent {
|
||||
public final String projectName;
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package pro.gravit.launcher.events.request;
|
||||
|
||||
import pro.gravit.launcher.events.RequestEvent;
|
||||
|
||||
public class SetPasswordRequestEvent extends RequestEvent {
|
||||
@Override
|
||||
public String getType() {
|
||||
return "setPassword";
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package pro.gravit.launcher.hwid;
|
||||
|
||||
@Deprecated
|
||||
public interface HWID {
|
||||
|
||||
int getLevel(); //Уровень доверия, насколько уникальные значения
|
||||
|
||||
int getAntiLevel(); //Уровень лживости, насколько фальшивые значения
|
||||
|
||||
int compare(HWID hwid);
|
||||
|
||||
boolean isNull();
|
||||
|
||||
void normalize();
|
||||
}
|
|
@ -72,20 +72,23 @@ public final class ClientProfile implements Comparable<ClientProfile> {
|
|||
@LauncherNetworkAPI
|
||||
private String mainClass;
|
||||
|
||||
public static class ServerProfile
|
||||
{
|
||||
public static class ServerProfile {
|
||||
public String name;
|
||||
public String serverAddress;
|
||||
public int serverPort;
|
||||
public boolean isDefault = true;
|
||||
|
||||
public InetSocketAddress toSocketAddress() {
|
||||
return InetSocketAddress.createUnresolved(serverAddress, serverPort);
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
private List<ServerProfile> servers = new ArrayList<>(1);
|
||||
public ServerProfile getDefaultServerProfile()
|
||||
{
|
||||
for(ServerProfile profile : servers)
|
||||
{
|
||||
if(profile.isDefault) return profile;
|
||||
|
||||
public ServerProfile getDefaultServerProfile() {
|
||||
for (ServerProfile profile : servers) {
|
||||
if (profile.isDefault) return profile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -127,6 +130,10 @@ public String getAssetDir() {
|
|||
return assetDir;
|
||||
}
|
||||
|
||||
public List<String> getUpdateExclusions() {
|
||||
return Collections.unmodifiableList(updateExclusions);
|
||||
}
|
||||
|
||||
public FileNameMatcher getClientUpdateMatcher(/*boolean excludeOptional*/) {
|
||||
String[] updateArray = update.toArray(new String[0]);
|
||||
String[] verifyArray = updateVerify.toArray(new String[0]);
|
||||
|
@ -169,28 +176,36 @@ public void updateOptionalGraph() {
|
|||
if (file.dependenciesFile != null) {
|
||||
file.dependencies = new OptionalFile[file.dependenciesFile.length];
|
||||
for (int i = 0; i < file.dependenciesFile.length; ++i) {
|
||||
file.dependencies[i] = getOptionalFile(file.dependenciesFile[i].name, file.dependenciesFile[i].type);
|
||||
file.dependencies[i] = getOptionalFile(file.dependenciesFile[i].name);
|
||||
}
|
||||
}
|
||||
if (file.conflictFile != null) {
|
||||
file.conflict = new OptionalFile[file.conflictFile.length];
|
||||
for (int i = 0; i < file.conflictFile.length; ++i) {
|
||||
file.conflict[i] = getOptionalFile(file.conflictFile[i].name, file.conflictFile[i].type);
|
||||
file.conflict[i] = getOptionalFile(file.conflictFile[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<String> getShared() {
|
||||
return updateShared;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void markOptional(OptionalFile file) {
|
||||
|
||||
if (file.mark) return;
|
||||
|
@ -210,6 +225,7 @@ public void markOptional(OptionalFile file) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void unmarkOptional(OptionalFile file) {
|
||||
if (!file.mark) return;
|
||||
file.mark = false;
|
||||
|
@ -236,6 +252,7 @@ public void unmarkOptional(OptionalFile file) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushOptionalFile(HashedDir dir, boolean digest) {
|
||||
for (OptionalFile opt : updateOptional) {
|
||||
if (opt.type.equals(OptionalType.FILE) && !opt.mark) {
|
||||
|
@ -245,6 +262,7 @@ public void pushOptionalFile(HashedDir dir, boolean digest) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushOptionalJvmArgs(Collection<String> jvmArgs1) {
|
||||
for (OptionalFile opt : updateOptional) {
|
||||
if (opt.type.equals(OptionalType.JVMARGS) && opt.mark) {
|
||||
|
@ -253,6 +271,7 @@ public void pushOptionalJvmArgs(Collection<String> jvmArgs1) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushOptionalClientArgs(Collection<String> clientArgs1) {
|
||||
for (OptionalFile opt : updateOptional) {
|
||||
if (opt.type.equals(OptionalType.CLIENTARGS) && opt.mark) {
|
||||
|
@ -261,6 +280,7 @@ public void pushOptionalClientArgs(Collection<String> clientArgs1) {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pushOptionalClassPath(pushOptionalClassPathCallback callback) throws IOException {
|
||||
for (OptionalFile opt : updateOptional) {
|
||||
if (opt.type.equals(OptionalType.CLASSPATH) && opt.mark) {
|
||||
|
@ -273,6 +293,7 @@ public int getServerPort() {
|
|||
ServerProfile profile = getDefaultServerProfile();
|
||||
return profile == null ? 25565 : profile.serverPort;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public InetSocketAddress getServerSocketAddress() {
|
||||
return InetSocketAddress.createUnresolved(getServerAddress(), getServerPort());
|
||||
|
@ -358,11 +379,6 @@ public void verify() {
|
|||
for (OptionalFile f : updateOptional) {
|
||||
if (f == null) throw new IllegalArgumentException("Found null entry in updateOptional");
|
||||
if (f.name == null) throw new IllegalArgumentException("Optional: name must not be null");
|
||||
if (f.list == null) throw new IllegalArgumentException("Optional: list must not be null");
|
||||
for (String s : f.list) {
|
||||
if (s == null)
|
||||
throw new IllegalArgumentException(String.format("Found null entry in updateOptional.%s.list", f.name));
|
||||
}
|
||||
if (f.conflictFile != null) for (OptionalDepend s : f.conflictFile) {
|
||||
if (s == null)
|
||||
throw new IllegalArgumentException(String.format("Found null entry in updateOptional.%s.conflictFile", f.name));
|
||||
|
@ -410,7 +426,9 @@ public enum Version {
|
|||
MC115("1.15", 573),
|
||||
MC1151("1.15.1", 575),
|
||||
MC1152("1.15.2", 578),
|
||||
MC1161("1.16.1", 736);
|
||||
MC1161("1.16.1", 736),
|
||||
MC1162("1.16.2", 751),
|
||||
MC1163("1.16.3", 753);
|
||||
private static final Map<String, Version> VERSIONS;
|
||||
|
||||
static {
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package pro.gravit.launcher.profiles.optional;
|
||||
|
||||
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;
|
||||
|
@ -16,10 +18,14 @@ public class OptionalFile {
|
|||
@LauncherNetworkAPI
|
||||
public final long permissions = 0L;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public String[] list;
|
||||
@LauncherNetworkAPI
|
||||
@Deprecated
|
||||
public OptionalType type;
|
||||
@LauncherNetworkAPI
|
||||
public List<OptionalAction> actions;
|
||||
@LauncherNetworkAPI
|
||||
public boolean mark;
|
||||
@LauncherNetworkAPI
|
||||
public boolean visible = true;
|
||||
|
@ -41,6 +47,7 @@ public class OptionalFile {
|
|||
public int subTreeLevel = 1;
|
||||
@LauncherNetworkAPI
|
||||
public boolean isPreset;
|
||||
@Deprecated
|
||||
public transient Set<OptionalFile> dependenciesCount;
|
||||
private volatile transient Collection<BiConsumer<OptionalFile, Boolean>> watchList = null;
|
||||
|
||||
|
@ -138,8 +145,6 @@ public void clearAllWatchers() {
|
|||
|
||||
public void watchEvent(boolean isMark) {
|
||||
if (watchList == null) return;
|
||||
watchList.forEach((e) -> {
|
||||
e.accept(this, isMark);
|
||||
});
|
||||
watchList.forEach((e) -> e.accept(this, isMark));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package pro.gravit.launcher.profiles.optional;
|
||||
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class OptionalView {
|
||||
public Set<OptionalFile> enabled = new HashSet<>();
|
||||
public Map<OptionalFile, Set<OptionalFile>> dependenciesCountMap = new HashMap<>();
|
||||
public Set<OptionalFile> all;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends OptionalAction> Set<T> getActionsByClass(Class<T> clazz) {
|
||||
Set<T> results = new HashSet<>();
|
||||
for (OptionalFile e : enabled) {
|
||||
if (e.actions != null) {
|
||||
for (OptionalAction a : e.actions) {
|
||||
if (clazz.isAssignableFrom(a.getClass())) {
|
||||
results.add((T) a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public Set<OptionalAction> getEnabledActions() {
|
||||
Set<OptionalAction> results = new HashSet<>();
|
||||
for (OptionalFile e : enabled) {
|
||||
if (e.actions != null) {
|
||||
results.addAll(e.actions);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public Set<OptionalAction> getDisabledActions() {
|
||||
Set<OptionalAction> results = new HashSet<>();
|
||||
for (OptionalFile e : all) {
|
||||
if (enabled.contains(e)) continue;
|
||||
if (e.actions != null) {
|
||||
results.addAll(e.actions);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 OptionalView(ClientProfile profile) {
|
||||
this.all = profile.getOptional();
|
||||
for (OptionalFile f : this.all) {
|
||||
if (f.mark) enable(f);
|
||||
}
|
||||
}
|
||||
|
||||
public OptionalView(OptionalView view) {
|
||||
this.enabled = new HashSet<>(view.enabled);
|
||||
this.dependenciesCountMap = new HashMap<>(view.dependenciesCountMap);
|
||||
this.all = view.all;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package pro.gravit.launcher.profiles.optional.actions;
|
||||
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
public class OptionalAction {
|
||||
public static final ProviderMap<OptionalAction> providers = new ProviderMap<>();
|
||||
private static boolean registerProviders = false;
|
||||
|
||||
public static void registerProviders() {
|
||||
if (!registerProviders) {
|
||||
providers.register("file", OptionalActionFile.class);
|
||||
providers.register("clientArgs", OptionalActionClientArgs.class);
|
||||
providers.register("jvmArgs", OptionalActionJvmArgs.class);
|
||||
providers.register("classpath", OptionalActionClassPath.class);
|
||||
registerProviders = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package pro.gravit.launcher.profiles.optional.actions;
|
||||
|
||||
public class OptionalActionClassPath extends OptionalAction {
|
||||
public String[] args;
|
||||
public boolean useAltClasspath = false;
|
||||
|
||||
public OptionalActionClassPath() {
|
||||
}
|
||||
|
||||
public OptionalActionClassPath(String[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public OptionalActionClassPath(String[] args, boolean useAltClasspath) {
|
||||
this.args = args;
|
||||
this.useAltClasspath = useAltClasspath;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package pro.gravit.launcher.profiles.optional.actions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OptionalActionClientArgs extends OptionalAction {
|
||||
public List<String> args;
|
||||
|
||||
public OptionalActionClientArgs() {
|
||||
}
|
||||
|
||||
public OptionalActionClientArgs(List<String> args) {
|
||||
this.args = args;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package pro.gravit.launcher.profiles.optional.actions;
|
||||
|
||||
import pro.gravit.launcher.hasher.HashedDir;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class OptionalActionFile extends OptionalAction {
|
||||
public Map<String, String> files;
|
||||
|
||||
public void injectToHashedDir(HashedDir dir) {
|
||||
if (files == null) return;
|
||||
files.forEach((k, v) -> {
|
||||
HashedDir.FindRecursiveResult firstPath = dir.findRecursive(k);
|
||||
if (v != null && !v.isEmpty()) {
|
||||
LogHelper.dev("Debug findRecursive: name %s, parent: ", firstPath.name, firstPath.parent == null ? "null" : "not null", firstPath.entry == null ? "null" : "not null");
|
||||
HashedDir.FindRecursiveResult secondPath = dir.findRecursive(v);
|
||||
LogHelper.dev("Debug findRecursive: name %s, parent: ", secondPath.name, secondPath.parent == null ? "null" : "not null", secondPath.entry == null ? "null" : "not null");
|
||||
firstPath.parent.moveTo(firstPath.name, secondPath.parent, secondPath.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void disableInHashedDir(HashedDir dir) {
|
||||
if (files == null) return;
|
||||
files.forEach((k, v) -> {
|
||||
HashedDir.FindRecursiveResult firstPath = dir.findRecursive(k);
|
||||
firstPath.parent.remove(firstPath.name);
|
||||
});
|
||||
}
|
||||
|
||||
public OptionalActionFile() {
|
||||
}
|
||||
|
||||
public OptionalActionFile(Map<String, String> files) {
|
||||
this.files = files;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package pro.gravit.launcher.profiles.optional.actions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OptionalActionJvmArgs extends OptionalAction {
|
||||
public List<String> args;
|
||||
|
||||
public OptionalActionJvmArgs() {
|
||||
}
|
||||
|
||||
public OptionalActionJvmArgs(List<String> args) {
|
||||
this.args = args;
|
||||
}
|
||||
}
|
|
@ -4,23 +4,22 @@
|
|||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
|
||||
public static StdWebSocketService service;
|
||||
private static long session = SecurityHelper.secureRandom.nextLong();
|
||||
private static UUID session = UUID.randomUUID();
|
||||
@LauncherNetworkAPI
|
||||
public final UUID requestUUID = UUID.randomUUID();
|
||||
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
||||
|
||||
public static long getSession() {
|
||||
public static UUID getSession() {
|
||||
return Request.session;
|
||||
}
|
||||
|
||||
public static void setSession(long session) {
|
||||
public static void setSession(UUID session) {
|
||||
Request.session = session;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||
import pro.gravit.launcher.hwid.HWID;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.auth.password.AuthECPassword;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
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;
|
||||
|
@ -23,8 +21,6 @@ public final class AuthRequest extends Request<AuthRequestEvent> implements WebS
|
|||
private final boolean getSession;
|
||||
@LauncherNetworkAPI
|
||||
private final ConnectTypes authType;
|
||||
@LauncherNetworkAPI
|
||||
public boolean initProxy;
|
||||
|
||||
public AuthRequest(String login, byte[] password) {
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
|
@ -43,15 +39,6 @@ public AuthRequest(String login, byte[] password, String auth_id) {
|
|||
authType = ConnectTypes.CLIENT;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public AuthRequest(String login, byte[] password, HWID hwid, 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;
|
||||
}
|
||||
|
||||
public AuthRequest(String login, byte[] encryptedPassword, String auth_id, ConnectTypes authType) {
|
||||
this.login = login;
|
||||
this.password = new AuthECPassword(encryptedPassword.clone());
|
||||
|
@ -68,10 +55,21 @@ public AuthRequest(String login, String password, String auth_id, ConnectTypes a
|
|||
this.getSession = false;
|
||||
}
|
||||
|
||||
public AuthRequest(String login, AuthPasswordInterface password, String auth_id, boolean getSession, ConnectTypes authType) {
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
this.auth_id = auth_id;
|
||||
this.getSession = getSession;
|
||||
this.authType = authType;
|
||||
}
|
||||
|
||||
public static void registerProviders() {
|
||||
if (!registerProviders) {
|
||||
providers.register("plain", AuthPlainPassword.class);
|
||||
providers.register("rsa", AuthECPassword.class);
|
||||
providers.register("2fa", Auth2FAPassword.class);
|
||||
providers.register("signature", AuthSignaturePassword.class);
|
||||
providers.register("totp", AuthTOTPPassword.class);
|
||||
registerProviders = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
public final class CheckServerRequest extends Request<CheckServerRequestEvent> implements WebSocketRequest {
|
||||
@LauncherNetworkAPI
|
||||
private final String username;
|
||||
public final String username;
|
||||
@LauncherNetworkAPI
|
||||
private final String serverID;
|
||||
public final String serverID;
|
||||
|
||||
|
||||
public CheckServerRequest(String username, String serverID) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package pro.gravit.launcher.request.auth;
|
||||
|
||||
import pro.gravit.launcher.events.request.CurrentUserRequestEvent;
|
||||
import pro.gravit.launcher.request.Request;
|
||||
|
||||
public class CurrentUserRequest extends Request<CurrentUserRequestEvent> {
|
||||
@Override
|
||||
public String getType() {
|
||||
return "currentUser";
|
||||
}
|
||||
}
|
|
@ -10,11 +10,11 @@ public final class JoinServerRequest extends Request<JoinServerRequestEvent> imp
|
|||
|
||||
// Instance
|
||||
@LauncherNetworkAPI
|
||||
private final String username;
|
||||
public final String username;
|
||||
@LauncherNetworkAPI
|
||||
private final String accessToken;
|
||||
public final String accessToken;
|
||||
@LauncherNetworkAPI
|
||||
private final String serverID;
|
||||
public final String serverID;
|
||||
|
||||
|
||||
public JoinServerRequest(String username, String accessToken, String serverID) {
|
||||
|
|
|
@ -5,14 +5,22 @@
|
|||
import pro.gravit.launcher.request.Request;
|
||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class RestoreSessionRequest extends Request<RestoreSessionRequestEvent> implements WebSocketRequest {
|
||||
@LauncherNetworkAPI
|
||||
public final long session;
|
||||
public final UUID session;
|
||||
public boolean needUserInfo;
|
||||
|
||||
public RestoreSessionRequest(long session) {
|
||||
public RestoreSessionRequest(UUID session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public RestoreSessionRequest(UUID session, boolean needUserInfo) {
|
||||
this.session = session;
|
||||
this.needUserInfo = needUserInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "restoreSession";
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package pro.gravit.launcher.request.auth.password;
|
||||
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
|
||||
public class Auth2FAPassword implements AuthRequest.AuthPasswordInterface {
|
||||
public AuthRequest.AuthPasswordInterface firstPassword;
|
||||
public AuthRequest.AuthPasswordInterface secondPassword;
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
return firstPassword != null && firstPassword.check() && secondPassword != null && secondPassword.check();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package pro.gravit.launcher.request.auth.password;
|
||||
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
|
||||
public class AuthSignaturePassword implements AuthRequest.AuthPasswordInterface {
|
||||
public byte[] signature;
|
||||
public byte[] publicKey;
|
||||
public byte[] salt;
|
||||
|
||||
@Override
|
||||
public boolean check() {
|
||||
return true;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue