Fix login start packet decoding for 1.18.2 up to 1.20.2 (#421)

Signed-off-by: Fred Heinecke <fred.heinecke@yahoo.com>
This commit is contained in:
solidDoWant
2025-06-29 07:37:26 -05:00
committed by GitHub
parent 749b090c73
commit 805cebd856
10 changed files with 217 additions and 33 deletions
+67 -6
View File
@@ -21,10 +21,11 @@ func DecodeHandshake(data interface{}) (*Handshake, error) {
buffer := bytes.NewBuffer(dataBytes)
var err error
handshake.ProtocolVersion, err = ReadVarInt(buffer)
protocolVersion, err := ReadVarInt(buffer)
if err != nil {
return nil, err
}
handshake.ProtocolVersion = ProtocolVersion(protocolVersion)
handshake.ServerAddress, err = ReadString(buffer)
if err != nil {
@@ -48,13 +49,13 @@ func DecodeHandshake(data interface{}) (*Handshake, error) {
}
// DecodeLoginStart takes the Packet.Data bytes and decodes a LoginStart message from it
func DecodeLoginStart(data interface{}) (*LoginStart, error) {
func DecodeLoginStart(protocolVersion ProtocolVersion, data interface{}) (*LoginStart, error) {
dataBytes, ok := data.([]byte)
if !ok {
return nil, errors.New(invalidPacketDataBytesMsg)
}
loginStart := &LoginStart{}
loginStart := NewLoginStart()
buffer := bytes.NewBuffer(dataBytes)
var err error
@@ -63,9 +64,69 @@ func DecodeLoginStart(data interface{}) (*LoginStart, error) {
return loginStart, errors.Wrap(err, "failed to read username")
}
loginStart.PlayerUuid, err = ReadUuid(buffer)
if err != nil {
return loginStart, errors.Wrap(err, "failed to read player uuid")
// These versions can send player keypair data. Ignore it.
// References:
// * https://github.com/MCCTeam/Minecraft-Console-Client/blob/f785f509f228bf787c237ac139e6f666a960819a/MinecraftClient/Protocol/Handlers/Protocol18.cs#L2808-L2828
// * https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol?oldid=2772902#Login_Start
if protocolVersion >= ProtocolVersion1_19 && protocolVersion <= ProtocolVersion1_19_2 {
hasSignatureData, err := ReadBoolean(buffer)
if err != nil {
return loginStart, errors.Wrap(err, "failed to read has signature data flag")
}
if hasSignatureData {
// Read and discard the data
_, err = ReadLong(buffer) // Expiration time
if err != nil {
return loginStart, errors.Wrap(err, "failed to read expiration time")
}
pubKeyLength, err := ReadVarInt(buffer) // Length of the public key
if err != nil {
return loginStart, errors.Wrap(err, "failed to read public key length")
}
_, err = ReadByteArray(buffer, pubKeyLength) // Public key data
if err != nil {
return loginStart, errors.Wrap(err, "failed to read public key")
}
signatureLength, err := ReadVarInt(buffer) // Length of the signature
if err != nil {
return loginStart, errors.Wrap(err, "failed to read signature length")
}
_, err = ReadByteArray(buffer, signatureLength) // Signature data
if err != nil {
return loginStart, errors.Wrap(err, "failed to read signature")
}
}
}
// References:
// * https://github.com/MCCTeam/Minecraft-Console-Client/blob/f785f509f228bf787c237ac139e6f666a960819a/MinecraftClient/Protocol/Handlers/Protocol18.cs#L2831-L2853
// * https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol?oldid=2772944#Login_Start
switch {
case protocolVersion >= ProtocolVersion1_19_2 && protocolVersion < ProtocolVersion1_20_2:
// Check to see if a UUID was provided at all
hasUUID, err := ReadBoolean(buffer)
if err != nil {
return loginStart, errors.Wrap(err, "failed to read has uuid flag")
}
if !hasUUID {
break
}
fallthrough
case protocolVersion >= ProtocolVersion1_20_2:
// For 1.20.2 and later, the UUID is always present
playerUuid, err := ReadUuid(buffer)
if err != nil {
return loginStart, errors.Wrap(err, "failed to read player uuid")
}
loginStart.PlayerUuid = playerUuid
default:
// For versions before 1.19.2, the UUID is not present
}
return loginStart, nil