fhmq / hmq

High performance mqtt broker
Apache License 2.0
1.33k stars 276 forks source link

Packet fields validation #111

Closed lucasvmx closed 3 years ago

lucasvmx commented 3 years ago

Issue #104

This PR implements the following rules:

Reference: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.pdf

The character data in a UTF-8 encoded string MUST be well-formed UTF-8 as defined by the Unicode specification [Unicode] and restated in RFC 3629 [RFC3629]. In particular this data MUST NOT include encodings of code points between U+D800 and U+DFFF. If a Server or Client receives a Control Packet containing ill-formed UTF-8 it MUST close the Network Connection [MQTT-1.5.3-1].

A UTF-8 encoded string MUST NOT include an encoding of the null character U+0000. If a receiver (Server or Client) receives a Control Packet containing U+0000 it MUST close the Network Connection [MQTT-1.5.3-2].

lucasvmx commented 3 years ago

Code used to test (based on @stapelberg code):

package main

import (
    "fmt"
    "log"

    mqtt "github.com/eclipse/paho.mqtt.golang"
)

func publishInvalid() error {
    opts := mqtt.NewClientOptions().AddBroker("tcp://localhost:1883")
    opts.SetClientID("TESTER")
    mqttClient := mqtt.NewClient(opts)
    if token := mqttClient.Connect(); token.Wait() && token.Error() != nil {
        return fmt.Errorf("MQTT connection failed: %v", token.Error())
    }

    token := mqttClient.Publish("foo/valid", 0, true /* retained */, []byte("payload"))
    token.Wait()

    token = mqttClient.Publish("foo/invalid/\u0000", 0, true /* retained */, []byte("hello world"))
    token.Wait()

    token = mqttClient.Publish("foo/invalid\xec\x8c", 0, true /* retained */, []byte("payload\xec\x8c\x04\x10\x27"))
    token.Wait()

    return nil
}

func main() {
    if err := publishInvalid(); err != nil {
        log.Fatal(err)
    }
}