From 8cb3a29fd752ed4649b57181e1f6598d8973b7b3 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 13 Apr 2018 12:30:41 +0100 Subject: [PATCH] Fix a variety of protocol handling errors. Closes #704 Closes #705 Closes #730 Closes #732 Thanks to Umberto Boscolo. --- test/broker/01-connect-invalid-id-utf8.py | 40 ++++++++++++++++++++ test/broker/01-connect-uname-invalid-utf8.py | 40 ++++++++++++++++++++ test/broker/07-will-invalid-utf8.py | 2 +- test/broker/07-will-no-flag.py | 40 ++++++++++++++++++++ test/broker/Makefile | 3 ++ test/mosq_test.py | 4 +- 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100755 test/broker/01-connect-invalid-id-utf8.py create mode 100755 test/broker/01-connect-uname-invalid-utf8.py create mode 100755 test/broker/07-will-no-flag.py diff --git a/test/broker/01-connect-invalid-id-utf8.py b/test/broker/01-connect-invalid-id-utf8.py new file mode 100755 index 00000000..6f9c0c54 --- /dev/null +++ b/test/broker/01-connect-invalid-id-utf8.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# Test whether a client id with invalid UTF-8 fails. + +import time +import inspect, os, sys +# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],".."))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +import struct +import mosq_test + +rc = 1 +keepalive = 60 +connect_packet = mosq_test.gen_connect("connect-invalid-utf8", keepalive=keepalive) +b = list(struct.unpack("B"*len(connect_packet), connect_packet)) +b[21] = 0 # Client id should never have a 0x0000 +connect_packet = struct.pack("B"*len(b), *b) + +cmd = ['../../src/mosquitto', '-p', '1888'] +broker = mosq_test.start_broker(filename=os.path.basename(__file__), cmd=cmd) + +try: + time.sleep(0.5) + + sock = mosq_test.do_client_connect(connect_packet, "") + # Exception occurs if connack packet returned + rc = 0 + sock.close() +finally: + broker.terminate() + broker.wait() + if rc: + (stdo, stde) = broker.communicate() + print(stde) + +exit(rc) + diff --git a/test/broker/01-connect-uname-invalid-utf8.py b/test/broker/01-connect-uname-invalid-utf8.py new file mode 100755 index 00000000..f680dccf --- /dev/null +++ b/test/broker/01-connect-uname-invalid-utf8.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# Test whether a username with invalid UTF-8 fails. + +import time +import inspect, os, sys +# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],".."))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +import struct +import mosq_test + +rc = 1 +keepalive = 60 +connect_packet = mosq_test.gen_connect("connect-invalid-utf8", keepalive=keepalive, username="invalid/utf8") +b = list(struct.unpack("B"*len(connect_packet), connect_packet)) +b[43] = 0 # Username should never have a 0x0000 +connect_packet = struct.pack("B"*len(b), *b) + +cmd = ['../../src/mosquitto', '-p', '1888'] +broker = mosq_test.start_broker(filename=os.path.basename(__file__), cmd=cmd) + +try: + time.sleep(0.5) + + sock = mosq_test.do_client_connect(connect_packet, "") + # Exception occurs if connack packet returned + rc = 0 + sock.close() +finally: + broker.terminate() + broker.wait() + if rc: + (stdo, stde) = broker.communicate() + print(stde) + +exit(rc) + diff --git a/test/broker/07-will-invalid-utf8.py b/test/broker/07-will-invalid-utf8.py index 3ac2c190..13a96389 100755 --- a/test/broker/07-will-invalid-utf8.py +++ b/test/broker/07-will-invalid-utf8.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Test whether a PUBLISH to a topic with an invalid UTF-8 topic fails +# Test whether a will topic with invalid UTF-8 fails import time import inspect, os, sys diff --git a/test/broker/07-will-no-flag.py b/test/broker/07-will-no-flag.py new file mode 100755 index 00000000..69be72f4 --- /dev/null +++ b/test/broker/07-will-no-flag.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# Test whether a connection is disconnected if it sets the will flag but does +# not provide a will payload. + +import inspect, os, sys +# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],".."))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +import struct +import mosq_test + +rc = 1 +keepalive = 10 +connect_packet = mosq_test.gen_connect("will-no-payload", keepalive=keepalive, will_topic="will/topic", will_qos=1, will_retain=True) +b = list(struct.unpack("B"*len(connect_packet), connect_packet)) + +bmod = b[0:len(b)-2] +bmod[1] = bmod[1] - 2 # Reduce remaining length by two to remove final two payload length values + +connect_packet = struct.pack("B"*len(bmod), *bmod) + +cmd = ['../../src/mosquitto', '-p', '1888'] +broker = mosq_test.start_broker(filename=os.path.basename(__file__), cmd=cmd) + +try: + sock = mosq_test.do_client_connect(connect_packet, "") + sock.close() + rc = 0 +finally: + broker.terminate() + broker.wait() + if rc: + (stdo, stde) = broker.communicate() + print(stde) + +exit(rc) + diff --git a/test/broker/Makefile b/test/broker/Makefile index bf9b89ec..ab56baa5 100644 --- a/test/broker/Makefile +++ b/test/broker/Makefile @@ -21,6 +21,7 @@ test : test-compile 01 02 03 04 05 06 07 08 09 10 11 ./01-connect-invalid-id-0-311.py ./01-connect-invalid-id-missing.py ./01-connect-invalid-reserved.py + ./01-connect-invalid-id-utf8.py ./01-connect-anon-denied.py ./01-connect-uname-no-password-denied.py ./01-connect-uname-password-denied.py @@ -31,6 +32,7 @@ else endif ./01-connect-uname-no-flag.py ./01-connect-uname-pwd-no-flag.py + ./01-connect-uname-invalid-utf8.py 02 : @@ -83,6 +85,7 @@ endif ./07-will-null.py ./07-will-null-topic.py ./07-will-invalid-utf8.py + ./07-will-no-flag.py 08 : ifeq ($(WITH_TLS),yes) diff --git a/test/mosq_test.py b/test/mosq_test.py index 96bfd3f0..febcae5c 100644 --- a/test/mosq_test.py +++ b/test/mosq_test.py @@ -52,11 +52,11 @@ def packet_matches(name, recvd, expected): try: print("Received: "+to_string(recvd)) except struct.error: - print("Received (not decoded): "+recvd) + print("Received (not decoded, len=%d): %s" % (len(recvd), recvd)) try: print("Expected: "+to_string(expected)) except struct.error: - print("Expected (not decoded): "+expected) + print("Expected (not decoded, len=%d): %s" % (len(expected), expected)) return 0 else: