diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java index d1101d6a5a..5ef7e1ce6a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftSessionHandler.java @@ -67,6 +67,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerChatPacket; import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerCommandPacket; import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.session.ChatSessionUpdatePacket; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket; import com.velocitypowered.proxy.protocol.packet.config.ActiveFeaturesPacket; @@ -280,6 +281,10 @@ default boolean handle(SessionPlayerChatPacket packet) { return false; } + default boolean handle(ChatSessionUpdatePacket packet) { + return false; + } + default boolean handle(SystemChatPacket packet) { return false; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 8880233bb3..4025f8314b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -31,6 +31,7 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; +import com.velocitypowered.proxy.config.PlayerInfoForwarding; import com.velocitypowered.proxy.connection.ConnectionTypes; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; @@ -65,6 +66,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatHandler; import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyCommandHandler; +import com.velocitypowered.proxy.protocol.packet.chat.session.ChatSessionUpdatePacket; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionChatHandler; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionCommandHandler; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket; @@ -241,6 +243,30 @@ public boolean handle(ClientSettingsPacket packet) { return true; // will forward onto the server } + @Override + public boolean handle(ChatSessionUpdatePacket packet) { + // If client UUIDs are not forwarded to the backend, the client players's + // profile key signature will not be valid for the backend player's offline + // UUID, and the backend will kick the client with "Invalid signature for + // profile public key". The Notchian server does not require the client to + // send this packet if enforce-secure-profile=false, so we can simply + // filter it. + + // Note: if the Notchian client did not receive a valid profile key pair + // from the authentication server, it also will not send this packet to the + // server (net/minecraft/client/multiplayer/ClientPacketListener.java). + if (server.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.NONE) { + return true; + } + + VelocityServerConnection serverConnection = player.getConnectedServer(); + if (serverConnection == null) { + return true; + } + serverConnection.ensureConnected().write(packet); + return true; + } + @Override public boolean handle(SessionPlayerCommandPacket packet) { if (player.getCurrentServer().isEmpty()) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index 2971087685..97e65de46d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -102,6 +102,7 @@ import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerChatPacket; import com.velocitypowered.proxy.protocol.packet.chat.keyed.KeyedPlayerCommandPacket; import com.velocitypowered.proxy.protocol.packet.chat.legacy.LegacyChatPacket; +import com.velocitypowered.proxy.protocol.packet.chat.session.ChatSessionUpdatePacket; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerChatPacket; import com.velocitypowered.proxy.protocol.packet.chat.session.SessionPlayerCommandPacket; import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerCommandPacket; @@ -321,6 +322,19 @@ public enum StateRegistry { map(0x07, MINECRAFT_1_21_2, false), map(0x08, MINECRAFT_1_21_6, false), map(0x09, MINECRAFT_26_1, false)); + serverbound.register( + ChatSessionUpdatePacket.class, + ChatSessionUpdatePacket::new, + map(0x20, MINECRAFT_1_19_3, false), + map(0x06, MINECRAFT_1_19_4, false), + map(0x06, MINECRAFT_1_20_2, false), + map(0x07, MINECRAFT_1_20_5, false), + map(0x07, MINECRAFT_1_21, false), + map(0x08, MINECRAFT_1_21_2, false), + map(0x08, MINECRAFT_1_21_4, false), + map(0x09, MINECRAFT_1_21_6, false), + map(0x09, MINECRAFT_1_21_9, false), + map(0x0A, MINECRAFT_26_1, false)); serverbound.register( ClientSettingsPacket.class, ClientSettingsPacket::new, diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/ChatSessionUpdatePacket.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/ChatSessionUpdatePacket.java new file mode 100644 index 0000000000..40156dd903 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/chat/session/ChatSessionUpdatePacket.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2018-2023 Velocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.velocitypowered.proxy.protocol.packet.chat.session; + +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.protocol.MinecraftPacket; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; +import java.util.UUID; + +public class ChatSessionUpdatePacket implements MinecraftPacket { + + private UUID sessionId; + private long expiresAt; + private byte[] publicKey; + private byte[] keySignature; + + public ChatSessionUpdatePacket() { + } + + @Override + public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + this.sessionId = ProtocolUtils.readUuid(buf); + this.expiresAt = buf.readLong(); + this.publicKey = ProtocolUtils.readByteArray(buf, 512); + this.keySignature = ProtocolUtils.readByteArray(buf, 4096); + } + + @Override + public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion) { + ProtocolUtils.writeUuid(buf, sessionId); + buf.writeLong(expiresAt); + ProtocolUtils.writeByteArray(buf, publicKey); + ProtocolUtils.writeByteArray(buf, keySignature); + } + + @Override + public boolean handle(MinecraftSessionHandler handler) { + return handler.handle(this); + } +}