Some protocol violations or bugs in Mosquitto
Hi, I have found some protocol specification violations in Mosquitto, attached below are the details. The version of Mosquitto: version 2.0.18 The version of the Operating System: Ubuntu 24.04
According to the specification of MQTTv5.0:
[MQTT-3.10.3-2]
The Payload of an UNSUBSCRIBE packet MUST contain at least one Topic Filter.
But if we send such a packet that contains no topic filter to the broker:
echo 107e00064d514973647003cc8b8600145542463562636f6939375765546c694c37564c4600086748627239437a680018576c58416432686a6469616536334966415737594d586c72001a77654e4f376d3248774d6234566552526f586e6b47426e705871001a3858646b6d335a34634a486c594866347468676b6a63544c5a383224000e58564b6c7a7832493347677a7151b60131776e317a5947313132494355356e596468a2027890 | xxd -p -r | nc 172.17.0.7 1883
Mosquitto unexpectedly returned a response message instead of rejecting or breaking the connection.
According to the specification of MQTTv5.0:
[MQTT-3.8.3-2]
The Payload MUST contain at least one Topic Filter and Subscription Options pair
Similarly, we send a Subscribe message that does not contain any topic filters
echo 103c00064d514973647003c21226001455794367394a7632646146646941386f4e70553300016f0015326b364f5478555630374f44655547387a5a37666aa25f68ac001c644862384e33363353484870594e70546572364d4957397144555079000f7172794d62366d32707063794d774b00116c6d3455366f746e72716a466343416254001954684d4c506c30413942696135336645384a3635536f42705782024000 | xxd -p -r | nc 172.17.0.7 1883
According to the specification of MQTTv5.0:
[MQTT-3.3.4-6]
A PUBLISH packet sent from a Client to a Server MUST NOT contain a Subscription Identifier.
Send such a packet:
echo 106100044d5154540540b3b037119afb60e317001901215c5326000f766e72366d4541644d78553c44327800173049574d36324268715a6179524b5a62536749534a31360013317675535434755733374e64397846585a38570008676235716d5836363554000841684b3146454962f71a16010109000c79a506aff5eef39ed5210cd60bba849b523155596942337761334c376e765936573739413862666a46414e4e3172647544345773415778724a6667386d3258653363 | xxd -p -r | nc 172.17.0.7 1883
Mosquitto expected that such a request should be denied, but received it.
The Response Topic MUST NOT contain wildcard characters [MQTT-3.3.2-14]
However, if we send such packet like:
10820100044d51545405d648be021901000e6f795a707564585068416f7946583a028000000003001739367638484375394f314551316c76754a32347a485256080018567736646a464767544a6648357a3059504a6279724d343700056241664e33000850316345567633740014355154705337784478434532674177393169384c000165
3d46000954795264796b3352659bd8330100026a77f21008000623636b6259530beef8d9142600134654484e57677a4e776472703032476b424a730006357762526c706953397453
Mosquitto ignored the response topic value in the PUBLISH message and then returned the corresponding PUBREC response message.
# MQTT v5
3.3.2.3.2 Payload Format Indicator
· 0 (0x00) Byte Indicates that the Payload is unspecified bytes, which is equivalent to not sending a Payload Format Indicator.
· 1 (0x01) Byte Indicates that the Payload is UTF-8 Encoded Character Data. The UTF-8 data in the Payload MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] and restated in RFC 3629 [RFC3629].
According to this description, when the Payload Format Indicator in the PUBLISH message is set to 1, the payload in the PUBLISH message must be UTF-8 encoded. However, it appears that Mosquitto does not validate this.
PoC:
echo 106e00044d515454056e866e0711c4f23d2e17010012764d78635176754e4b6163615164477247521d0300027a4e260009577852505166527043000a6e467067664149535563000f487a4134464c4d3352526c6231486c00104e364958486246414654713051374b79000559304c56433d3900087751586170725838415f060101090001b8423663546c627950717a306b363233664d3249426c36717a6a5a474546456a6f3845363038fe | xxd -r -p | nc 127.0.0.1 1883
Similarity,
# MQTT v5
3.1.3.2.3 Payload Format Indicator
Followed by the value of the Payload Format Indicator, either of:
· 0 (0x00) Byte Indicates that the Will Message is unspecified bytes, which is equivalent to not sending a Payload Format Indicator.
· 1 (0x01) Byte Indicates that the Will Message is UTF-8 Encoded Character Data. The UTF-8 data in the Payload MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] and restated in RFC 3629 [RFC3629]
According to this description, when the Payload Format Indicator in the CONNECT message is set to 1, the will message in the CONNECT message must be UTF-8 encoded. However, it appears that Mosquitto does not validate this.
POC:
106300044d51545405a6fd850c11987da8451900270b5434c60004534d763907010118e7f5bf8600104371794d4a3374706e773872744b364300126c397a7a71763353325647714f6a475951fe0016354278463574494f433735413474654d745869475467
MQTTv5
format: $share/{ShareName}/{filter}
The ShareName MUST NOT contain the characters "/", "+" or "#", but MUST be followed by a "/" character.
This "/" character MUST be followed by a Topic Filter.
If we send a packet the shared topic is "$share/{ShareName}/", i.e., filter is empty, and the broker will not reject it. I guess it is an unexpected behavior.
Packet:
101000044d5154540502003c032100140000
820f00010000092473686172652f312f00
# MQTTv5
It is a Protocol Error to set the No Local bit to 1 on a Shared Subscription [MQTT-3.8.3-4].
But, if we send such an invalid packet to the broker, it responds to a SUBACK (code: successful) message rather than reject.
105700044d5154540540a3110d118fb95f59190121012f22cc75001e66304e79317a416b5369314f46396937397464756d53665a41686f4f6575001d774d51623130793346627158754c3043305455556b55364b5132364b45
8218ff000000122473686172652f653862676633616e2f474706
In MQTT 5.0, the requester can specify an expected Response Topic in the request message. After taking appropriate action based on the request message, the responder publishes a response message to the Response Topic carried in the request. If the requester has subscribed to that Response Topic, it will receive the response.
Ref 1: https://www.emqx.com/en/blog/mqtt5-request-response
In MQTT 5.0, I believe this property field should not be allowed to be empty, because it will play a role in message transmission in some scenarios.
Packet:
10a10100044d51545405a6d79b13170122e432260002766100024d5127c1f00b75000c3667713668573039766670314102dd44adf20300144b526a5343646e53427066393358395531756b470800002600094835774f764d6e4f37001466345a314b636936466648545078614461337063000f476234475670636c737132496830440005307648626400194d46344f6d6c72764951773877755a6a666f3331636c457278
@songxpu your first example is incorrect:
You are connecting with MQTTv3. If you use CONNECT with MQTTv3.1.1 or MQTTv5, mosquitto correctly disconnects the client because of a malformed packet (see below).
It would be great if you include a mosquitto log for each of your examples and if you could keep the examples as simple as possible (e.g. complex client, username, will messages and SUBSCRIBE messages when you only want to show a UNSUBSCRIBE).
1729024663: mosquitto version 2.0.18 starting
...
1729025569: New client connected from 127.0.0.1:62463 as UBF5bcoi97WeTliL7VLF (p1, c0, k35718, u'weNO7m2HwMb4VeRRoXnkGBnpXq').
1729025569: Will message specified (24 bytes) (r0, q1).
1729025569: gHbr9Czh
1729025569: Sending CONNACK to UBF5bcoi97WeTliL7VLF (0, 0)
1729025569: Received PUBLISH from UBF5bcoi97WeTliL7VLF (d0, q1, r0, m46593, 'XVKlzx2I3GgzqQ', ... (18 bytes))
1729025569: Sending PUBACK to UBF5bcoi97WeTliL7VLF (m46593, rc0)
1729025569: Received UNSUBSCRIBE from UBF5bcoi97WeTliL7VLF
1729025569: Sending UNSUBACK to UBF5bcoi97WeTliL7VLF
1729025569: Client UBF5bcoi97WeTliL7VLF closed its connection.
...
1729025955: New connection from 127.0.0.1:63245 on port 1883.
1729025955: New client connected from 127.0.0.1:63245 as UBF5bcoi97WeTliL7VLF (p2, c0, k35718, u'weNO7m2HwMb4VeRRoXnkGBnpXq').
1729025955: Will message specified (24 bytes) (r0, q1).
1729025955: gHbr9Czh
1729025955: Sending CONNACK to UBF5bcoi97WeTliL7VLF (1, 0)
1729025955: Received PUBLISH from UBF5bcoi97WeTliL7VLF (d0, q1, r0, m46593, 'XVKlzx2I3GgzqQ', ... (18 bytes))
1729025955: Sending PUBACK to UBF5bcoi97WeTliL7VLF (m46593, rc0)
1729025955: Received UNSUBSCRIBE from UBF5bcoi97WeTliL7VLF
1729025955: Client UBF5bcoi97WeTliL7VLF disconnected due to malformed packet.
@songxpu your second example is incorrect too:
You are connecting with MQTTv3. If you use CONNECT with MQTTv3.1.1 or MQTTv5, mosquitto correctly disconnects the client because of a malformed packet (see below).
@songxpu Thanks for the reports, I've now pushed changes for the remaining issues except for those related to the payload format indicator. The spec states that the broker "MAY" validate the payload. I'm choosing not to do that for the 2.0.x branch.
The changes are part of 2.0.20