[ANY] Небольшой рефактор.

Обнаружил isClient и IS_CLIENT, ещё пару подобных пережитков...
This commit is contained in:
Zaxar163 2021-07-21 19:43:47 +03:00
parent dfa2b042e4
commit eb9871123b
No known key found for this signature in database
GPG key ID: BC54673329B5017D
34 changed files with 454 additions and 438 deletions

View file

@ -278,11 +278,11 @@ public void invoke(String... args) throws Exception {
public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception {
verifyArgs(args, 1); verifyArgs(args, 1);
AuthProviderPair pair = config.getAuthProviderPair(args[0]); AuthProviderPair pair = config.getAuthProviderPair(args[0]);
if(pair == null) { if (pair == null) {
logger.error("Pair not found"); logger.error("Pair not found");
return; return;
} }
if(pair.isUseCore()){ if (pair.isUseCore()) {
pair.core.close(); pair.core.close();
} else { } else {
pair.provider.close(); pair.provider.close();
@ -293,7 +293,8 @@ public void invoke(String... args) throws Exception {
pair.core = new RejectAuthCoreProvider(); pair.core = new RejectAuthCoreProvider();
pair.core.init(instance); pair.core.init(instance);
} }
};commands.put("resetauth", resetauth); };
commands.put("resetauth", resetauth);
return commands; return commands;
} }
@ -394,7 +395,7 @@ public void run() {
modulesManager.invokeEvent(new LaunchServerFullInitEvent(this)); modulesManager.invokeEvent(new LaunchServerFullInitEvent(this));
logger.info("LaunchServer started"); logger.info("LaunchServer started");
} catch (Throwable e) { } catch (Throwable e) {
logger.error("LaunchServer startup failed",e); logger.error("LaunchServer startup failed", e);
JVMHelper.RUNTIME.exit(-1); JVMHelper.RUNTIME.exit(-1);
} }
} }

View file

@ -46,6 +46,29 @@ public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social, Textur
this.textureProvider = textureProvider; this.textureProvider = textureProvider;
} }
public static Set<String> getFeatures(Class<?> clazz) {
Set<String> list = new HashSet<>();
getFeatures(clazz, list);
return list;
}
public static void getFeatures(Class<?> clazz, Set<String> list) {
Features features = clazz.getAnnotation(Features.class);
if (features != null) {
for (Feature feature : features.value()) {
list.add(feature.value());
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && superClass != Object.class) {
getFeatures(superClass, list);
}
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> i : interfaces) {
getFeatures(i, list);
}
}
public final <T> T isSupport(Class<T> clazz) { public final <T> T isSupport(Class<T> clazz) {
if (core == null) return null; if (core == null) return null;
T result = null; T result = null;
@ -118,29 +141,6 @@ public final void close() throws IOException {
} }
} }
public static Set<String> getFeatures(Class<?> clazz) {
Set<String> list = new HashSet<>();
getFeatures(clazz, list);
return list;
}
public static void getFeatures(Class<?> clazz, Set<String> list) {
Features features = clazz.getAnnotation(Features.class);
if (features != null) {
for (Feature feature : features.value()) {
list.add(feature.value());
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null && superClass != Object.class) {
getFeatures(superClass, list);
}
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> i : interfaces) {
getFeatures(i, list);
}
}
public final boolean isUseCore() { public final boolean isUseCore() {
return core != null; return core != null;
} }

View file

@ -24,6 +24,21 @@ public static void registerProviders() {
} }
} }
public abstract void init(LaunchServer server, AuthCoreProvider provider);
public abstract List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client);
public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException;
@SuppressWarnings("unchecked")
public <T> T isSupport(Class<T> clazz) {
if (clazz.isAssignableFrom(getClass())) return (T) this;
return null;
}
@Override
public abstract void close() throws IOException;
public static class SocialResult { public static class SocialResult {
public String login; public String login;
public AuthRequest.AuthPasswordInterface password; public AuthRequest.AuthPasswordInterface password;
@ -43,19 +58,4 @@ public static SocialResult ofUser(User user) {
return new SocialResult(null, null, user); return new SocialResult(null, null, user);
} }
} }
public abstract void init(LaunchServer server, AuthCoreProvider provider);
public abstract List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client);
public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException;
@SuppressWarnings("unchecked")
public <T> T isSupport(Class<T> clazz) {
if (clazz.isAssignableFrom(getClass())) return (T) this;
return null;
}
@Override
public abstract void close() throws IOException;
} }

View file

@ -41,6 +41,140 @@ public class JsonCoreProvider extends AuthCoreProvider {
public PasswordVerifier passwordVerifier; public PasswordVerifier passwordVerifier;
private transient HttpClient client; private transient HttpClient client;
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
HttpRequest.BodyPublisher publisher;
if (request != null) {
publisher = HttpRequest.BodyPublishers.ofString(request.toString());
} else {
publisher = HttpRequest.BodyPublishers.noBody();
}
try {
HttpRequest.Builder request1 = HttpRequest.newBuilder()
.method("POST", publisher)
.uri(new URI(url))
.header("Content-Type", "application/json; charset=UTF-8")
.header("Accept", "application/json")
.timeout(Duration.ofMillis(10000));
if (bearerToken != null) {
request1.header("Authentication", "Bearer ".concat(bearerToken));
}
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
int statusCode = response.statusCode();
if (200 > statusCode || statusCode > 300) {
if (statusCode >= 500) {
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
} else if (statusCode >= 300 && statusCode <= 400) {
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
} else if (statusCode == 403 || statusCode == 401) {
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
}
return null;
}
try (Reader reader = new InputStreamReader(response.body())) {
return Launcher.gsonManager.gson.fromJson(reader, clazz);
}
} catch (Exception e) {
return null;
}
}
@Override
public User getUserByUsername(String username) {
return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class);
}
@Override
public User getUserByLogin(String login) {
if (getUserByLoginUrl != null) {
return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class);
}
return super.getUserByLogin(login);
}
@Override
public User getUserByUUID(UUID uuid) {
return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class);
}
@Override
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
if (getUserSessionByOAuthAccessTokenUrl == null) {
return null;
}
JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class);
if (response == null) return null;
if (!response.expired) throw new OAuthAccessTokenExpired();
return response.session;
}
@Override
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
if (getAuthDetailsUrl != null) {
JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class);
if (response == null) return super.getDetails(client);
return response.details;
}
return super.getDetails(client);
}
@Override
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class);
return response == null ? null : response.toAuthReport();
}
@Override
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
}
@Override
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
JsonUser jsonUser = (JsonUser) user;
if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) {
if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) {
return PasswordVerifyReport.OK;
} else {
return PasswordVerifyReport.FAILED;
}
}
if (user == null) {
return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class);
}
return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class);
}
@Override
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class);
if (response == null) return null;
if (response.error != null) throw new AuthException(response.error);
JsonUser user1 = (JsonUser) user;
user1.accessToken = response.minecraftAccessToken;
return response.toAuthReport();
}
@Override
public void init(LaunchServer server) {
client = HttpClient.newBuilder().build();
}
@Override
protected boolean updateServerID(User user, String serverID) throws IOException {
JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class);
if (successResponse == null) return false;
return successResponse.success;
}
@Override
public void close() throws IOException {
}
public <T, R> R jsonRequest(T request, String url, Class<R> clazz) {
return jsonRequest(request, url, bearerToken, clazz, client);
}
public static class JsonGetUserByUsername { public static class JsonGetUserByUsername {
public String username; public String username;
@ -142,99 +276,6 @@ public static class JsonGetDetailsResponse {
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details; public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
} }
@Override
public User getUserByUsername(String username) {
return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class);
}
@Override
public User getUserByLogin(String login) {
if (getUserByLoginUrl != null) {
return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class);
}
return super.getUserByLogin(login);
}
@Override
public User getUserByUUID(UUID uuid) {
return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class);
}
@Override
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
if (getUserSessionByOAuthAccessTokenUrl == null) {
return null;
}
JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class);
if (response == null) return null;
if (!response.expired) throw new OAuthAccessTokenExpired();
return response.session;
}
@Override
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
if (getAuthDetailsUrl != null) {
JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class);
if (response == null) return super.getDetails(client);
return response.details;
}
return super.getDetails(client);
}
@Override
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class);
return response == null ? null : response.toAuthReport();
}
@Override
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
}
@Override
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
JsonUser jsonUser = (JsonUser) user;
if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) {
if (passwordVerifier.check(((AuthPlainPassword) password).password, jsonUser.password)) {
return PasswordVerifyReport.OK;
} else {
return PasswordVerifyReport.FAILED;
}
}
if (user == null) {
return jsonRequest(new JsonPasswordVerify(null, null), verifyPasswordUrl, PasswordVerifyReport.class);
}
return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID()), verifyPasswordUrl, PasswordVerifyReport.class);
}
@Override
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class);
if (response == null) return null;
if (response.error != null) throw new AuthException(response.error);
JsonUser user1 = (JsonUser) user;
user1.accessToken = response.minecraftAccessToken;
return response.toAuthReport();
}
@Override
public void init(LaunchServer server) {
client = HttpClient.newBuilder().build();
}
@Override
protected boolean updateServerID(User user, String serverID) throws IOException {
JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class);
if (successResponse == null) return false;
return successResponse.success;
}
@Override
public void close() throws IOException {
}
public static class JsonUser implements User { public static class JsonUser implements User {
private String username; private String username;
private UUID uuid; private UUID uuid;
@ -319,45 +360,4 @@ public String toString() {
'}'; '}';
} }
} }
public <T, R> R jsonRequest(T request, String url, Class<R> clazz) {
return jsonRequest(request, url, bearerToken, clazz, client);
}
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
HttpRequest.BodyPublisher publisher;
if (request != null) {
publisher = HttpRequest.BodyPublishers.ofString(request.toString());
} else {
publisher = HttpRequest.BodyPublishers.noBody();
}
try {
HttpRequest.Builder request1 = HttpRequest.newBuilder()
.method("POST", publisher)
.uri(new URI(url))
.header("Content-Type", "application/json; charset=UTF-8")
.header("Accept", "application/json")
.timeout(Duration.ofMillis(10000));
if (bearerToken != null) {
request1.header("Authentication", "Bearer ".concat(bearerToken));
}
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
int statusCode = response.statusCode();
if (200 > statusCode || statusCode > 300) {
if (statusCode >= 500) {
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
} else if (statusCode >= 300 && statusCode <= 400) {
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
} else if (statusCode == 403 || statusCode == 401) {
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
}
return null;
}
try (Reader reader = new InputStreamReader(response.body())) {
return Launcher.gsonManager.gson.fromJson(reader, clazz);
}
} catch (Exception e) {
return null;
}
}
} }

View file

@ -41,6 +41,13 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
public String tableHWID = "hwids"; public String tableHWID = "hwids";
public String tableHWIDLog = "hwidLog"; public String tableHWIDLog = "hwidLog";
public PasswordVerifier passwordVerifier;
public double criticalCompareLevel = 1.0;
public String customQueryByUUIDSQL;
public String customQueryByUsernameSQL;
public String customQueryByLoginSQL;
public String customUpdateAuthSQL;
public String customUpdateServerIdSQL;
private transient String sqlFindHardwareByPublicKey; private transient String sqlFindHardwareByPublicKey;
private transient String sqlFindHardwareByData; private transient String sqlFindHardwareByData;
private transient String sqlFindHardwareById; private transient String sqlFindHardwareById;
@ -50,10 +57,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
private transient String sqlUpdateHardwareBanned; private transient String sqlUpdateHardwareBanned;
private transient String sqlUpdateUsers; private transient String sqlUpdateUsers;
private transient String sqlUsersByHwidId; private transient String sqlUsersByHwidId;
public PasswordVerifier passwordVerifier;
public double criticalCompareLevel = 1.0;
// Prepared SQL queries // Prepared SQL queries
private transient String queryByUUIDSQL; private transient String queryByUUIDSQL;
private transient String queryByUsernameSQL; private transient String queryByUsernameSQL;
@ -61,12 +64,6 @@ public class MySQLCoreProvider extends AuthCoreProvider implements AuthSupportHa
private transient String updateAuthSQL; private transient String updateAuthSQL;
private transient String updateServerIDSQL; private transient String updateServerIDSQL;
public String customQueryByUUIDSQL;
public String customQueryByUsernameSQL;
public String customQueryByLoginSQL;
public String customUpdateAuthSQL;
public String customUpdateServerIdSQL;
@Override @Override
public User getUserByUsername(String username) { public User getUserByUsername(String username) {
try { try {
@ -154,16 +151,20 @@ public void init(LaunchServer server) {
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1", updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=? LIMIT 1",
table, serverIDColumn, uuidColumn); table, serverIDColumn, uuidColumn);
String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey"; String hardwareInfoCols = "id, hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, graphicCard, banned, publicKey";
if(sqlFindHardwareByPublicKey == null) sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID); if (sqlFindHardwareByPublicKey == null)
if(sqlFindHardwareById == null) sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID); sqlFindHardwareByPublicKey = String.format("SELECT %s FROM %s WHERE `publicKey` = ?", hardwareInfoCols, tableHWID);
if(sqlUsersByHwidId == null) sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn); if (sqlFindHardwareById == null)
sqlFindHardwareById = String.format("SELECT %s FROM %s WHERE `id` = ?", hardwareInfoCols, tableHWID);
if (sqlUsersByHwidId == null)
sqlUsersByHwidId = String.format("SELECT %s FROM %s WHERE `%s` = ?", userInfoCols, table, hardwareIdColumn);
if (sqlFindHardwareByData == null) if (sqlFindHardwareByData == null)
sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID); sqlFindHardwareByData = String.format("SELECT %s FROM %s", hardwareInfoCols, tableHWID);
if (sqlCreateHardware == null) if (sqlCreateHardware == null)
sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID); sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `graphicCard`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID);
if (sqlCreateHWIDLog == null) if (sqlCreateHWIDLog == null)
sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog); sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog);
if(sqlUpdateHardwarePublicKey == null) sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID); if (sqlUpdateHardwarePublicKey == null)
sqlUpdateHardwarePublicKey = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID);
sqlUpdateHardwareBanned = String.format("UPDATE %s SET `banned` = ? WHERE `id` = ?", tableHWID); sqlUpdateHardwareBanned = String.format("UPDATE %s SET `banned` = ? WHERE `id` = ?", tableHWID);
sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn); sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", table, hardwareIdColumn, uuidColumn);
} }
@ -405,6 +406,50 @@ public void unbanHardware(UserHardware hardware) {
} }
} }
public static class MySQLUserHardware implements UserHardware {
private final HardwareReportRequest.HardwareInfo hardwareInfo;
private final long id;
private byte[] publicKey;
private boolean banned;
public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) {
this.hardwareInfo = hardwareInfo;
this.publicKey = publicKey;
this.id = id;
this.banned = banned;
}
@Override
public HardwareReportRequest.HardwareInfo getHardwareInfo() {
return hardwareInfo;
}
@Override
public byte[] getPublicKey() {
return publicKey;
}
@Override
public String getId() {
return String.valueOf(id);
}
@Override
public boolean isBanned() {
return banned;
}
@Override
public String toString() {
return "MySQLUserHardware{" +
"hardwareInfo=" + hardwareInfo +
", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) +
", id=" + id +
", banned=" + banned +
'}';
}
}
public class MySQLUser implements User, UserSupportHardware { public class MySQLUser implements User, UserSupportHardware {
protected UUID uuid; protected UUID uuid;
protected String username; protected String username;
@ -468,48 +513,4 @@ public String toString() {
'}'; '}';
} }
} }
public static class MySQLUserHardware implements UserHardware {
private final HardwareReportRequest.HardwareInfo hardwareInfo;
private byte[] publicKey;
private final long id;
private boolean banned;
public MySQLUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) {
this.hardwareInfo = hardwareInfo;
this.publicKey = publicKey;
this.id = id;
this.banned = banned;
}
@Override
public HardwareReportRequest.HardwareInfo getHardwareInfo() {
return hardwareInfo;
}
@Override
public byte[] getPublicKey() {
return publicKey;
}
@Override
public String getId() {
return String.valueOf(id);
}
@Override
public boolean isBanned() {
return banned;
}
@Override
public String toString() {
return "MySQLUserHardware{" +
"hardwareInfo=" + hardwareInfo +
", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) +
", id=" + id +
", banned=" + banned +
'}';
}
}
} }

View file

@ -3,6 +3,8 @@
import java.time.LocalDateTime; import java.time.LocalDateTime;
public interface UserSupportBanInfo { public interface UserSupportBanInfo {
UserBanInfo getBanInfo();
interface UserBanInfo { interface UserBanInfo {
String getId(); String getId();
@ -22,6 +24,4 @@ default LocalDateTime getEndDate() {
return null; return null;
} }
} }
UserBanInfo getBanInfo();
} }

View file

@ -2,9 +2,9 @@
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.SecurityHelper; import pro.gravit.utils.helper.SecurityHelper;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
@ -15,7 +15,7 @@ public class DigestPasswordVerifier extends PasswordVerifier {
private byte[] digest(String text) throws NoSuchAlgorithmException { private byte[] digest(String text) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance(algo); MessageDigest digest = MessageDigest.getInstance(algo);
return digest.digest(text.getBytes(StandardCharsets.UTF_8)); return digest.digest(IOHelper.encode(text));
} }
@Override @Override

View file

@ -2,9 +2,9 @@
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.SecurityHelper; import pro.gravit.utils.helper.SecurityHelper;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
@ -16,8 +16,8 @@ public class DoubleDigestPasswordVerifier extends PasswordVerifier {
private byte[] digest(String text) throws NoSuchAlgorithmException { private byte[] digest(String text) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance(algo); MessageDigest digest = MessageDigest.getInstance(algo);
byte[] firstDigest = digest.digest(text.getBytes(StandardCharsets.UTF_8)); byte[] firstDigest = digest.digest(IOHelper.encode(text));
return toHexMode ? digest.digest(SecurityHelper.toHex(firstDigest).getBytes(StandardCharsets.UTF_8)) : digest.digest(firstDigest); return toHexMode ? digest.digest(IOHelper.encode(SecurityHelper.toHex(firstDigest))) : digest.digest(firstDigest);
} }
@Override @Override

View file

@ -5,9 +5,18 @@
import java.net.http.HttpClient; import java.net.http.HttpClient;
public class JsonPasswordVerifier extends PasswordVerifier { public class JsonPasswordVerifier extends PasswordVerifier {
private transient final HttpClient client = HttpClient.newBuilder().build();
public String url; public String url;
public String bearerToken; public String bearerToken;
private transient final HttpClient client = HttpClient.newBuilder().build();
@Override
public boolean check(String encryptedPassword, String password) {
JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
if (response != null) {
return response.success;
}
return false;
}
public static class JsonPasswordRequest { public static class JsonPasswordRequest {
public String encryptedPassword; public String encryptedPassword;
@ -22,13 +31,4 @@ public JsonPasswordRequest(String encryptedPassword, String password) {
public static class JsonPasswordResponse { public static class JsonPasswordResponse {
public boolean success; public boolean success;
} }
@Override
public boolean check(String encryptedPassword, String password) {
JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
if (response != null) {
return response.success;
}
return false;
}
} }

View file

@ -14,6 +14,7 @@
import javax.crypto.NoSuchPaddingException; import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -37,7 +38,6 @@
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import static pro.gravit.utils.helper.IOHelper.UNICODE_CHARSET;
import static pro.gravit.utils.helper.IOHelper.newZipEntry; import static pro.gravit.utils.helper.IOHelper.newZipEntry;
public class BuildContext { public class BuildContext {
@ -72,8 +72,14 @@ public void pushFile(String filename, StreamObject object) throws IOException {
} }
public void pushFile(String filename, Object object, Type type) throws IOException { public void pushFile(String filename, Object object, Type type) throws IOException {
String bytes = Launcher.gsonManager.gson.toJson(object, type); ZipEntry zip = IOHelper.newZipEntry(filename);
pushBytes(filename, bytes.getBytes(UNICODE_CHARSET)); output.putNextEntry(zip);
try (BufferedWriter w = IOHelper.newWriter(IOHelper.nonClosing(output))) {
Launcher.gsonManager.gson.toJson(object, type);
}
output.closeEntry();
fileList.add(filename);
pushBytes(filename, IOHelper.encode(Launcher.gsonManager.gson.toJson(object, type)));
} }
public void pushDir(Path dir, String targetDir, Map<String, byte[]> hashMap, boolean hidden) throws IOException { public void pushDir(Path dir, String targetDir, Map<String, byte[]> hashMap, boolean hidden) throws IOException {
@ -211,7 +217,7 @@ private EncryptedRuntimeDirVisitor(ZipOutputStream output, String aesKey, Map<St
byte[] key = SecurityHelper.fromHex(aesKey); byte[] key = SecurityHelper.fromHex(aesKey);
byte[] compatKey = SecurityHelper.getAESKey(key); byte[] compatKey = SecurityHelper.getAESKey(key);
sKeySpec = new SecretKeySpec(compatKey, "AES/CBC/PKCS5Padding"); sKeySpec = new SecretKeySpec(compatKey, "AES/CBC/PKCS5Padding");
iKeySpec = new IvParameterSpec("8u3d90ikr7o67lsq".getBytes()); iKeySpec = new IvParameterSpec(IOHelper.encode("8u3d90ikr7o67lsq"));
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -35,7 +35,8 @@ public void invoke(String... args) throws Exception {
if (args.length > 2) pair = server.config.getAuthProviderPair(args[2]); if (args.length > 2) pair = server.config.getAuthProviderPair(args[2]);
else pair = server.config.getAuthProviderPair(); else pair = server.config.getAuthProviderPair();
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); if (pair.isUseCore())
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
String login = args[0]; String login = args[0];
String password = args[1]; String password = args[1];

View file

@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException {
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]); if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
else pair = server.config.getAuthProviderPair(); else pair = server.config.getAuthProviderPair();
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); if (pair.isUseCore())
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
UUID uuid = parseUUID(args[0]); UUID uuid = parseUUID(args[0]);
// Get UUID by username // Get UUID by username

View file

@ -34,7 +34,8 @@ public void invoke(String... args) throws CommandException, IOException {
if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]); if (args.length > 1) pair = server.config.getAuthProviderPair(args[1]);
else pair = server.config.getAuthProviderPair(); else pair = server.config.getAuthProviderPair();
if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1])); if (pair == null) throw new IllegalStateException(String.format("Auth %s not found", args[1]));
if(pair.isUseCore()) throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name)); if (pair.isUseCore())
throw new UnsupportedOperationException(String.format("Please use `config auth.%s.core COMMAND ARGS`", pair.name));
String username = parseUsername(args[0]); String username = parseUsername(args[0]);
// Get UUID by username // Get UUID by username

View file

@ -78,7 +78,7 @@ public void invoke(String... args) {
} else { } else {
printCheckResult(String.format("auth.%s.handler", name), "", true); printCheckResult(String.format("auth.%s.handler", name), "", true);
} }
if(!pair.isUseCore()) { if (!pair.isUseCore()) {
printCheckResult(String.format("auth.%s", name), "AuthProvider/AuthHandler may be removed in future release", null); printCheckResult(String.format("auth.%s", name), "AuthProvider/AuthHandler may be removed in future release", null);
} }
}); });

View file

@ -16,11 +16,11 @@
import java.util.Map; import java.util.Map;
public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable { public class WhitelistComponent extends Component implements AutoCloseable, Reconfigurable {
private transient LaunchServer server;
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
public String message = "auth.message.techwork"; public String message = "auth.message.techwork";
public boolean enabled = true; public boolean enabled = true;
public List<String> whitelist = new ArrayList<>(); public List<String> whitelist = new ArrayList<>();
private transient LaunchServer server;
@Override @Override
public void init(LaunchServer launchServer) { public void init(LaunchServer launchServer) {

View file

@ -182,6 +182,14 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
return options.toArray(new MakeProfileOption[0]); return options.toArray(new MakeProfileOption[0]);
} }
private static Path findFirstDir(Path path) throws IOException {
return Files.list(path).findFirst().orElse(null);
}
private static Path findFirstMavenFile(Path path) throws IOException {
return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow();
}
public interface MakeProfileOption { public interface MakeProfileOption {
} }
@ -192,11 +200,6 @@ public static class MakeProfileOptionForge implements MakeProfileOption {
public String minecraftVersion; public String minecraftVersion;
public String mcpVersion; public String mcpVersion;
public List<String> makeClientArgs() {
if (launchTarget == null) return List.of();
return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion);
}
public MakeProfileOptionForge() { public MakeProfileOptionForge() {
} }
@ -230,14 +233,11 @@ public MakeProfileOptionForge(Path clientDir) throws IOException {
String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-"); String[] minecraftFullVersion = minecraftPath.getFileName().toString().split("-");
mcpVersion = minecraftFullVersion[1]; mcpVersion = minecraftFullVersion[1];
} }
}
private static Path findFirstDir(Path path) throws IOException { public List<String> makeClientArgs() {
return Files.list(path).findFirst().orElse(null); if (launchTarget == null) return List.of();
return List.of("--launchTarget", launchTarget, "--fml.forgeVersion", forgeVersion, "--fml.mcVersion", minecraftVersion, "--fml.forgeGroup", forgeGroup, "--fml.mcpVersion", mcpVersion);
} }
private static Path findFirstMavenFile(Path path) throws IOException {
return Files.list(Files.list(path).findFirst().orElseThrow()).filter(e -> e.getFileName().toString().endsWith(".jar")).findFirst().orElseThrow();
} }
public static class MakeProfileOptionLaunchWrapper implements MakeProfileOption { public static class MakeProfileOptionLaunchWrapper implements MakeProfileOption {
@ -248,11 +248,6 @@ public static class MakeProfileOptionFabric implements MakeProfileOption {
public String jimfsPath; public String jimfsPath;
public String guavaPath; public String guavaPath;
public List<String> getAltClassPath() {
if (jimfsPath == null || guavaPath == null) return List.of();
return List.of(jimfsPath, guavaPath);
}
public MakeProfileOptionFabric() { public MakeProfileOptionFabric() {
} }
@ -267,6 +262,11 @@ public MakeProfileOptionFabric(Path clientDir) throws IOException {
guavaPath = clientDir.relativize(findFirstMavenFile(clientDir.resolve("libraries/com/google/guava/guava/"))).toString(); guavaPath = clientDir.relativize(findFirstMavenFile(clientDir.resolve("libraries/com/google/guava/guava/"))).toString();
} }
} }
public List<String> getAltClassPath() {
if (jimfsPath == null || guavaPath == null) return List.of();
return List.of(jimfsPath, guavaPath);
}
} }
public static class MakeProfileOptionLiteLoader implements MakeProfileOption { public static class MakeProfileOptionLiteLoader implements MakeProfileOption {

View file

@ -210,26 +210,6 @@ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, Auth
} }
} }
public static class CheckServerReport {
public UUID uuid;
public User user;
public PlayerProfile playerProfile;
public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) {
this.uuid = uuid;
this.user = user;
this.playerProfile = playerProfile;
}
public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) {
return new CheckServerReport(user.getUUID(), user, playerProfile);
}
public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) {
return new CheckServerReport(uuid, null, playerProfile);
}
}
public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException { public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException {
if (client.auth == null) return null; if (client.auth == null) return null;
if (client.auth.isUseCore()) { if (client.auth.isUseCore()) {
@ -397,6 +377,26 @@ private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.Au
return password; return password;
} }
public static class CheckServerReport {
public UUID uuid;
public User user;
public PlayerProfile playerProfile;
public CheckServerReport(UUID uuid, User user, PlayerProfile playerProfile) {
this.uuid = uuid;
this.user = user;
this.playerProfile = playerProfile;
}
public static CheckServerReport ofUser(User user, PlayerProfile playerProfile) {
return new CheckServerReport(user.getUUID(), user, playerProfile);
}
public static CheckServerReport ofUUID(UUID uuid, PlayerProfile playerProfile) {
return new CheckServerReport(uuid, null, playerProfile);
}
}
public static class AuthReport { public static class AuthReport {
public final String minecraftAccessToken; public final String minecraftAccessToken;
public final String oauthAccessToken; public final String oauthAccessToken;

View file

@ -6,8 +6,8 @@
import pro.gravit.launchserver.auth.RequiredDAO; import pro.gravit.launchserver.auth.RequiredDAO;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.utils.HookSet; import pro.gravit.utils.HookSet;
import pro.gravit.utils.helper.IOHelper;
import java.nio.charset.StandardCharsets;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -46,11 +46,11 @@ public void clear() {
} }
private byte[] compressClient(Client client) { private byte[] compressClient(Client client) {
return Launcher.gsonManager.gson.toJson(client).getBytes(StandardCharsets.UTF_8); //Compress using later return IOHelper.encode(Launcher.gsonManager.gson.toJson(client)); //Compress using later
} }
private Client decompressClient(byte[] client) { private Client decompressClient(byte[] client) {
return Launcher.gsonManager.gson.fromJson(new String(client, StandardCharsets.UTF_8), Client.class); //Compress using later return Launcher.gsonManager.gson.fromJson(IOHelper.decode(client), Client.class); //Compress using later
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")

View file

@ -19,8 +19,8 @@
public class UpdatesManager { public class UpdatesManager {
private final LaunchServer server; private final LaunchServer server;
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
private volatile Map<String, HashedDir> updatesDirMap;
private final Path cacheFile; private final Path cacheFile;
private volatile Map<String, HashedDir> updatesDirMap;
public UpdatesManager(LaunchServer server) { public UpdatesManager(LaunchServer server) {
this.server = server; this.server = server;

View file

@ -9,6 +9,7 @@
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launchserver.socket.NettyConnectContext; import pro.gravit.launchserver.socket.NettyConnectContext;
import pro.gravit.utils.helper.IOHelper;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -21,6 +22,12 @@
public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> { public class NettyWebAPIHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
private static final TreeSet<SeverletPathPair> severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length())); private static final TreeSet<SeverletPathPair> severletList = new TreeSet<>(Comparator.comparingInt((e) -> -e.key.length()));
private static final DefaultFullHttpResponse ERROR_500 = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer(IOHelper.encode("Internal Server Error 500")));
static {
ERROR_500.retain();
}
private final NettyConnectContext context; private final NettyConnectContext context;
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
@ -54,7 +61,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) thro
pair.callback.handle(ctx, msg, context); pair.callback.handle(ctx, msg, context);
} catch (Throwable e) { } catch (Throwable e) {
logger.error("WebAPI Error", e); logger.error("WebAPI Error", e);
ctx.writeAndFlush(new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR, Unpooled.wrappedBuffer("Internal Server Error 500".getBytes())), ctx.voidPromise()); ctx.writeAndFlush(ERROR_500, ctx.voidPromise());
} }
isNext = false; isNext = false;
break; break;
@ -92,11 +99,11 @@ default Map<String, String> getParamsFromUri(String uri) {
} }
default FullHttpResponse simpleResponse(HttpResponseStatus status, String body) { default FullHttpResponse simpleResponse(HttpResponseStatus status, String body) {
return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(body.getBytes()) : Unpooled.buffer()); return new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(body)) : Unpooled.buffer());
} }
default FullHttpResponse simpleJsonResponse(HttpResponseStatus status, Object body) { default FullHttpResponse simpleJsonResponse(HttpResponseStatus status, Object body) {
DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(Launcher.gsonManager.gson.toJson(body).getBytes()) : Unpooled.buffer()); DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, body != null ? Unpooled.wrappedBuffer(IOHelper.encode(Launcher.gsonManager.gson.toJson(body))) : Unpooled.buffer());
httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON); httpResponse.headers().add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
return httpResponse; return httpResponse;
} }

View file

@ -17,16 +17,14 @@ public <T extends WebSocketEvent> boolean eventHandle(T event) {
SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event; SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event;
if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) { if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) {
LauncherEngine.exitLauncher(80); LauncherEngine.exitLauncher(80);
} } else if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
else if(event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
try { try {
Request.restore(); Request.restore();
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
} }
} }
} } else if (event instanceof ExtendedTokenRequestEvent) {
else if (event instanceof ExtendedTokenRequestEvent) {
ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event; ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event;
String token = event1.getExtendedToken(); String token = event1.getExtendedToken();
if (token != null) { if (token != null) {

View file

@ -1,19 +0,0 @@
package pro.gravit.launcher;
import javafx.application.Application;
import java.util.concurrent.atomic.AtomicReference;
@Deprecated
public abstract class JSApplication extends Application {
private static final AtomicReference<JSApplication> INSTANCE = new AtomicReference<>();
public JSApplication() {
INSTANCE.set(this);
}
public static JSApplication getInstance() {
return INSTANCE.get();
}
}

View file

@ -38,7 +38,6 @@
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class LauncherEngine { public class LauncherEngine {
public static final AtomicBoolean IS_CLIENT = new AtomicBoolean(false);
public static ClientLauncherProcess.ClientParams clientParams; public static ClientLauncherProcess.ClientParams clientParams;
public static LauncherGuardInterface guard; public static LauncherGuardInterface guard;
public static ClientModuleManager modulesManager; public static ClientModuleManager modulesManager;
@ -133,14 +132,6 @@ public static void verifyNoAgent() {
throw new SecurityException("JavaAgent found"); throw new SecurityException("JavaAgent found");
} }
public ECPublicKey getClientPublicKey() {
return publicKey;
}
public byte[] sign(byte[] bytes) {
return SecurityHelper.sign(bytes, privateKey);
}
public static LauncherGuardInterface tryGetStdGuard() { public static LauncherGuardInterface tryGetStdGuard() {
switch (Launcher.getConfig().guardType) { switch (Launcher.getConfig().guardType) {
case "no": case "no":
@ -159,6 +150,14 @@ public static LauncherEngine newInstance(boolean clientInstance) {
return new LauncherEngine(clientInstance); return new LauncherEngine(clientInstance);
} }
public ECPublicKey getClientPublicKey() {
return publicKey;
}
public byte[] sign(byte[] bytes) {
return SecurityHelper.sign(bytes, privateKey);
}
public void readKeys() throws IOException, InvalidKeySpecException { public void readKeys() throws IOException, InvalidKeySpecException {
if (privateKey != null || publicKey != null) return; if (privateKey != null || publicKey != null) return;
Path dir = DirBridge.dir; Path dir = DirBridge.dir;

View file

@ -12,20 +12,6 @@ private DialogService() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public interface DialogServiceImplementation {
void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback);
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback);
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback);
void showTextDialog(String header, Consumer<String> onApplyCallback, Runnable onCloseCallback);
}
public interface DialogServiceNotificationImplementation {
void createNotification(NotificationEvent.NotificationType type, String head, String message);
}
public static void setDialogImpl(DialogServiceImplementation impl) { public static void setDialogImpl(DialogServiceImplementation impl) {
DialogService.dialogImpl = impl; DialogService.dialogImpl = impl;
} }
@ -74,4 +60,18 @@ public static void showTextDialog(String header, Consumer<String> onApplyCallbac
checkIfAvailable(); checkIfAvailable();
dialogImpl.showTextDialog(header, onApplyCallback, onCloseCallback); dialogImpl.showTextDialog(header, onApplyCallback, onCloseCallback);
} }
public interface DialogServiceImplementation {
void showDialog(String header, String text, Runnable onApplyCallback, Runnable onCloseCallback);
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback);
void showApplyDialog(String header, String text, Runnable onApplyCallback, Runnable onDenyCallback, Runnable onCloseCallback);
void showTextDialog(String header, Consumer<String> onApplyCallback, Runnable onCloseCallback);
}
public interface DialogServiceNotificationImplementation {
void createNotification(NotificationEvent.NotificationType type, String head, String message);
}
} }

View file

@ -49,7 +49,7 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
socket.connect(address); socket.connect(address);
try (HInput input = new HInput(socket.getInputStream())) { try (HInput input = new HInput(socket.getInputStream())) {
byte[] serialized = input.readByteArray(0); byte[] serialized = input.readByteArray(0);
ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(new String(serialized, IOHelper.UNICODE_CHARSET), ClientLauncherProcess.ClientParams.class); ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(IOHelper.decode(serialized), ClientLauncherProcess.ClientParams.class);
params.clientHDir = new HashedDir(input); params.clientHDir = new HashedDir(input);
params.assetHDir = new HashedDir(input); params.assetHDir = new HashedDir(input);
boolean isNeedReadJavaDir = input.readBoolean(); boolean isNeedReadJavaDir = input.readBoolean();
@ -61,7 +61,6 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
} }
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
LauncherEngine.IS_CLIENT.set(true);
LauncherEngine engine = LauncherEngine.clientInstance(); LauncherEngine engine = LauncherEngine.clientInstance();
JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true); JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true);
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();

View file

@ -221,7 +221,7 @@ public void runWriteParams(SocketAddress address) throws IOException {
} }
Socket socket = serverSocket.accept(); Socket socket = serverSocket.accept();
try (HOutput output = new HOutput(socket.getOutputStream())) { try (HOutput output = new HOutput(socket.getOutputStream())) {
byte[] serializedMainParams = Launcher.gsonManager.gson.toJson(params).getBytes(IOHelper.UNICODE_CHARSET); byte[] serializedMainParams = IOHelper.encode(Launcher.gsonManager.gson.toJson(params));
output.writeByteArray(serializedMainParams, 0); output.writeByteArray(serializedMainParams, 0);
params.clientHDir.write(output); params.clientHDir.write(output);
params.assetHDir.write(output); params.assetHDir.write(output);

View file

@ -14,6 +14,7 @@ public abstract class LauncherModule {
protected InitStatus initStatus = InitStatus.CREATED; protected InitStatus initStatus = InitStatus.CREATED;
private LauncherModulesContext context; private LauncherModulesContext context;
private LauncherTrustManager.CheckClassResult checkResult; private LauncherTrustManager.CheckClassResult checkResult;
protected LauncherModule() { protected LauncherModule() {
moduleInfo = new LauncherModuleInfo("UnknownModule"); moduleInfo = new LauncherModuleInfo("UnknownModule");
} }

View file

@ -6,6 +6,8 @@
public abstract class OptionalTrigger { public abstract class OptionalTrigger {
public static ProviderMap<OptionalTrigger> providers = new ProviderMap<>("OptionalTriggers"); public static ProviderMap<OptionalTrigger> providers = new ProviderMap<>("OptionalTriggers");
private static boolean isRegisteredProviders = false; private static boolean isRegisteredProviders = false;
public boolean required;
public boolean inverted;
public static void registerProviders() { public static void registerProviders() {
if (!isRegisteredProviders) { if (!isRegisteredProviders) {
@ -15,9 +17,6 @@ public static void registerProviders() {
} }
} }
public boolean required;
public boolean inverted;
protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context); protected abstract boolean isTriggered(OptionalFile optional, OptionalTriggerContext context);
public boolean check(OptionalFile optional, OptionalTriggerContext context) { public boolean check(OptionalFile optional, OptionalTriggerContext context) {

View file

@ -17,14 +17,14 @@
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest { public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
public static StdWebSocketService service; public static StdWebSocketService service;
private static UUID session = UUID.randomUUID(); private static UUID session = UUID.randomUUID();
private static AuthRequestEvent.OAuthRequestEvent oauth; private static AuthRequestEvent.OAuthRequestEvent oauth;
private static Map<String, String> extendedTokens; private static Map<String, String> extendedTokens;
private static String authId; private static String authId;
private static long tokenExpiredTime; private static long tokenExpiredTime;
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
@LauncherNetworkAPI @LauncherNetworkAPI
public final UUID requestUUID = UUID.randomUUID(); public final UUID requestUUID = UUID.randomUUID();
private transient final AtomicBoolean started = new AtomicBoolean(false); private transient final AtomicBoolean started = new AtomicBoolean(false);

View file

@ -42,6 +42,20 @@ public AsyncDownloader() {
callback = IGNORE; callback = IGNORE;
} }
public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
if (sslSocketFactory != null) return sslSocketFactory;
SSLContext sslContext = makeSSLContext();
sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
if (sslContext != null) return sslContext;
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom());
return sslContext;
}
public void downloadFile(URL url, Path target, long size) throws IOException { public void downloadFile(URL url, Path target, long size) throws IOException {
if (isClosed) throw new IOException("Download interrupted"); if (isClosed) throw new IOException("Download interrupted");
URLConnection connection = url.openConnection(); URLConnection connection = url.openConnection();
@ -73,20 +87,6 @@ public void downloadFile(URL url, Path target) throws IOException {
} }
} }
public static SSLSocketFactory makeSSLSocketFactory() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
if (sslSocketFactory != null) return sslSocketFactory;
SSLContext sslContext = makeSSLContext();
sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
public static SSLContext makeSSLContext() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException, KeyManagementException {
if (sslContext != null) return sslContext;
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, CertificatePinningTrustManager.getTrustManager().getTrustManagers(), new SecureRandom());
return sslContext;
}
public void downloadListInOneThread(List<SizedFile> files, String baseURL, Path targetDir) throws URISyntaxException, IOException { public void downloadListInOneThread(List<SizedFile> files, String baseURL, Path targetDir) throws URISyntaxException, IOException {
URI baseUri = new URI(baseURL); URI baseUri = new URI(baseURL);
String scheme = baseUri.getScheme(); String scheme = baseUri.getScheme();

View file

@ -10,32 +10,13 @@
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
public class Downloader { public class Downloader {
public interface DownloadCallback {
void apply(long fullDiff);
void onComplete(Path path);
}
private final CompletableFuture<Void> future; private final CompletableFuture<Void> future;
private final AsyncDownloader asyncDownloader; private final AsyncDownloader asyncDownloader;
private Downloader(CompletableFuture<Void> future, AsyncDownloader downloader) { private Downloader(CompletableFuture<Void> future, AsyncDownloader downloader) {
this.future = future; this.future = future;
this.asyncDownloader = downloader; this.asyncDownloader = downloader;
} }
public CompletableFuture<Void> getFuture() {
return future;
}
public void cancel() {
this.asyncDownloader.isClosed = true;
}
public boolean isCanceled() {
return this.asyncDownloader.isClosed;
}
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
final boolean closeExecutor; final boolean closeExecutor;
LogHelper.info("Download with legacy mode"); LogHelper.info("Download with legacy mode");
@ -60,4 +41,22 @@ public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, Str
} }
}), asyncDownloader); }), asyncDownloader);
} }
public CompletableFuture<Void> getFuture() {
return future;
}
public void cancel() {
this.asyncDownloader.isClosed = true;
}
public boolean isCanceled() {
return this.asyncDownloader.isClosed;
}
public interface DownloadCallback {
void apply(long fullDiff);
void onComplete(Path path);
}
} }

View file

@ -589,6 +589,29 @@ public static void write(Path file, byte[] bytes) throws IOException {
Files.write(file, bytes, WRITE_OPTIONS); Files.write(file, bytes, WRITE_OPTIONS);
} }
public static InputStream nonClosing(InputStream in) {
return new FilterInputStream(in) {
@Override
public void close() {
// ignore
}
};
}
public static OutputStream nonClosing(OutputStream out) {
return new FilterOutputStream(out) {
@Override
public void write(byte[] b, int offset, int len) throws IOException {
super.out.write(b, offset, len);
}
@Override
public void close() {
// ignore
}
};
}
private static class MoveFileVisitor implements FileVisitor<Path> { private static class MoveFileVisitor implements FileVisitor<Path> {
private final Path from, to; private final Path from, to;

View file

@ -26,41 +26,15 @@ public class Downloader {
private static boolean isCertificatePinning; private static boolean isCertificatePinning;
@LauncherInject("launcher.noHttp2") @LauncherInject("launcher.noHttp2")
private static boolean isNoHttp2; private static boolean isNoHttp2;
public interface DownloadCallback {
void apply(long fullDiff);
void onComplete(Path path);
}
protected final HttpClient client; protected final HttpClient client;
protected final ExecutorService executor; protected final ExecutorService executor;
protected CompletableFuture<Void> future;
protected final LinkedList<DownloadTask> tasks = new LinkedList<>(); protected final LinkedList<DownloadTask> tasks = new LinkedList<>();
protected CompletableFuture<Void> future;
protected Downloader(HttpClient client, ExecutorService executor) { protected Downloader(HttpClient client, ExecutorService executor) {
this.client = client; this.client = client;
this.executor = executor; this.executor = executor;
} }
public void cancel() {
for (DownloadTask task : tasks) {
if (!task.isCompleted()) {
task.cancel();
}
}
tasks.clear();
executor.shutdownNow();
}
public boolean isCanceled() {
return executor.isTerminated();
}
public CompletableFuture<Void> getFuture() {
return future;
}
public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { public static Downloader downloadList(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
boolean closeExecutor = false; boolean closeExecutor = false;
LogHelper.info("Download with Java 11+ HttpClient"); LogHelper.info("Download with Java 11+ HttpClient");
@ -96,8 +70,22 @@ public static Downloader newDownloader(ExecutorService executor) {
return new Downloader(client, executor); return new Downloader(client, executor);
} }
private static class ConsumerObject { public void cancel() {
Consumer<HttpResponse<Path>> next = null; for (DownloadTask task : tasks) {
if (!task.isCompleted()) {
task.cancel();
}
}
tasks.clear();
executor.shutdownNow();
}
public boolean isCanceled() {
return executor.isTerminated();
}
public CompletableFuture<Void> getFuture() {
return future;
} }
public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception { public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> files, String baseURL, Path targetDir, DownloadCallback callback, ExecutorService executor, int threads) throws Exception {
@ -136,24 +124,6 @@ public CompletableFuture<Void> downloadFiles(List<AsyncDownloader.SizedFile> fil
return future; return future;
} }
public static class DownloadTask {
public final ProgressTrackingBodyHandler<Path> bodyHandler;
public final CompletableFuture<HttpResponse<Path>> completableFuture;
public DownloadTask(ProgressTrackingBodyHandler<Path> bodyHandler, CompletableFuture<HttpResponse<Path>> completableFuture) {
this.bodyHandler = bodyHandler;
this.completableFuture = completableFuture;
}
public boolean isCompleted() {
return completableFuture.isDone() | completableFuture.isCompletedExceptionally();
}
public void cancel() {
bodyHandler.cancel();
}
}
protected DownloadTask sendAsync(AsyncDownloader.SizedFile file, URI baseUri, Path targetDir, DownloadCallback callback) throws Exception { protected DownloadTask sendAsync(AsyncDownloader.SizedFile file, URI baseUri, Path targetDir, DownloadCallback callback) throws Exception {
IOHelper.createParentDirs(targetDir.resolve(file.filePath)); IOHelper.createParentDirs(targetDir.resolve(file.filePath));
ProgressTrackingBodyHandler<Path> bodyHandler = makeBodyHandler(targetDir.resolve(file.filePath), callback); ProgressTrackingBodyHandler<Path> bodyHandler = makeBodyHandler(targetDir.resolve(file.filePath), callback);
@ -187,6 +157,34 @@ protected ProgressTrackingBodyHandler<Path> makeBodyHandler(Path file, DownloadC
return new ProgressTrackingBodyHandler<>(HttpResponse.BodyHandlers.ofFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE), callback); return new ProgressTrackingBodyHandler<>(HttpResponse.BodyHandlers.ofFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE), callback);
} }
public interface DownloadCallback {
void apply(long fullDiff);
void onComplete(Path path);
}
private static class ConsumerObject {
Consumer<HttpResponse<Path>> next = null;
}
public static class DownloadTask {
public final ProgressTrackingBodyHandler<Path> bodyHandler;
public final CompletableFuture<HttpResponse<Path>> completableFuture;
public DownloadTask(ProgressTrackingBodyHandler<Path> bodyHandler, CompletableFuture<HttpResponse<Path>> completableFuture) {
this.bodyHandler = bodyHandler;
this.completableFuture = completableFuture;
}
public boolean isCompleted() {
return completableFuture.isDone() | completableFuture.isCompletedExceptionally();
}
public void cancel() {
bodyHandler.cancel();
}
}
public static class ProgressTrackingBodyHandler<T> implements HttpResponse.BodyHandler<T> { public static class ProgressTrackingBodyHandler<T> implements HttpResponse.BodyHandler<T> {
private final HttpResponse.BodyHandler<T> delegate; private final HttpResponse.BodyHandler<T> delegate;
private final DownloadCallback callback; private final DownloadCallback callback;

View file

@ -1,4 +1,5 @@
# Modification of the launcher sashok724's v3 from Gravit [![Build Status](https://travis-ci.com/GravitLauncher/Launcher.svg?branch=master)](https://travis-ci.com/GravitLauncher/Launcher) # Modification of the launcher sashok724's v3 from Gravit [![Build Status](https://travis-ci.com/GravitLauncher/Launcher.svg?branch=master)](https://travis-ci.com/GravitLauncher/Launcher)
* [Discord channel](https://discord.gg/b9QG4ygY75) * [Discord channel](https://discord.gg/b9QG4ygY75)
* [See license](LICENSE) * [See license](LICENSE)