Handle truncated start login frame (#400)

This commit is contained in:
Geoff Bourne
2025-04-26 21:24:41 -05:00
committed by GitHub
parent 4ba55a9ccd
commit 419692825e
3 changed files with 24 additions and 13 deletions
+2 -2
View File
@@ -55,12 +55,12 @@ func DecodeLoginStart(data interface{}) (*LoginStart, error) {
loginStart.Name, err = ReadString(buffer) loginStart.Name, err = ReadString(buffer)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to read username") return loginStart, errors.Wrap(err, "failed to read username")
} }
loginStart.PlayerUuid, err = ReadUuid(buffer) loginStart.PlayerUuid, err = ReadUuid(buffer)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to read player uuid") return loginStart, errors.Wrap(err, "failed to read player uuid")
} }
return loginStart, nil return loginStart, nil
+4 -2
View File
@@ -1,3 +1,5 @@
// Package mcproto provides functions to read types and decode frames declared
// at https://minecraft.wiki/w/Java_Edition_protocol
package mcproto package mcproto
import ( import (
@@ -27,7 +29,7 @@ const MaxFrameLength = 2097151
func ReadPacket(reader *bufio.Reader, addr net.Addr, state State) (*Packet, error) { func ReadPacket(reader *bufio.Reader, addr net.Addr, state State) (*Packet, error) {
logrus. logrus.
WithField("client", addr). WithField("client", addr).
Debug("Reading packet") Trace("Reading packet")
if state == StateHandshaking { if state == StateHandshaking {
data, err := reader.Peek(1) data, err := reader.Peek(1)
@@ -158,7 +160,7 @@ func ReadUTF16BEString(reader io.Reader, symbolLen uint16) (string, error) {
func ReadFrame(reader io.Reader, addr net.Addr) (*Frame, error) { func ReadFrame(reader io.Reader, addr net.Addr) (*Frame, error) {
logrus. logrus.
WithField("client", addr). WithField("client", addr).
Debug("Reading frame") Trace("Reading frame")
var err error var err error
frame := &Frame{} frame := &Frame{}
+12 -3
View File
@@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"io" "io"
@@ -227,7 +228,7 @@ func (c *Connector) HandleConnection(ctx context.Context, frontendConn net.Conn)
logrus. logrus.
WithField("client", clientAddr). WithField("client", clientAddr).
Info("Got connection") Debug("Got connection")
defer logrus.WithField("client", clientAddr).Debug("Closing frontend connection") defer logrus.WithField("client", clientAddr).Debug("Closing frontend connection")
// Tee-off the inspected content to a buffer so that we can retransmit it to the backend connection // Tee-off the inspected content to a buffer so that we can retransmit it to the backend connection
@@ -273,8 +274,15 @@ func (c *Connector) HandleConnection(ctx context.Context, frontendConn net.Conn)
var playerInfo *PlayerInfo = nil var playerInfo *PlayerInfo = nil
if handshake.NextState == mcproto.StateLogin { if handshake.NextState == mcproto.StateLogin {
playerInfo, err = c.readUserInfo(bufferedReader, clientAddr, handshake.NextState) playerInfo, err = c.readPlayerInfo(bufferedReader, clientAddr, handshake.NextState)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) {
logrus.
WithError(err).
WithField("clientAddr", clientAddr).
WithField("player", playerInfo).
Warn("Truncated buffer while reading player info")
} else {
logrus. logrus.
WithError(err). WithError(err).
WithField("clientAddr", clientAddr). WithField("clientAddr", clientAddr).
@@ -282,6 +290,7 @@ func (c *Connector) HandleConnection(ctx context.Context, frontendConn net.Conn)
c.metrics.Errors.With("type", "read").Add(1) c.metrics.Errors.With("type", "read").Add(1)
return return
} }
}
logrus. logrus.
WithField("client", clientAddr). WithField("client", clientAddr).
WithField("player", playerInfo). WithField("player", playerInfo).
@@ -319,7 +328,7 @@ func (c *Connector) HandleConnection(ctx context.Context, frontendConn net.Conn)
} }
} }
func (c *Connector) readUserInfo(bufferedReader *bufio.Reader, clientAddr net.Addr, state mcproto.State) (*PlayerInfo, error) { func (c *Connector) readPlayerInfo(bufferedReader *bufio.Reader, clientAddr net.Addr, state mcproto.State) (*PlayerInfo, error) {
loginPacket, err := mcproto.ReadPacket(bufferedReader, clientAddr, state) loginPacket, err := mcproto.ReadPacket(bufferedReader, clientAddr, state)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read login packet: %w", err) return nil, fmt.Errorf("failed to read login packet: %w", err)