diff --git a/ChangeLog.txt b/ChangeLog.txt index 8e619c0c..e382b41c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,6 @@ +Security: +- Broker will reject Will messages that attempt to publish to $CONTROL/. + Broker: - Fix $SYS messages being expired after 60 seconds and hence unchanged values disappearing. diff --git a/src/handle_connect.c b/src/handle_connect.c index 7e102ee4..63824b0c 100644 --- a/src/handle_connect.c +++ b/src/handle_connect.c @@ -375,6 +375,10 @@ static int will__read(struct mosquitto *context, const char *client_id, struct m will_struct->msg.topic = will_topic_mount; } + if(!strncmp(will_struct->msg.topic, "$CONTROL/", strlen("$CONTROL/"))){ + rc = MOSQ_ERR_ACL_DENIED; + goto error_cleanup; + } rc = mosquitto_pub_topic_check(will_struct->msg.topic); if(rc) goto error_cleanup; diff --git a/test/broker/07-will-control.py b/test/broker/07-will-control.py new file mode 100755 index 00000000..68d2eccb --- /dev/null +++ b/test/broker/07-will-control.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# Test whether a client setting a will with $CONTROL in is denied + +from mosq_test_helper import * + + +def do_test(start_broker, proto_ver): + rc = 1 + mid = 1 + connect_packet = mosq_test.gen_connect("will", will_topic="$CONTROL/dynamic-security/v1", will_payload=b"will-message", proto_ver=proto_ver) + + port = mosq_test.get_port() + if start_broker: + broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port) + + try: + sock = mosq_test.client_connect_only(port=port) + sock.send(connect_packet) + d = sock.recv(1) + if d == b"": + rc = 0 + + sock.close() + except mosq_test.TestError: + pass + except Exception as e: + print(e) + finally: + if start_broker: + broker.terminate() + broker.wait() + (stdo, stde) = broker.communicate() + if rc: + print(stde.decode('utf-8')) + exit(rc) + else: + return rc + + +def all_tests(start_broker=False): + rc = do_test(start_broker, proto_ver=4) + if rc: + return rc; + rc = do_test(start_broker, proto_ver=5) + if rc: + return rc; + return 0 + +if __name__ == '__main__': + all_tests(True) diff --git a/test/broker/Makefile b/test/broker/Makefile index b2c86788..a65874c2 100644 --- a/test/broker/Makefile +++ b/test/broker/Makefile @@ -125,6 +125,7 @@ msg_sequence_test: ./06-bridge-reconnect-local-out.py 07 : + ./07-will-control.py ./07-will-delay-invalid-573191.py ./07-will-delay-reconnect.py ./07-will-delay-recover.py diff --git a/test/broker/test.py b/test/broker/test.py index 602b97bc..4afee881 100755 --- a/test/broker/test.py +++ b/test/broker/test.py @@ -101,6 +101,7 @@ tests = [ (3, './06-bridge-per-listener-settings.py'), (2, './06-bridge-reconnect-local-out.py'), + (1, './07-will-control.py'), (1, './07-will-delay-invalid-573191.py'), (1, './07-will-delay-reconnect.py'), (1, './07-will-delay-recover.py'),