Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,32 +1,56 @@
package pro.gravit.launcher.base.events.request;

import pro.gravit.launcher.core.LauncherNetworkAPI;
import pro.gravit.launcher.base.events.ExtendedTokenRequestEvent;
import pro.gravit.launcher.base.events.RequestEvent;
import pro.gravit.launcher.base.profiles.ClientProfile;

import java.util.UUID;


public class SetProfileRequestEvent extends RequestEvent {
public class SetProfileRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
public static final String CLIENT_PROFILE_EXTENDED_TOKEN_NAME = "clientProfile";
@SuppressWarnings("unused")
private static final UUID uuid = UUID.fromString("08c0de9e-4364-4152-9066-8354a3a48541");
@LauncherNetworkAPI
public final ClientProfile newProfile;
@LauncherNetworkAPI
public final String tag;
public final String profileExtendedToken;
public final long profileExtendedTokenExpire;

public SetProfileRequestEvent(ClientProfile newProfile) {
this.newProfile = newProfile;
this.tag = null;
this(newProfile, null, null, 0);
}

public SetProfileRequestEvent(ClientProfile newProfile, String tag) {
this(newProfile, tag, null, 0);
}

public SetProfileRequestEvent(ClientProfile newProfile, String tag, String profileExtendedToken, long profileExtendedTokenExpire) {
this.newProfile = newProfile;
this.tag = tag;
this.profileExtendedToken = profileExtendedToken;
this.profileExtendedTokenExpire = profileExtendedTokenExpire;
}

@Override
public String getType() {
return "setProfile";
}

@Override
public String getExtendedTokenName() {
return CLIENT_PROFILE_EXTENDED_TOKEN_NAME;
}

@Override
public String getExtendedToken() {
return profileExtendedToken;
}

@Override
public long getExtendedTokenExpire() {
return profileExtendedTokenExpire;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class OptionalFile implements ProfileFeatureAPI.OptionalMod {
public List<OptionalAction> actions;
@LauncherNetworkAPI
public boolean mark;
public transient boolean enabledByDefault;
@LauncherNetworkAPI
public boolean visible = true;
@LauncherNetworkAPI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ public class OptionalView {

public OptionalView(ClientProfile profile) {
this.all = profile.getOptional();
for (OptionalFile f : this.all) {
if (f.mark) enable(f, true, null);
}
}

public OptionalView(OptionalView view) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public ProfileSettingsImpl(ClientProfile profile, LauncherBackendImpl backend) {
this.flags.add(Flag.LINUX_WAYLAND_SUPPORT);
}
processTriggers(profile, this.view);
applyEnabledByDefault(this.view);
}

@Override
Expand Down Expand Up @@ -183,7 +184,7 @@ public ProfileSettingsImpl copy() {
cloned.profile = profile;
cloned.ram = new HashMap<>(ram);
cloned.flags = new HashSet<>(flags);
cloned.enabled = new HashSet<>(enabled);
cloned.enabled = enabled == null ? null : new HashSet<>(enabled);
if(view != null) {
cloned.view = new OptionalView(profile, view);
}
Expand All @@ -207,12 +208,16 @@ public void initAfterGson(ClientProfile profile, LauncherBackendImpl backend) {
this.profile = profile;
this.view = new OptionalView(profile);
processTriggers(profile, this.view);
for(var e : enabled) {
var opt = profile.getOptionalFile(e);
if(opt == null) {
continue;
if (enabled == null) {
applyEnabledByDefault(this.view);
} else {
for(var e : enabled) {
var opt = profile.getOptionalFile(e);
if (opt == null) {
continue;
}
enableOptional(opt, (var1, var2) -> {});
}
enableOptional(opt, (var1, var2) -> {});
}
if(this.saveJavaPath != null) {
backend.getAvailableJava().thenAccept((javas) -> {
Expand All @@ -237,11 +242,12 @@ public void initAfterGson(ClientProfile profile, LauncherBackendImpl backend) {
public void processTriggers(ClientProfile profile, OptionalView view) {
TriggerManagerContext context = new TriggerManagerContext(profile);
for (OptionalFile optional : view.all) {
optional.enabledByDefault = optional.mark;
if (optional.limited) {
if (!backend.hasPermission("launcher.runtime.optionals.%s.%s.show"
.formatted(profile.getUUID(),
optional.name.toLowerCase(Locale.ROOT)))) {
view.disable(optional, null);
optional.enabledByDefault = false;
optional.visible = false;
} else {
optional.visible = true;
Expand All @@ -260,10 +266,17 @@ public void processTriggers(ClientProfile profile, OptionalView view) {
}
}
if (isRequired) {
if (fail == 0) view.enable(optional, true, null);
else view.disable(optional, null);
optional.enabledByDefault = fail == 0;
} else {
if (success > 0) view.enable(optional, false, null);
if (success > 0) optional.enabledByDefault = true;
}
}
}

private void applyEnabledByDefault(OptionalView view) {
for (OptionalFile optional : view.all) {
if (optional.visible && optional.enabledByDefault) {
view.enable(optional, false, null);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.base.ClientPermissions;
import pro.gravit.launcher.base.events.request.AuthRequestEvent;
import pro.gravit.launcher.base.events.request.SetProfileRequestEvent;
import pro.gravit.launcher.base.profiles.ClientProfile;
import pro.gravit.launcher.base.profiles.PlayerProfile;
import pro.gravit.launcher.base.request.auth.AuthRequest;
Expand All @@ -20,6 +21,7 @@
import pro.gravit.launchserver.auth.core.interfaces.session.UserSessionSupportKeys;
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportProperties;
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
import pro.gravit.launchserver.auth.profiles.ProfilesProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
Expand All @@ -29,12 +31,15 @@

import javax.crypto.Cipher;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

public class AuthManager {
private transient final LaunchServer server;
private transient final Logger logger = LogManager.getLogger();
private transient final JwtParser checkServerTokenParser;
private transient final JwtParser clientProfileTokenParser;

public AuthManager(LaunchServer server) {
this.server = server;
Expand All @@ -43,6 +48,11 @@ public AuthManager(LaunchServer server) {
.require("tokenType", "checkServer")
.verifyWith(server.keyAgreementManager.ecdsaPublicKey)
.build();
this.clientProfileTokenParser = Jwts.parser()
.requireIssuer("LaunchServer")
.require("tokenType", SetProfileRequestEvent.CLIENT_PROFILE_EXTENDED_TOKEN_NAME)
.verifyWith(server.keyAgreementManager.ecdsaPublicKey)
.build();
}

public String newCheckServerToken(String serverName, String authId, boolean publicOnly) {
Expand All @@ -66,6 +76,34 @@ public CheckServerTokenInfo parseCheckServerToken(String token) {
}
}

public String newClientProfileToken(UUID profileUUID, String profileTag, String authId) {
var builder = Jwts.builder()
.issuer("LaunchServer")
.claim("tokenType", SetProfileRequestEvent.CLIENT_PROFILE_EXTENDED_TOKEN_NAME)
.claim("profileUUID", profileUUID.toString());
if (profileTag != null) {
builder = builder.claim("profileTag", profileTag);
}
if (authId != null) {
builder = builder.claim("authId", authId);
}
return builder.setExpiration(Date.from(LocalDateTime.now().plusSeconds(server.config.netty.security.launcherTokenExpire).toInstant(ZoneOffset.UTC)))
.signWith(server.keyAgreementManager.ecdsaPrivateKey)
.compact();
}

public ClientProfileTokenInfo parseClientProfileToken(String token) {
try {
var jwt = clientProfileTokenParser.parseClaimsJws(token).getBody();
return new ClientProfileTokenInfo(
UUID.fromString(jwt.get("profileUUID", String.class)),
jwt.get("profileTag", String.class),
jwt.get("authId", String.class));
} catch (Exception e) {
return null;
}
}

/**
* Create AuthContext
*
Expand Down Expand Up @@ -298,6 +336,9 @@ private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.Au
public record CheckServerTokenInfo(String serverName, String authId, boolean isPublic) {
}

public record ClientProfileTokenInfo(UUID profileUUID, String profileTag, String authId) {
}

public static class CheckServerVerifier implements RestoreResponse.ExtendedTokenProvider {
private final LaunchServer server;

Expand All @@ -319,11 +360,45 @@ public boolean accept(Client client, AuthProviderPair pair, String extendedToken
client.permissions.addPerm("launchserver.checkserver.extended");
client.permissions.addPerm("launchserver.profile.%s.show".formatted(info.serverName));
}
try {
UUID profileUUID = UUID.fromString(info.serverName);
ProfilesProvider.CompletedProfile profile = server.config.profilesProvider.get(profileUUID, null);
if(profile != null) {
client.profile = profile;
}
} catch (IllegalArgumentException ignored) {
// serverName may be a custom value, profile restore from this token is optional
}
client.setProperty("launchserver.serverName", info.serverName);
return true;
}
}

public static class ClientProfileTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
private final LaunchServer server;

public ClientProfileTokenVerifier(LaunchServer server) {
this.server = server;
}

@Override
public boolean accept(Client client, AuthProviderPair pair, String extendedToken) {
var info = server.authManager.parseClientProfileToken(extendedToken);
if (info == null) {
return false;
}
if(info.authId() != null && pair != null && !info.authId().equals(pair.name)) {
return false;
}
ProfilesProvider.CompletedProfile profile = server.config.profilesProvider.get(info.profileUUID(), info.profileTag());
if (profile == null) {
return false;
}
client.profile = profile;
return true;
}
}

public static class CheckServerReport {
public UUID uuid;
public User user;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pro.gravit.launcher.base.events.request.AuthRequestEvent;
import pro.gravit.launcher.base.events.request.LauncherRequestEvent;
import pro.gravit.launcher.base.events.request.RestoreRequestEvent;
import pro.gravit.launcher.base.events.request.SetProfileRequestEvent;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
Expand Down Expand Up @@ -34,6 +35,7 @@ public static void registerProviders(LaunchServer server) {
providers.put("publicKey", new AdvancedProtectHandler.PublicKeyTokenVerifier(server));
providers.put("hardware", new AdvancedProtectHandler.HardwareInfoTokenVerifier(server));
providers.put("checkServer", new AuthManager.CheckServerVerifier(server));
providers.put(SetProfileRequestEvent.CLIENT_PROFILE_EXTENDED_TOKEN_NAME, new AuthManager.ClientProfileTokenVerifier(server));
registeredProviders = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
return;
}
client.profile = profile;
sendResult(new SetProfileRequestEvent(profile.getProfile(), profile.getTag()));
sendResult(new SetProfileRequestEvent(profile.getProfile(), profile.getTag(),
server.authManager.newClientProfileToken(profile.getUuid(), profile.getTag(), client.auth_id),
server.config.netty.security.launcherTokenExpire * 1000));
}

@Override
Expand Down