Launcher/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java

119 lines
4.9 KiB
Java

package pro.gravit.launchserver.socket.response.update;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.netty.channel.ChannelHandlerContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.base.events.request.LauncherRequestEvent;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.SimpleResponse;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
import pro.gravit.utils.Version;
import pro.gravit.utils.helper.SecurityHelper;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
public class LauncherResponse extends SimpleResponse {
public Version version;
public String hash;
public byte[] digest;
public int launcher_type;
public String secureHash;
public String secureSalt;
@Override
public String getType() {
return "launcher";
}
@Override
public void execute(ChannelHandlerContext ctx, Client client) {
byte[] bytes;
if (hash != null)
bytes = Base64.getDecoder().decode(hash);
else
bytes = digest;
if (launcher_type == 1) // JAR
{
byte[] hash = server.launcherBinary.getDigest();
if (hash == null)
service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
client.checkSign = true;
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
} else {
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
}
} else if (launcher_type == 2) //EXE
{
byte[] hash = server.launcherEXEBinary.getDigest();
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
client.checkSign = true;
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
} else {
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
}
} else sendError("Request launcher type error");
}
public String createLauncherExtendedToken() {
return Jwts.builder()
.setIssuer("LaunchServer")
.claim("checkSign", true)
.setExpiration(Date.from(LocalDateTime.now().plusSeconds(server.config.netty.security.launcherTokenExpire).toInstant(ZoneOffset.UTC)))
.signWith(server.keyAgreementManager.ecdsaPrivateKey, SignatureAlgorithm.ES256)
.compact();
}
private boolean checkSecure(String hash, String salt) {
if (hash == null || salt == null) return false;
byte[] normal_hash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256,
server.runtime.clientCheckSecret.concat(".").concat(salt));
byte[] launcher_hash = Base64.getDecoder().decode(hash);
return Arrays.equals(normal_hash, launcher_hash);
}
public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
private final JwtParser parser;
private final Logger logger = LogManager.getLogger();
public LauncherTokenVerifier(LaunchServer server) {
parser = Jwts.parser()
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
.requireIssuer("LaunchServer")
.build();
}
@Override
public boolean accept(Client client, AuthProviderPair pair, String extendedToken) {
try {
var jwt = parser.parseClaimsJws(extendedToken);
client.checkSign = jwt.getBody().get("checkSign", Boolean.class);
client.type = AuthResponse.ConnectTypes.CLIENT;
return true;
} catch (Exception e) {
logger.error("JWT check failed", e);
return false;
}
}
}
@Override
public ThreadSafeStatus getThreadSafeStatus() {
return ThreadSafeStatus.READ_WRITE;
}
}