Fixes 1.19.2 -> 1.19.0 Protocol (#200)

* implemented 1.19.2 -> 1.19.0 Signatures

* moved Protocol Patching

* removed old loading

* some finally improvements

* fixed compile issue

* finally fixed edge-case

* resolve conflict #1
This commit is contained in:
F 2022-11-05 23:08:10 +01:00 committed by GitHub
parent 7622f73a74
commit 683a7128b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 279 additions and 3 deletions

View File

@ -36,6 +36,10 @@ public abstract class AbstractFabricVersionProvider extends BaseVersionProvider
multiconnectIntegration();
}
// This method indicates the correct clientside version, in case Auto Detect is used you still need the version that ViaVersion uses
public void onFinallySetVersion(final int realClientsideVersion) {
}
private void multiconnectIntegration() {
if (!FabricLoader.getInstance().isModLoaded("multiconnect")) return;
try {
@ -102,6 +106,7 @@ public abstract class AbstractFabricVersionProvider extends BaseVersionProvider
if (blocked || !supported) serverVer = info.getProtocolVersion();
this.onFinallySetVersion(serverVer);
return serverVer;
}
NativeVersionProvider natProvider = Via.getManager().getProviders().get(NativeVersionProvider.class);

View File

@ -5,3 +5,7 @@ dependencies {
modImplementation("net.fabricmc.fabric-api:fabric-api:0.60.0+1.19.2")
modImplementation("com.terraformersmc:modmenu:4.0.6")
}
tasks.compileJava {
options.release.set(17)
}

View File

@ -12,6 +12,7 @@ import com.viaversion.fabric.common.util.JLoggerToLog4j;
import com.viaversion.fabric.mc119.commands.VRCommandHandler;
import com.viaversion.fabric.mc119.platform.FabricPlatform;
import com.viaversion.fabric.mc119.platform.VFLoader;
import com.viaversion.fabric.mc119.signatures1_19_0.ProtocolPatcher1_19_0;
import com.viaversion.viaversion.ViaManagerImpl;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.MappingDataLoader;
@ -83,6 +84,8 @@ public class ViaFabric implements ModInitializer {
config = new VFConfig(FabricLoader.getInstance().getConfigDir().resolve("ViaFabric")
.resolve("viafabric.yml").toFile());
ProtocolPatcher1_19_0.patch();
INIT_FUTURE.complete(null);
}

View File

@ -0,0 +1,35 @@
package com.viaversion.fabric.mc119.mixin.signatures1_19_0;
import com.viaversion.fabric.mc119.signatures1_19_0.MessageSigner1_19_0;
import com.viaversion.fabric.mc119.signatures1_19_0.ProtocolPatcher1_19_0;
import net.minecraft.command.argument.DecoratableArgumentList;
import net.minecraft.network.encryption.Signer;
import net.minecraft.network.message.ArgumentSignatureDataMap;
import net.minecraft.network.message.MessageMetadata;
import net.minecraft.network.message.MessageSignatureData;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
import java.util.stream.Collectors;
@Mixin(ArgumentSignatureDataMap.class)
public class ArgumentSignatureDataMapMixin {
@Inject(method = "sign", at = @At("HEAD"), cancellable = true)
private static void injectSign(DecoratableArgumentList<?> arguments, ArgumentSignatureDataMap.ArgumentSigner signer, CallbackInfoReturnable<ArgumentSignatureDataMap> cir) {
if (ProtocolPatcher1_19_0.shouldFixKeys) {
final List<ArgumentSignatureDataMap.Entry> list = ArgumentSignatureDataMap.toNameValuePairs(arguments).stream().map(entry -> {
final MessageMetadata metadata = MessageSigner1_19_0.get();
final MessageSignatureData messageSignatureData = MessageSigner1_19_0.sign((Signer) signer, Text.literal(entry.getFirst()), metadata.sender(), metadata.timestamp(), metadata.salt());
return new ArgumentSignatureDataMap.Entry(entry.getFirst(), messageSignatureData);
}).collect(Collectors.toList());
cir.setReturnValue(new ArgumentSignatureDataMap(list));
}
}
}

View File

@ -0,0 +1,44 @@
package com.viaversion.fabric.mc119.mixin.signatures1_19_0;
import com.mojang.brigadier.ParseResults;
import com.viaversion.fabric.mc119.signatures1_19_0.MessageSigner1_19_0;
import com.viaversion.fabric.mc119.signatures1_19_0.ProtocolPatcher1_19_0;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.command.CommandSource;
import net.minecraft.network.encryption.Signer;
import net.minecraft.network.message.*;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerEntity.class)
public class ClientPlayerEntityMixin {
@Shadow
@Final
protected MinecraftClient client;
@Inject(method = "signChatMessage", at = @At("HEAD"), cancellable = true)
public void injectSignChatMessage(MessageMetadata metadata, DecoratedContents content, LastSeenMessageList lastSeenMessages, CallbackInfoReturnable<MessageSignatureData> cir) {
if (ProtocolPatcher1_19_0.shouldFixKeys) {
try {
final Signer signer = this.client.getProfileKeys().getSigner();
if (signer != null)
cir.setReturnValue(MessageSigner1_19_0.sign(signer, content.decorated(), metadata.sender(), metadata.timestamp(), metadata.salt()));
} catch (Exception ignored) {}
cir.cancel();
}
}
@Inject(method = "signArguments", at = @At(value = "HEAD"))
public void injectSignArguments(MessageMetadata signer, ParseResults<CommandSource> parseResults, @Nullable Text preview, LastSeenMessageList lastSeenMessages, CallbackInfoReturnable<ArgumentSignatureDataMap> cir) {
MessageSigner1_19_0.track(signer);
}
}

View File

@ -0,0 +1,51 @@
package com.viaversion.fabric.mc119.mixin.signatures1_19_0;
import com.viaversion.fabric.mc119.signatures1_19_0.IPublicKeyData;
import com.viaversion.fabric.mc119.signatures1_19_0.ProtocolPatcher1_19_0;
import net.minecraft.network.encryption.NetworkEncryptionUtils;
import net.minecraft.network.encryption.PlayerPublicKey;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.time.Instant;
import java.util.UUID;
@Mixin(PlayerPublicKey.PublicKeyData.class)
public class PlayerPublicKeyChPublicKeyDataMixin implements IPublicKeyData {
@Shadow @Final private Instant expiresAt;
@Shadow @Final
PublicKey key;
@Unique
private byte[] _1_19_0Key;
@Redirect(method = { "write", "verifyKey" }, at = @At(value = "FIELD", target = "Lnet/minecraft/network/encryption/PlayerPublicKey$PublicKeyData;keySignature:[B"))
public byte[] replaceKeys(PlayerPublicKey.PublicKeyData instance) {
if (this._1_19_0Key != null && ProtocolPatcher1_19_0.shouldFixKeys)
return this._1_19_0Key;
return instance.keySignature();
}
@Inject(method = "toSerializedString", at = @At(value = "HEAD"), cancellable = true)
public void injectToSerializedString(UUID playerUuid, CallbackInfoReturnable<byte[]> cir) {
if (ProtocolPatcher1_19_0.shouldFixKeys)
cir.setReturnValue((this.expiresAt.toEpochMilli() + NetworkEncryptionUtils.encodeRsaPublicKey(this.key)).getBytes(StandardCharsets.UTF_8));
}
@Override
public void set1_19_0Key(ByteBuffer byteBuffer) {
this._1_19_0Key = byteBuffer.array();
}
}

View File

@ -0,0 +1,19 @@
package com.viaversion.fabric.mc119.mixin.signatures1_19_0;
import com.mojang.authlib.yggdrasil.response.KeyPairResponse;
import com.viaversion.fabric.mc119.signatures1_19_0.IPublicKeyData;
import net.minecraft.client.util.ProfileKeys;
import net.minecraft.network.encryption.PlayerPublicKey;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ProfileKeys.class)
public class ProfileKeysMixin {
@Inject(method = "decodeKeyPairResponse", at = @At("RETURN"))
private static void trackLegacyKey(KeyPairResponse keyPairResponse, CallbackInfoReturnable<PlayerPublicKey.PublicKeyData> cir) {
((IPublicKeyData) (Object) cir.getReturnValue()).set1_19_0Key(keyPairResponse.getLegacyPublicKeySignature());
}
}

View File

@ -4,6 +4,7 @@ import com.viaversion.fabric.common.config.VFConfig;
import com.viaversion.fabric.common.provider.AbstractFabricVersionProvider;
import com.viaversion.fabric.mc119.ViaFabric;
import com.viaversion.fabric.mc119.service.ProtocolAutoDetector;
import com.viaversion.fabric.mc119.signatures1_19_0.ProtocolPatcher1_19_0;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.channel.ChannelPipeline;
import net.minecraft.network.ClientConnection;
@ -28,9 +29,13 @@ public class FabricVersionProvider extends AbstractFabricVersionProvider {
return ProtocolAutoDetector.detectVersion(address);
}
@Override
public void onFinallySetVersion(int realClientsideVersion) {
ProtocolPatcher1_19_0.shouldFixKeys = realClientsideVersion <= ProtocolVersion.v1_19.getVersion();
}
@Override
protected boolean isMulticonnectHandler(ChannelPipeline pipe) {
return pipe.get(ClientConnection.class).getPacketListener()
.getClass().getName().startsWith("net.earthcomputer.multiconnect");
return pipe.get(ClientConnection.class).getPacketListener().getClass().getName().startsWith("net.earthcomputer.multiconnect");
}
}

View File

@ -0,0 +1,8 @@
package com.viaversion.fabric.mc119.signatures1_19_0;
import java.nio.ByteBuffer;
public interface IPublicKeyData {
void set1_19_0Key(final ByteBuffer byteBuffer);
}

View File

@ -0,0 +1,44 @@
package com.viaversion.fabric.mc119.signatures1_19_0;
import net.minecraft.network.encryption.Signer;
import net.minecraft.network.message.MessageMetadata;
import net.minecraft.network.message.MessageSignatureData;
import net.minecraft.text.Text;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class MessageSigner1_19_0 {
public static final List<MessageMetadata> TRACKED_METADATA_LIST = new ArrayList<>();
public static MessageMetadata get() {
MessageMetadata i = TRACKED_METADATA_LIST.get(TRACKED_METADATA_LIST.size() - 1);
TRACKED_METADATA_LIST.remove(i);
return i;
}
public static void track(final MessageMetadata metadata) {
TRACKED_METADATA_LIST.add(metadata);
}
public static MessageSignatureData sign(Signer signer, Text decorateText, final UUID sender, final Instant timeStamp, final long salt) {
return new MessageSignatureData(signer.sign((sign -> {
final byte[] data = new byte[32];
final ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN);
buffer.putLong(salt);
buffer.putLong(sender.getMostSignificantBits()).putLong(sender.getLeastSignificantBits());
buffer.putLong(timeStamp.getEpochSecond());
sign.update(data);
sign.update(Text.Serializer.toSortedJsonString(decorateText).getBytes(StandardCharsets.UTF_8));
})));
}
}

View File

@ -0,0 +1,41 @@
package com.viaversion.fabric.mc119.signatures1_19_0;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.Protocol1_19_1To1_19;
// This class modifies the 1.19.1 -> 1.19.0 transformers so that they simply pass through the original Minecraft key.
public class ProtocolPatcher1_19_0 {
public static boolean shouldFixKeys = false;
public static void patch() {
final Protocol1_19_1To1_19 protocol1_19_1To1_19 = Via.getManager().getProtocolManager().getProtocol(Protocol1_19_1To1_19.class);
assert protocol1_19_1To1_19 != null;
protocol1_19_1To1_19.registerServerbound(State.LOGIN, ServerboundLoginPackets.HELLO.getId(), ServerboundLoginPackets.HELLO.getId(), new PacketRemapper() {
@Override
public void registerMap() {
this.map(Type.STRING);
this.map(Type.OPTIONAL_PROFILE_KEY);
this.read(Type.OPTIONAL_UUID);
}
}, true);
protocol1_19_1To1_19.registerClientbound(State.LOGIN, ClientboundLoginPackets.HELLO.getId(), ClientboundLoginPackets.HELLO.getId(), new PacketRemapper() {
@Override
public void registerMap() {
}
}, true);
protocol1_19_1To1_19.registerServerbound(State.LOGIN, ServerboundLoginPackets.ENCRYPTION_KEY.getId(), ServerboundLoginPackets.ENCRYPTION_KEY.getId(), new PacketRemapper() {
@Override
public void registerMap() {
}
}, true);
}
}

View File

@ -50,7 +50,8 @@
"mixins.viafabric119.address.json",
"mixins.viafabric119.gui.json",
"mixins.viafabric119.debug.json",
"mixins.viafabric119.pipeline.json"
"mixins.viafabric119.pipeline.json",
"mixins.viafabric119.signatures.json"
],
"custom": {
"modmenu": {

View File

@ -0,0 +1,16 @@
{
"required": true,
"compatibilityLevel": "JAVA_16",
"package": "com.viaversion.fabric.mc119.mixin.signatures1_19_0",
"mixins": [
],
"client": [
"ArgumentSignatureDataMapMixin",
"PlayerPublicKeyChPublicKeyDataMixin",
"ClientPlayerEntityMixin",
"ProfileKeysMixin"
],
"injectors": {
"defaultRequire": 0
}
}