Skip to content

Commit 42f6be3

Browse files
authored
Merge pull request #705 from Konicai/fix-1.19.1
Fix 1.19.1
2 parents cb1ab3c + 535d200 commit 42f6be3

File tree

9 files changed

+169
-56
lines changed

9 files changed

+169
-56
lines changed

src/main/java/com/github/steveice10/mc/protocol/ClientListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public void packetSent(Session session, Packet packet) {
125125

126126
if (this.targetState == ProtocolState.LOGIN) {
127127
GameProfile profile = session.getFlag(MinecraftConstants.PROFILE_KEY);
128-
session.send(new ServerboundHelloPacket(profile.getName(), null, null, null, profile.getId()));
128+
session.send(new ServerboundHelloPacket(profile.getName(), null, profile.getId()));
129129
} else {
130130
session.send(new ServerboundStatusRequestPacket());
131131
}

src/main/java/com/github/steveice10/mc/protocol/ServerListener.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,7 @@
3030
import net.kyori.adventure.text.Component;
3131

3232
import javax.crypto.SecretKey;
33-
import java.security.KeyPair;
34-
import java.security.KeyPairGenerator;
35-
import java.security.NoSuchAlgorithmException;
36-
import java.security.PrivateKey;
33+
import java.security.*;
3734
import java.util.Arrays;
3835
import java.util.Random;
3936
import java.util.UUID;
@@ -58,8 +55,9 @@ public class ServerListener extends SessionAdapter {
5855
}
5956
}
6057

61-
private byte[] verifyToken = new byte[4];
58+
private final byte[] verifyToken = new byte[4];
6259
private String username = "";
60+
private ServerboundHelloPacket.ProfilePublicKeyData profilePublicKeyData;
6361

6462
private long lastPingTime = 0;
6563
private int lastPingId = 0;
@@ -101,6 +99,7 @@ public void packetReceived(Session session, Packet packet) {
10199
if (protocol.getState() == ProtocolState.LOGIN) {
102100
if (packet instanceof ServerboundHelloPacket) {
103101
this.username = ((ServerboundHelloPacket) packet).getUsername();
102+
this.profilePublicKeyData = ((ServerboundHelloPacket) packet).getPublicKey();
104103

105104
if (session.getFlag(MinecraftConstants.VERIFY_USERS_KEY, true)) {
106105
session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.verifyToken));
@@ -110,9 +109,17 @@ public void packetReceived(Session session, Packet packet) {
110109
} else if (packet instanceof ServerboundKeyPacket) {
111110
ServerboundKeyPacket keyPacket = (ServerboundKeyPacket) packet;
112111
PrivateKey privateKey = KEY_PAIR.getPrivate();
113-
if (!Arrays.equals(this.verifyToken, keyPacket.getVerifyToken(privateKey))) {
114-
session.disconnect("Invalid nonce!");
115-
return;
112+
113+
if (this.profilePublicKeyData != null) {
114+
if (!keyPacket.verifyWithSaltSignature(this.verifyToken, this.profilePublicKeyData)) {
115+
session.disconnect("Invalid profile key setup!");
116+
return;
117+
}
118+
} else {
119+
if (!Arrays.equals(this.verifyToken, keyPacket.getVerifyToken(privateKey))) {
120+
session.disconnect("Invalid nonce!");
121+
return;
122+
}
116123
}
117124

118125
SecretKey key = keyPacket.getSecretKey(privateKey);

src/main/java/com/github/steveice10/mc/protocol/codec/MinecraftCodecHelper.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@
4848
import java.util.List;
4949
import java.util.Map;
5050
import java.util.UUID;
51-
import java.util.function.ObjIntConsumer;
52-
import java.util.function.ToIntFunction;
51+
import java.util.function.*;
5352

5453
@RequiredArgsConstructor
5554
public class MinecraftCodecHelper extends BasePacketCodecHelper {
@@ -64,6 +63,24 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
6463

6564
protected CompoundTag registry;
6665

66+
@Nullable
67+
public <T> T readNullable(ByteBuf buf, Function<ByteBuf, T> ifPresent) {
68+
if (buf.readBoolean()) {
69+
return ifPresent.apply(buf);
70+
} else {
71+
return null;
72+
}
73+
}
74+
75+
public <T> void writeNullable(ByteBuf buf, @Nullable T value, BiConsumer<ByteBuf, T> ifPresent) {
76+
if (value != null) {
77+
buf.writeBoolean(true);
78+
ifPresent.accept(buf, value);
79+
} else {
80+
buf.writeBoolean(false);
81+
}
82+
}
83+
6784
public UUID readUUID(ByteBuf buf) {
6885
return new UUID(buf.readLong(), buf.readLong());
6986
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.github.steveice10.mc.protocol.data.game;
2+
3+
public enum ChatFilterType {
4+
PASS_THROUGH,
5+
FULLY_FILTERED,
6+
PARTIALLY_FILTERED;
7+
8+
public static final ChatFilterType[] VALUES = values();
9+
10+
public static ChatFilterType from(int id) {
11+
return VALUES[id];
12+
}
13+
}

src/main/java/com/github/steveice10/mc/protocol/packet/ingame/clientbound/ClientboundPlayerChatPacket.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper;
44
import com.github.steveice10.mc.protocol.codec.MinecraftPacket;
55
import com.github.steveice10.mc.protocol.data.game.BuiltinChatType;
6+
import com.github.steveice10.mc.protocol.data.game.ChatFilterType;
67
import com.github.steveice10.mc.protocol.data.game.LastSeenMessage;
78
import io.netty.buffer.ByteBuf;
89
import lombok.AllArgsConstructor;
@@ -13,6 +14,7 @@
1314

1415
import java.io.IOException;
1516
import java.util.ArrayList;
17+
import java.util.BitSet;
1618
import java.util.List;
1719
import java.util.UUID;
1820

@@ -29,6 +31,8 @@ public class ClientboundPlayerChatPacket implements MinecraftPacket {
2931
private final long salt;
3032
private final List<LastSeenMessage> lastSeenMessages;
3133
private final @Nullable Component unsignedContent;
34+
private final BitSet filterMask;
35+
private final ChatFilterType filterType;
3236
/**
3337
* Is {@link BuiltinChatType} defined in the order sent by the server in the login packet.
3438
*/
@@ -66,6 +70,13 @@ public ClientboundPlayerChatPacket(ByteBuf in, MinecraftCodecHelper helper) {
6670
this.unsignedContent = null;
6771
}
6872

73+
this.filterType = ChatFilterType.from(helper.readVarInt(in));
74+
if (filterType == ChatFilterType.PARTIALLY_FILTERED) {
75+
this.filterMask = BitSet.valueOf(helper.readLongArray(in));
76+
} else {
77+
this.filterMask = new BitSet(0);
78+
}
79+
6980
this.chatType = helper.readVarInt(in);
7081
this.name = helper.readComponent(in);
7182
if (in.readBoolean()) {
@@ -112,6 +123,11 @@ public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOExcepti
112123
out.writeBoolean(false);
113124
}
114125

126+
helper.writeVarInt(out, this.filterType.ordinal());
127+
if (this.filterType == ChatFilterType.PARTIALLY_FILTERED) {
128+
helper.writeLongArray(out, this.filterMask.toLongArray());
129+
}
130+
115131
helper.writeVarInt(out, this.chatType);
116132
helper.writeComponent(out, this.name);
117133
if (this.targetName != null) {

src/main/java/com/github/steveice10/mc/protocol/packet/login/serverbound/ServerboundHelloPacket.java

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,57 @@
77
import lombok.Data;
88
import lombok.NonNull;
99
import lombok.With;
10+
import org.jetbrains.annotations.Contract;
1011
import org.jetbrains.annotations.Nullable;
1112

1213
import java.io.IOException;
1314
import java.security.GeneralSecurityException;
1415
import java.security.KeyFactory;
1516
import java.security.PublicKey;
1617
import java.security.spec.X509EncodedKeySpec;
18+
import java.time.Instant;
1719
import java.util.UUID;
1820

1921
@Data
2022
@With
2123
@AllArgsConstructor
2224
public class ServerboundHelloPacket implements MinecraftPacket {
2325
private final @NonNull String username;
24-
private final @Nullable Long expiresAt;
25-
private final @Nullable PublicKey publicKey;
26-
private final byte @Nullable[] keySignature;
26+
private final @Nullable ProfilePublicKeyData publicKey;
2727
private final @Nullable UUID profileId;
2828

2929
public ServerboundHelloPacket(ByteBuf in, MinecraftCodecHelper helper) throws IOException {
3030
this.username = helper.readString(in);
3131
if (in.readBoolean()) {
32+
this.publicKey = new ProfilePublicKeyData(in, helper);
33+
} else {
34+
this.publicKey = null;
35+
}
36+
this.profileId = helper.readNullable(in, helper::readUUID);
37+
}
38+
39+
@Override
40+
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
41+
helper.writeString(out, this.username);
42+
out.writeBoolean(this.publicKey != null);
43+
if (this.publicKey != null) {
44+
this.publicKey.serialize(out, helper);
45+
}
46+
helper.writeNullable(out, this.profileId, helper::writeUUID);
47+
}
48+
49+
@Override
50+
public boolean isPriority() {
51+
return true;
52+
}
53+
54+
// Likely temporary; will be moved to AuthLib when full public key support is developed
55+
public static class ProfilePublicKeyData {
56+
private final long expiresAt;
57+
private final PublicKey publicKey;
58+
private final byte[] keySignature;
59+
60+
public ProfilePublicKeyData(ByteBuf in, MinecraftCodecHelper helper) throws IOException {
3261
this.expiresAt = in.readLong();
3362
byte[] publicKey = helper.readByteArray(in);
3463
this.keySignature = helper.readByteArray(in);
@@ -38,36 +67,32 @@ public ServerboundHelloPacket(ByteBuf in, MinecraftCodecHelper helper) throws IO
3867
} catch (GeneralSecurityException e) {
3968
throw new IOException("Could not decode public key.", e);
4069
}
41-
} else {
42-
this.expiresAt = null;
43-
this.publicKey = null;
44-
this.keySignature = null;
4570
}
46-
if (in.readBoolean()) {
47-
this.profileId = helper.readUUID(in);
48-
} else {
49-
this.profileId = null;
71+
72+
public ProfilePublicKeyData(long expiresAt, PublicKey publicKey, byte[] keySignature) {
73+
this.expiresAt = expiresAt;
74+
this.publicKey = publicKey;
75+
this.keySignature = keySignature;
5076
}
51-
}
5277

53-
@Override
54-
public void serialize(ByteBuf out, MinecraftCodecHelper helper) throws IOException {
55-
helper.writeString(out, this.username);
56-
out.writeBoolean(this.publicKey != null);
57-
if (this.publicKey != null) {
78+
private void serialize(ByteBuf out, MinecraftCodecHelper helper) {
5879
out.writeLong(this.expiresAt);
5980
byte[] encoded = this.publicKey.getEncoded();
6081
helper.writeByteArray(out, encoded);
6182
helper.writeByteArray(out, this.keySignature);
6283
}
63-
out.writeBoolean(this.profileId != null);
64-
if (this.profileId != null) {
65-
helper.writeUUID(out, this.profileId);
84+
85+
@Contract("-> new")
86+
public Instant getExpiresAt() {
87+
return Instant.ofEpochMilli(this.expiresAt);
6688
}
67-
}
6889

69-
@Override
70-
public boolean isPriority() {
71-
return true;
90+
public PublicKey getPublicKey() {
91+
return publicKey;
92+
}
93+
94+
public byte[] getKeySignature() {
95+
return keySignature;
96+
}
7297
}
7398
}

0 commit comments

Comments
 (0)