diff --git a/PaperSpigot-Server-Patches/0002-NMS-Imports.patch b/PaperSpigot-Server-Patches/0002-NMS-Imports.patch index fba271c21..b1c74c306 100644 --- a/PaperSpigot-Server-Patches/0002-NMS-Imports.patch +++ b/PaperSpigot-Server-Patches/0002-NMS-Imports.patch @@ -1,4 +1,4 @@ -From 7fee9dc3034109162551f2a2470f26ad2d0ce71b Mon Sep 17 00:00:00 2001 +From ffe864216f308380e78fc7cdc36d13000aebb758 Mon Sep 17 00:00:00 2001 From: Techcable Date: Sun, 16 Aug 2015 12:18:44 -0700 Subject: [PATCH] NMS Imports @@ -8,7 +8,7 @@ Only use code decompiled with BuildTools diff --git a/src/main/java/net/minecraft/server/BlockState.java b/src/main/java/net/minecraft/server/BlockState.java new file mode 100644 -index 0000000..3cada5a +index 00000000..3cada5af --- /dev/null +++ b/src/main/java/net/minecraft/server/BlockState.java @@ -0,0 +1,42 @@ @@ -56,7 +56,7 @@ index 0000000..3cada5a +} diff --git a/src/main/java/net/minecraft/server/BlockStateBoolean.java b/src/main/java/net/minecraft/server/BlockStateBoolean.java new file mode 100644 -index 0000000..7fb0960 +index 00000000..7fb09600 --- /dev/null +++ b/src/main/java/net/minecraft/server/BlockStateBoolean.java @@ -0,0 +1,29 @@ @@ -91,7 +91,7 @@ index 0000000..7fb0960 +} diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java new file mode 100644 -index 0000000..0b555df +index 00000000..0b555dff --- /dev/null +++ b/src/main/java/net/minecraft/server/BlockStateEnum.java @@ -0,0 +1,63 @@ @@ -160,7 +160,7 @@ index 0000000..0b555df +} diff --git a/src/main/java/net/minecraft/server/BlockStateInteger.java b/src/main/java/net/minecraft/server/BlockStateInteger.java new file mode 100644 -index 0000000..4e7e489 +index 00000000..4e7e489c --- /dev/null +++ b/src/main/java/net/minecraft/server/BlockStateInteger.java @@ -0,0 +1,67 @@ @@ -233,7 +233,7 @@ index 0000000..4e7e489 +} diff --git a/src/main/java/net/minecraft/server/BlockStateList.java b/src/main/java/net/minecraft/server/BlockStateList.java new file mode 100644 -index 0000000..8a815a6 +index 00000000..8a815a64 --- /dev/null +++ b/src/main/java/net/minecraft/server/BlockStateList.java @@ -0,0 +1,191 @@ @@ -430,7 +430,7 @@ index 0000000..8a815a6 +} diff --git a/src/main/java/net/minecraft/server/CommandScoreboard.java b/src/main/java/net/minecraft/server/CommandScoreboard.java new file mode 100644 -index 0000000..27d08a7 +index 00000000..27d08a7d --- /dev/null +++ b/src/main/java/net/minecraft/server/CommandScoreboard.java @@ -0,0 +1,1003 @@ @@ -1439,7 +1439,7 @@ index 0000000..27d08a7 +} diff --git a/src/main/java/net/minecraft/server/EULA.java b/src/main/java/net/minecraft/server/EULA.java new file mode 100644 -index 0000000..c872029 +index 00000000..c872029d --- /dev/null +++ b/src/main/java/net/minecraft/server/EULA.java @@ -0,0 +1,62 @@ @@ -1507,7 +1507,7 @@ index 0000000..c872029 +} diff --git a/src/main/java/net/minecraft/server/IBlockState.java b/src/main/java/net/minecraft/server/IBlockState.java new file mode 100644 -index 0000000..7e35d33 +index 00000000..7e35d335 --- /dev/null +++ b/src/main/java/net/minecraft/server/IBlockState.java @@ -0,0 +1,14 @@ @@ -1525,9 +1525,60 @@ index 0000000..7e35d33 + + String a(T t0); +} +diff --git a/src/main/java/net/minecraft/server/PacketDecoder.java b/src/main/java/net/minecraft/server/PacketDecoder.java +new file mode 100644 +index 00000000..bbebe3a9 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/PacketDecoder.java +@@ -0,0 +1,45 @@ ++package net.minecraft.server; ++ ++import io.netty.buffer.ByteBuf; ++import io.netty.channel.ChannelHandlerContext; ++import io.netty.handler.codec.ByteToMessageDecoder; ++import java.io.IOException; ++import java.util.List; ++import org.apache.logging.log4j.LogManager; ++import org.apache.logging.log4j.Logger; ++import org.apache.logging.log4j.Marker; ++import org.apache.logging.log4j.MarkerManager; ++ ++public class PacketDecoder extends ByteToMessageDecoder { ++ ++ private static final Logger a = LogManager.getLogger(); ++ private static final Marker b = MarkerManager.getMarker("PACKET_RECEIVED", NetworkManager.b); ++ private final EnumProtocolDirection c; ++ ++ public PacketDecoder(EnumProtocolDirection enumprotocoldirection) { ++ this.c = enumprotocoldirection; ++ } ++ ++ protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { ++ if (bytebuf.readableBytes() != 0) { ++ PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); ++ int i = packetdataserializer.e(); ++ Packet packet = ((EnumProtocol) channelhandlercontext.channel().attr(NetworkManager.c).get()).a(this.c, i); ++ ++ if (packet == null) { ++ throw new IOException("Bad packet id " + i); ++ } else { ++ packet.a(packetdataserializer); ++ if (packetdataserializer.readableBytes() > 0) { ++ throw new IOException("Packet " + ((EnumProtocol) channelhandlercontext.channel().attr(NetworkManager.c).get()).a() + "/" + i + " (" + packet.getClass().getSimpleName() + ") was larger than I expected, found " + packetdataserializer.readableBytes() + " bytes extra whilst reading packet " + i); ++ } else { ++ list.add(packet); ++ if (PacketDecoder.a.isDebugEnabled()) { ++ PacketDecoder.a.debug(PacketDecoder.b, " IN: [{}:{}] {}", new Object[] { channelhandlercontext.channel().attr(NetworkManager.c).get(), Integer.valueOf(i), packet.getClass().getName()}); ++ } ++ ++ } ++ } ++ } ++ } ++} diff --git a/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java b/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java new file mode 100644 -index 0000000..6385ab2 +index 00000000..6385ab2d --- /dev/null +++ b/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java @@ -0,0 +1,39 @@ @@ -1571,5 +1622,5 @@ index 0000000..6385ab2 + } +} -- -2.8.0 +2.13.0 diff --git a/PaperSpigot-Server-Patches/0018-Limit-the-length-of-buffered-bytes-to-read.patch b/PaperSpigot-Server-Patches/0018-Limit-the-length-of-buffered-bytes-to-read.patch index 951afb832..958ff6ef9 100644 --- a/PaperSpigot-Server-Patches/0018-Limit-the-length-of-buffered-bytes-to-read.patch +++ b/PaperSpigot-Server-Patches/0018-Limit-the-length-of-buffered-bytes-to-read.patch @@ -1,25 +1,64 @@ -From 4f0bb86504c547058285f7619d0f45933fd637f8 Mon Sep 17 00:00:00 2001 +From 3900793f7df11ef83cfcd62aaa98fcf1ba72d618 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Mon, 28 Mar 2016 15:41:31 -0700 Subject: [PATCH] Limit the length of buffered bytes to read -This is a particularly severe/exploitable issue -- clients can send packets forcing the server to allocate any valid array size, without actually sending any data for it to fill. This is fixed by limiting the size of read byte arrays to at most Short.MAX_VALUE. +This is a particularly severe/exploitable issue -- clients can send packets forcing the server to allocate any valid array size, without actually sending any data for it to fill. This is fixed by limiting the size of read byte arrays to at most Short.MAX_VALUE (31 KB). + +However, we have to make an exception for 1.7 ProtocolSupport clients, +or they will crash. For them we limit the packets to 31 MB, which should +still be plenty although it leaves the server slightly more vulnearable. The arrays in encryption packets are limited to 256 bytes. diff --git a/src/main/java/net/minecraft/server/PacketDataSerializer.java b/src/main/java/net/minecraft/server/PacketDataSerializer.java -index f426c2e..71ec6a7 100644 +index f426c2e1..b3f5c99e 100644 --- a/src/main/java/net/minecraft/server/PacketDataSerializer.java +++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java -@@ -46,9 +46,17 @@ public class PacketDataSerializer extends ByteBuf { +@@ -22,12 +22,30 @@ import java.nio.charset.Charset; + import java.util.UUID; + + import org.bukkit.craftbukkit.inventory.CraftItemStack; // CraftBukkit ++// TacoSpigot start ++import net.techcable.tacospigot.CompatHacks; ++// TacoSpigot end + + public class PacketDataSerializer extends ByteBuf { + + private final ByteBuf a; + +- public PacketDataSerializer(ByteBuf bytebuf) { ++ // TacoSpigot start ++ private final boolean allowLargePackets; ++ public PacketDataSerializer(ByteBuf buf) { ++ this(buf, null); ++ } ++ public PacketDataSerializer(ByteBuf bytebuf, EntityPlayer player) { ++ /* ++ * By default, we limit the size of the received byte array to Short.MAX_VALUE, which is 31 KB. ++ * However, we make an exception for 1.7 clients that are connected via ProtocolSupport, ++ * and limit them to 31 MEGABYTES as they seem to need to send larger packets sometimes. ++ * Although a 31 MB limit leaves the server slightly vulnerable, ++ * it's still much better than the old system of having no limit, ++ * which would leave the server vulnerable to packets up to 2 GIGABYTES in size. ++ */ ++ this.allowLargePackets = player != null && CompatHacks.isProtocolSupport17(player); ++ // TacoSpigot end + this.a = bytebuf; + } + +@@ -46,9 +64,20 @@ public class PacketDataSerializer extends ByteBuf { this.writeBytes(abyte); } + // TacoSpigot start ++ private static final int DEFAULT_LIMIT = Short.MAX_VALUE; ++ private static final int LARGE_PACKET_LIMIT = Short.MAX_VALUE * 1024; public byte[] a() { - byte[] abyte = new byte[this.e()]; -+ // TacoSpigot start - limit the size of the received byte array to Short.MAX_VALUE -+ return readByteArray(Short.MAX_VALUE); ++ // TacoSpigot start ++ int limit = allowLargePackets ? LARGE_PACKET_LIMIT : DEFAULT_LIMIT; ++ return readByteArray(limit); + } + public byte[] readByteArray(int limit) { @@ -30,8 +69,47 @@ index f426c2e..71ec6a7 100644 this.readBytes(abyte); return abyte; } +diff --git a/src/main/java/net/minecraft/server/PacketDecoder.java b/src/main/java/net/minecraft/server/PacketDecoder.java +index bbebe3a9..2f63a421 100644 +--- a/src/main/java/net/minecraft/server/PacketDecoder.java ++++ b/src/main/java/net/minecraft/server/PacketDecoder.java +@@ -9,12 +9,25 @@ import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; + import org.apache.logging.log4j.Marker; + import org.apache.logging.log4j.MarkerManager; ++// TacoSpigot start ++import java.lang.ref.WeakReference; ++// TacoSpigot end + + public class PacketDecoder extends ByteToMessageDecoder { + + private static final Logger a = LogManager.getLogger(); + private static final Marker b = MarkerManager.getMarker("PACKET_RECEIVED", NetworkManager.b); + private final EnumProtocolDirection c; ++ // TacoSpigot start ++ private WeakReference playerRef; ++ public void setPlayer(EntityPlayer p) { ++ playerRef = new WeakReference<>(p); ++ } ++ public EntityPlayer getPlayer() { ++ WeakReference playerRef = this.playerRef; ++ return playerRef != null ? playerRef.get() : null; ++ } ++ // TacoSpigot end + + public PacketDecoder(EnumProtocolDirection enumprotocoldirection) { + this.c = enumprotocoldirection; +@@ -22,7 +35,7 @@ public class PacketDecoder extends ByteToMessageDecoder { + + protected void decode(ChannelHandlerContext channelhandlercontext, ByteBuf bytebuf, List list) throws Exception { + if (bytebuf.readableBytes() != 0) { +- PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf); ++ PacketDataSerializer packetdataserializer = new PacketDataSerializer(bytebuf, this.getPlayer()); // TacoSpigot - pass player + int i = packetdataserializer.e(); + Packet packet = ((EnumProtocol) channelhandlercontext.channel().attr(NetworkManager.c).get()).a(this.c, i); + diff --git a/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java b/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java -index a591b2f..2d408b5 100644 +index a591b2f3..2d408b54 100644 --- a/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java +++ b/src/main/java/net/minecraft/server/PacketLoginInEncryptionBegin.java @@ -12,8 +12,10 @@ public class PacketLoginInEncryptionBegin implements Packet protocolApiClass = Class.forName("protocolsupport.api.ProtocolSupportAPI"); ++ Class protocolVersionClass = Class.forName("protocolsupport.api.ProtocolVersion"); ++ GET_PLAYER_PROTOCOL_VERSION_HANDLE = MethodHandles.publicLookup().findStatic( ++ protocolApiClass, ++ "getProtocolVersion", ++ MethodType.methodType( ++ protocolVersionClass, ++ Player.class ++ ) ++ ); ++ GET_PROTOCOL_VERSION_NAME_HANLDLE = MethodHandles.publicLookup().findVirtual( ++ protocolVersionClass, ++ "getName", ++ MethodType.methodType(String.class) ++ ); ++ } ++ public String getProtocolSupportVersion(EntityPlayer player) { ++ return SneakyThrows.sneakyThrowing(() -> { ++ Object protocolVersion = GET_PLAYER_PROTOCOL_VERSION_HANDLE.invoke(player.getBukkitEntity()); ++ if (protocolVersion != null) { ++ return (String) GET_PROTOCOL_VERSION_NAME_HANLDLE.invoke(protocolVersion); ++ } ++ return null; ++ }); ++ } ++ @Nullable ++ /* package */ static ProtocolSupportCompat create() { ++ try { ++ return new ProtocolSupportCompat(); ++ } catch (NoSuchMethodException | ClassNotFoundException ignored) { ++ return null; ++ } catch (IllegalAccessException e) { ++ throw new RuntimeException("Unexpected error enabling ProtocolSupport compat", e); ++ } ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/techcable/tacospigot/function/CheckedSupplier.java b/src/main/java/net/techcable/tacospigot/function/CheckedSupplier.java +new file mode 100644 +index 00000000..31216729 +--- /dev/null ++++ b/src/main/java/net/techcable/tacospigot/function/CheckedSupplier.java +@@ -0,0 +1,5 @@ ++package net.techcable.tacospigot.function; ++ ++public interface CheckedSupplier { ++ T get() throws Throwable; ++} +diff --git a/src/main/java/net/techcable/tacospigot/utils/SneakyThrows.java b/src/main/java/net/techcable/tacospigot/utils/SneakyThrows.java +new file mode 100644 +index 00000000..f5ef6200 +--- /dev/null ++++ b/src/main/java/net/techcable/tacospigot/utils/SneakyThrows.java +@@ -0,0 +1,22 @@ ++package net.techcable.tacospigot.utils; ++ ++import net.techcable.tacospigot.function.CheckedSupplier; ++ ++public class SneakyThrows { ++ private SneakyThrows() {} ++ ++ public static T sneakyThrowing(CheckedSupplier action) { ++ try { ++ return action.get(); ++ } catch (Throwable throwable) { ++ throw sneakyThrow0(throwable); ++ } ++ } ++ public static AssertionError sneakyThrow(Throwable t) { ++ throw SneakyThrows.sneakyThrow0(t); ++ } ++ @SuppressWarnings("unchecked") // The one time erasure is actually a good thing ++ private static AssertionError sneakyThrow0(Throwable t) throws T { ++ throw (T) t; ++ } ++} -- -2.7.4 +2.13.0