forked from TuxCoding/FastLogin
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)
|
||||
# including making pull requests review easier
|
||||
|
||||
# Human readable name in the actions tab
|
||||
name: Java CI
|
||||
@ -45,4 +46,4 @@ jobs:
|
||||
# Run non-interactive, package (with compile+test),
|
||||
# ignore snapshot updates, because they are likely to have breaking changes, enforce checksums to validate
|
||||
# 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.PublicKey;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -27,7 +26,7 @@ public class EncryptionUtil {
|
||||
public static final String KEY_PAIR_ALGORITHM = "RSA";
|
||||
|
||||
private EncryptionUtil() {
|
||||
//utility
|
||||
// utility
|
||||
}
|
||||
|
||||
/**
|
||||
@ -43,7 +42,7 @@ public class EncryptionUtil {
|
||||
keyPairGenerator.initialize(1_024);
|
||||
return keyPairGenerator.generateKeyPair();
|
||||
} catch (NoSuchAlgorithmException nosuchalgorithmexception) {
|
||||
//Should be existing in every vm
|
||||
// Should be existing in every vm
|
||||
throw new ExceptionInInitializerError(nosuchalgorithmexception);
|
||||
}
|
||||
}
|
||||
@ -65,9 +64,9 @@ public class EncryptionUtil {
|
||||
/**
|
||||
* 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 publicKey public key of the server
|
||||
* @param publicKey public key of the server
|
||||
* @return the server id formatted as a hexadecimal string.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param cipher decryption cipher initialized with the private key
|
||||
* @param sharedKey the encrypted shared key
|
||||
* @param privateKey private server key
|
||||
* @param sharedKey the encrypted shared key
|
||||
* @return shared secret key
|
||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||
*/
|
||||
@ -106,16 +105,18 @@ public class EncryptionUtil {
|
||||
* Decrypted the given data using the cipher.
|
||||
*
|
||||
* @param cipher decryption cypher initialized with the private key
|
||||
* @param data the encrypted data
|
||||
* @param data the encrypted data
|
||||
* @return clear text data
|
||||
* @throws GeneralSecurityException if it fails to decrypt the data
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
private static byte[] getServerIdHash(String sessionId, PublicKey publicKey, SecretKey sharedSecret)
|
||||
private static byte[] getServerIdHash(
|
||||
String sessionId, PublicKey publicKey, SecretKey sharedSecret)
|
||||
throws NoSuchAlgorithmException {
|
||||
// byte[] a(String var0, PublicKey var1, SecretKey var2)
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-1");
|
||||
|
@ -21,7 +21,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.3</version>
|
||||
<version>3.2.4</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.15-SNAPSHOT</version>
|
||||
<version>1.16-R0.5-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -31,6 +31,8 @@ import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
|
||||
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
|
||||
@ -38,31 +40,41 @@ import org.geysermc.floodgate.FloodgateAPI;
|
||||
*/
|
||||
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 boolean initialHandlerClazzFound;
|
||||
private static final MethodHandle uniqueIdSetter;
|
||||
|
||||
static {
|
||||
MethodHandle setHandle = null;
|
||||
boolean handlerFound = false;
|
||||
try {
|
||||
Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
Class.forName("net.md_5.bungee.connection.InitialHandler");
|
||||
handlerFound = true;
|
||||
|
||||
Field uuidField = InitialHandler.class.getDeclaredField(UUID_FIELD_NAME);
|
||||
uuidField.setAccessible(true);
|
||||
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) {
|
||||
reflectiveOperationException.printStackTrace();
|
||||
}
|
||||
|
||||
initialHandlerClazzFound = handlerFound;
|
||||
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) {
|
||||
this.plugin = plugin;
|
||||
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
|
||||
//with the offline uuid this makes it possible to set the skin then
|
||||
final PendingConnection connection = loginEvent.getConnection();
|
||||
final InitialHandler initialHandler = (InitialHandler) connection;
|
||||
|
||||
PendingConnection connection = loginEvent.getConnection();
|
||||
if (connection.isOnlineMode()) {
|
||||
LoginSession session = plugin.getSession().get(connection);
|
||||
LoginResult loginProfile = initialHandler.getLoginProfile();
|
||||
|
||||
UUID verifiedUUID = connection.getUniqueId();
|
||||
String verifiedUsername = connection.getName();
|
||||
session.setUuid(verifiedUUID);
|
||||
session.setVerifiedUsername(loginProfile.getName());
|
||||
session.setVerifiedUsername(verifiedUsername);
|
||||
|
||||
StoredProfile playerProfile = session.getProfile();
|
||||
playerProfile.setId(verifiedUUID);
|
||||
|
||||
//bungeecord will do this automatically so override it on disabled option
|
||||
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
||||
String username = loginProfile.getName();
|
||||
setOfflineId(initialHandler, username);
|
||||
}
|
||||
// bungeecord will do this automatically so override it on disabled option
|
||||
if (uniqueIdSetter != null) {
|
||||
InitialHandler initialHandler = (InitialHandler) connection;
|
||||
|
||||
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
|
||||
// this is null on offline mode
|
||||
loginProfile.setProperties(emptyProperties);
|
||||
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
||||
setOfflineId(initialHandler, verifiedUsername);
|
||||
}
|
||||
|
||||
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();
|
||||
try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) {
|
||||
if (generatedKeys != null && generatedKeys.next()) {
|
||||
if (generatedKeys.next()) {
|
||||
playerProfile.setRowId(generatedKeys.getInt(1));
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.github.games647.fastlogin.core;
|
||||
import com.github.games647.craftapi.model.Profile;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@ -86,6 +87,21 @@ public class StoredProfile extends Profile {
|
||||
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
|
||||
public synchronized String toString() {
|
||||
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);
|
||||
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) {
|
||||
expireTime = MAX_EXPIRE_RATE;
|
||||
}
|
||||
@ -132,7 +132,7 @@ public class FastLoginCore<P extends C, C, T extends PlatformPlugin<C>> {
|
||||
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()) {
|
||||
config.set(key, config.get(key));
|
||||
}
|
||||
|
Reference in New Issue
Block a user