Merge branch 'release/v5.2.7'

This commit is contained in:
Gravita 2021-12-11 15:04:25 +07:00
commit 3a77a59eac
13 changed files with 312 additions and 95 deletions

View file

@ -1,70 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master, dev ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, dev ]
schedule:
- cron: '28 4 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View file

@ -5,6 +5,7 @@
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.core.MySQLCoreProvider; import pro.gravit.launchserver.auth.core.MySQLCoreProvider;
import pro.gravit.launchserver.auth.core.PostgresSQLCoreProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider; import pro.gravit.launchserver.auth.texture.TextureProvider;
import java.io.IOException; import java.io.IOException;
@ -39,7 +40,7 @@ public static Set<String> getFeatures(Class<?> clazz) {
public void internalShowOAuthWarnMessage() { public void internalShowOAuthWarnMessage() {
if(!warnOAuthShow) { if(!warnOAuthShow) {
if(!(core instanceof MySQLCoreProvider)) { // MySQL upgraded later if(!(core instanceof MySQLCoreProvider) && !(core instanceof PostgresSQLCoreProvider)) { // MySQL and PostgreSQL upgraded later
logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName()); logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName());
} }
warnOAuthShow = true; warnOAuthShow = true;

View file

@ -43,6 +43,7 @@ public static void registerProviders() {
if (!registredProviders) { if (!registredProviders) {
providers.register("reject", RejectAuthCoreProvider.class); providers.register("reject", RejectAuthCoreProvider.class);
providers.register("mysql", MySQLCoreProvider.class); providers.register("mysql", MySQLCoreProvider.class);
providers.register("postgresql", PostgresSQLCoreProvider.class);
providers.register("memory", MemoryAuthCoreProvider.class); providers.register("memory", MemoryAuthCoreProvider.class);
providers.register("http", HttpAuthCoreProvider.class); providers.register("http", HttpAuthCoreProvider.class);
registredProviders = true; registredProviders = true;

View file

@ -0,0 +1,260 @@
package pro.gravit.launchserver.auth.core;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.ClientPermissions;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.MySQLSourceConfig;
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
import pro.gravit.launchserver.auth.password.PasswordVerifier;
import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException;
import java.sql.*;
import java.util.UUID;
public class PostgresSQLCoreProvider extends AuthCoreProvider {
private transient final Logger logger = LogManager.getLogger();
public PostgreSQLSourceConfig postgresSQLHolder;
public String uuidColumn;
public String usernameColumn;
public String accessTokenColumn;
public String passwordColumn;
public String serverIDColumn;
public String table;
public PasswordVerifier passwordVerifier;
public String customQueryByUUIDSQL;
public String customQueryByUsernameSQL;
public String customQueryByLoginSQL;
public String customUpdateAuthSQL;
public String customUpdateServerIdSQL;
// Prepared SQL queries
private transient String queryByUUIDSQL;
private transient String queryByUsernameSQL;
private transient String queryByLoginSQL;
private transient String updateAuthSQL;
private transient String updateServerIDSQL;
@Override
public User getUserByUsername(String username) {
try {
return query(queryByUsernameSQL, username);
} catch (IOException e) {
logger.error("SQL error", e);
return null;
}
}
@Override
public User getUserByUUID(UUID uuid) {
try {
return query(queryByUUIDSQL, uuid.toString());
} catch (IOException e) {
logger.error("SQL error", e);
return null;
}
}
@Override
public User getUserByLogin(String login) {
try {
return query(queryByLoginSQL, login);
} catch (IOException e) {
logger.error("SQL error", e);
return null;
}
}
@Override
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
return null;
}
@Override
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
return null;
}
@Override
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) getUserByLogin(login);
if(postgresSQLUser == null) {
throw AuthException.wrongPassword();
}
if(context != null) {
AuthPlainPassword plainPassword = (AuthPlainPassword) password;
if(plainPassword == null) {
throw AuthException.wrongPassword();
}
if(!passwordVerifier.check(postgresSQLUser.password, plainPassword.password)) {
throw AuthException.wrongPassword();
}
}
MySQLUserSession session = new MySQLUserSession(postgresSQLUser);
if (minecraftAccess) {
String minecraftAccessToken = SecurityHelper.randomStringToken();
updateAuth(postgresSQLUser, minecraftAccessToken);
return AuthManager.AuthReport.ofMinecraftAccessToken(minecraftAccessToken, session);
} else {
return AuthManager.AuthReport.ofMinecraftAccessToken(null, session);
}
}
@Override
public void init(LaunchServer server) {
if (postgresSQLHolder == null) logger.error("postgresSQLHolder cannot be null");
if (uuidColumn == null) logger.error("uuidColumn cannot be null");
if (usernameColumn == null) logger.error("usernameColumn cannot be null");
if (accessTokenColumn == null) logger.error("accessTokenColumn cannot be null");
if (serverIDColumn == null) logger.error("serverIDColumn cannot be null");
if (table == null) logger.error("table cannot be null");
// Prepare SQL queries
String userInfoCols = String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
queryByUUIDSQL = customQueryByUUIDSQL != null ? customQueryByUUIDSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1", userInfoCols,
table, uuidColumn);
queryByUsernameSQL = customQueryByUsernameSQL != null ? customQueryByUsernameSQL : String.format("SELECT %s FROM %s WHERE %s=? LIMIT 1",
userInfoCols, table, usernameColumn);
queryByLoginSQL = customQueryByLoginSQL != null ? customQueryByLoginSQL : queryByUsernameSQL;
updateAuthSQL = customUpdateAuthSQL != null ? customUpdateAuthSQL : String.format("UPDATE %s SET %s=?, %s=NULL WHERE %s=?",
table, accessTokenColumn, serverIDColumn, uuidColumn);
updateServerIDSQL = customUpdateServerIdSQL != null ? customUpdateServerIdSQL : String.format("UPDATE %s SET %s=? WHERE %s=?",
table, serverIDColumn, uuidColumn);
}
protected boolean updateAuth(User user, String accessToken) throws IOException {
try (Connection c = postgresSQLHolder.getConnection()) {
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) user;
postgresSQLUser.accessToken = accessToken;
PreparedStatement s = c.prepareStatement(updateAuthSQL);
s.setString(1, accessToken);
s.setString(2, user.getUUID().toString());
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
return s.executeUpdate() > 0;
} catch (SQLException e) {
throw new IOException(e);
}
}
@Override
protected boolean updateServerID(User user, String serverID) throws IOException {
try (Connection c = postgresSQLHolder.getConnection()) {
PostgresSQLUser postgresSQLUser = (PostgresSQLUser) user;
postgresSQLUser.serverId = serverID;
PreparedStatement s = c.prepareStatement(updateServerIDSQL);
s.setString(1, serverID);
s.setString(2, user.getUUID().toString());
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
return s.executeUpdate() > 0;
} catch (SQLException e) {
throw new IOException(e);
}
}
@Override
public void close() throws IOException {
postgresSQLHolder.close();
}
private PostgresSQLUser constructUser(ResultSet set) throws SQLException {
return set.next() ? new PostgresSQLUser(UUID.fromString(set.getString(uuidColumn)), set.getString(usernameColumn),
set.getString(accessTokenColumn), set.getString(serverIDColumn), set.getString(passwordColumn), new ClientPermissions()) : null;
}
private User query(String sql, String value) throws IOException {
try (Connection c = postgresSQLHolder.getConnection()) {
PreparedStatement s = c.prepareStatement(sql);
s.setString(1, value);
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
try (ResultSet set = s.executeQuery()) {
return constructUser(set);
}
} catch (SQLException e) {
throw new IOException(e);
}
}
public static class PostgresSQLUser implements User {
protected UUID uuid;
protected String username;
protected String accessToken;
protected String serverId;
protected String password;
protected ClientPermissions permissions;
public PostgresSQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
this.uuid = uuid;
this.username = username;
this.accessToken = accessToken;
this.serverId = serverId;
this.password = password;
this.permissions = permissions;
}
@Override
public String getUsername() {
return username;
}
@Override
public UUID getUUID() {
return uuid;
}
@Override
public String getServerId() {
return serverId;
}
@Override
public String getAccessToken() {
return accessToken;
}
@Override
public ClientPermissions getPermissions() {
return permissions;
}
@Override
public String toString() {
return "PostgresSQLUser{" +
"uuid=" + uuid +
", username='" + username + '\'' +
", permissions=" + permissions +
'}';
}
}
public static class MySQLUserSession implements UserSession {
private final PostgresSQLUser user;
private final String id;
public MySQLUserSession(PostgresSQLUser user) {
this.user = user;
this.id = user.username;
}
@Override
public String getID() {
return id;
}
@Override
public User getUser() {
return user;
}
@Override
public long getExpireIn() {
return 0;
}
}
}

View file

@ -56,6 +56,10 @@ public synchronized void compile() {
if (available != null) { if (available != null) {
return; return;
} }
if (perms == null) {
perms = new ArrayList<>(0);
}
available = new ArrayList<>(perms.size()); available = new ArrayList<>(perms.size());
for (String a : perms) { for (String a : perms) {
available.add(new PermissionPattern(a)); available.add(new PermissionPattern(a));

View file

@ -481,7 +481,9 @@ public enum Version {
MC1164("1.16.4", 754), MC1164("1.16.4", 754),
MC1165("1.16.5", 754), MC1165("1.16.5", 754),
MC117("1.17", 755), MC117("1.17", 755),
MC1171("1.17.1", 756); MC1171("1.17.1", 756),
MC118("1.18", 757),
MC1181("1.18.1", 757);
private static final Map<String, Version> VERSIONS; private static final Map<String, Version> VERSIONS;
static { static {

View file

@ -80,7 +80,7 @@ public void enable(OptionalFile file, boolean manual, BiConsumer<OptionalFile, B
} }
if (file.conflict != null) { if (file.conflict != null) {
for (OptionalFile conflict : file.conflict) { for (OptionalFile conflict : file.conflict) {
disable(conflict, null); disable(conflict, callback);
} }
} }
} }

View file

@ -6,7 +6,7 @@ public final class Version implements Comparable<Version> {
public static final int MAJOR = 5; public static final int MAJOR = 5;
public static final int MINOR = 2; public static final int MINOR = 2;
public static final int PATCH = 6; public static final int PATCH = 7;
public static final int BUILD = 1; public static final int BUILD = 1;
public static final Version.Type RELEASE = Type.STABLE; public static final Version.Type RELEASE = Type.STABLE;
public final int major; public final int major;

View file

@ -430,11 +430,15 @@ public static Path resolveIncremental(Path dir, String name, String extension) {
} }
public static Path resolveJavaBin(Path javaDir) { public static Path resolveJavaBin(Path javaDir) {
return resolveJavaBin(javaDir, false);
}
public static Path resolveJavaBin(Path javaDir, boolean isConsole) {
// Get Java binaries path // Get Java binaries path
Path javaBinDir = (javaDir == null ? JVM_DIR : javaDir).resolve("bin"); Path javaBinDir = (javaDir == null ? JVM_DIR : javaDir).resolve("bin");
// Verify has "javaw.exe" file // Verify has "javaw.exe" file
if (!LogHelper.isDebugEnabled()) { if (!isConsole && !LogHelper.isDebugEnabled()) {
Path javawExe = javaBinDir.resolve("javaw.exe"); Path javawExe = javaBinDir.resolve("javaw.exe");
if (isFile(javawExe)) if (isFile(javawExe))
return javawExe; return javawExe;

View file

@ -141,14 +141,16 @@ public void run(String... args) throws Throwable {
} }
Class<?> mainClass; Class<?> mainClass;
if (config.classpath != null && !config.classpath.isEmpty()) { if (config.classpath != null && !config.classpath.isEmpty()) {
if (!ServerAgent.isAgentStarted()) { if(config.classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) {
LogHelper.warning("JavaAgent not found. Using URLClassLoader");
URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new); URL[] urls = config.classpath.stream().map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
ucp = new PublicURLClassLoader(urls); ucp = new PublicURLClassLoader(urls);
Thread.currentThread().setContextClassLoader(ucp); Thread.currentThread().setContextClassLoader(ucp);
loader = ucp; loader = ucp;
} else { } else if(config.classLoaderConfig == ClientProfile.ClassLoaderConfig.AGENT) {
LogHelper.info("Found %d custom classpath elements", config.classpath.size()); if (!ServerAgent.isAgentStarted()) {
LogHelper.error("JavaAgent not found");
System.exit(-1);
}
for (String c : config.classpath) for (String c : config.classpath)
ServerAgent.addJVMClassPath(c); ServerAgent.addJVMClassPath(c);
} }
@ -207,6 +209,7 @@ public Config getDefaultConfig() {
newConfig.args = new ArrayList<>(); newConfig.args = new ArrayList<>();
newConfig.classpath = new ArrayList<>(); newConfig.classpath = new ArrayList<>();
newConfig.address = "ws://localhost:9274/api"; newConfig.address = "ws://localhost:9274/api";
newConfig.classLoaderConfig = ClientProfile.ClassLoaderConfig.SYSTEM_ARGS;
newConfig.env = LauncherConfig.LauncherEnvironment.STD; newConfig.env = LauncherConfig.LauncherEnvironment.STD;
return newConfig; return newConfig;
} }
@ -219,6 +222,7 @@ public static final class Config {
public boolean autoloadLibraries; public boolean autoloadLibraries;
public String logFile; public String logFile;
public List<String> classpath; public List<String> classpath;
public ClientProfile.ClassLoaderConfig classLoaderConfig;
public String librariesDir; public String librariesDir;
public String mainclass; public String mainclass;
public List<String> args; public List<String> args;

View file

@ -1,5 +1,6 @@
package pro.gravit.launcher.server.setup; package pro.gravit.launcher.server.setup;
import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.Request;
import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.StdWebSocketService;
import pro.gravit.launcher.server.ServerWrapper; import pro.gravit.launcher.server.ServerWrapper;
@ -57,6 +58,7 @@ public void run() throws Exception {
System.out.println("Print your server name:"); System.out.println("Print your server name:");
wrapper.config.serverName = commands.commandHandler.readLine(); wrapper.config.serverName = commands.commandHandler.readLine();
wrapper.config.mainclass = mainClassName; wrapper.config.mainclass = mainClassName;
boolean altMode = false;
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
if(!Request.isAvailable() || Request.getRequestService().isClosed()) { if(!Request.isAvailable() || Request.getRequestService().isClosed()) {
System.out.println("Print launchserver websocket host( ws://host:port/api ):"); System.out.println("Print launchserver websocket host( ws://host:port/api ):");
@ -85,6 +87,12 @@ public void run() throws Exception {
} }
} }
} }
if(wrapper.profile != null && wrapper.profile.getVersion().compareTo(ClientProfile.Version.MC118) >= 0) {
LogHelper.info("Switch to alternative start mode (1.18)");
wrapper.config.classpath.add(jarName);
wrapper.config.classLoaderConfig = ClientProfile.ClassLoaderConfig.LAUNCHER;
altMode = true;
}
wrapper.saveConfig(); wrapper.saveConfig();
LogHelper.info("Generate start script"); LogHelper.info("Generate start script");
Path startScript; Path startScript;
@ -99,8 +107,9 @@ public void run() throws Exception {
if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) { if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) {
writer.append("#!/bin/bash\n\n"); writer.append("#!/bin/bash\n\n");
} }
writer.append(IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home"))).toAbsolutePath().toString()); writer.append("\"");
writer.append(" "); writer.append(IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")), true).toAbsolutePath().toString());
writer.append("\" ");
if (mainClassName.contains("bungee")) { if (mainClassName.contains("bungee")) {
LogHelper.info("Found BungeeCord mainclass. Modules dir change to modules_srv"); LogHelper.info("Found BungeeCord mainclass. Modules dir change to modules_srv");
writer.append(JVMHelper.jvmProperty("serverwrapper.modulesDir", "modules_srv")); writer.append(JVMHelper.jvmProperty("serverwrapper.modulesDir", "modules_srv"));
@ -115,10 +124,12 @@ public void run() throws Exception {
writer.append("-cp "); writer.append("-cp ");
String pathServerWrapper = IOHelper.getCodeSource(ServerWrapper.class).getFileName().toString(); String pathServerWrapper = IOHelper.getCodeSource(ServerWrapper.class).getFileName().toString();
writer.append(pathServerWrapper); writer.append(pathServerWrapper);
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) { if(!altMode) {
writer.append(";"); if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
} else writer.append(":"); writer.append(";");
writer.append(jarName); } else writer.append(":");
writer.append(jarName);
}
writer.append(" "); writer.append(" ");
writer.append(ServerWrapper.class.getName()); writer.append(ServerWrapper.class.getName());
writer.append("\n"); writer.append("\n");

View file

@ -5,7 +5,7 @@
id 'org.openjfx.javafxplugin' version '0.0.10' apply false id 'org.openjfx.javafxplugin' version '0.0.10' apply false
} }
group = 'pro.gravit.launcher' group = 'pro.gravit.launcher'
version = '5.2.6 ' version = '5.2.7'
apply from: 'props.gradle' apply from: 'props.gradle'

View file

@ -1,19 +1,19 @@
project.ext { project.ext {
verAsm = '9.2' verAsm = '9.2'
verNetty = '4.1.68.Final' verNetty = '4.1.70.Final'
verOshiCore = '5.8.0' verOshiCore = '5.8.5'
verJunit = '5.7.2' verJunit = '5.8.2'
verGuavaC = '30.1.1-jre' verGuavaC = '30.1.1-jre'
verJansi = '2.3.4' verJansi = '2.3.4'
verJline = '3.20.0' verJline = '3.21.0'
verJwt = '0.11.2' verJwt = '0.11.2'
verBcprov = '1.69' verBcprov = '1.70'
verGson = '2.8.9' verGson = '2.8.9'
verBcpkix = '1.69' verBcpkix = '1.70'
verSlf4j = '1.7.32' verSlf4j = '1.7.32'
verLog4j = '2.14.1' verLog4j = '2.15.0'
verMySQLConn = '8.0.26' verMySQLConn = '8.0.27'
verPostgreSQLConn = '42.2.24' verPostgreSQLConn = '42.3.1'
verProguard = '7.2.0-beta2' verProguard = '7.2.0-beta2'
verLaunch4j = '3.14' verLaunch4j = '3.14'
verHibernate = '5.5.6.Final' verHibernate = '5.5.6.Final'