From 7ac5bddbc3c227e0ed9385904a2bd9621078e2de Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 19 Jan 2014 22:08:19 -0500 Subject: [PATCH] Allow indexed messages to validate themselves. Also, catch exceptions from an embedded channel, and cause them to close the connection. It's ugly, but it means that the client doesn't crash if it connects to a screwy bungycord that's trying a 1.6 handshake for some reason. --- .../FMLIndexedMessageToMessageCodec.java | 18 +++++++++++++----- .../network/internal/FMLProxyPacket.java | 18 +++++++++++++++++- .../network/internal/FMLRuntimeCodec.java | 17 ++++++++++++++++- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/main/java/cpw/mods/fml/common/network/FMLIndexedMessageToMessageCodec.java b/src/main/java/cpw/mods/fml/common/network/FMLIndexedMessageToMessageCodec.java index 6562d66813..a355a511a3 100644 --- a/src/main/java/cpw/mods/fml/common/network/FMLIndexedMessageToMessageCodec.java +++ b/src/main/java/cpw/mods/fml/common/network/FMLIndexedMessageToMessageCodec.java @@ -1,16 +1,14 @@ package cpw.mods.fml.common.network; -import java.util.List; - -import cpw.mods.fml.common.network.internal.FMLProxyPacket; - import gnu.trove.map.hash.TByteObjectHashMap; import gnu.trove.map.hash.TObjectByteHashMap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandler.Sharable; +import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageCodec; +import java.util.List; +import cpw.mods.fml.common.network.internal.FMLProxyPacket; @Sharable public abstract class FMLIndexedMessageToMessageCodec extends MessageToMessageCodec { @@ -43,6 +41,7 @@ public abstract class FMLIndexedMessageToMessageCodec extends MessageToMessag @Override protected final void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List out) throws Exception { + testMessageValidity(msg); ByteBuf payload = msg.payload(); byte discriminator = payload.readByte(); Class clazz = discriminators.get(discriminator); @@ -54,4 +53,13 @@ public abstract class FMLIndexedMessageToMessageCodec extends MessageToMessag decodeInto(ctx, payload.slice(), newMsg); out.add(newMsg); } + + /** + * Called to verify the message received. This can be used to hard disconnect in case of an unexpected packet, + * say due to a weird protocol mismatch. Use with caution. + * @param msg + */ + protected void testMessageValidity(FMLProxyPacket msg) + { + } } diff --git a/src/main/java/cpw/mods/fml/common/network/internal/FMLProxyPacket.java b/src/main/java/cpw/mods/fml/common/network/internal/FMLProxyPacket.java index 3f8732125c..af1e97596a 100644 --- a/src/main/java/cpw/mods/fml/common/network/internal/FMLProxyPacket.java +++ b/src/main/java/cpw/mods/fml/common/network/internal/FMLProxyPacket.java @@ -10,6 +10,9 @@ import net.minecraft.network.Packet; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.client.C17PacketCustomPayload; import net.minecraft.network.play.server.S3FPacketCustomPayload; +import org.apache.logging.log4j.Level; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.network.FMLNetworkException; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.handshake.NetworkDispatcher; import cpw.mods.fml.relauncher.Side; @@ -63,7 +66,20 @@ public class FMLProxyPacket extends Packet { if (internalChannel != null) { internalChannel.attr(NetworkRegistry.NET_HANDLER).set(this.netHandler); - internalChannel.writeInbound(this); + try + { + internalChannel.writeInbound(this); + } + catch (FMLNetworkException ne) + { + FMLLog.log(Level.ERROR, ne, "There was a network exception handling a packet on channel %s", channel); + dispatcher.rejectHandshake(ne.getMessage()); + } + catch (Throwable t) + { + FMLLog.log(Level.ERROR, t, "There was a critical exception handling a packet on channel %s", channel); + dispatcher.rejectHandshake("A fatal error has occured, this connection is terminated"); + } } } diff --git a/src/main/java/cpw/mods/fml/common/network/internal/FMLRuntimeCodec.java b/src/main/java/cpw/mods/fml/common/network/internal/FMLRuntimeCodec.java index 1d611a4eb5..d1f6ba99cc 100644 --- a/src/main/java/cpw/mods/fml/common/network/internal/FMLRuntimeCodec.java +++ b/src/main/java/cpw/mods/fml/common/network/internal/FMLRuntimeCodec.java @@ -1,8 +1,11 @@ package cpw.mods.fml.common.network.internal; -import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; +import com.google.common.primitives.Bytes; +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec; +import cpw.mods.fml.common.network.FMLNetworkException; public class FMLRuntimeCodec extends FMLIndexedMessageToMessageCodec { public FMLRuntimeCodec() @@ -24,4 +27,16 @@ public class FMLRuntimeCodec extends FMLIndexedMessageToMessageCodec msg.fromBytes(source); } + @Override + protected void testMessageValidity(FMLProxyPacket msg) + { + if (msg.payload().getByte(0) == 0 && msg.payload().readableBytes() > 2) + { + FMLLog.severe("The connection appears to have sent an invalid FML packet of type 0, this is likely because it think's it's talking to 1.6.4 FML"); + byte[] badData = new byte[msg.payload().readableBytes()]; + msg.payload().getBytes(0, badData); + FMLLog.info("Bad data : %s",Bytes.asList(badData)); + throw new FMLNetworkException("Invalid FML packet"); + } + } }