[FEATURE] ProtectHandler

This commit is contained in:
Gravit 2019-03-14 23:54:08 +07:00
parent 7e5fafa159
commit 37be6b86c3
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
13 changed files with 152 additions and 1 deletions

View file

@ -8,6 +8,8 @@
import ru.gravit.launcher.managers.GarbageManager; import ru.gravit.launcher.managers.GarbageManager;
import ru.gravit.launcher.profiles.ClientProfile; import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.serialize.signed.SignedObjectHolder; import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
import ru.gravit.launchserver.auth.protect.NoProtectHandler;
import ru.gravit.launchserver.auth.protect.ProtectHandler;
import ru.gravit.launchserver.components.AuthLimiterComponent; import ru.gravit.launchserver.components.AuthLimiterComponent;
import ru.gravit.launchserver.auth.handler.AuthHandler; import ru.gravit.launchserver.auth.handler.AuthHandler;
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler; import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
@ -89,6 +91,8 @@ public static final class Config {
public AuthHandler authHandler; public AuthHandler authHandler;
public ProtectHandler protectHandler;
public PermissionsHandler permissionsHandler; public PermissionsHandler permissionsHandler;
public TextureProvider textureProvider; public TextureProvider textureProvider;
@ -159,6 +163,10 @@ public void verify() {
if (authHandler == null) { if (authHandler == null) {
throw new NullPointerException("AuthHandler must not be null"); throw new NullPointerException("AuthHandler must not be null");
} }
if(protectHandler == null)
{
throw new NullPointerException("ProtectHandler must not be null");
}
if (authProvider == null || authProvider[0] == null) { if (authProvider == null || authProvider[0] == null) {
throw new NullPointerException("AuthProvider must not be null"); throw new NullPointerException("AuthProvider must not be null");
} }
@ -377,6 +385,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
PermissionsHandler.registerHandlers(); PermissionsHandler.registerHandlers();
Response.registerResponses(); Response.registerResponses();
Component.registerComponents(); Component.registerComponents();
ProtectHandler.registerHandlers();
LaunchServer.server = this; LaunchServer.server = this;
// Set command handler // Set command handler
@ -435,6 +444,10 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
for (AuthProvider provider : config.authProvider) { for (AuthProvider provider : config.authProvider) {
provider.init(); provider.init();
} }
if(config.protectHandler != null)
{
config.protectHandler.checkLaunchServerLicense();
}
config.authHandler.init(); config.authHandler.init();
if(config.components != null) if(config.components != null)
{ {
@ -546,6 +559,7 @@ public static void initGson() {
Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
Launcher.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter());
Launcher.gson = Launcher.gsonBuilder.create(); Launcher.gson = Launcher.gsonBuilder.create();
//Human readable //Human readable
@ -557,6 +571,7 @@ public static void initGson() {
LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter()); LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
LaunchServer.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter());
LaunchServer.gson = LaunchServer.gsonBuilder.create(); LaunchServer.gson = LaunchServer.gsonBuilder.create();
} }
@ -608,6 +623,7 @@ private void generateConfigIfNotExists() throws IOException {
newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh"; newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh";
newConfig.authHandler = new MemoryAuthHandler(); newConfig.authHandler = new MemoryAuthHandler();
newConfig.hwidHandler = new AcceptHWIDHandler(); newConfig.hwidHandler = new AcceptHWIDHandler();
newConfig.protectHandler = new NoProtectHandler();
newConfig.authProvider = new AuthProvider[]{new RejectAuthProvider("Настройте authProvider")}; newConfig.authProvider = new AuthProvider[]{new RejectAuthProvider("Настройте authProvider")};
newConfig.textureProvider = new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png"); newConfig.textureProvider = new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png");

View file

@ -0,0 +1,16 @@
package ru.gravit.launchserver.auth.protect;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.utils.helper.SecurityHelper;
public class NoProtectHandler extends ProtectHandler {
@Override
public String generateSecureToken(AuthResponse.AuthContext context) {
return SecurityHelper.randomStringToken();
}
@Override
public void checkLaunchServerLicense() {
// None
}
}

View file

@ -0,0 +1,46 @@
package ru.gravit.launchserver.auth.protect;
import ru.gravit.launchserver.auth.AuthException;
import ru.gravit.launchserver.auth.handler.AuthHandler;
import ru.gravit.launchserver.response.auth.AuthResponse;
import ru.gravit.utils.helper.VerifyHelper;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public abstract class ProtectHandler {
private static final Map<String, Class<? extends ProtectHandler>> PROTECT_HANDLERS = new ConcurrentHashMap<>(4);
private static boolean registredHandl = false;
public static void registerHandler(String name, Class<? extends ProtectHandler> adapter) {
VerifyHelper.verifyIDName(name);
VerifyHelper.putIfAbsent(PROTECT_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"),
String.format("Protect handler has been already registered: '%s'", name));
}
public static Class<? extends ProtectHandler> getHandlerClass(String name) {
return PROTECT_HANDLERS.get(name);
}
public static String getHandlerName(Class<ProtectHandler> clazz) {
for (Map.Entry<String, Class<? extends ProtectHandler>> e : PROTECT_HANDLERS.entrySet()) {
if (e.getValue().equals(clazz)) return e.getKey();
}
return null;
}
public static void registerHandlers() {
if (!registredHandl) {
registerHandler("none", NoProtectHandler.class);
registredHandl = true;
}
}
public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
//public abstract
}

View file

@ -0,0 +1,37 @@
package ru.gravit.launchserver.config;
import com.google.gson.*;
import ru.gravit.launchserver.auth.handler.AuthHandler;
import ru.gravit.launchserver.auth.protect.ProtectHandler;
import ru.gravit.utils.helper.LogHelper;
import java.lang.reflect.Type;
public class ProtectHandlerAdapter implements JsonSerializer<ProtectHandler>, JsonDeserializer<ProtectHandler> {
private static final String PROP_NAME = "type";
@Override
public ProtectHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class<? extends ProtectHandler> cls = ProtectHandler.getHandlerClass(typename);
if(cls == null)
{
LogHelper.error("ProtectHandler %s not found", typename);
return null;
}
return (ProtectHandler) context.deserialize(json, cls);
}
@Override
public JsonElement serialize(ProtectHandler src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jo = context.serialize(src).getAsJsonObject();
@SuppressWarnings("unchecked")
String classPath = ProtectHandler.getHandlerName((Class<ProtectHandler>) src.getClass());
jo.add(PROP_NAME, new JsonPrimitive(classPath));
return jo;
}
}

View file

@ -137,10 +137,12 @@ public void reply() throws Exception {
requestError("Internal auth handler error"); requestError("Internal auth handler error");
return; return;
} }
String protectToken = server.config.protectHandler.generateSecureToken(context);
writeNoError(output); writeNoError(output);
// Write profile and UUID // Write profile and UUID
ProfileByUUIDResponse.getProfile(server, uuid, result.username, client).write(output); ProfileByUUIDResponse.getProfile(server, uuid, result.username, client).write(output);
output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH); output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
clientData.permissions.write(output); clientData.permissions.write(output);
output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT);
} }
} }

View file

@ -215,6 +215,7 @@ function doAuth(login, rsaPassword) {
overlay.show(processing.overlay, function (event) { overlay.show(processing.overlay, function (event) {
FunctionalBridge.getHWID.join(); FunctionalBridge.getHWID.join();
makeAuthRequest(login, rsaPassword, function (result) { makeAuthRequest(login, rsaPassword, function (result) {
FunctionalBridge.setAuthParams(result);
loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions}; loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions};
overlay.hide(0, function () { overlay.hide(0, function () {

View file

@ -3,6 +3,7 @@
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ru.gravit.launcher.HWID; import ru.gravit.launcher.HWID;
import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.LauncherAPI;
import ru.gravit.launcher.events.request.AuthRequestEvent;
import ru.gravit.launcher.guard.LauncherGuardManager; import ru.gravit.launcher.guard.LauncherGuardManager;
import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.FileNameMatcher;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
@ -103,6 +104,12 @@ public static HasherStore getDefaultHasherStore() {
return HasherManager.getDefaultStore(); return HasherManager.getDefaultStore();
} }
@LauncherAPI
public static void setAuthParams(AuthRequestEvent event)
{
LauncherGuardManager.guard.setProtectToken(event.protectToken);
}
@FunctionalInterface @FunctionalInterface
public interface HashedDirRunnable { public interface HashedDirRunnable {
SignedObjectHolder<HashedDir> run() throws Exception; SignedObjectHolder<HashedDir> run() throws Exception;

View file

@ -11,4 +11,5 @@ public interface LauncherGuardInterface {
void init(boolean clientInstance); void init(boolean clientInstance);
void addCustomParams(ClientLauncherContext context); void addCustomParams(ClientLauncherContext context);
void addCustomEnv(ClientLauncherContext context); void addCustomEnv(ClientLauncherContext context);
void setProtectToken(String token);
} }

View file

@ -43,4 +43,9 @@ public void addCustomParams(ClientLauncherContext context) {
public void addCustomEnv(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) {
} }
@Override
public void setProtectToken(String token) {
}
} }

View file

@ -40,4 +40,9 @@ public void addCustomParams(ClientLauncherContext context) {
public void addCustomEnv(ClientLauncherContext context) { public void addCustomEnv(ClientLauncherContext context) {
} }
@Override
public void setProtectToken(String token) {
}
} }

View file

@ -69,4 +69,9 @@ public void addCustomEnv(ClientLauncherContext context) {
env.put("GUARD_LICENSE_KEY", config.guardLicenseKey); env.put("GUARD_LICENSE_KEY", config.guardLicenseKey);
} }
} }
@Override
public void setProtectToken(String token) {
}
} }

View file

@ -118,7 +118,8 @@ protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOExce
PlayerProfile pp = new PlayerProfile(input); PlayerProfile pp = new PlayerProfile(input);
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH); String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
ClientPermissions permissions = new ClientPermissions(input); ClientPermissions permissions = new ClientPermissions(input);
return new AuthRequestEvent(pp, accessToken, permissions); String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
return new AuthRequestEvent(permissions, pp, accessToken, protectToken);
} }
@Override @Override

View file

@ -20,6 +20,8 @@ public AuthRequestEvent() {
public PlayerProfile playerProfile; public PlayerProfile playerProfile;
@LauncherNetworkAPI @LauncherNetworkAPI
public String accessToken; public String accessToken;
@LauncherNetworkAPI
public String protectToken;
public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) { public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) {
this.playerProfile = pp; this.playerProfile = pp;
@ -27,6 +29,13 @@ public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions
this.permissions = permissions; this.permissions = permissions;
} }
public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken) {
this.permissions = permissions;
this.playerProfile = playerProfile;
this.accessToken = accessToken;
this.protectToken = protectToken;
}
@Override @Override
public UUID getUUID() { public UUID getUUID() {
return uuid; return uuid;