Prepare for changes made in CloudburstMC/Protocol#205

This commit is contained in:
Tim203 2023-06-03 11:47:50 +02:00
parent 246ebddc78
commit c5d4b86564
No known key found for this signature in database
GPG key ID: 736F3CD49EF01DBF
26 changed files with 50 additions and 128 deletions

View file

@ -35,7 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;

View file

@ -41,7 +41,7 @@ import lombok.Setter;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;

View file

@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;

View file

@ -33,7 +33,7 @@ import org.cloudburstmc.math.vector.Vector3i;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.item;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Potion;

View file

@ -37,7 +37,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.codec.v567.Bedrock_v567;
import org.cloudburstmc.protocol.bedrock.codec.v575.Bedrock_v575;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.physics.PistonBehavior;

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;

View file

@ -30,8 +30,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.item.custom.CustomItemData;

View file

@ -42,9 +42,9 @@ import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.codec.v567.Bedrock_v567;
import org.cloudburstmc.protocol.bedrock.codec.v575.Bedrock_v575;
import org.cloudburstmc.protocol.bedrock.codec.v582.Bedrock_v582;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.registry.type;
import lombok.Builder;
import lombok.Value;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.common.DefinitionRegistry;
import java.util.Map;

View file

@ -26,7 +26,7 @@
package org.geysermc.geyser.registry.type;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
public class GeyserBedrockBlock implements BlockDefinition {
private final int runtimeId;

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.registry.type;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.geysermc.geyser.item.type.Item;
/**

View file

@ -30,8 +30,8 @@ import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;

View file

@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import lombok.Builder;
import lombok.Value;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.common.DefinitionRegistry;

View file

@ -60,7 +60,6 @@ import com.github.steveice10.packetlib.event.session.*;
import com.github.steveice10.packetlib.packet.Packet;
import com.github.steveice10.packetlib.tcp.TcpClientSession;
import com.github.steveice10.packetlib.tcp.TcpSession;
import com.nimbusds.jwt.SignedJWT;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@ -171,7 +170,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
* Used for Floodgate skin uploading
*/
@Setter
private List<SignedJWT> certChainData;
private List<String> certChainData;
@NotNull
@Setter

View file

@ -30,7 +30,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.nimbusds.jwt.SignedJWT;
import lombok.Getter;
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
import org.geysermc.floodgate.util.WebsocketEventType;
@ -191,14 +190,14 @@ public final class FloodgateSkinUploader {
};
}
public void uploadSkin(List<SignedJWT> chainData, String clientData) {
public void uploadSkin(List<String> chainData, String clientData) {
if (chainData == null || clientData == null) {
return;
}
ObjectNode node = JACKSON.createObjectNode();
ArrayNode chainDataNode = JACKSON.createArrayNode();
chainData.forEach(jwt -> chainDataNode.add(jwt.serialize()));
chainData.forEach(chainDataNode::add);
node.set("chain_data", chainDataNode);
node.put("client_data", clientData);

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.inventory.chest;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket;

View file

@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import it.unimi.dsi.fastutil.Pair;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.util.TriState;
import org.geysermc.geyser.registry.type.ItemMapping;

View file

@ -37,7 +37,7 @@ import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.GeyserItemStack;

View file

@ -39,7 +39,7 @@ import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryActionData;

View file

@ -37,7 +37,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUp
import it.unimi.dsi.fastutil.ints.*;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.MultiRecipeData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.recipe.RecipeData;

View file

@ -33,7 +33,7 @@ import lombok.experimental.UtilityClass;
import org.cloudburstmc.math.GenericMath;
import org.cloudburstmc.math.vector.Vector2i;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;

View file

@ -35,7 +35,7 @@ import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;

View file

@ -28,17 +28,12 @@ package org.geysermc.geyser.util;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.Payload;
import com.nimbusds.jose.shaded.json.JSONObject;
import com.nimbusds.jose.shaded.json.JSONValue;
import com.nimbusds.jwt.SignedJWT;
import org.cloudburstmc.protocol.bedrock.packet.LoginPacket;
import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket;
import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult;
import org.cloudburstmc.protocol.bedrock.util.ChainValidationResult.IdentityData;
import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils;
import org.cloudburstmc.protocol.common.util.Preconditions;
import org.geysermc.cumulus.form.CustomForm;
import org.geysermc.cumulus.form.ModalForm;
import org.geysermc.cumulus.form.SimpleForm;
@ -54,15 +49,9 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import javax.crypto.SecretKey;
import java.net.URI;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.function.BiConsumer;
public class LoginEncryptionUtils {
@ -70,106 +59,44 @@ public class LoginEncryptionUtils {
private static boolean HAS_SENT_ENCRYPTION_MESSAGE = false;
private static boolean validateChainData(List<SignedJWT> chain) throws Exception {
if (chain.size() != 3) {
return false;
}
Payload identity = null;
ECPublicKey lastKey = null;
boolean mojangSigned = false;
Iterator<SignedJWT> iterator = chain.iterator();
while (iterator.hasNext()) {
SignedJWT jwt = iterator.next();
identity = jwt.getPayload();
// x509 cert is expected in every claim
URI x5u = jwt.getHeader().getX509CertURL();
if (x5u == null) {
return false;
}
ECPublicKey expectedKey = EncryptionUtils.generateKey(jwt.getHeader().getX509CertURL().toString());
// First key is self-signed
if (lastKey == null) {
lastKey = expectedKey;
} else if (!lastKey.equals(expectedKey)) {
return false;
}
if (!EncryptionUtils.verifyJwt(jwt, lastKey)) {
return false;
}
if (mojangSigned) {
return !iterator.hasNext();
}
if (lastKey.equals(EncryptionUtils.getMojangPublicKey())) {
mojangSigned = true;
}
Object payload = JSONValue.parse(jwt.getPayload().toString());
Preconditions.checkArgument(payload instanceof JSONObject, "Payload is not an object");
Object identityPublicKey = ((JSONObject) payload).get("identityPublicKey");
Preconditions.checkArgument(identityPublicKey instanceof String, "identityPublicKey node is missing in chain");
lastKey = EncryptionUtils.generateKey((String) identityPublicKey);
}
return mojangSigned;
}
public static void encryptPlayerConnection(GeyserSession session, LoginPacket loginPacket) {
encryptConnectionWithCert(session, loginPacket.getExtra().getParsedString(), loginPacket.getChain());
encryptConnectionWithCert(session, loginPacket.getExtra(), loginPacket.getChain());
}
private static void encryptConnectionWithCert(GeyserSession session, String clientData, List<SignedJWT> certChainData) {
private static void encryptConnectionWithCert(GeyserSession session, String clientData, List<String> certChainData) {
try {
GeyserImpl geyser = session.getGeyser();
boolean validChain = validateChainData(certChainData);
ChainValidationResult result = EncryptionUtils.validateChain(certChainData);
geyser.getLogger().debug(String.format("Is player data valid? %s", validChain));
geyser.getLogger().debug(String.format("Is player data signed? %s", result.signed()));
if (!validChain && !session.getGeyser().getConfig().isEnableProxyConnections()) {
if (!result.signed() && !session.getGeyser().getConfig().isEnableProxyConnections()) {
session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.remote.invalid_xbox_account"));
return;
}
JWSObject jwt = certChainData.get(certChainData.size() - 1);
JsonNode payload = JSON_MAPPER.readTree(jwt.getPayload().toBytes());
if (payload.get("extraData").getNodeType() != JsonNodeType.OBJECT) {
throw new RuntimeException("AuthData was not found!");
}
JsonNode extraData = payload.get("extraData");
session.setAuthenticationData(new AuthData(
extraData.get("displayName").asText(),
UUID.fromString(extraData.get("identity").asText()),
extraData.get("XUID").asText()
));
IdentityData extraData = result.identityClaims().extraData;
session.setAuthenticationData(new AuthData(extraData.displayName, extraData.identity, extraData.xuid));
session.setCertChainData(certChainData);
if (payload.get("identityPublicKey").getNodeType() != JsonNodeType.STRING) {
throw new RuntimeException("Identity Public Key was not found!");
PublicKey identityPublicKey = result.identityClaims().parsedIdentityPublicKey();
byte[] clientDataPayload = EncryptionUtils.verifyClientData(clientData, identityPublicKey);
if (clientDataPayload == null) {
throw new IllegalStateException("Client data isn't signed by the given chain data");
}
ECPublicKey identityPublicKey = EncryptionUtils.generateKey(payload.get("identityPublicKey").textValue());
JWSObject clientJwt = JWSObject.parse(clientData);
EncryptionUtils.verifyJwt(clientJwt, identityPublicKey);
JsonNode clientDataJson = JSON_MAPPER.readTree(clientJwt.getPayload().toBytes());
JsonNode clientDataJson = JSON_MAPPER.readTree(clientDataPayload);
BedrockClientData data = JSON_MAPPER.convertValue(clientDataJson, BedrockClientData.class);
data.setOriginalString(clientData);
session.setClientData(data);
try {
LoginEncryptionUtils.startEncryptionHandshake(session, identityPublicKey);
startEncryptionHandshake(session, identityPublicKey);
} catch (Throwable e) {
// An error can be thrown on older Java 8 versions about an invalid key
if (geyser.getConfig().isDebugMode()) {
if (true || geyser.getConfig().isDebugMode()) {
e.printStackTrace();
}
@ -182,14 +109,11 @@ public class LoginEncryptionUtils {
}
private static void startEncryptionHandshake(GeyserSession session, PublicKey key) throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
generator.initialize(new ECGenParameterSpec("secp384r1"));
KeyPair serverKeyPair = generator.generateKeyPair();
KeyPair serverKeyPair = EncryptionUtils.createKeyPair();
byte[] token = EncryptionUtils.generateRandomToken();
ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket();
packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize());
packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token));
session.sendUpstreamPacketImmediately(packet);
SecretKey encryptionKey = EncryptionUtils.getSecretKey(serverKeyPair.getPrivate(), key, token);

View file

@ -30,8 +30,8 @@ package org.geysermc.geyser.translator.inventory.item;
//import com.github.steveice10.opennbt.tag.builtin.IntTag;
//import it.unimi.dsi.fastutil.Pair;
//import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
//import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
//import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleItemDefinition;
//import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
//import org.cloudburstmc.protocol.bedrock.data.definitions.SimpleItemDefinition;
//import org.geysermc.geyser.api.item.custom.CustomItemOptions;
//import org.geysermc.geyser.api.util.TriState;
//import org.geysermc.geyser.item.GeyserCustomItemOptions;