mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-07-30 10:47:33 +02:00
Fail safely if BungeeCord implementation specific classes are not found
This commit is contained in:
3
.github/workflows/maven.yml
vendored
3
.github/workflows/maven.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
|
# Automatically build, run unit and integration tests to detect errors early (CI provided by GitHub)
|
||||||
|
# including making pull requests review easier
|
||||||
|
|
||||||
# Human readable name in the actions tab
|
# Human readable name in the actions tab
|
||||||
name: Java CI
|
name: Java CI
|
||||||
@ -45,4 +46,4 @@ jobs:
|
|||||||
# Run non-interactive, package (with compile+test),
|
# Run non-interactive, package (with compile+test),
|
||||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
|
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
|
||||||
# possible errors in dependencies
|
# possible errors in dependencies
|
||||||
run: mvn test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml
|
run: mvn package test --batch-mode --no-snapshot-updates --strict-checksums --file pom.xml
|
||||||
|
@ -10,7 +10,6 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
@ -27,7 +26,7 @@ public class EncryptionUtil {
|
|||||||
public static final String KEY_PAIR_ALGORITHM = "RSA";
|
public static final String KEY_PAIR_ALGORITHM = "RSA";
|
||||||
|
|
||||||
private EncryptionUtil() {
|
private EncryptionUtil() {
|
||||||
//utility
|
// utility
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +42,7 @@ public class EncryptionUtil {
|
|||||||
keyPairGenerator.initialize(1_024);
|
keyPairGenerator.initialize(1_024);
|
||||||
return keyPairGenerator.generateKeyPair();
|
return keyPairGenerator.generateKeyPair();
|
||||||
} catch (NoSuchAlgorithmException nosuchalgorithmexception) {
|
} catch (NoSuchAlgorithmException nosuchalgorithmexception) {
|
||||||
//Should be existing in every vm
|
// Should be existing in every vm
|
||||||
throw new ExceptionInInitializerError(nosuchalgorithmexception);
|
throw new ExceptionInInitializerError(nosuchalgorithmexception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,9 +64,9 @@ public class EncryptionUtil {
|
|||||||
/**
|
/**
|
||||||
* Generate the server id based on client and server data.
|
* Generate the server id based on client and server data.
|
||||||
*
|
*
|
||||||
* @param sessionId session for the current login attempt
|
* @param sessionId session for the current login attempt
|
||||||
* @param sharedSecret shared secret between the client and the server
|
* @param sharedSecret shared secret between the client and the server
|
||||||
* @param publicKey public key of the server
|
* @param publicKey public key of the server
|
||||||
* @return the server id formatted as a hexadecimal string.
|
* @return the server id formatted as a hexadecimal string.
|
||||||
*/
|
*/
|
||||||
public static String getServerIdHashString(String sessionId, SecretKey sharedSecret, PublicKey publicKey) {
|
public static String getServerIdHashString(String sessionId, SecretKey sharedSecret, PublicKey publicKey) {
|
||||||
@ -85,8 +84,8 @@ public class EncryptionUtil {
|
|||||||
/**
|
/**
|
||||||
* Decrypts the content and extracts the key spec.
|
* Decrypts the content and extracts the key spec.
|
||||||
*
|
*
|
||||||
* @param cipher decryption cipher initialized with the private key
|
* @param privateKey private server key
|
||||||
* @param sharedKey the encrypted shared key
|
* @param sharedKey the encrypted shared key
|
||||||
* @return shared secret key
|
* @return shared secret key
|
||||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||||
*/
|
*/
|
||||||
@ -106,16 +105,18 @@ public class EncryptionUtil {
|
|||||||
* Decrypted the given data using the cipher.
|
* Decrypted the given data using the cipher.
|
||||||
*
|
*
|
||||||
* @param cipher decryption cypher initialized with the private key
|
* @param cipher decryption cypher initialized with the private key
|
||||||
* @param data the encrypted data
|
* @param data the encrypted data
|
||||||
* @return clear text data
|
* @return clear text data
|
||||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||||
*/
|
*/
|
||||||
private static byte[] decrypt(Cipher cipher, byte[] data) throws GeneralSecurityException {
|
private static byte[] decrypt(Cipher cipher, byte[] data) throws GeneralSecurityException {
|
||||||
// inlined: byte[] a(int var0, Key var1, byte[] var2), Cipher a(int var0, String var1, Key var2)
|
// inlined: byte[] a(int var0, Key var1, byte[] var2), Cipher a(int var0, String var1, Key
|
||||||
|
// var2)
|
||||||
return cipher.doFinal(data);
|
return cipher.doFinal(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] getServerIdHash(String sessionId, PublicKey publicKey, SecretKey sharedSecret)
|
private static byte[] getServerIdHash(
|
||||||
|
String sessionId, PublicKey publicKey, SecretKey sharedSecret)
|
||||||
throws NoSuchAlgorithmException {
|
throws NoSuchAlgorithmException {
|
||||||
// byte[] a(String var0, PublicKey var1, SecretKey var2)
|
// byte[] a(String var0, PublicKey var1, SecretKey var2)
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
<version>3.2.3</version>
|
<version>3.2.4</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-proxy</artifactId>
|
<artifactId>bungeecord-proxy</artifactId>
|
||||||
<version>1.15-SNAPSHOT</version>
|
<version>1.16-R0.5-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ import net.md_5.bungee.event.EventHandler;
|
|||||||
import net.md_5.bungee.event.EventPriority;
|
import net.md_5.bungee.event.EventPriority;
|
||||||
|
|
||||||
import org.geysermc.floodgate.FloodgateAPI;
|
import org.geysermc.floodgate.FloodgateAPI;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables online mode logins for specified users and sends plugin message to the Bukkit version of this plugin in
|
* Enables online mode logins for specified users and sends plugin message to the Bukkit version of this plugin in
|
||||||
@ -38,31 +40,41 @@ import org.geysermc.floodgate.FloodgateAPI;
|
|||||||
*/
|
*/
|
||||||
public class ConnectListener implements Listener {
|
public class ConnectListener implements Listener {
|
||||||
|
|
||||||
private final FastLoginBungee plugin;
|
|
||||||
private final RateLimiter rateLimiter;
|
|
||||||
|
|
||||||
private final Property[] emptyProperties = {};
|
|
||||||
private final boolean floodGateAvailable;
|
|
||||||
|
|
||||||
|
|
||||||
private static final String UUID_FIELD_NAME = "uniqueId";
|
private static final String UUID_FIELD_NAME = "uniqueId";
|
||||||
|
private static final boolean initialHandlerClazzFound;
|
||||||
private static final MethodHandle uniqueIdSetter;
|
private static final MethodHandle uniqueIdSetter;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
MethodHandle setHandle = null;
|
MethodHandle setHandle = null;
|
||||||
|
boolean handlerFound = false;
|
||||||
try {
|
try {
|
||||||
Lookup lookup = MethodHandles.lookup();
|
Lookup lookup = MethodHandles.lookup();
|
||||||
|
|
||||||
|
Class.forName("net.md_5.bungee.connection.InitialHandler");
|
||||||
|
handlerFound = true;
|
||||||
|
|
||||||
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
||||||
uuidField.setAccessible(true);
|
uuidField.setAccessible(true);
|
||||||
setHandle = lookup.unreflectSetter(uuidField);
|
setHandle = lookup.unreflectSetter(uuidField);
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
Logger logger = LoggerFactory.getLogger(ConnectListener.class);
|
||||||
|
logger.error(
|
||||||
|
"Cannot find Bungee initial handler; Disabling premium UUID and skin won't work.",
|
||||||
|
classNotFoundException
|
||||||
|
);
|
||||||
} catch (ReflectiveOperationException reflectiveOperationException) {
|
} catch (ReflectiveOperationException reflectiveOperationException) {
|
||||||
reflectiveOperationException.printStackTrace();
|
reflectiveOperationException.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialHandlerClazzFound = handlerFound;
|
||||||
uniqueIdSetter = setHandle;
|
uniqueIdSetter = setHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final FastLoginBungee plugin;
|
||||||
|
private final RateLimiter rateLimiter;
|
||||||
|
private final Property[] emptyProperties = {};
|
||||||
|
private final boolean floodGateAvailable;
|
||||||
|
|
||||||
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter, boolean floodgateAvailable) {
|
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter, boolean floodgateAvailable) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.rateLimiter = rateLimiter;
|
this.rateLimiter = rateLimiter;
|
||||||
@ -97,29 +109,31 @@ public class ConnectListener implements Listener {
|
|||||||
|
|
||||||
//use the login event instead of the post login event in order to send the login success packet to the client
|
//use the login event instead of the post login event in order to send the login success packet to the client
|
||||||
//with the offline uuid this makes it possible to set the skin then
|
//with the offline uuid this makes it possible to set the skin then
|
||||||
final PendingConnection connection = loginEvent.getConnection();
|
PendingConnection connection = loginEvent.getConnection();
|
||||||
final InitialHandler initialHandler = (InitialHandler) connection;
|
|
||||||
|
|
||||||
if (connection.isOnlineMode()) {
|
if (connection.isOnlineMode()) {
|
||||||
LoginSession session = plugin.getSession().get(connection);
|
LoginSession session = plugin.getSession().get(connection);
|
||||||
LoginResult loginProfile = initialHandler.getLoginProfile();
|
|
||||||
|
|
||||||
UUID verifiedUUID = connection.getUniqueId();
|
UUID verifiedUUID = connection.getUniqueId();
|
||||||
|
String verifiedUsername = connection.getName();
|
||||||
session.setUuid(verifiedUUID);
|
session.setUuid(verifiedUUID);
|
||||||
session.setVerifiedUsername(loginProfile.getName());
|
session.setVerifiedUsername(verifiedUsername);
|
||||||
|
|
||||||
StoredProfile playerProfile = session.getProfile();
|
StoredProfile playerProfile = session.getProfile();
|
||||||
playerProfile.setId(verifiedUUID);
|
playerProfile.setId(verifiedUUID);
|
||||||
|
|
||||||
//bungeecord will do this automatically so override it on disabled option
|
// bungeecord will do this automatically so override it on disabled option
|
||||||
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
if (uniqueIdSetter != null) {
|
||||||
String username = loginProfile.getName();
|
InitialHandler initialHandler = (InitialHandler) connection;
|
||||||
setOfflineId(initialHandler, username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
|
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
||||||
// this is null on offline mode
|
setOfflineId(initialHandler, verifiedUsername);
|
||||||
loginProfile.setProperties(emptyProperties);
|
}
|
||||||
|
|
||||||
|
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
|
||||||
|
// this is null on offline mode
|
||||||
|
LoginResult loginProfile = initialHandler.getLoginProfile();
|
||||||
|
loginProfile.setProperties(emptyProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ public class AuthStorage {
|
|||||||
|
|
||||||
saveStmt.execute();
|
saveStmt.execute();
|
||||||
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
|
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
|
||||||
if (generatedKeys != null && generatedKeys.next()) {
|
if (generatedKeys.next()) {
|
||||||
playerProfile.setRowId(generatedKeys.getInt(1));
|
playerProfile.setRowId(generatedKeys.getInt(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.github.games647.fastlogin.core;
|
|||||||
import com.github.games647.craftapi.model.Profile;
|
import com.github.games647.craftapi.model.Profile;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
@ -86,6 +87,21 @@ public class StoredProfile extends Profile {
|
|||||||
this.lastLogin = lastLogin;
|
this.lastLogin = lastLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof StoredProfile)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
StoredProfile that = (StoredProfile) o;
|
||||||
|
return rowId == that.rowId && premium == that.premium
|
||||||
|
&& Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(super.hashCode(), rowId, premium, lastIp, lastLogin);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized String toString() {
|
public synchronized String toString() {
|
||||||
return this.getClass().getSimpleName() + '{' +
|
return this.getClass().getSimpleName() + '{' +
|
||||||
|
@ -90,7 +90,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int maxCon = config.getInt("anti-bot.connections", 200);
|
int maxCon = config.getInt("anti-bot.connections", 200);
|
||||||
long expireTime = config.getInt("anti-bot.expire", 5) * 60 * 1_000L;
|
long expireTime = config.getLong("anti-bot.expire", 5) * 60 * 1_000L;
|
||||||
if (expireTime > MAX_EXPIRE_RATE) {
|
if (expireTime > MAX_EXPIRE_RATE) {
|
||||||
expireTime = MAX_EXPIRE_RATE;
|
expireTime = MAX_EXPIRE_RATE;
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
|||||||
config = configProvider.load(reader, defaults);
|
config = configProvider.load(reader, defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
//explicitly add keys here, because Configuration.getKeys doesn't return the keys from the default configuration
|
// explicitly add keys here, because Configuration.getKeys doesn't return the keys from the default configuration
|
||||||
for (String key : defaults.getKeys()) {
|
for (String key : defaults.getKeys()) {
|
||||||
config.set(key, config.get(key));
|
config.set(key, config.get(key));
|
||||||
}
|
}
|
||||||
|
2
pom.xml
2
pom.xml
@ -52,7 +52,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>pl.project13.maven</groupId>
|
<groupId>pl.project13.maven</groupId>
|
||||||
<artifactId>git-commit-id-plugin</artifactId>
|
<artifactId>git-commit-id-plugin</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.3</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
Reference in New Issue
Block a user