mirror of
https://github.com/mochi-mqtt/server.git
synced 2025-09-26 20:21:12 +08:00
Allow 0 byte usernames if correctly formed (#181)
* Allow 0 byte usernames if correctly formed * Allow 0 byte usernames if correctly formed
This commit is contained in:
@@ -412,6 +412,10 @@ func (pk *Packet) ConnectDecode(buf []byte) error {
|
||||
}
|
||||
|
||||
if pk.Connect.UsernameFlag { // [MQTT-3.1.3-12]
|
||||
if offset >= len(buf) { // we are at the end of the packet
|
||||
return ErrProtocolViolationFlagNoUsername // [MQTT-3.1.2-17]
|
||||
}
|
||||
|
||||
pk.Connect.Username, offset, err = decodeBytes(buf, offset)
|
||||
if err != nil {
|
||||
return ErrMalformedUsername
|
||||
@@ -451,10 +455,6 @@ func (pk *Packet) ConnectValidate() Code {
|
||||
return ErrProtocolViolationUsernameTooLong
|
||||
}
|
||||
|
||||
if pk.Connect.UsernameFlag && len(pk.Connect.Username) == 0 {
|
||||
return ErrProtocolViolationFlagNoUsername // [MQTT-3.1.2-17]
|
||||
}
|
||||
|
||||
if !pk.Connect.UsernameFlag && len(pk.Connect.Username) > 0 {
|
||||
return ErrProtocolViolationUsernameNoFlag // [MQTT-3.1.2-16]
|
||||
}
|
||||
|
@@ -71,7 +71,7 @@ const (
|
||||
TConnectInvalidWillFlagNoPayload
|
||||
TConnectInvalidWillFlagQosOutOfRange
|
||||
TConnectInvalidWillSurplusRetain
|
||||
TConnectNotCleanNoClientID
|
||||
TConnectZeroByteUsername
|
||||
TConnectSpecInvalidUTF8D800
|
||||
TConnectSpecInvalidUTF8DFFF
|
||||
TConnectSpecInvalidUTF80000
|
||||
@@ -498,6 +498,43 @@ var TPacketData = map[byte]TPacketCases{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: TConnectZeroByteUsername,
|
||||
Desc: "username flag but 0 byte username",
|
||||
Group: "decode",
|
||||
RawBytes: []byte{
|
||||
Connect << 4, 23, // Fixed header
|
||||
0, 4, // Protocol Name - MSB+LSB
|
||||
'M', 'Q', 'T', 'T', // Protocol Name
|
||||
5, // Protocol Version
|
||||
130, // Packet Flags
|
||||
0, 30, // Keepalive
|
||||
5, // length
|
||||
17, 0, 0, 0, 120, // Session Expiry Interval (17)
|
||||
0, 3, // Client ID - MSB+LSB
|
||||
'z', 'e', 'n', // Client ID "zen"
|
||||
0, 0, // Username MSB+LSB
|
||||
},
|
||||
Packet: &Packet{
|
||||
FixedHeader: FixedHeader{
|
||||
Type: Connect,
|
||||
Remaining: 23,
|
||||
},
|
||||
ProtocolVersion: 5,
|
||||
Connect: ConnectParams{
|
||||
ProtocolName: []byte("MQTT"),
|
||||
Clean: true,
|
||||
Keepalive: 30,
|
||||
ClientIdentifier: "zen",
|
||||
Username: []byte{},
|
||||
UsernameFlag: true,
|
||||
},
|
||||
Properties: Properties{
|
||||
SessionExpiryInterval: uint32(120),
|
||||
SessionExpiryIntervalFlag: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Fail States
|
||||
{
|
||||
@@ -624,6 +661,24 @@ var TPacketData = map[byte]TPacketCases{
|
||||
'm', 'o', 'c',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Case: TConnectInvalidFlagNoUsername,
|
||||
Desc: "username flag with no username bytes",
|
||||
Group: "decode",
|
||||
FailFirst: ErrProtocolViolationFlagNoUsername,
|
||||
RawBytes: []byte{
|
||||
Connect << 4, 17, // Fixed header
|
||||
0, 4, // Protocol Name - MSB+LSB
|
||||
'M', 'Q', 'T', 'T', // Protocol Name
|
||||
5, // Protocol Version
|
||||
130, // Flags
|
||||
0, 20, // Keepalive
|
||||
0,
|
||||
0, 3, // Client ID - MSB+LSB
|
||||
'z', 'e', 'n', // Client ID "zen"
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: TConnectMalPassword,
|
||||
Desc: "malformed password",
|
||||
@@ -784,20 +839,6 @@ var TPacketData = map[byte]TPacketCases{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: TConnectInvalidFlagNoUsername,
|
||||
Desc: "has username flag but no username",
|
||||
Group: "validate",
|
||||
Expect: ErrProtocolViolationFlagNoUsername,
|
||||
Packet: &Packet{
|
||||
FixedHeader: FixedHeader{Type: Connect},
|
||||
ProtocolVersion: 4,
|
||||
Connect: ConnectParams{
|
||||
ProtocolName: []byte("MQTT"),
|
||||
UsernameFlag: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: TConnectInvalidUsernameNoFlag,
|
||||
Desc: "has username but no flag",
|
||||
|
@@ -748,6 +748,33 @@ func TestServerEstablishConnectionInvalidConnect(t *testing.T) {
|
||||
r.Close()
|
||||
}
|
||||
|
||||
// See https://github.com/mochi-co/mqtt/issues/178
|
||||
func TestServerEstablishConnectionZeroByteUsernameIsValid(t *testing.T) {
|
||||
s := newServer()
|
||||
|
||||
r, w := net.Pipe()
|
||||
o := make(chan error)
|
||||
go func() {
|
||||
o <- s.EstablishConnection("tcp", r)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
w.Write(packets.TPacketData[packets.Connect].Get(packets.TConnectZeroByteUsername).RawBytes)
|
||||
w.Write(packets.TPacketData[packets.Disconnect].Get(packets.TDisconnect).RawBytes)
|
||||
}()
|
||||
|
||||
// receive the connack error
|
||||
go func() {
|
||||
_, err := io.ReadAll(w)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
err := <-o
|
||||
require.NoError(t, err)
|
||||
|
||||
r.Close()
|
||||
}
|
||||
|
||||
func TestServerEstablishConnectionInvalidConnectAckFailure(t *testing.T) {
|
||||
s := newServer()
|
||||
|
||||
|
Reference in New Issue
Block a user