fix: do not send login disconnect packet before switching to login state

This commit is contained in:
mworzala 2023-12-28 07:58:33 -05:00 committed by Matt Worzala
parent 8859af87ba
commit 6d5b1ea77e
1 changed files with 74 additions and 75 deletions

View File

@ -39,95 +39,94 @@ public final class HandshakeListener {
public static void listener(@NotNull ClientHandshakePacket packet, @NotNull PlayerConnection connection) {
String address = packet.serverAddress();
// Bungee support (IP forwarding)
if (BungeeCordProxy.isEnabled() && connection instanceof PlayerSocketConnection socketConnection && packet.intent() == 2) {
final String[] split = address.split("\00");
if (split.length == 3 || split.length == 4) {
boolean hasProperties = split.length == 4;
if (BungeeCordProxy.isBungeeGuardEnabled() && !hasProperties) {
bungeeDisconnect(socketConnection);
return;
}
address = split[0];
final SocketAddress socketAddress = new java.net.InetSocketAddress(split[1],
((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort());
socketConnection.setRemoteAddress(socketAddress);
UUID playerUuid = java.util.UUID.fromString(
split[2]
.replaceFirst(
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"
)
);
List<GameProfile.Property> properties = new ArrayList<>();
if (hasProperties) {
boolean foundBungeeGuardToken = false;
final String rawPropertyJson = split[3];
final JsonArray propertyJson = JsonParser.parseString(rawPropertyJson).getAsJsonArray();
for (JsonElement element : propertyJson) {
final JsonObject jsonObject = element.getAsJsonObject();
final JsonElement name = jsonObject.get("name");
final JsonElement value = jsonObject.get("value");
final JsonElement signature = jsonObject.get("signature");
if (name == null || value == null) continue;
final String nameString = name.getAsString();
final String valueString = value.getAsString();
final String signatureString = signature == null ? null : signature.getAsString();
if (BungeeCordProxy.isBungeeGuardEnabled() && nameString.equals("bungeeguard-token")) {
if (foundBungeeGuardToken || !BungeeCordProxy.isValidBungeeGuardToken(valueString)) {
bungeeDisconnect(socketConnection);
return;
}
foundBungeeGuardToken = true;
}
properties.add(new GameProfile.Property(nameString, valueString, signatureString));
}
if (BungeeCordProxy.isBungeeGuardEnabled() && !foundBungeeGuardToken) {
bungeeDisconnect(socketConnection);
return;
}
}
final GameProfile gameProfile = new GameProfile(playerUuid, "test", properties);
socketConnection.UNSAFE_setProfile(gameProfile);
} else {
bungeeDisconnect(socketConnection);
return;
}
}
if (connection instanceof PlayerSocketConnection) {
// Give to the connection the server info that the client used
((PlayerSocketConnection) connection).refreshServerInformation(address, packet.serverPort(), packet.protocolVersion());
}
switch (packet.intent()) {
case 1 -> {
connection.setClientState(ConnectionState.STATUS);
connection.setServerState(ConnectionState.STATUS);
}
case 2 -> {
if (packet.protocolVersion() == MinecraftServer.PROTOCOL_VERSION) {
connection.setClientState(ConnectionState.LOGIN);
connection.setServerState(ConnectionState.LOGIN);
} else {
connection.setClientState(ConnectionState.LOGIN);
connection.setServerState(ConnectionState.LOGIN);
if (packet.protocolVersion() != MinecraftServer.PROTOCOL_VERSION) {
// Incorrect client version
disconnect(connection, INVALID_VERSION_TEXT);
}
// Bungee support (IP forwarding)
if (BungeeCordProxy.isEnabled() && connection instanceof PlayerSocketConnection socketConnection) {
final String[] split = address.split("\00");
if (split.length == 3 || split.length == 4) {
boolean hasProperties = split.length == 4;
if (BungeeCordProxy.isBungeeGuardEnabled() && !hasProperties) {
bungeeDisconnect(socketConnection);
return;
}
address = split[0];
final SocketAddress socketAddress = new java.net.InetSocketAddress(split[1],
((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort());
socketConnection.setRemoteAddress(socketAddress);
UUID playerUuid = java.util.UUID.fromString(
split[2]
.replaceFirst(
"(\\p{XDigit}{8})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}{4})(\\p{XDigit}+)", "$1-$2-$3-$4-$5"
)
);
List<GameProfile.Property> properties = new ArrayList<>();
if (hasProperties) {
boolean foundBungeeGuardToken = false;
final String rawPropertyJson = split[3];
final JsonArray propertyJson = JsonParser.parseString(rawPropertyJson).getAsJsonArray();
for (JsonElement element : propertyJson) {
final JsonObject jsonObject = element.getAsJsonObject();
final JsonElement name = jsonObject.get("name");
final JsonElement value = jsonObject.get("value");
final JsonElement signature = jsonObject.get("signature");
if (name == null || value == null) continue;
final String nameString = name.getAsString();
final String valueString = value.getAsString();
final String signatureString = signature == null ? null : signature.getAsString();
if (BungeeCordProxy.isBungeeGuardEnabled() && nameString.equals("bungeeguard-token")) {
if (foundBungeeGuardToken || !BungeeCordProxy.isValidBungeeGuardToken(valueString)) {
bungeeDisconnect(socketConnection);
return;
}
foundBungeeGuardToken = true;
}
properties.add(new GameProfile.Property(nameString, valueString, signatureString));
}
if (BungeeCordProxy.isBungeeGuardEnabled() && !foundBungeeGuardToken) {
bungeeDisconnect(socketConnection);
return;
}
}
final GameProfile gameProfile = new GameProfile(playerUuid, "test", properties);
socketConnection.UNSAFE_setProfile(gameProfile);
} else {
bungeeDisconnect(socketConnection);
return;
}
}
}
default -> {
// Unexpected error
}
}
if (connection instanceof PlayerSocketConnection) {
// Give to the connection the server info that the client used
((PlayerSocketConnection) connection).refreshServerInformation(address, packet.serverPort(), packet.protocolVersion());
}
}
private static void disconnect(@NotNull PlayerConnection connection, @NotNull Component reason) {