Fail safely if BungeeCord implementation specific classes are not found

This commit is contained in:
games647
2021-03-15 13:40:28 +01:00
parent 357430b5ad
commit 4bc328c37c
8 changed files with 69 additions and 37 deletions

View File

@ -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

View File

@ -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");

View File

@ -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>

View File

@ -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);
}
}
}
}

View File

@ -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));
}
}

View File

@ -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() + '{' +

View File

@ -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));
}

View File

@ -52,7 +52,7 @@
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.0.0</version>
<version>4.0.3</version>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration>