diff --git a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java index c537d477d..6d3534f5a 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java @@ -158,6 +158,8 @@ public interface TabListEntry extends KeyIdentifiable { /** * Sets the {@link IdentifiedKey} of the {@link TabListEntry}. + *

This is only intended and only works for players currently not connected to this proxy.

+ *

For any player currently connected to this proxy this will be filled automatically.

* * @param playerKey key to set * @return {@code this}, for chaining diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index a369d79c9..33cae2f9a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -176,9 +176,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player, this.onlineMode = onlineMode; if (connection.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { - this.tabList = new VelocityTabList(this); + this.tabList = new VelocityTabList(this, server); } else { - this.tabList = new VelocityTabListLegacy(this); + this.tabList = new VelocityTabListLegacy(this, server); } this.playerKey = playerKey; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/crypto/IdentifiedKeyImpl.java b/proxy/src/main/java/com/velocitypowered/proxy/crypto/IdentifiedKeyImpl.java index f9eb028cb..b22371024 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/crypto/IdentifiedKeyImpl.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/crypto/IdentifiedKeyImpl.java @@ -17,6 +17,7 @@ package com.velocitypowered.proxy.crypto; +import com.google.common.base.Objects; import com.velocitypowered.api.proxy.crypto.IdentifiedKey; import java.nio.charset.StandardCharsets; import java.security.PublicKey; @@ -95,4 +96,20 @@ public class IdentifiedKeyImpl implements IdentifiedKey { + ", isSignatureValid=" + isSignatureValid + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof IdentifiedKey)) { + return false; + } + IdentifiedKey that = (IdentifiedKey) o; // This cannot be simplified because checkstyle doesn't like it. + + return Objects.equal(this.getSignedPublicKey(), that.getSignedPublicKey()) + && Objects.equal(this.getExpiryTemporal(), that.getExpiryTemporal()) + && Arrays.equals(this.getSignature(), that.getSignature()) + && Objects.equal(this.getSigner(), that.getSigner()); + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java index 0f1e6e04c..5dc9f3d57 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java @@ -18,6 +18,8 @@ package com.velocitypowered.proxy.tablist; import com.google.common.base.Preconditions; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.crypto.IdentifiedKey; import com.velocitypowered.api.proxy.player.TabList; import com.velocitypowered.api.proxy.player.TabListEntry; @@ -31,6 +33,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -41,10 +44,15 @@ public class VelocityTabList implements TabList { protected final ConnectedPlayer player; protected final MinecraftConnection connection; + protected final ProxyServer proxyServer; protected final Map entries = new ConcurrentHashMap<>(); - public VelocityTabList(final ConnectedPlayer player) { + /** + * Creates a new VelocityTabList. + */ + public VelocityTabList(final ConnectedPlayer player, final ProxyServer proxyServer) { this.player = player; + this.proxyServer = proxyServer; this.connection = player.getConnection(); } @@ -156,11 +164,29 @@ public class VelocityTabList implements TabList { if (name == null || properties == null) { throw new IllegalStateException("Got null game profile for ADD_PLAYER"); } + // Verify key + IdentifiedKey providedKey = item.getPlayerKey(); + Optional connected = proxyServer.getPlayer(uuid); + if (connected.isPresent()) { + IdentifiedKey expectedKey = connected.get().getIdentifiedKey(); + if (providedKey != null) { + if (!Objects.equals(expectedKey, providedKey)) { + throw new IllegalStateException("Server provided incorrect player key in playerlist for " + + name + " UUID: " + uuid); + } + } else { + // Substitute the key + // It shouldn't be propagated to remove the signature. + providedKey = expectedKey; + } + } + entries.putIfAbsent(item.getUuid(), (VelocityTabListEntry) TabListEntry.builder() .tabList(this) .profile(new GameProfile(uuid, name, properties)) .displayName(item.getDisplayName()) .latency(item.getLatency()) + .playerKey(providedKey) .gameMode(item.getGameMode()) .build()); break; @@ -199,6 +225,10 @@ public class VelocityTabList implements TabList { void updateEntry(int action, TabListEntry entry) { if (entries.containsKey(entry.getProfile().getId())) { PlayerListItem.Item packetItem = PlayerListItem.Item.from(entry); + + Optional existing = proxyServer.getPlayer(entry.getProfile().getId()); + existing.ifPresent(value -> packetItem.setPlayerKey(value.getIdentifiedKey())); + connection.write(new PlayerListItem(action, Collections.singletonList(packetItem))); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java index 95bfe6df1..567ae6bb5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java @@ -18,6 +18,7 @@ package com.velocitypowered.proxy.tablist; import com.google.common.collect.ImmutableList; +import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.player.TabListEntry; import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.proxy.connection.client.ConnectedPlayer; @@ -35,8 +36,8 @@ public class VelocityTabListLegacy extends VelocityTabList { private final Map nameMapping = new ConcurrentHashMap<>(); - public VelocityTabListLegacy(final ConnectedPlayer player) { - super(player); + public VelocityTabListLegacy(final ConnectedPlayer player, final ProxyServer proxyServer) { + super(player, proxyServer); } @Deprecated