From 6b489b5843769142365cb67fd967d04d914c99f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20N=C3=A9meth?= Date: Fri, 10 Jun 2022 17:01:30 +0200 Subject: [PATCH] Signature forwarding works --- .../audience/PacketGroupingAudience.java | 3 +- .../server/crypto/MessageSignature.java | 25 +++++++++++++ .../net/minestom/server/entity/Player.java | 3 +- .../server/listener/ChatMessageListener.java | 16 ++++----- .../server/message/MessageSender.java | 23 ++++++++++++ .../minestom/server/message/Messenger.java | 18 ++++++---- .../client/play/ClientChatMessagePacket.java | 15 +++----- .../server/play/PlayerChatMessagePacket.java | 35 +++++++++++-------- 8 files changed, 95 insertions(+), 43 deletions(-) create mode 100644 src/main/java/net/minestom/server/crypto/MessageSignature.java create mode 100644 src/main/java/net/minestom/server/message/MessageSender.java diff --git a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java index 062ecf41d..326f9a221 100644 --- a/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java +++ b/src/main/java/net/minestom/server/adventure/audience/PacketGroupingAudience.java @@ -58,7 +58,8 @@ public interface PacketGroupingAudience extends ForwardingAudience { @Override default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) { - Messenger.sendMessage(this.getPlayers(), message, ChatPosition.fromMessageType(type), source.uuid()); + // FIXME: 2022. 06. 10. +// Messenger.send(this.getPlayers(), message, ChatPosition.fromMessageType(type), source.uuid()); } @Override diff --git a/src/main/java/net/minestom/server/crypto/MessageSignature.java b/src/main/java/net/minestom/server/crypto/MessageSignature.java new file mode 100644 index 000000000..fbce6f5f1 --- /dev/null +++ b/src/main/java/net/minestom/server/crypto/MessageSignature.java @@ -0,0 +1,25 @@ +package net.minestom.server.crypto; + +import net.minestom.server.utils.binary.BinaryReader; +import net.minestom.server.utils.binary.BinaryWriter; +import net.minestom.server.utils.binary.Writeable; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.UUID; + +public record MessageSignature(Instant timestamp, long salt, byte[] signature) implements Writeable { + public static final UUID UNSIGNED_SENDER = new UUID(0,0); + public static final MessageSignature UNSIGNED = new MessageSignature(Instant.ofEpochMilli(0), 0, new byte[0]); + + public MessageSignature(BinaryReader reader) { + this(Instant.ofEpochMilli(reader.readLong()), reader.readLong(), reader.readByteArray()); + } + + @Override + public void write(@NotNull BinaryWriter writer) { + writer.writeLong(timestamp.toEpochMilli()); + writer.writeLong(salt); + writer.writeByteArray(signature); + } +} diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index c1378989a..993bfd4b4 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -24,6 +24,7 @@ import net.minestom.server.command.CommandSender; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; +import net.minestom.server.crypto.MessageSignature; import net.minestom.server.effects.Effects; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.fakeplayer.FakePlayer; @@ -672,7 +673,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable, * @param message the message that the player will send */ public void chat(@NotNull String message) { - addPacketToQueue(new ClientChatMessagePacket(message, 0, 0, new byte[0], false)); + addPacketToQueue(new ClientChatMessagePacket(message, MessageSignature.UNSIGNED, false)); } @Override diff --git a/src/main/java/net/minestom/server/listener/ChatMessageListener.java b/src/main/java/net/minestom/server/listener/ChatMessageListener.java index f82ca0e91..1aad230fe 100644 --- a/src/main/java/net/minestom/server/listener/ChatMessageListener.java +++ b/src/main/java/net/minestom/server/listener/ChatMessageListener.java @@ -1,13 +1,13 @@ package net.minestom.server.listener; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.event.ClickEvent; import net.minestom.server.MinecraftServer; import net.minestom.server.command.CommandManager; import net.minestom.server.entity.Player; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.player.PlayerChatEvent; import net.minestom.server.message.ChatPosition; +import net.minestom.server.message.MessageSender; import net.minestom.server.message.Messenger; import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.packet.client.play.ClientChatMessagePacket; @@ -58,20 +58,16 @@ public class ChatMessageListener { final Collection recipients = playerChatEvent.getRecipients(); if (!recipients.isEmpty()) { // delegate to the messenger to avoid sending messages we shouldn't be - Messenger.sendMessage(recipients, textObject, ChatPosition.CHAT, player.getUuid()); + Messenger.sendSignedPlayerMessage(recipients, textObject, ChatPosition.CHAT, + new MessageSender(player.getUuid(), player.getDisplayName() != null ? player.getDisplayName() : + Component.text(player.getUsername()), player.getTeam() == null ? + null : player.getTeam().getTeamDisplayName()), packet.signature()); } }); } private static @NotNull Component buildDefaultChatMessage(@NotNull Player player, @NotNull String message) { - final String username = player.getUsername(); - return Component.translatable("chat.type.text") - .args(Component.text(username) - .insertion(username) - .clickEvent(ClickEvent.suggestCommand("/msg " + username + " ")) - .hoverEvent(player), - Component.text(message) - ); + return Component.text(message); } } \ No newline at end of file diff --git a/src/main/java/net/minestom/server/message/MessageSender.java b/src/main/java/net/minestom/server/message/MessageSender.java new file mode 100644 index 000000000..574e04c79 --- /dev/null +++ b/src/main/java/net/minestom/server/message/MessageSender.java @@ -0,0 +1,23 @@ +package net.minestom.server.message; + +import net.kyori.adventure.text.Component; +import net.minestom.server.crypto.MessageSignature; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public record MessageSender(UUID uuid, @NotNull Component displayName, @Nullable Component teamName) { + + public static MessageSender forUnsigned(@NotNull Component displayName, @Nullable Component teamName) { + return new MessageSender(MessageSignature.UNSIGNED_SENDER, displayName, teamName); + } + + public static MessageSender forUnsigned(@NotNull Component displayName) { + return new MessageSender(MessageSignature.UNSIGNED_SENDER, displayName, null); + } + + public static MessageSender forSigned(@NotNull UUID uuid, @NotNull Component displayName) { + return new MessageSender(uuid, displayName, null); + } +} diff --git a/src/main/java/net/minestom/server/message/Messenger.java b/src/main/java/net/minestom/server/message/Messenger.java index 9df46169f..a85261657 100644 --- a/src/main/java/net/minestom/server/message/Messenger.java +++ b/src/main/java/net/minestom/server/message/Messenger.java @@ -2,7 +2,9 @@ package net.minestom.server.message; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.crypto.MessageSignature; import net.minestom.server.entity.Player; +import net.minestom.server.network.packet.server.play.PlayerChatMessagePacket; import net.minestom.server.network.packet.server.play.SystemChatPacket; import net.minestom.server.utils.PacketUtils; import org.jetbrains.annotations.NotNull; @@ -15,6 +17,7 @@ import java.io.StringReader; import java.util.Collection; import java.util.Objects; import java.util.UUID; +import java.util.stream.Collectors; /** * Utility class to handle client chat settings. @@ -24,7 +27,6 @@ public final class Messenger { * The message sent to the client if they send a chat message but it is rejected by the server. */ public static final Component CANNOT_SEND_MESSAGE = Component.translatable("chat.cannotSend", NamedTextColor.RED); - private static final UUID NO_SENDER = new UUID(0, 0); private static final SystemChatPacket CANNOT_SEND_PACKET = new SystemChatPacket(CANNOT_SEND_MESSAGE, ChatPosition.SYSTEM_MESSAGE.getID()); private static final NBTCompound CHAT_REGISTRY; @@ -246,6 +248,7 @@ public final class Messenger { * @param uuid the UUID of the sender, if any * @return if the message was sent */ + //fixme public static boolean sendMessage(@NotNull Player player, @NotNull Component message, @NotNull ChatPosition position, @Nullable UUID uuid) { if (getChatMessageType(player).accepts(position)) { player.sendPacket(new SystemChatPacket(message, 1)); @@ -257,15 +260,16 @@ public final class Messenger { /** * Sends a message to some players, respecting their chat settings. * - * @param players the players + * @param recipients the players * @param message the message * @param position the position - * @param uuid the UUID of the sender, if any */ - public static void sendMessage(@NotNull Collection players, @NotNull Component message, - @NotNull ChatPosition position, @Nullable UUID uuid) { - PacketUtils.sendGroupedPacket(players, new SystemChatPacket(message, 1), - player -> getChatMessageType(player).accepts(position)); + public static void sendSignedPlayerMessage(@NotNull Collection recipients, @NotNull Component message, + @NotNull ChatPosition position, @NotNull MessageSender sender, + @NotNull MessageSignature signature) { + PacketUtils.sendGroupedPacket(recipients.stream().filter(x -> x.getSettings().getChatMessageType() == null || + x.getSettings().getChatMessageType().accepts(position)).collect(Collectors.toList()), + PlayerChatMessagePacket.signed(message, position, sender, signature)); } /** diff --git a/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java index e8c79f050..012359f8e 100644 --- a/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/play/ClientChatMessagePacket.java @@ -1,13 +1,12 @@ package net.minestom.server.network.packet.client.play; +import net.minestom.server.crypto.MessageSignature; import net.minestom.server.network.packet.client.ClientPacket; import net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -public record ClientChatMessagePacket(@NotNull String message, - long timestamp, long salt, - byte[] signature, boolean signed) implements ClientPacket { +public record ClientChatMessagePacket(@NotNull String message, MessageSignature signature, boolean signedPreview) implements ClientPacket { public ClientChatMessagePacket { if (message.length() > 256) { throw new IllegalArgumentException("Message cannot be more than 256 characters long."); @@ -15,17 +14,13 @@ public record ClientChatMessagePacket(@NotNull String message, } public ClientChatMessagePacket(BinaryReader reader) { - this(reader.readSizedString(256), - reader.readLong(), reader.readLong(), - reader.readByteArray(), reader.readBoolean()); + this(reader.readSizedString(256), new MessageSignature(reader), reader.readBoolean()); } @Override public void write(@NotNull BinaryWriter writer) { writer.writeSizedString(message); - writer.writeLong(timestamp); - writer.writeLong(salt); - writer.writeByteArray(signature); - writer.writeBoolean(signed); + writer.write(signature); + writer.writeBoolean(signedPreview); } } diff --git a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java index 55c4ac94d..13ba75721 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/PlayerChatMessagePacket.java @@ -1,6 +1,9 @@ package net.minestom.server.network.packet.server.play; import net.kyori.adventure.text.Component; +import net.minestom.server.crypto.MessageSignature; +import net.minestom.server.message.ChatPosition; +import net.minestom.server.message.MessageSender; import net.minestom.server.network.packet.server.ComponentHoldingServerPacket; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; @@ -20,28 +23,32 @@ import java.util.function.UnaryOperator; public record PlayerChatMessagePacket(@NotNull Component signedContent, @Nullable Component unsignedContent, int type, @NotNull UUID uuid, @NotNull Component displayName, @Nullable Component teamDisplayName, - long timestamp, long salt, - byte[] signature) implements ComponentHoldingServerPacket { + @NotNull MessageSignature signature) implements ComponentHoldingServerPacket { public PlayerChatMessagePacket(BinaryReader reader) { - this(reader.readComponent(), reader.readBoolean() ? reader.readComponent() : null, - reader.readVarInt(), reader.readUuid(), - reader.readComponent(), reader.readBoolean() ? reader.readComponent() : null, - reader.readLong(), reader.readLong(), reader.readByteArray()); + this(reader.readComponent(), reader.readNullableComponent(), reader.readVarInt(), reader.readUuid(), + reader.readComponent(), reader.readNullableComponent(), new MessageSignature(reader)); + } + + public static PlayerChatMessagePacket unsigned(@NotNull Component message, ChatPosition type, @NotNull MessageSender sender) { + return new PlayerChatMessagePacket(message, null, type.getID(), MessageSignature.UNSIGNED_SENDER, + sender.displayName(), sender.teamName(), MessageSignature.UNSIGNED); + } + + public static PlayerChatMessagePacket signed(@NotNull Component message, ChatPosition type, @NotNull MessageSender sender, + @NotNull MessageSignature signature) { + return new PlayerChatMessagePacket(message, null, type.getID(), sender.uuid(), + sender.displayName(), sender.teamName(), signature); } @Override public void write(@NotNull BinaryWriter writer) { writer.writeComponent(signedContent); - writer.writeBoolean(unsignedContent != null); - if (unsignedContent != null) writer.writeComponent(unsignedContent); + writer.writeNullableComponent(unsignedContent); writer.writeVarInt(type); writer.writeUuid(uuid); writer.writeComponent(displayName); - writer.writeBoolean(teamDisplayName != null); - if (teamDisplayName != null) writer.writeComponent(teamDisplayName); - writer.writeLong(timestamp); - writer.writeLong(salt); - writer.writeByteArray(signature); + writer.writeNullableComponent(teamDisplayName); + writer.write(signature); } @Override @@ -57,6 +64,6 @@ public record PlayerChatMessagePacket(@NotNull Component signedContent, @Nullabl @Override public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator operator) { return new PlayerChatMessagePacket(signedContent, unsignedContent, type, - uuid, displayName, teamDisplayName, timestamp, salt, signature); + uuid, displayName, teamDisplayName, signature); } }