1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2026-01-04 15:31:48 +00:00

GeyserDump and legacy Spigot versions support. Made proxy data flexible

This commit is contained in:
Tim203
2020-12-01 23:18:22 +01:00
parent a92890174e
commit 01df0283e9
7 changed files with 131 additions and 35 deletions

View File

@@ -52,31 +52,31 @@ public final class HandshakeHandler {
try {
String[] dataArray = handshakeData.split("\0");
boolean isBungeeData = dataArray.length == 5;
// this can be Bungee data (without skin) or Floodgate data
if (dataArray.length == 4) {
isBungeeData = FloodgateCipher.hasHeader(dataArray[3]);
String data = null;
for (String value : dataArray) {
if (FloodgateCipher.hasHeader(value)) {
data = value;
break;
}
}
boolean proxy = configHolder.get().isProxy();
//todo remove this check
if (proxy && isBungeeData || !isBungeeData && dataArray.length != 2) {
if (data == null) {
return ResultType.NOT_FLOODGATE_DATA.getCachedResult();
}
// calculate the expected Base64 encoded IV length.
int expectedIvLength = 4 * ((AesCipher.IV_LENGTH + 2) / 3);
int lastSplitIndex = dataArray[1].lastIndexOf(0x21);
int lastSplitIndex = data.lastIndexOf(0x21);
byte[] floodgateData;
byte[] rawSkinData = null;
// if it has a RawSkin
if (lastSplitIndex - expectedIvLength != 0) {
floodgateData = dataArray[1].substring(0, lastSplitIndex).getBytes(Charsets.UTF_8);
rawSkinData = dataArray[1].substring(lastSplitIndex + 1).getBytes(Charsets.UTF_8);
floodgateData = data.substring(0, lastSplitIndex).getBytes(Charsets.UTF_8);
rawSkinData = data.substring(lastSplitIndex + 1).getBytes(Charsets.UTF_8);
} else {
floodgateData = dataArray[1].getBytes(Charsets.UTF_8);
floodgateData = data.getBytes(Charsets.UTF_8);
}
// actual decryption
@@ -137,9 +137,5 @@ public final class HandshakeHandler {
private final String[] handshakeData;
private final BedrockData bedrockData;
private final FloodgatePlayer floodgatePlayer;
public boolean isBungeeData() {
return handshakeData.length == 4 || handshakeData.length == 5;
}
}
}

View File

@@ -51,5 +51,7 @@ public class FloodgateConfigHolder {
public void set(FloodgateConfig config) {
this.config = config;
// for Geyser dump
org.geysermc.floodgate.util.FloodgateConfigHolder.setConfig(config);
}
}

View File

@@ -27,6 +27,7 @@ package org.geysermc.floodgate.addon.data;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.geysermc.floodgate.util.ReflectionUtils.getCastedValue;
import static org.geysermc.floodgate.util.ReflectionUtils.getField;
import static org.geysermc.floodgate.util.ReflectionUtils.getFieldOfType;
import static org.geysermc.floodgate.util.ReflectionUtils.getMethod;
import static org.geysermc.floodgate.util.ReflectionUtils.getPrefixedClass;
@@ -53,6 +54,7 @@ import org.geysermc.floodgate.util.ReflectionUtils;
@RequiredArgsConstructor
public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object> {
private static final Field IS_BUNGEE_DATA;
private static final Field SOCKET_ADDRESS;
private static final Class<?> HANDSHAKE_PACKET;
private static final Field HANDSHAKE_HOST;
@@ -74,6 +76,10 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
private static final Object READY_TO_ACCEPT_PROTOCOL_STATE;
static {
Class<?> spigotConfig = ReflectionUtils.getClass("org.spigotmc.SpigotConfig");
IS_BUNGEE_DATA = getField(spigotConfig, "bungee");
checkNotNull(IS_BUNGEE_DATA, "bungee field cannot be null. Are you using CraftBukkit?");
Class<?> networkManager = getPrefixedClass("NetworkManager");
checkNotNull(networkManager, "NetworkManager class cannot be null");
@@ -155,7 +161,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
private final FloodgateLogger logger;
private Object networkManager;
private FloodgatePlayer fPlayer;
private boolean bungee;
private boolean bungeeData;
private boolean done;
@Override
@@ -194,9 +200,11 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
fPlayer = result.getFloodgatePlayer();
BedrockData bedrockData = result.getBedrockData();
String[] data = result.getHandshakeData();
if (bungee = result.isBungeeData()) {
String[] data = result.getHandshakeData();
bungeeData = isBungeeData();
if (bungeeData) {
setValue(packet, HANDSHAKE_HOST, data[0] + '\0' +
bedrockData.getIp() + '\0' +
fPlayer.getCorrectUniqueId() +
@@ -213,7 +221,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
setValue(networkManager, SOCKET_ADDRESS, newAddress);
}
} else if (isLogin) {
if (!bungee) {
if (!bungeeData) {
// we have to fake the offline player (login) cycle
Object loginListener = PACKET_LISTENER.get(networkManager);
@@ -249,7 +257,7 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
ctx.fireChannelRead(packet);
}
if (isHandshake && bungee || isLogin && !bungee || fPlayer == null) {
if (isHandshake && bungeeData || isLogin && !bungeeData || fPlayer == null) {
// we're done, we'll just wait for the loginSuccessCall
done = true;
}
@@ -261,4 +269,9 @@ public final class SpigotDataHandler extends SimpleChannelInboundHandler<Object>
super.exceptionCaught(ctx, cause);
cause.printStackTrace();
}
@SuppressWarnings("ConstantConditions")
private boolean isBungeeData() {
return ReflectionUtils.getCastedValue(null, IS_BUNGEE_DATA);
}
}

View File

@@ -36,13 +36,17 @@ import org.geysermc.floodgate.platform.command.Command;
import org.geysermc.floodgate.platform.command.CommandRegistration;
import org.geysermc.floodgate.platform.command.CommandUtil;
import org.geysermc.floodgate.util.ReflectionUtils;
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
public final class SpigotCommandRegistration implements CommandRegistration {
private final SpigotVersionSpecificMethods versionSpecificMethods;
private final JavaPlugin plugin;
private final CommandUtil commandUtil;
private final CommandMap commandMap;
public SpigotCommandRegistration(JavaPlugin plugin, CommandUtil commandUtil) {
public SpigotCommandRegistration(SpigotVersionSpecificMethods versionSpecificMethods,
JavaPlugin plugin, CommandUtil commandUtil) {
this.versionSpecificMethods = versionSpecificMethods;
this.plugin = plugin;
this.commandUtil = commandUtil;
this.commandMap = ReflectionUtils.getCastedValue(Bukkit.getPluginManager(), "commandMap");
@@ -50,16 +54,21 @@ public final class SpigotCommandRegistration implements CommandRegistration {
@Override
public void register(Command command) {
commandMap.register("floodgate", new SpigotCommand(plugin, commandUtil, command));
SpigotCommand spigotCommand =
new SpigotCommand(versionSpecificMethods, plugin, commandUtil, command);
commandMap.register("floodgate", spigotCommand);
}
protected static class SpigotCommand extends org.bukkit.command.Command {
private final SpigotVersionSpecificMethods versionSpecificMethods;
private final JavaPlugin plugin;
private final CommandUtil commandUtil;
private final Command command;
protected SpigotCommand(JavaPlugin plugin, CommandUtil commandUtil, Command command) {
protected SpigotCommand(SpigotVersionSpecificMethods versionSpecificMethods,
JavaPlugin plugin, CommandUtil commandUtil, Command command) {
super(command.getName(), command.getDescription(), "", Collections.emptyList());
this.versionSpecificMethods = versionSpecificMethods;
this.plugin = plugin;
this.commandUtil = commandUtil;
this.command = command;
@@ -90,13 +99,7 @@ public final class SpigotCommandRegistration implements CommandRegistration {
}
Player player = (Player) sender;
String locale;
try {
locale = player.getLocale();
} catch (Exception exception) {
// server is older then 1.12.0
locale = player.spigot().getLocale();
}
String locale = versionSpecificMethods.getLocale(player);
command.execute(sender, player.getUniqueId(), sender.getName(), locale, args);
}

View File

@@ -51,6 +51,7 @@ import org.geysermc.floodgate.pluginmessage.SpigotSkinHandler;
import org.geysermc.floodgate.skin.SkinHandler;
import org.geysermc.floodgate.util.LanguageManager;
import org.geysermc.floodgate.util.SpigotCommandUtil;
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
@RequiredArgsConstructor
public final class SpigotPlatformModule extends AbstractModule {
@@ -87,8 +88,10 @@ public final class SpigotPlatformModule extends AbstractModule {
@Provides
@Singleton
public CommandRegistration commandRegistration(CommandUtil commandUtil) {
return new SpigotCommandRegistration(plugin, commandUtil);
public CommandRegistration commandRegistration(
SpigotVersionSpecificMethods versionSpecificMethods,
CommandUtil commandUtil) {
return new SpigotCommandRegistration(versionSpecificMethods, plugin, commandUtil);
}
@Provides
@@ -114,8 +117,11 @@ public final class SpigotPlatformModule extends AbstractModule {
@Provides
@Singleton
public SkinHandler skinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
SpigotVersionSpecificMethods versionSpecificMethods,
FloodgateConfigHolder configHolder) {
return new SpigotSkinHandler(messageHandler, logger, plugin, configHolder);
return new SpigotSkinHandler(
messageHandler, logger, versionSpecificMethods, plugin, configHolder
);
}
/*

View File

@@ -40,6 +40,7 @@ import org.geysermc.floodgate.platform.pluginmessage.PluginMessageHandler;
import org.geysermc.floodgate.skin.SkinHandler;
import org.geysermc.floodgate.skin.SkinUploader.UploadResult;
import org.geysermc.floodgate.util.ReflectionUtils;
import org.geysermc.floodgate.util.SpigotVersionSpecificMethods;
public class SpigotSkinHandler extends SkinHandler {
private static final Method GET_PROFILE_METHOD;
@@ -51,12 +52,15 @@ public class SpigotSkinHandler extends SkinHandler {
GET_PROFILE_METHOD = ReflectionUtils.getMethod(craftPlayerClass, "getProfile");
}
private final SpigotVersionSpecificMethods versionSpecificMethods;
private final SpigotPlugin plugin;
private final FloodgateConfigHolder configHolder;
public SpigotSkinHandler(PluginMessageHandler messageHandler, FloodgateLogger logger,
SpigotVersionSpecificMethods versionSpecificMethods,
SpigotPlugin plugin, FloodgateConfigHolder configHolder) {
super(messageHandler, logger);
this.versionSpecificMethods = versionSpecificMethods;
this.plugin = plugin;
this.configHolder = configHolder;
}
@@ -86,8 +90,8 @@ public class SpigotSkinHandler extends SkinHandler {
plugin.getServer().getScheduler().runTask(plugin, () -> {
for (Player p : Bukkit.getOnlinePlayers()) {
if (p != player) {
p.hidePlayer(plugin, player);
p.showPlayer(plugin, player);
versionSpecificMethods.hidePlayer(p, player);
versionSpecificMethods.showPlayer(p, player);
}
}
});

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Floodgate
*/
package org.geysermc.floodgate.util;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.geysermc.floodgate.SpigotPlugin;
public final class SpigotVersionSpecificMethods {
private static final boolean NEW_GET_LOCALE;
private static final boolean NEW_VISIBILITY;
static {
NEW_GET_LOCALE = ReflectionUtils.getMethod(Player.class, "getLocale") != null;
NEW_VISIBILITY = null != ReflectionUtils.getMethod(
Player.class, "hidePlayer",
Plugin.class, Player.class
);
}
private final SpigotPlugin plugin;
public SpigotVersionSpecificMethods(SpigotPlugin plugin) {
this.plugin = plugin;
}
public String getLocale(Player player) {
if (NEW_GET_LOCALE) {
return player.getLocale();
}
return player.spigot().getLocale();
}
public void hidePlayer(Player hideFor, Player playerToHide) {
if (NEW_VISIBILITY) {
hideFor.hidePlayer(plugin, playerToHide);
return;
}
hideFor.hidePlayer(playerToHide);
}
public void showPlayer(Player showFor, Player playerToShow) {
if (NEW_VISIBILITY) {
showFor.hidePlayer(plugin, playerToShow);
return;
}
showFor.hidePlayer(playerToShow);
}
}