More kicking

Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
This commit is contained in:
Joshua Castle 2024-04-10 03:18:28 -07:00
parent 92d46424c3
commit decce7ce27
No known key found for this signature in database
GPG key ID: 7ECA1A2FC38ABA9F
2 changed files with 118 additions and 25 deletions

View file

@ -27,23 +27,37 @@ package org.geysermc.geyser.network;
import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
import com.github.steveice10.mc.protocol.codec.PacketCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper;
import org.cloudburstmc.protocol.bedrock.codec.BedrockPacketSerializer;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipmentSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622; import org.cloudburstmc.protocol.bedrock.codec.v622.Bedrock_v622;
import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630; import org.cloudburstmc.protocol.bedrock.codec.v630.Bedrock_v630;
import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649; import org.cloudburstmc.protocol.bedrock.codec.v649.Bedrock_v649;
import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662; import org.cloudburstmc.protocol.bedrock.codec.v662.Bedrock_v662;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.cloudburstmc.protocol.bedrock.packet.ClientCacheBlobStatusPacket; import org.cloudburstmc.protocol.bedrock.packet.ClientCacheBlobStatusPacket;
import org.cloudburstmc.protocol.bedrock.packet.ClientCheatAbilityPacket; import org.cloudburstmc.protocol.bedrock.packet.ClientCheatAbilityPacket;
import org.cloudburstmc.protocol.bedrock.packet.CraftingEventPacket;
import org.cloudburstmc.protocol.bedrock.packet.CreatePhotoPacket; import org.cloudburstmc.protocol.bedrock.packet.CreatePhotoPacket;
import org.cloudburstmc.protocol.bedrock.packet.EditorNetworkPacket; import org.cloudburstmc.protocol.bedrock.packet.EditorNetworkPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.cloudburstmc.protocol.bedrock.packet.LabTablePacket; import org.cloudburstmc.protocol.bedrock.packet.LabTablePacket;
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.PhotoTransferPacket; import org.cloudburstmc.protocol.bedrock.packet.PhotoTransferPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket; import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket;
import org.cloudburstmc.protocol.bedrock.packet.SubClientLoginPacket; import org.cloudburstmc.protocol.bedrock.packet.SubClientLoginPacket;
import org.cloudburstmc.protocol.common.util.VarInts;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList; import java.util.ArrayList;
@ -176,24 +190,102 @@ public final class GameProtocol {
private static BedrockCodec processCodec(BedrockCodec codec) { private static BedrockCodec processCodec(BedrockCodec codec) {
return codec.toBuilder() return codec.toBuilder()
// De-register unused serverbound EDU packets // Illegal unused serverbound EDU packets
.deregisterPacket(PhotoTransferPacket.class) .updateSerializer(PhotoTransferPacket.class, setIllegalSerializer())
.deregisterPacket(LabTablePacket.class) .updateSerializer(LabTablePacket.class, setIllegalSerializer())
.deregisterPacket(CreatePhotoPacket.class) .updateSerializer(CreatePhotoPacket.class, setIllegalSerializer())
.deregisterPacket(PhotoInfoRequestPacket.class) .updateSerializer(PhotoInfoRequestPacket.class, setIllegalSerializer())
// De-register unused serverbound packets for featured servers // Illegal unused serverbound packets for featured servers
.deregisterPacket(PurchaseReceiptPacket.class) .updateSerializer(PurchaseReceiptPacket.class, setIllegalSerializer())
// De-register unused serverbound packets for editor // Illegal unused serverbound packets for editor
.deregisterPacket(EditorNetworkPacket.class) .updateSerializer(EditorNetworkPacket.class, setIllegalSerializer())
// De-register unused serverbound packets that are deprecated // Illegal unused serverbound packets that are deprecated
.deregisterPacket(ClientCheatAbilityPacket.class) .updateSerializer(ClientCheatAbilityPacket.class, setIllegalSerializer())
// De-register unused serverbound packets that relate to unused features // Illegal unusued serverbound packets that relate to unused features
.deregisterPacket(PlayerAuthInputPacket.class) .updateSerializer(PlayerAuthInputPacket.class, setIllegalSerializer())
.deregisterPacket(ClientCacheBlobStatusPacket.class) .updateSerializer(ClientCacheBlobStatusPacket.class, setIllegalSerializer())
.deregisterPacket(SubClientLoginPacket.class) .updateSerializer(SubClientLoginPacket.class, setIllegalSerializer())
// Illegal serverbound packets due to Geyser specific setup
.updateSerializer(InventoryContentPacket.class, new InventoryContentSerializer_v407() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!");
}
})
.updateSerializer(InventorySlotPacket.class, new InventorySlotSerializer_v407() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) {
throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!");
}
})
// Ignored serverbound packets
.updateSerializer(CraftingEventPacket.class, getIgnoredSerializer()) // Make illegal when 1.20.40 is removed
// Ignored only when serverbound
.updateSerializer(MobArmorEquipmentPacket.class, new MobArmorEquipmentSerializer_v291() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobArmorEquipmentPacket packet) {
}
})
// Valid serverbound packets where reading of some fields can be skipped
.updateSerializer(MobEquipmentPacket.class, new MobEquipmentSerializer_v291() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MobEquipmentPacket packet) {
packet.setRuntimeEntityId(VarInts.readUnsignedLong(buffer));
fakeItemRead(buffer);
packet.setInventorySlot(buffer.readUnsignedByte());
packet.setHotbarSlot(buffer.readUnsignedByte());
packet.setContainerId(buffer.readByte());
}
})
.build(); .build();
} }
/**
* Fake reading an item from the buffer to improve performance.
*
* @param buffer
*/
private static void fakeItemRead(ByteBuf buffer) {
VarInts.readInt(buffer); // Runtime ID
buffer.skipBytes(2); // count
VarInts.readUnsignedInt(buffer); // damage
boolean hasNetId = buffer.readBoolean();
if (hasNetId) {
VarInts.readInt(buffer);
}
VarInts.readInt(buffer); // Block runtime ID
int streamSize = VarInts.readInt(buffer);
buffer.skipBytes(streamSize);
}
private static <T extends BedrockPacket> BedrockPacketSerializer<T> setIllegalSerializer() {
return new BedrockPacketSerializer<T>() {
@Override
public void serialize(ByteBuf buffer, BedrockCodecHelper helper, T packet) {
throw new IllegalArgumentException("Server tried to send unused packet " + packet.getClass().getSimpleName() + "!");
}
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, T packet) {
throw new IllegalArgumentException("Client tried to send unused packet " + packet.getClass().getSimpleName() + "!");
}
};
}
private static <T extends BedrockPacket> BedrockPacketSerializer<T> getIgnoredSerializer() {
return new BedrockPacketSerializer<T>() {
@Override
public void serialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) {
}
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) {
}
};
}
private GameProtocol() { private GameProtocol() {
} }
} }

View file

@ -27,10 +27,11 @@ package org.geysermc.geyser.network;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.DecoderException;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import java.util.stream.Stream;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InvalidPacketHandler extends ChannelInboundHandlerAdapter { public class InvalidPacketHandler extends ChannelInboundHandlerAdapter {
public static final String NAME = "rak-error-handler"; public static final String NAME = "rak-error-handler";
@ -39,19 +40,19 @@ public class InvalidPacketHandler extends ChannelInboundHandlerAdapter {
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (!(cause instanceof DecoderException)) { Throwable rootCause = Stream.iterate(cause, Throwable::getCause)
.filter(element -> element.getCause() == null)
.findFirst()
.orElse(cause);
if (!(rootCause instanceof IllegalArgumentException)) {
super.exceptionCaught(ctx, cause); super.exceptionCaught(ctx, cause);
return; return;
} }
Throwable actualCause = cause.getCause(); // Kick users that try to send illegal packets
session.getGeyser().getLogger().warning(rootCause.getMessage());
if (!(actualCause instanceof IllegalArgumentException)) {
super.exceptionCaught(ctx, actualCause);
return;
}
// Kick users that try to send Clientbound packets
session.disconnect("Invalid packet received!"); session.disconnect("Invalid packet received!");
} }
} }