mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 16:41:46 +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) {
|
||||
providers.register("none", NoProtectHandler.class);
|
||||
providers.register("std", StdProtectHandler.class);
|
||||
providers.register("advanced", AdvancedProtectHandler.class);
|
||||
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 String username;
|
||||
public String verifyToken;
|
||||
public TrustLevel trustLevel;
|
||||
public transient LogHelper.OutputEnity logOutput;
|
||||
|
||||
public transient AuthProviderPair auth;
|
||||
|
@ -48,4 +49,8 @@ public enum Type {
|
|||
SERVER,
|
||||
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.ProfileByUUIDResponse;
|
||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
||||
import pro.gravit.launchserver.socket.response.secure.GetSecureTokenResponse;
|
||||
import pro.gravit.launchserver.socket.response.secure.VerifySecureTokenResponse;
|
||||
import pro.gravit.launchserver.socket.response.secure.GetSecureLevelInfoResponse;
|
||||
import pro.gravit.launchserver.socket.response.secure.VerifySecureLevelKeyResponse;
|
||||
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
||||
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
||||
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
||||
|
@ -123,12 +123,12 @@ public static void registerResponses() {
|
|||
providers.register("batchProfileByUsername", BatchProfileByUsername.class);
|
||||
providers.register("profileByUsername", ProfileByUsername.class);
|
||||
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
||||
providers.register("getSecureToken", GetSecureTokenResponse.class);
|
||||
providers.register("verifySecureToken", VerifySecureTokenResponse.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);
|
||||
}
|
||||
|
||||
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.request.WebSocketEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.secure.VerifySecureLevelKeyRequest;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
import pro.gravit.utils.UniversalJsonAdapter;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
|
@ -97,8 +98,6 @@ public void registerResults() {
|
|||
results.register("error", ErrorRequestEvent.class);
|
||||
results.register("update", UpdateRequestEvent.class);
|
||||
results.register("restoreSession", RestoreSessionRequestEvent.class);
|
||||
results.register("getSecureToken", GetSecureTokenRequestEvent.class);
|
||||
results.register("verifySecureToken", VerifySecureTokenRequestEvent.class);
|
||||
results.register("log", LogEvent.class);
|
||||
results.register("cmdExec", ExecCommandRequestEvent.class);
|
||||
results.register("getAvailabilityAuth", GetAvailabilityAuthRequestEvent.class);
|
||||
|
@ -108,6 +107,8 @@ public void registerResults() {
|
|||
results.register("notification", NotificationEvent.class);
|
||||
results.register("signal", SignalEvent.class);
|
||||
results.register("exit", ExitRequestEvent.class);
|
||||
results.register("getSecureLevelInfo", GetSecureLevelInfoRequestEvent.class);
|
||||
results.register("verifySecureLevelKey", VerifySecureLevelKeyRequestEvent.class);
|
||||
}
|
||||
|
||||
public void waitIfNotConnected() {
|
||||
|
|
Loading…
Reference in a new issue