From 764aa4e8dc55f144bdb237566a0dd75ef0c07576 Mon Sep 17 00:00:00 2001 From: Thomas De Backer Date: Mon, 8 Feb 2021 20:48:20 +0100 Subject: [PATCH 01/19] Correct interface binding Signed-off-by: Thomas De Backer --- src/net.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/net.c b/src/net.c index dcc9db36..67332870 100644 --- a/src/net.c +++ b/src/net.c @@ -640,7 +640,8 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr } } freeifaddrs(ifaddr); - log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s not found.", listener->bind_interface); + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s.", + listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "ipv4" : "ipv6"); return MOSQ_ERR_NOT_FOUND; } #endif @@ -654,6 +655,9 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener) char service[10]; int rc; int ss_opt = 1; +#ifndef WIN32 + bool interface_bound = false; +#endif if(!listener) return MOSQ_ERR_INVAL; @@ -718,12 +722,14 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener) #ifndef WIN32 if(listener->bind_interface){ + /* It might be possible that an interface does not support all relevant sa_families. + * We should successfully find at least one. */ if(net__bind_interface(listener, rp)){ COMPAT_CLOSE(sock); - freeaddrinfo(ainfo); - mosquitto__free(listener->socks); - return 1; + listener->sock_count--; + continue; } + interface_bound = true; } #endif @@ -745,6 +751,13 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener) } freeaddrinfo(ainfo); +#ifndef WIN32 + if(listener->bind_interface && !interface_bound){ + mosquitto__free(listener->socks); + return 1; + } +#endif + return 0; } From fd2f764d361e038eae6140a3ee16dbf5c75c299f Mon Sep 17 00:00:00 2001 From: Thomas De Backer Date: Mon, 8 Feb 2021 23:36:21 +0100 Subject: [PATCH 02/19] Check host address binding before overwriting Signed-off-by: Thomas De Backer --- src/net.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/net.c b/src/net.c index 67332870..05b56d69 100644 --- a/src/net.c +++ b/src/net.c @@ -624,23 +624,37 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr && ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){ if(rp->ai_addr->sa_family == AF_INET){ - memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, - &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, - sizeof(struct in_addr)); - - freeifaddrs(ifaddr); - return MOSQ_ERR_SUCCESS; + if(listener->host && + memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof(struct in_addr))){ + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address does not match specified listener host."); + }else{ + memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, + &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, + sizeof(struct in_addr)); + + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } }else if(rp->ai_addr->sa_family == AF_INET6){ - memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, - &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, - sizeof(struct in6_addr)); - freeifaddrs(ifaddr); - return MOSQ_ERR_SUCCESS; + if(listener->host && + memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof(struct in6_addr))){ + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address does not match specified listener host."); + }else{ + memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, + &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, + sizeof(struct in6_addr)); + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } } } } freeifaddrs(ifaddr); - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s.", + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "ipv4" : "ipv6"); return MOSQ_ERR_NOT_FOUND; } From 6bea9f7b32f983ea02a592d33dca2d1da4e67655 Mon Sep 17 00:00:00 2001 From: Vidar Madsen Date: Thu, 18 Feb 2021 15:34:53 +0100 Subject: [PATCH 03/19] Handle stale stored messages with conflicting message IDs. Signed-off-by: Vidar Madsen --- src/database.c | 26 ++++++++++++++++++++++++++ src/handle_publish.c | 7 +++++++ 2 files changed, 33 insertions(+) diff --git a/src/database.c b/src/database.c index db18b9f1..414d7780 100644 --- a/src/database.c +++ b/src/database.c @@ -893,6 +893,32 @@ int db__message_reconnect_reset(struct mosquitto *context) } +int db__message_remove_incoming(struct mosquitto* context, uint16_t mid) +{ + struct mosquitto_client_msg* tail, * tmp; + bool deleted = false; + + if (!context) return MOSQ_ERR_INVAL; + + DL_FOREACH_SAFE(context->msgs_in.inflight, tail, tmp) { + if (tail->mid == mid) { + if (tail->store->qos != 2) { + return MOSQ_ERR_PROTOCOL; + } + db__message_remove(&context->msgs_in, tail); + deleted = true; + } + } + + if (deleted) { + return MOSQ_ERR_SUCCESS; + } + else { + return MOSQ_ERR_NOT_FOUND; + } +} + + int db__message_release_incoming(struct mosquitto *context, uint16_t mid) { struct mosquitto_client_msg *tail, *tmp; diff --git a/src/handle_publish.c b/src/handle_publish.c index 68359b69..55fb3c20 100644 --- a/src/handle_publish.c +++ b/src/handle_publish.c @@ -285,6 +285,13 @@ int handle__publish(struct mosquitto *context) if(msg->qos > 0){ db__message_store_find(context, msg->source_mid, &stored); } + + if (stored && (stored->qos != msg->qos || stored->payloadlen != msg->payloadlen || strcmp(stored->topic, msg->topic) || memcmp(stored->payload, msg->payload, msg->payloadlen))){ + log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID from %s detected. Clearing from storage.", context->id); + db__message_remove_incoming(context, stored->mid); + stored = NULL; + } + if(!stored){ if(msg->qos == 0 || db__ready_for_flight(&context->msgs_in, msg->qos) From ebfcc84cdaa03d444eeb11339f82edbc043806e6 Mon Sep 17 00:00:00 2001 From: Vidar Madsen Date: Fri, 19 Feb 2021 13:53:50 +0100 Subject: [PATCH 04/19] Add new function to header. Minor tweaks. Signed-off-by: Vidar Madsen --- src/database.c | 1 - src/handle_publish.c | 6 +++--- src/mosquitto_broker_internal.h | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/database.c b/src/database.c index 414d7780..3016df34 100644 --- a/src/database.c +++ b/src/database.c @@ -918,7 +918,6 @@ int db__message_remove_incoming(struct mosquitto* context, uint16_t mid) } } - int db__message_release_incoming(struct mosquitto *context, uint16_t mid) { struct mosquitto_client_msg *tail, *tmp; diff --git a/src/handle_publish.c b/src/handle_publish.c index 55fb3c20..75bc8f23 100644 --- a/src/handle_publish.c +++ b/src/handle_publish.c @@ -286,9 +286,9 @@ int handle__publish(struct mosquitto *context) db__message_store_find(context, msg->source_mid, &stored); } - if (stored && (stored->qos != msg->qos || stored->payloadlen != msg->payloadlen || strcmp(stored->topic, msg->topic) || memcmp(stored->payload, msg->payload, msg->payloadlen))){ - log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID from %s detected. Clearing from storage.", context->id); - db__message_remove_incoming(context, stored->mid); + if (stored && msg->source_mid != 0 && (stored->qos != msg->qos || stored->payloadlen != msg->payloadlen || strcmp(stored->topic, msg->topic) || memcmp(stored->payload, msg->payload, msg->payloadlen) )){ + log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", msg->source_mid, context->id); + db__message_remove_incoming(context, msg->source_mid); stored = NULL; } diff --git a/src/mosquitto_broker_internal.h b/src/mosquitto_broker_internal.h index 5b88710f..78b8d0af 100644 --- a/src/mosquitto_broker_internal.h +++ b/src/mosquitto_broker_internal.h @@ -639,6 +639,7 @@ int persist__restore(void); int db__message_count(int *count); int db__message_delete_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state expect_state, int qos); int db__message_insert(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, uint8_t qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties, bool update); +int db__message_remove_incoming(struct mosquitto* context, uint16_t mid); int db__message_release_incoming(struct mosquitto *context, uint16_t mid); int db__message_update_outgoing(struct mosquitto *context, uint16_t mid, enum mosquitto_msg_state state, int qos); void db__message_dequeue_first(struct mosquitto *context, struct mosquitto_msg_data *msg_data); From 2a38b7115b605bce3e9c9bcf7c376bfce345e80c Mon Sep 17 00:00:00 2001 From: Abilio Marques Date: Fri, 26 Feb 2021 01:00:48 +0100 Subject: [PATCH 05/19] brige: fix backoff not working for remote broker returned errors Signed-off-by: Abilio Marques --- src/bridge.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bridge.c b/src/bridge.c index d10d1269..8487dbb8 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -313,10 +313,8 @@ int bridge__connect_step3(struct mosquitto *context) rc = send__connect(context, context->keepalive, context->clean_start, NULL); if(rc == MOSQ_ERR_SUCCESS){ - bridge__backoff_reset(context); return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ - bridge__backoff_reset(context); return MOSQ_ERR_SUCCESS; }else{ if(rc == MOSQ_ERR_TLS){ @@ -454,10 +452,8 @@ int bridge__connect(struct mosquitto *context) rc2 = send__connect(context, context->keepalive, context->clean_start, NULL); if(rc2 == MOSQ_ERR_SUCCESS){ - bridge__backoff_reset(context); return rc; }else if(rc2 == MOSQ_ERR_ERRNO && errno == ENOTCONN){ - bridge__backoff_reset(context); return MOSQ_ERR_SUCCESS; }else{ if(rc2 == MOSQ_ERR_TLS){ @@ -562,6 +558,8 @@ int bridge__on_connect(struct mosquitto *context) } } + bridge__backoff_reset(context); + return MOSQ_ERR_SUCCESS; } From 64f697d55da1d02cd40d43e5349c83aeae681f41 Mon Sep 17 00:00:00 2001 From: Roger Light Date: Wed, 3 Mar 2021 22:21:24 +0000 Subject: [PATCH 06/19] Fix `tls_version` behaviour not matching documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was setting the exact TLS version to use, not the minimium TLS version to use. Closes #2110. Thanks to Petter Jönsson. --- ChangeLog.txt | 8 ++++++++ src/net.c | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index a83937e2..73b29b75 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,11 @@ +2.0.9 - 2021-03-xx +================== + +Broker: +- Fix `tls_version` behaviour not matching documentation. It was setting the + exact TLS version to use, not the minimium TLS version to use. Closes #2110. + + 2.0.8 - 2021-02-25 ================== diff --git a/src/net.c b/src/net.c index dcc9db36..2c7b0cf8 100644 --- a/src/net.c +++ b/src/net.c @@ -335,14 +335,14 @@ int net__tls_server_ctx(struct mosquitto__listener *listener) }else if(!strcmp(listener->tls_version, "tlsv1.3")){ SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); }else if(!strcmp(listener->tls_version, "tlsv1.2")){ - SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_3); + SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); }else if(!strcmp(listener->tls_version, "tlsv1.1")){ - SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); + SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); #else }else if(!strcmp(listener->tls_version, "tlsv1.2")){ SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); }else if(!strcmp(listener->tls_version, "tlsv1.1")){ - SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2); + SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); #endif }else{ log__printf(NULL, MOSQ_LOG_ERR, "Error: Unsupported tls_version \"%s\".", listener->tls_version); From 83334afee8d271c54b4f94bc93eaa0f252b237aa Mon Sep 17 00:00:00 2001 From: Roger Light Date: Wed, 3 Mar 2021 22:44:50 +0000 Subject: [PATCH 07/19] Remove redunant function delaration. --- include/mosquitto.h | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/include/mosquitto.h b/include/mosquitto.h index 3e304836..587888a6 100644 --- a/include/mosquitto.h +++ b/include/mosquitto.h @@ -1604,40 +1604,6 @@ libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt */ libmosq_EXPORT int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value); -/* - * Function: mosquitto_string_option - * - * Used to set const char* options for the client. - * - * Parameters: - * mosq - a valid mosquitto instance. - * option - the option to set. - * value - the option specific value. - * - * Options: - * MOSQ_OPT_TLS_ENGINE - * Configure the client for TLS Engine support. Pass a TLS Engine ID - * to be used when creating TLS connections. - * Must be set before . - * MOSQ_OPT_TLS_KEYFORM - * Configure the client to treat the keyfile differently depending - * on its type. Must be set before . - * Set as either "pem" or "engine", to determine from where the - * private key for a TLS connection will be obtained. Defaults to - * "pem", a normal private key file. - * MOSQ_OPT_TLS_KPASS_SHA1 - * Where the TLS Engine requires the use of a password to be - * accessed, this option allows a hex encoded SHA1 hash of the - * private key password to be passed to the engine directly. - * Must be set before . - * MOSQ_OPT_TLS_ALPN - * If the broker being connected to has multiple services available - * on a single TLS port, such as both MQTT and WebSockets, use this - * option to configure the ALPN option for the connection. - */ -libmosq_EXPORT int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value); - - /* * Function: mosquitto_reconnect_delay_set * From 7baca428da1822c0ece3ba526ef8065c49c7dfa7 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 4 Mar 2021 09:49:29 +0000 Subject: [PATCH 08/19] Remove obsolete tests. --- test/broker/03-publish-b2c-timeout-qos1.py | 71 ------------------- test/broker/03-publish-b2c-timeout-qos2.py | 81 ---------------------- test/broker/03-publish-c2b-timeout-qos2.py | 52 -------------- 3 files changed, 204 deletions(-) delete mode 100755 test/broker/03-publish-b2c-timeout-qos1.py delete mode 100755 test/broker/03-publish-b2c-timeout-qos2.py delete mode 100755 test/broker/03-publish-c2b-timeout-qos2.py diff --git a/test/broker/03-publish-b2c-timeout-qos1.py b/test/broker/03-publish-b2c-timeout-qos1.py deleted file mode 100755 index a30d1af8..00000000 --- a/test/broker/03-publish-b2c-timeout-qos1.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 - -# Test whether a SUBSCRIBE to a topic with QoS 2 results in the correct SUBACK packet. - -from mosq_test_helper import * - - -def helper(port): - connect_packet = mosq_test.gen_connect("test-helper", keepalive=60) - connack_packet = mosq_test.gen_connack(rc=0) - - mid = 128 - publish_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message") - puback_packet = mosq_test.gen_puback(mid) - - sock = mosq_test.do_client_connect(connect_packet, connack_packet, connack_error="helper connack") - mosq_test.do_send_receive(sock, publish_packet, puback_packet, "helper puback") - sock.close() - - -def do_test(proto_ver): - rc = 1 - mid = 3265 - keepalive = 60 - connect_packet = mosq_test.gen_connect("pub-qos1-timeout-test", keepalive=keepalive, proto_ver=proto_ver) - connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver) - - subscribe_packet = mosq_test.gen_subscribe(mid, "qos1/timeout/test", 1, proto_ver=proto_ver) - suback_packet = mosq_test.gen_suback(mid, 1, proto_ver=proto_ver) - - mid = 1 - publish_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message", proto_ver=proto_ver) - publish_dup_packet = mosq_test.gen_publish("qos1/timeout/test", qos=1, mid=mid, payload="timeout-message", dup=True, proto_ver=proto_ver) - puback_packet = mosq_test.gen_puback(mid, proto_ver=proto_ver) - - port = mosq_test.get_port() - broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port) - - try: - sock = mosq_test.do_client_connect(connect_packet, connack_packet) - mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback") - - helper(port) - # Should have now received a publish command - - mosq_test.expect_packet(sock, "publish", publish_packet) - # Wait for longer than 5 seconds to get republish with dup set - # This is covered by the 8 second timeout - - mosq_test.expect_packet(sock, "dup publish", publish_dup_packet) - sock.send(puback_packet) - rc = 0 - - sock.close() - except mosq_test.TestError: - pass - finally: - broker.terminate() - broker.wait() - (stdo, stde) = broker.communicate() - if rc: - print(stde.decode('utf-8')) - print("proto_ver=%d" % (proto_ver)) - exit(rc) - - -do_test(proto_ver=4) -do_test(proto_ver=5) - -exit(0) - diff --git a/test/broker/03-publish-b2c-timeout-qos2.py b/test/broker/03-publish-b2c-timeout-qos2.py deleted file mode 100755 index 6b80bf18..00000000 --- a/test/broker/03-publish-b2c-timeout-qos2.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 - -# Test whether a SUBSCRIBE to a topic with QoS 2 results in the correct SUBACK packet. - -from mosq_test_helper import * - - -def helper(port): - connect_packet = mosq_test.gen_connect("test-helper", keepalive=60) - connack_packet = mosq_test.gen_connack(rc=0) - - mid = 312 - publish_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message") - pubrec_packet = mosq_test.gen_pubrec(mid) - pubrel_packet = mosq_test.gen_pubrel(mid) - pubcomp_packet = mosq_test.gen_pubcomp(mid) - - sock = mosq_test.do_client_connect(connect_packet, connack_packet, connack_error="helper connack") - mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "helper pubrec") - mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "helper pubcomp") - sock.close() - - -def do_test(proto_ver): - rc = 1 - mid = 3265 - keepalive = 60 - connect_packet = mosq_test.gen_connect("pub-qo2-timeout-test", keepalive=keepalive, proto_ver=proto_ver) - connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver) - - subscribe_packet = mosq_test.gen_subscribe(mid, "qos2/timeout/test", 2, proto_ver=proto_ver) - suback_packet = mosq_test.gen_suback(mid, 2, proto_ver=proto_ver) - - mid = 1 - publish_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message", proto_ver=proto_ver) - publish_dup_packet = mosq_test.gen_publish("qos2/timeout/test", qos=2, mid=mid, payload="timeout-message", dup=True, proto_ver=proto_ver) - pubrec_packet = mosq_test.gen_pubrec(mid, proto_ver=proto_ver) - pubrel_packet = mosq_test.gen_pubrel(mid, proto_ver=proto_ver) - pubcomp_packet = mosq_test.gen_pubcomp(mid, proto_ver=proto_ver) - - port = mosq_test.get_port() - broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port) - - try: - sock = mosq_test.do_client_connect(connect_packet, connack_packet) - mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback") - - helper(port) - # Should have now received a publish command - - mosq_test.expect_packet(sock, "publish", publish_packet) - # Wait for longer than 5 seconds to get republish with dup set - # This is covered by the 8 second timeout - - mosq_test.expect_packet(sock, "dup publish", publish_dup_packet) - mosq_test.do_send_receive(sock, pubrec_packet, pubrel_packet, "pubrel") - - # Wait for longer than 5 seconds to get republish with dup set - # This is covered by the 8 second timeout - - mosq_test.expect_packet(sock, "dup pubrel", pubrel_packet) - sock.send(pubcomp_packet) - rc = 0 - - sock.close() - except mosq_test.TestError: - pass - finally: - broker.terminate() - broker.wait() - (stdo, stde) = broker.communicate() - if rc: - print(stde.decode('utf-8')) - print("proto_ver=%d" % (proto_ver)) - exit(rc) - - -do_test(proto_ver=4) -do_test(proto_ver=5) -exit(0) - diff --git a/test/broker/03-publish-c2b-timeout-qos2.py b/test/broker/03-publish-c2b-timeout-qos2.py deleted file mode 100755 index 54538fe2..00000000 --- a/test/broker/03-publish-c2b-timeout-qos2.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 - -# Test whether a PUBLISH to a topic with QoS 2 results in the correct packet -# flow. This test introduces delays into the flow in order to force the broker -# to send duplicate PUBREC and PUBCOMP messages. - -from mosq_test_helper import * - - -def do_test(port): - rc = 1 - keepalive = 600 - connect_packet = mosq_test.gen_connect("pub-qos2-timeout-test", keepalive=keepalive, proto_ver=proto_ver) - connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver) - - mid = 1926 - publish_packet = mosq_test.gen_publish("pub/qos2/test", qos=2, mid=mid, payload="timeout-message", proto_ver=proto_ver) - pubrec_packet = mosq_test.gen_pubrec(mid, proto_ver=proto_ver) - pubrel_packet = mosq_test.gen_pubrel(mid, proto_ver=proto_ver) - pubcomp_packet = mosq_test.gen_pubcomp(mid, proto_ver=proto_ver) - - port = mosq_test.get_port() - broker = mosq_test.start_broker(filename=os.path.basename(__file__), port=port) - - try: - sock = mosq_test.do_client_connect(connect_packet, connack_packet) - mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "pubrec") - - # Timeout is 8 seconds which means the broker should repeat the PUBREC. - - mosq_test.expect_packet(sock, "pubrec", pubrec_packet) - mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "pubcomp") - - rc = 0 - - sock.close() - except mosq_test.TestError: - pass - finally: - broker.terminate() - broker.wait() - (stdo, stde) = broker.communicate() - if rc: - print(stde.decode('utf-8')) - print("proto_ver=%d" % (proto_ver)) - exit(rc) - - -do_test(proto_ver=4) -do_test(proto_ver=5) -exit(0) - From f89a3c3fc081728f5ccaa74b3e4d447d3706c6f1 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Sat, 6 Mar 2021 00:57:37 +0000 Subject: [PATCH 09/19] Fix messages to `$` prefixed topics being rejected. Closes #2111. Thanks to yellowgg2. --- ChangeLog.txt | 1 + src/retain.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 73b29b75..ffc5f40e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -4,6 +4,7 @@ Broker: - Fix `tls_version` behaviour not matching documentation. It was setting the exact TLS version to use, not the minimium TLS version to use. Closes #2110. +- Fix messages to `$` prefixed topics being rejected. Closes #2111. 2.0.8 - 2021-02-25 diff --git a/src/retain.c b/src/retain.c index ca9e7313..ee8ad609 100644 --- a/src/retain.c +++ b/src/retain.c @@ -83,7 +83,10 @@ int retain__store(const char *topic, struct mosquitto_msg_store *stored, char ** assert(split_topics); HASH_FIND(hh, db.retains, split_topics[0], strlen(split_topics[0]), retainhier); - if(retainhier == NULL) return MOSQ_ERR_NOT_FOUND; + if(retainhier == NULL){ + retainhier = retain__add_hier_entry(NULL, &db.retains, split_topics[0], (uint16_t)strlen(split_topics[0])); + if(!retainhier) return MOSQ_ERR_NOMEM; + } for(i=0; split_topics[i] != NULL; i++){ slen = strlen(split_topics[i]); From e401def06dd68ce70c101eac5c3e051a3ea72392 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 8 Mar 2021 23:23:45 +0000 Subject: [PATCH 10/19] Fix QoS 0 messages not being delivered when max_queued_bytes was configured. Closes #2123. Thanks to quackgizmo. --- ChangeLog.txt | 2 + lib/mosquitto_internal.h | 4 +- src/database.c | 6 +-- test/broker/02-subpub-qos0-queued-bytes.py | 61 ++++++++++++++++++++++ test/broker/Makefile | 1 + test/broker/test.py | 1 + 6 files changed, 70 insertions(+), 5 deletions(-) create mode 100755 test/broker/02-subpub-qos0-queued-bytes.py diff --git a/ChangeLog.txt b/ChangeLog.txt index ffc5f40e..ee2fd96b 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -5,6 +5,8 @@ Broker: - Fix `tls_version` behaviour not matching documentation. It was setting the exact TLS version to use, not the minimium TLS version to use. Closes #2110. - Fix messages to `$` prefixed topics being rejected. Closes #2111. +- Fix QoS 0 messages not being delivered when max_queued_bytes was configured. + Closes #2123. 2.0.8 - 2021-02-25 diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 04bdf92a..02008af1 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -190,8 +190,8 @@ struct mosquitto_msg_data{ #ifdef WITH_BROKER struct mosquitto_client_msg *inflight; struct mosquitto_client_msg *queued; - unsigned long msg_bytes; - unsigned long msg_bytes12; + long msg_bytes; + long msg_bytes12; int msg_count; int msg_count12; #else diff --git a/src/database.c b/src/database.c index db18b9f1..77eb4520 100644 --- a/src/database.c +++ b/src/database.c @@ -53,7 +53,7 @@ bool db__ready_for_flight(struct mosquitto_msg_data *msgs, int qos) if(db.config->max_queued_messages == 0 && db.config->max_inflight_bytes == 0){ return true; } - valid_bytes = msgs->msg_bytes - db.config->max_inflight_bytes < db.config->max_queued_bytes; + valid_bytes = ((msgs->msg_bytes - (ssize_t)db.config->max_inflight_bytes) < (ssize_t)db.config->max_queued_bytes); valid_count = msgs->msg_count - msgs->inflight_maximum < db.config->max_queued_messages; if(db.config->max_queued_messages == 0){ @@ -90,8 +90,8 @@ bool db__ready_for_queue(struct mosquitto *context, int qos, struct mosquitto_ms { int source_count; int adjust_count; - size_t source_bytes; - size_t adjust_bytes = db.config->max_inflight_bytes; + long source_bytes; + ssize_t adjust_bytes = (ssize_t)db.config->max_inflight_bytes; bool valid_bytes; bool valid_count; diff --git a/test/broker/02-subpub-qos0-queued-bytes.py b/test/broker/02-subpub-qos0-queued-bytes.py new file mode 100755 index 00000000..7ca08e80 --- /dev/null +++ b/test/broker/02-subpub-qos0-queued-bytes.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +from mosq_test_helper import * + +def write_config(filename, port): + with open(filename, 'w') as f: + f.write("listener %d\n" % (port)) + f.write("allow_anonymous true\n") + f.write("max_inflight_messages 20\n") + f.write("max_inflight_bytes 1000000\n") + f.write("max_queued_messages 20\n") + f.write("max_queued_bytes 1000000\n") + +def do_test(proto_ver): + rc = 1 + keepalive = 60 + connect_packet = mosq_test.gen_connect("subpub-qos0-bytes", keepalive=keepalive, proto_ver=proto_ver) + connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver) + + connect_packet_helper = mosq_test.gen_connect("qos0-bytes-helper", keepalive=keepalive, proto_ver=proto_ver) + + mid = 1 + subscribe_packet = mosq_test.gen_subscribe(mid, "subpub/qos0/queued/bytes", 1, proto_ver=proto_ver) + suback_packet = mosq_test.gen_suback(mid, 1, proto_ver=proto_ver) + + publish_packet0 = mosq_test.gen_publish("subpub/qos0/queued/bytes", qos=0, payload="message", proto_ver=proto_ver) + + + port = mosq_test.get_port() + conf_file = os.path.basename(__file__).replace('.py', '.conf') + write_config(conf_file, port) + broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port) + + try: + sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=4, port=port, connack_error="connack 1") + + mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback") + + helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet, timeout=4, port=port, connack_error="connack helper") + + helper.send(publish_packet0) + mosq_test.expect_packet(sock, "publish0", publish_packet0) + rc = 0 + + sock.close() + except mosq_test.TestError: + pass + finally: + os.remove(conf_file) + broker.terminate() + broker.wait() + (stdo, stde) = broker.communicate() + if rc: + print(stde.decode('utf-8')) + print("proto_ver=%d" % (proto_ver)) + exit(rc) + + +do_test(proto_ver=4) +do_test(proto_ver=5) +exit(0) diff --git a/test/broker/Makefile b/test/broker/Makefile index fcb6839d..01816063 100644 --- a/test/broker/Makefile +++ b/test/broker/Makefile @@ -45,6 +45,7 @@ test : test-compile 01 02 03 04 05 06 07 08 09 10 11 12 13 14 ./02-subhier-crash.py ./02-subpub-qos0-long-topic.py ./02-subpub-qos0-oversize-payload.py + ./02-subpub-qos0-queued-bytes.py ./02-subpub-qos0-retain-as-publish.py ./02-subpub-qos0-send-retain.py ./02-subpub-qos0-subscription-id.py diff --git a/test/broker/test.py b/test/broker/test.py index 0514359a..62216203 100755 --- a/test/broker/test.py +++ b/test/broker/test.py @@ -28,6 +28,7 @@ tests = [ (1, './02-subhier-crash.py'), (1, './02-subpub-qos0-long-topic.py'), (1, './02-subpub-qos0-oversize-payload.py'), + (1, './02-subpub-qos0-queued-bytes.py'), (1, './02-subpub-qos0-retain-as-publish.py'), (1, './02-subpub-qos0-send-retain.py'), (1, './02-subpub-qos0-subscription-id.py'), From ace2aa764e19eb1fcb24fa796cebad365f09df11 Mon Sep 17 00:00:00 2001 From: Roger Light Date: Mon, 8 Mar 2021 23:57:04 +0000 Subject: [PATCH 11/19] Fix cmake epoll detection. --- ChangeLog.txt | 3 +++ src/CMakeLists.txt | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index ee2fd96b..47bda056 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -8,6 +8,9 @@ Broker: - Fix QoS 0 messages not being delivered when max_queued_bytes was configured. Closes #2123. +Build: +- Fix cmake epoll detection. + 2.0.8 - 2021-02-25 ================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f283c8d0..7be39889 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,11 @@ if (WITH_BUNDLED_DEPS) include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/deps) endif (WITH_BUNDLED_DEPS) +find_path(HAVE_SYS_EPOLL_H sys/epoll.h) +if (HAVE_SYS_EPOLL_H) + add_definitions("-DWITH_EPOLL") +endif() + option(INC_BRIDGE_SUPPORT "Include bridge support for connecting to other brokers?" ON) if (INC_BRIDGE_SUPPORT) From b7a08d5c406829a3da89bb105f18332755498ee9 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 12:45:04 +0000 Subject: [PATCH 12/19] Fix TLS bridge/lib incorrectly connecting on invalid CA file. Closes #2130. Thanks to becz. --- ChangeLog.txt | 20 ++++++++++++++++++-- lib/mosquitto.c | 1 + src/bridge.c | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 47bda056..ca5eccf4 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,13 +1,29 @@ -2.0.9 - 2021-03-xx +2.0.9 - 2021-03-11 ================== -Broker: +Security: +- If an empty or invalid CA file was provided to the client library for + verifying the remote broker, then the initial connection would fail but + subsequent connections would succeed without verifying the remote broker + certificate. Closes #2130. +- If an empty or invalid CA file was provided to the broker for verifying the + remote broker for an outgoing bridge connection then the initial connection + would fail but subsequent connections would succeed without verifying the + remote broker certificate. Closes #2130. + +Broker: +- Fix encrypted bridge connections incorrectly connecting when `bridge_cafile` + is empty or invalid. Closes #2130. - Fix `tls_version` behaviour not matching documentation. It was setting the exact TLS version to use, not the minimium TLS version to use. Closes #2110. - Fix messages to `$` prefixed topics being rejected. Closes #2111. - Fix QoS 0 messages not being delivered when max_queued_bytes was configured. Closes #2123. +Client library: +- Fix encrypted connections incorrectly connecting when the CA file passed to + `mosquitto_tls_set()` is empty or invalid. Closes #2130. + Build: - Fix cmake epoll detection. diff --git a/lib/mosquitto.c b/lib/mosquitto.c index 0dd4ac01..0d53f2e5 100644 --- a/lib/mosquitto.c +++ b/lib/mosquitto.c @@ -196,6 +196,7 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st #ifdef WITH_TLS mosq->ssl = NULL; mosq->ssl_ctx = NULL; + mosq->ssl_ctx_defaults = true; mosq->tls_cert_reqs = SSL_VERIFY_PEER; mosq->tls_insecure = false; mosq->want_write = false; diff --git a/src/bridge.c b/src/bridge.c index d10d1269..f5158dba 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -112,6 +112,7 @@ int bridge__new(struct mosquitto__bridge *bridge) new_context->tls_alpn = new_context->bridge->tls_alpn; new_context->tls_engine = db.config->default_listener.tls_engine; new_context->tls_keyform = db.config->default_listener.tls_keyform; + new_context->ssl_ctx_defaults = true; #ifdef FINAL_WITH_TLS_PSK new_context->tls_psk_identity = new_context->bridge->tls_psk_identity; new_context->tls_psk = new_context->bridge->tls_psk; From c11a2d5a8b582d5c3a319944f47d98d9230bcc63 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 14:00:08 +0000 Subject: [PATCH 13/19] Fix mosquitto_rr doc default version. Closes #2032. --- man/mosquitto_rr.1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/mosquitto_rr.1.xml b/man/mosquitto_rr.1.xml index 27309532..a62fbc72 100644 --- a/man/mosquitto_rr.1.xml +++ b/man/mosquitto_rr.1.xml @@ -632,7 +632,7 @@ , or the more verbose , , or . - Defaults to . + Defaults to . From 88d2c74ab2871eab8dfced0b34e686f2d5496a4e Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 15:02:31 +0000 Subject: [PATCH 14/19] Fix bridge backoff calculation. --- ChangeLog.txt | 1 + src/bridge.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index ca5eccf4..7aefb141 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -19,6 +19,7 @@ Broker: - Fix messages to `$` prefixed topics being rejected. Closes #2111. - Fix QoS 0 messages not being delivered when max_queued_bytes was configured. Closes #2123. +- Fix bridge increasing backoff calculation. Client library: - Fix encrypted connections incorrectly connecting when the CA file passed to diff --git a/src/bridge.c b/src/bridge.c index 54425a6e..f55315fb 100644 --- a/src/bridge.c +++ b/src/bridge.c @@ -645,11 +645,11 @@ void bridge__packet_cleanup(struct mosquitto *context) packet__cleanup(&(context->in_packet)); } -static int rand_between(int base, int cap) +static int rand_between(int low, int high) { int r; util__random_bytes(&r, sizeof(int)); - return (r % (cap - base)) + base; + return (abs(r) % (high - low)) + low; } static void bridge__backoff_step(struct mosquitto *context) @@ -684,6 +684,33 @@ static void bridge__backoff_reset(struct mosquitto *context) } } + +static void bridge_check_pending(struct mosquitto *context) +{ + int err; + socklen_t len; + + if(context->state == mosq_cs_connect_pending){ + len = sizeof(int); + if(!getsockopt(context->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &len)){ + if(err == 0){ + mosquitto__set_state(context, mosq_cs_new); +#if defined(WITH_ADNS) && defined(WITH_BRIDGE) + if(context->bridge){ + bridge__connect_step3(context); + } +#endif + }else if(err == ECONNREFUSED){ + do_disconnect(context, MOSQ_ERR_CONN_LOST); + return; + } + }else{ + do_disconnect(context, MOSQ_ERR_CONN_LOST); + return; + } + } +} + void bridge_check(void) { static time_t last_check = 0; @@ -702,6 +729,7 @@ void bridge_check(void) if(context->sock != INVALID_SOCKET){ mosquitto__check_keepalive(context); + bridge_check_pending(context); /* Check for bridges that are not round robin and not currently * connected to their primary broker. */ From f4d088b6d0021fbf0ac4f9c88fdafc8f74850f03 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 15:09:38 +0000 Subject: [PATCH 15/19] Improve logging of pull request. Improve handling of invalid combinations of listener address and bind interface configurations. Closes #2081. --- ChangeLog.txt | 2 ++ src/net.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7aefb141..54d5377a 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -20,6 +20,8 @@ Broker: - Fix QoS 0 messages not being delivered when max_queued_bytes was configured. Closes #2123. - Fix bridge increasing backoff calculation. +- Improve handling of invalid combinations of listener address and bind + interface configurations. Closes #2081. Client library: - Fix encrypted connections incorrectly connecting when the CA file passed to diff --git a/src/net.c b/src/net.c index c1e3d55f..bbdb2708 100644 --- a/src/net.c +++ b/src/net.c @@ -628,7 +628,10 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, sizeof(struct in_addr))){ - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address does not match specified listener host."); + + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).", + listener->bind_interface, listener->host); + return MOSQ_ERR_INVAL; }else{ memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, @@ -642,7 +645,10 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, sizeof(struct in6_addr))){ - log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address does not match specified listener host."); + + log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface address for %s does not match specified listener address (%s).", + listener->bind_interface, listener->host); + return MOSQ_ERR_INVAL; }else{ memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, @@ -655,7 +661,7 @@ static int net__bind_interface(struct mosquitto__listener *listener, struct addr } freeifaddrs(ifaddr); log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", - listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "ipv4" : "ipv6"); + listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); return MOSQ_ERR_NOT_FOUND; } #endif From 720ce01faf9e40984067580e33a64e0615b651b0 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 15:21:49 +0000 Subject: [PATCH 16/19] Minor tweaks to PR. --- src/database.c | 21 ++++++++------------- src/handle_publish.c | 7 ++++++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/database.c b/src/database.c index 0faf998e..2ba131c5 100644 --- a/src/database.c +++ b/src/database.c @@ -895,29 +895,24 @@ int db__message_reconnect_reset(struct mosquitto *context) int db__message_remove_incoming(struct mosquitto* context, uint16_t mid) { - struct mosquitto_client_msg* tail, * tmp; - bool deleted = false; + struct mosquitto_client_msg *tail, *tmp; - if (!context) return MOSQ_ERR_INVAL; + if(!context) return MOSQ_ERR_INVAL; - DL_FOREACH_SAFE(context->msgs_in.inflight, tail, tmp) { - if (tail->mid == mid) { - if (tail->store->qos != 2) { + DL_FOREACH_SAFE(context->msgs_in.inflight, tail, tmp){ + if(tail->mid == mid) { + if(tail->store->qos != 2){ return MOSQ_ERR_PROTOCOL; } db__message_remove(&context->msgs_in, tail); - deleted = true; + return MOSQ_ERR_SUCCESS; } } - if (deleted) { - return MOSQ_ERR_SUCCESS; - } - else { - return MOSQ_ERR_NOT_FOUND; - } + return MOSQ_ERR_NOT_FOUND; } + int db__message_release_incoming(struct mosquitto *context, uint16_t mid) { struct mosquitto_client_msg *tail, *tmp; diff --git a/src/handle_publish.c b/src/handle_publish.c index 75bc8f23..4686d350 100644 --- a/src/handle_publish.c +++ b/src/handle_publish.c @@ -286,7 +286,12 @@ int handle__publish(struct mosquitto *context) db__message_store_find(context, msg->source_mid, &stored); } - if (stored && msg->source_mid != 0 && (stored->qos != msg->qos || stored->payloadlen != msg->payloadlen || strcmp(stored->topic, msg->topic) || memcmp(stored->payload, msg->payload, msg->payloadlen) )){ + if(stored && msg->source_mid != 0 && + (stored->qos != msg->qos + || stored->payloadlen != msg->payloadlen + || strcmp(stored->topic, msg->topic) + || memcmp(stored->payload, msg->payload, msg->payloadlen) )){ + log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", msg->source_mid, context->id); db__message_remove_incoming(context, msg->source_mid); stored = NULL; From 891be8c2fe0b68dda327b2ebc09342f72ad8018d Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 19:57:51 +0000 Subject: [PATCH 17/19] Fix `max_keepalive` option not applying to keepalive=0. Closes #2117. Thanks to David Nadlinger. --- ChangeLog.txt | 2 ++ src/handle_connect.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 54d5377a..3d86cc58 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -22,6 +22,8 @@ Broker: - Fix bridge increasing backoff calculation. - Improve handling of invalid combinations of listener address and bind interface configurations. Closes #2081. +- Fix `max_keepalive` option not applying to clients connecting with keepalive + set to 0. Closes #2117. Client library: - Fix encrypted connections incorrectly connecting when the CA file passed to diff --git a/src/handle_connect.c b/src/handle_connect.c index 6dfd9e3a..c3355d90 100644 --- a/src/handle_connect.c +++ b/src/handle_connect.c @@ -244,7 +244,9 @@ int connect__on_authorised(struct mosquitto *context, void *auth_data_out, uint1 goto error; } } - if(context->keepalive > db.config->max_keepalive){ + if(db.config->max_keepalive && + (context->keepalive > db.config->max_keepalive || context->keepalive == 0)){ + context->keepalive = db.config->max_keepalive; if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_SERVER_KEEP_ALIVE, context->keepalive)){ rc = MOSQ_ERR_NOMEM; From f8838243fbb9689ce4195a6fbbb499ba477d1c65 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 21:04:16 +0000 Subject: [PATCH 18/19] Fix connections retrying very rapidly in some situations. Thanks to Abilio Marques. --- ChangeLog.txt | 1 + lib/loop.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog.txt b/ChangeLog.txt index 3d86cc58..063e29a1 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -28,6 +28,7 @@ Broker: Client library: - Fix encrypted connections incorrectly connecting when the CA file passed to `mosquitto_tls_set()` is empty or invalid. Closes #2130. +- Fix connections retrying very rapidly in some situations. Build: - Fix cmake epoll detection. diff --git a/lib/loop.c b/lib/loop.c index bc2ba7f4..046dde0b 100644 --- a/lib/loop.c +++ b/lib/loop.c @@ -203,6 +203,13 @@ static int interruptible_sleep(struct mosquitto *mosq, time_t reconnect_delay) char pairbuf; int maxfd = 0; +#ifndef WIN32 + if(read(mosq->sockpairR, &pairbuf, 1) == 0){ + } +#else + recv(mosq->sockpairR, &pairbuf, 1, 0); +#endif + local_timeout.tv_sec = reconnect_delay; #ifdef HAVE_PSELECT local_timeout.tv_nsec = 0; From bb73eed557af2122f46b62e791ef5e4289a144dc Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 11 Mar 2021 22:33:01 +0000 Subject: [PATCH 19/19] Bump version number and update web pages. --- CMakeLists.txt | 2 +- config.mk | 2 +- include/mosquitto.h | 2 +- installer/mosquitto.nsi | 2 +- installer/mosquitto64.nsi | 2 +- set-version.sh | 2 +- snap/snapcraft.yaml | 2 +- www/pages/download.md | 8 +- www/posts/2021/03/version-2-0-9-released.md | 101 ++++++++++++++++++++ 9 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 www/posts/2021/03/version-2-0-9-released.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 489105df..4963d4ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0042 NEW) project(mosquitto) -set (VERSION 2.0.8) +set (VERSION 2.0.9) list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") diff --git a/config.mk b/config.mk index 73e5cc39..d31b1160 100644 --- a/config.mk +++ b/config.mk @@ -127,7 +127,7 @@ WITH_XTREPORT=no # Also bump lib/mosquitto.h, CMakeLists.txt, # installer/mosquitto.nsi, installer/mosquitto64.nsi -VERSION=2.0.8 +VERSION=2.0.9 # Client library SO version. Bump if incompatible API/ABI changes are made. SOVERSION=1 diff --git a/include/mosquitto.h b/include/mosquitto.h index 587888a6..9aafcb32 100644 --- a/include/mosquitto.h +++ b/include/mosquitto.h @@ -66,7 +66,7 @@ extern "C" { #define LIBMOSQUITTO_MAJOR 2 #define LIBMOSQUITTO_MINOR 0 -#define LIBMOSQUITTO_REVISION 8 +#define LIBMOSQUITTO_REVISION 9 /* LIBMOSQUITTO_VERSION_NUMBER looks like 1002001 for e.g. version 1.2.1. */ #define LIBMOSQUITTO_VERSION_NUMBER (LIBMOSQUITTO_MAJOR*1000000+LIBMOSQUITTO_MINOR*1000+LIBMOSQUITTO_REVISION) diff --git a/installer/mosquitto.nsi b/installer/mosquitto.nsi index e34c7847..20487814 100644 --- a/installer/mosquitto.nsi +++ b/installer/mosquitto.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "Eclipse Mosquitto" -!define VERSION 2.0.8 +!define VERSION 2.0.9 OutFile "mosquitto-${VERSION}-install-windows-x86.exe" InstallDir "$PROGRAMFILES\mosquitto" diff --git a/installer/mosquitto64.nsi b/installer/mosquitto64.nsi index 4bd80f54..5ca2ca38 100644 --- a/installer/mosquitto64.nsi +++ b/installer/mosquitto64.nsi @@ -9,7 +9,7 @@ !define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' Name "Eclipse Mosquitto" -!define VERSION 2.0.8 +!define VERSION 2.0.9 OutFile "mosquitto-${VERSION}-install-windows-x64.exe" !include "x64.nsh" diff --git a/set-version.sh b/set-version.sh index a96b6a77..ba9b855a 100755 --- a/set-version.sh +++ b/set-version.sh @@ -2,7 +2,7 @@ MAJOR=2 MINOR=0 -REVISION=8 +REVISION=9 sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 0099409a..5e8289ba 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: mosquitto -version: 2.0.8 +version: 2.0.9 summary: Eclipse Mosquitto MQTT broker description: This is a message broker that supports version 5.0, 3.1.1, and 3.1 of the MQTT protocol. diff --git a/www/pages/download.md b/www/pages/download.md index 0d16e248..c181fdca 100644 --- a/www/pages/download.md +++ b/www/pages/download.md @@ -1,7 +1,7 @@ + +Versions 2.0.9, 1.6.14, and 1.5.11 of Mosquitto have been released. These are +bugfix releases and include a minor security fix. + +# 2.0.9 + +## Security +- If an empty or invalid CA file was provided to the client library for + verifying the remote broker, then the initial connection would fail but + subsequent connections would succeed without verifying the remote broker + certificate. Closes [#2130]. +- If an empty or invalid CA file was provided to the broker for verifying the + remote broker for an outgoing bridge connection then the initial connection + would fail but subsequent connections would succeed without verifying the + remote broker certificate. Closes [#2130]. + +## Broker +- Fix encrypted bridge connections incorrectly connecting when `bridge_cafile` + is empty or invalid. Closes [#2130]. +- Fix `tls_version` behaviour not matching documentation. It was setting the + exact TLS version to use, not the minimium TLS version to use. Closes [#2110]. +- Fix messages to `$` prefixed topics being rejected. Closes [#2111]. +- Fix QoS 0 messages not being delivered when max_queued_bytes was configured. + Closes [#2123]. +- Fix bridge increasing backoff calculation. +- Improve handling of invalid combinations of listener address and bind + interface configurations. Closes [#2081]. +- Fix `max_keepalive` option not applying to clients connecting with keepalive + set to 0. Closes [#2117]. + +## Client library +- Fix encrypted connections incorrectly connecting when the CA file passed to + `mosquitto_tls_set()` is empty or invalid. Closes [#2130]. +- Fix connections retrying very rapidly in some situations. + +## Build +- Fix cmake epoll detection. + +# 1.6.14 + +## Security +- If an empty or invalid CA file was provided to the client library for + verifying the remote broker, then the initial connection would fail but + subsequent connections would succeed without verifying the remote broker + certificate. Closes [#2130]. +- If an empty or invalid CA file was provided to the broker for verifying the + remote broker for an outgoing bridge connection then the initial connection + would fail but subsequent connections would succeed without verifying the + remote broker certificate. Closes [#2130]. + +## Broker +- Fix encrypted bridge connections incorrectly connecting when `bridge_cafile` + is empty or invalid. Closes [#2130]. + +## Client library +- Fix encrypted connections incorrectly connecting when the CA file passed to + `mosquitto_tls_set()` is empty or invalid. Closes [#2130]. +- Fix connections retrying very rapidly in some situations. + +## Clients +- Fix possible loss of data in `mosquitto_pub -l` when sending multiple long + lines. Closes [#2078]. + +# 1.5.11 + +## Security +- If an empty or invalid CA file was provided to the client library for + verifying the remote broker, then the initial connection would fail but + subsequent connections would succeed without verifying the remote broker + certificate. Closes [#2130]. +- If an empty or invalid CA file was provided to the broker for verifying the + remote broker for an outgoing bridge connection then the initial connection + would fail but subsequent connections would succeed without verifying the + remote broker certificate. Closes [#2130]. + +## Broker +- Fix encrypted bridge connections incorrectly connecting when `bridge_cafile` + is empty or invalid. Closes [#2130]. + +## Client library +- Fix encrypted connections incorrectly connecting when the CA file passed to + `mosquitto_tls_set()` is empty or invalid. Closes [#2130]. + +[#2040]: https://github.com/eclipse/mosquitto/issues/2040 +[#2078]: https://github.com/eclipse/mosquitto/issues/2078 +[#2081]: https://github.com/eclipse/mosquitto/issues/2081 +[#2110]: https://github.com/eclipse/mosquitto/issues/2110 +[#2111]: https://github.com/eclipse/mosquitto/issues/2111 +[#2117]: https://github.com/eclipse/mosquitto/issues/2117 +[#2123]: https://github.com/eclipse/mosquitto/issues/2123 +[#2130]: https://github.com/eclipse/mosquitto/issues/2130