mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
[FEATURE][EXPERIMENTAL] SecureLevel
This commit is contained in:
parent
8875146be3
commit
8dddb08255
16 changed files with 213 additions and 84 deletions
|
@ -0,0 +1,44 @@
|
||||||
|
package pro.gravit.launchserver.auth.protect;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.GetSecureLevelInfoRequestEvent;
|
||||||
|
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
public class AdvancedProtectHandler extends ProtectHandler implements SecureProtectHandler {
|
||||||
|
@Override
|
||||||
|
public String generateSecureToken(AuthResponse.AuthContext context) {
|
||||||
|
return SecurityHelper.randomStringToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateClientSecureToken() {
|
||||||
|
return SecurityHelper.randomStringToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyClientSecureToken(String token, String secureKey) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
|
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.isSecure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkLaunchServerLicense() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowGetSecureLevelInfo(Client client) {
|
||||||
|
return client.isSecure;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ public static void registerHandlers() {
|
||||||
if (!registredHandl) {
|
if (!registredHandl) {
|
||||||
providers.register("none", NoProtectHandler.class);
|
providers.register("none", NoProtectHandler.class);
|
||||||
providers.register("std", StdProtectHandler.class);
|
providers.register("std", StdProtectHandler.class);
|
||||||
|
providers.register("advanced", AdvancedProtectHandler.class);
|
||||||
registredHandl = true;
|
registredHandl = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package pro.gravit.launchserver.auth.protect.interfaces;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.GetSecureLevelInfoRequestEvent;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.security.interfaces.ECPublicKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
|
||||||
|
public interface SecureProtectHandler {
|
||||||
|
default byte[] generateSecureLevelKey()
|
||||||
|
{
|
||||||
|
return SecurityHelper.randomBytes(128);
|
||||||
|
}
|
||||||
|
default void verifySecureLevelKey(byte[] publicKey, byte[] signature) throws InvalidKeySpecException, SignatureException {
|
||||||
|
if(publicKey == null || signature == null) throw new InvalidKeySpecException();
|
||||||
|
ECPublicKey pubKey = SecurityHelper.toPublicECKey(publicKey);
|
||||||
|
SecurityHelper.newECVerifySignature(pubKey).update(signature);
|
||||||
|
}
|
||||||
|
GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event);
|
||||||
|
boolean allowGetSecureLevelInfo(Client client);
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ public class Client {
|
||||||
public ClientPermissions permissions;
|
public ClientPermissions permissions;
|
||||||
public String username;
|
public String username;
|
||||||
public String verifyToken;
|
public String verifyToken;
|
||||||
|
public TrustLevel trustLevel;
|
||||||
public transient LogHelper.OutputEnity logOutput;
|
public transient LogHelper.OutputEnity logOutput;
|
||||||
|
|
||||||
public transient AuthProviderPair auth;
|
public transient AuthProviderPair auth;
|
||||||
|
@ -48,4 +49,8 @@ public enum Type {
|
||||||
SERVER,
|
SERVER,
|
||||||
USER
|
USER
|
||||||
}
|
}
|
||||||
|
public static class TrustLevel
|
||||||
|
{
|
||||||
|
public byte[] verifySecureKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
||||||
import pro.gravit.launchserver.socket.response.secure.GetSecureTokenResponse;
|
import pro.gravit.launchserver.socket.response.secure.GetSecureLevelInfoResponse;
|
||||||
import pro.gravit.launchserver.socket.response.secure.VerifySecureTokenResponse;
|
import pro.gravit.launchserver.socket.response.secure.VerifySecureLevelKeyResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
||||||
|
@ -123,12 +123,12 @@ public static void registerResponses() {
|
||||||
providers.register("batchProfileByUsername", BatchProfileByUsername.class);
|
providers.register("batchProfileByUsername", BatchProfileByUsername.class);
|
||||||
providers.register("profileByUsername", ProfileByUsername.class);
|
providers.register("profileByUsername", ProfileByUsername.class);
|
||||||
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
||||||
providers.register("getSecureToken", GetSecureTokenResponse.class);
|
|
||||||
providers.register("verifySecureToken", VerifySecureTokenResponse.class);
|
|
||||||
providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
||||||
providers.register("register", RegisterResponse.class);
|
providers.register("register", RegisterResponse.class);
|
||||||
providers.register("setPassword", SetPasswordResponse.class);
|
providers.register("setPassword", SetPasswordResponse.class);
|
||||||
providers.register("exit", ExitResponse.class);
|
providers.register("exit", ExitResponse.class);
|
||||||
|
providers.register("getSecureLevelInfo", GetSecureLevelInfoResponse.class);
|
||||||
|
providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package pro.gravit.launchserver.socket.response.secure;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import pro.gravit.launcher.events.request.GetSecureLevelInfoRequestEvent;
|
||||||
|
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
|
public class GetSecureLevelInfoResponse extends SimpleResponse {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getSecureLevelInfo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
|
if(!(server.config.protectHandler instanceof SecureProtectHandler))
|
||||||
|
{
|
||||||
|
GetSecureLevelInfoRequestEvent response = new GetSecureLevelInfoRequestEvent(null);
|
||||||
|
response.enabled = false;
|
||||||
|
sendResult(response);
|
||||||
|
}
|
||||||
|
SecureProtectHandler secureProtectHandler = (SecureProtectHandler) server.config.protectHandler;
|
||||||
|
if(!secureProtectHandler.allowGetSecureLevelInfo(client))
|
||||||
|
{
|
||||||
|
sendError("Permissions denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(client.trustLevel == null) client.trustLevel = new Client.TrustLevel();
|
||||||
|
if(client.trustLevel.verifySecureKey == null) client.trustLevel.verifySecureKey = secureProtectHandler.generateSecureLevelKey();
|
||||||
|
GetSecureLevelInfoRequestEvent response = new GetSecureLevelInfoRequestEvent(client.trustLevel.verifySecureKey);
|
||||||
|
response.enabled = true;
|
||||||
|
sendResult(secureProtectHandler.onGetSecureLevelInfo(response));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
package pro.gravit.launchserver.socket.response.secure;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import pro.gravit.launcher.events.request.GetSecureTokenRequestEvent;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
|
||||||
|
|
||||||
public class GetSecureTokenResponse extends SimpleResponse {
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "getSecureToken";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
|
||||||
String secureToken = server.config.protectHandler.generateClientSecureToken();
|
|
||||||
client.verifyToken = secureToken;
|
|
||||||
sendResult(new GetSecureTokenRequestEvent(secureToken));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
|
||||||
|
public class VerifySecureLevelKeyResponse extends SimpleResponse {
|
||||||
|
public byte[] publicKey;
|
||||||
|
public byte[] signature;
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "verifySecureLevelKey";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
|
if(!(server.config.protectHandler instanceof SecureProtectHandler))
|
||||||
|
{
|
||||||
|
sendError("This method not allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SecureProtectHandler secureProtectHandler = (SecureProtectHandler) server.config.protectHandler;
|
||||||
|
try {
|
||||||
|
secureProtectHandler.verifySecureLevelKey(publicKey, signature);
|
||||||
|
} catch (InvalidKeySpecException e)
|
||||||
|
{
|
||||||
|
sendError("Invalid public key");
|
||||||
|
return;
|
||||||
|
} catch (SignatureException e)
|
||||||
|
{
|
||||||
|
sendError("Invalid signature");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendResult(new VerifySecureLevelKeyRequestEvent());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
package pro.gravit.launchserver.socket.response.secure;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import pro.gravit.launcher.events.request.VerifySecureTokenRequestEvent;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
|
||||||
|
|
||||||
public class VerifySecureTokenResponse extends SimpleResponse {
|
|
||||||
public String secureToken;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "verifySecureToken";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
|
||||||
boolean success = server.config.protectHandler.verifyClientSecureToken(secureToken, client.verifyToken);
|
|
||||||
if (success) client.isSecure = true;
|
|
||||||
sendResult(new VerifySecureTokenRequestEvent(success));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
|
public class GetSecureLevelInfoRequestEvent extends RequestEvent {
|
||||||
|
public final byte[] verifySecureKey;
|
||||||
|
public boolean enabled;
|
||||||
|
|
||||||
|
public GetSecureLevelInfoRequestEvent(byte[] verifySecureKey) {
|
||||||
|
this.verifySecureKey = verifySecureKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getSecureLevelInfo";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
package pro.gravit.launcher.events.request;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
|
||||||
|
|
||||||
public class GetSecureTokenRequestEvent extends RequestEvent {
|
|
||||||
@LauncherNetworkAPI
|
|
||||||
public final String secureToken;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "GetSecureToken";
|
|
||||||
}
|
|
||||||
|
|
||||||
public GetSecureTokenRequestEvent(String secureToken) {
|
|
||||||
this.secureToken = secureToken;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
|
public class VerifySecureLevelKeyRequestEvent extends RequestEvent {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "verifySecureLevelKey";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
package pro.gravit.launcher.events.request;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
|
||||||
|
|
||||||
public class VerifySecureTokenRequestEvent extends RequestEvent {
|
|
||||||
@LauncherNetworkAPI
|
|
||||||
public final boolean success;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "verifySecureToken";
|
|
||||||
}
|
|
||||||
|
|
||||||
public VerifySecureTokenRequestEvent(boolean success) {
|
|
||||||
this.success = success;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package pro.gravit.launcher.request.secure;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.GetSecureLevelInfoRequestEvent;
|
||||||
|
import pro.gravit.launcher.request.Request;
|
||||||
|
|
||||||
|
public class GetSecureLevelInfoRequest extends Request<GetSecureLevelInfoRequestEvent> {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getSecureLevelInfo";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package pro.gravit.launcher.request.secure;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.VerifySecureLevelKeyRequestEvent;
|
||||||
|
import pro.gravit.launcher.request.Request;
|
||||||
|
|
||||||
|
public class VerifySecureLevelKeyRequest extends Request<VerifySecureLevelKeyRequestEvent> {
|
||||||
|
public final byte[] publicKey;
|
||||||
|
public final byte[] signature;
|
||||||
|
|
||||||
|
public VerifySecureLevelKeyRequest(byte[] publicKey, byte[] signature) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "verifySecureLevelKey";
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.secure.VerifySecureLevelKeyRequest;
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
import pro.gravit.utils.UniversalJsonAdapter;
|
import pro.gravit.utils.UniversalJsonAdapter;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -97,8 +98,6 @@ public void registerResults() {
|
||||||
results.register("error", ErrorRequestEvent.class);
|
results.register("error", ErrorRequestEvent.class);
|
||||||
results.register("update", UpdateRequestEvent.class);
|
results.register("update", UpdateRequestEvent.class);
|
||||||
results.register("restoreSession", RestoreSessionRequestEvent.class);
|
results.register("restoreSession", RestoreSessionRequestEvent.class);
|
||||||
results.register("getSecureToken", GetSecureTokenRequestEvent.class);
|
|
||||||
results.register("verifySecureToken", VerifySecureTokenRequestEvent.class);
|
|
||||||
results.register("log", LogEvent.class);
|
results.register("log", LogEvent.class);
|
||||||
results.register("cmdExec", ExecCommandRequestEvent.class);
|
results.register("cmdExec", ExecCommandRequestEvent.class);
|
||||||
results.register("getAvailabilityAuth", GetAvailabilityAuthRequestEvent.class);
|
results.register("getAvailabilityAuth", GetAvailabilityAuthRequestEvent.class);
|
||||||
|
@ -108,6 +107,8 @@ public void registerResults() {
|
||||||
results.register("notification", NotificationEvent.class);
|
results.register("notification", NotificationEvent.class);
|
||||||
results.register("signal", SignalEvent.class);
|
results.register("signal", SignalEvent.class);
|
||||||
results.register("exit", ExitRequestEvent.class);
|
results.register("exit", ExitRequestEvent.class);
|
||||||
|
results.register("getSecureLevelInfo", GetSecureLevelInfoRequestEvent.class);
|
||||||
|
results.register("verifySecureLevelKey", VerifySecureLevelKeyRequestEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitIfNotConnected() {
|
public void waitIfNotConnected() {
|
||||||
|
|
Loading…
Reference in a new issue