Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package mosquitto [ Reason ] Mosquitto 2.0.8 is currently in testing, Mosquitto 2.0.9 was released on 2021-03-11 and has sufficiently important fixes in it that I believe should be in a Debian release. The full debdiff is 1110 lines. If I reduce that to code-only changes it drops to 387 (the remainder are documentation and extra tests), with about 150 lines of actual affected code. It is a small bugfix release with low risk but some reasonably important fixes. [ Impact ] I have listed the fixes below that I think are worth mentioning. The other changes are of minor impact or are fixing strict compiler warnings. Client and library: There is a fairly minor security issue that affects outgoing client connections only - if an empty or corrupt CA certificate is provided to a client, then the initial connection would fail but subsequent connections would succeed without verifying the remote server certificate. There is a new test for this behaviour, but it is not in the 2.0.9 release. Build: The CMake build script was not enabling epoll(), so poll() was being used instead which has a very detrimental impact on performance. Server: Messages published with QoS 0 were not being delivered when `max_queued_bytes` was configured. This has a big impact on users wanting to use QoS 0, which is the most common QoS, but also set some client limits. There is a new test to check this behaviour. Server: If the `max_keepalive` option was set, this did not apply to clients connecting with keepalive set to 0 (which means "infinite keepalive"). This gives a very straightforward means to circumvent the wishes of the server operator, although in itself it isn't very important. Server: The behaviour setting acceptable TLS versions did not match the documentation. Server: Messages to '$' prefixed MQTT topics were being rejected. This is not security critical but very annoying for a user wanting to use that feature. [ Tests ] The release introduces a new test that covers one issue. A test exists for the CA issue but is not part of this release. [ Risks ] I believe this to be low risk. Most of the code changes are reasonably simple. shairport-sync, kamailio-mqtt-module, and baresip-core depend on libmosquitto1. The changes to the library code are trivial. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] mosquitto_2.0.8-mosquitto-2.0.9.debdiff is the full debdiff. mosquitto_2.0.8-mosquitto-2.0.9-code.debdiff is the code only debdiff. unblock mosquitto/2.0.9-1 -- System Information: Debian Release: bullseye/sid APT prefers focal-updates APT policy: (500, 'focal-updates'), (500, 'focal-security'), (500, 'focal-proposed'), (500, 'focal'), (100, 'focal-backports') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 5.4.0-48-generic (SMP w/4 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
diff -Nru mosquitto-2.0.8/ChangeLog.txt mosquitto-2.0.9/ChangeLog.txt --- mosquitto-2.0.8/ChangeLog.txt 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/ChangeLog.txt 2021-03-11 22:37:20.000000000 +0000 @@ -1,3 +1,39 @@ +2.0.9 - 2021-03-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. +- 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. + + 2.0.8 - 2021-02-25 ================== diff -Nru mosquitto-2.0.8/CMakeLists.txt mosquitto-2.0.9/CMakeLists.txt --- mosquitto-2.0.8/CMakeLists.txt 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/CMakeLists.txt 2021-03-11 22:37:20.000000000 +0000 @@ -8,7 +8,7 @@ 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 -Nru mosquitto-2.0.8/config.mk mosquitto-2.0.9/config.mk --- mosquitto-2.0.8/config.mk 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/config.mk 2021-03-11 22:37:20.000000000 +0000 @@ -127,7 +127,7 @@ # 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 -Nru mosquitto-2.0.8/debian/changelog mosquitto-2.0.9/debian/changelog --- mosquitto-2.0.8/debian/changelog 2021-02-25 18:56:57.000000000 +0000 +++ mosquitto-2.0.9/debian/changelog 2021-03-11 22:53:34.000000000 +0000 @@ -1,3 +1,9 @@ +mosquitto (2.0.9-1) unstable; urgency=medium + + * New upstream release. + + -- Roger A. Light <ro...@atchoo.org> Thu, 11 Mar 2021 22:53:34 +0000 + mosquitto (2.0.8-1) unstable; urgency=medium * New upstream release. diff -Nru mosquitto-2.0.8/debian/control mosquitto-2.0.9/debian/control --- mosquitto-2.0.8/debian/control 2021-02-25 18:56:53.000000000 +0000 +++ mosquitto-2.0.9/debian/control 2021-03-11 22:53:28.000000000 +0000 @@ -11,7 +11,7 @@ libwebsockets-dev, libwrap0-dev, pkg-config, - uthash-dev (>=2.1.0), + uthash-dev, xsltproc, docbook-xsl Standards-Version: 4.5.0 diff -Nru mosquitto-2.0.8/include/mosquitto.h mosquitto-2.0.9/include/mosquitto.h --- mosquitto-2.0.8/include/mosquitto.h 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/include/mosquitto.h 2021-03-11 22:37:20.000000000 +0000 @@ -66,7 +66,7 @@ #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) @@ -1605,40 +1605,6 @@ 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 <mosquitto_connect>. - * MOSQ_OPT_TLS_KEYFORM - * Configure the client to treat the keyfile differently depending - * on its type. Must be set before <mosquitto_connect>. - * 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 <mosquitto_connect>. - * 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 * * Control the behaviour of the client when it has unexpectedly disconnected in diff -Nru mosquitto-2.0.8/installer/mosquitto64.nsi mosquitto-2.0.9/installer/mosquitto64.nsi --- mosquitto-2.0.8/installer/mosquitto64.nsi 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/installer/mosquitto64.nsi 2021-03-11 22:37:20.000000000 +0000 @@ -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 -Nru mosquitto-2.0.8/installer/mosquitto.nsi mosquitto-2.0.9/installer/mosquitto.nsi --- mosquitto-2.0.8/installer/mosquitto.nsi 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/installer/mosquitto.nsi 2021-03-11 22:37:20.000000000 +0000 @@ -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 -Nru mosquitto-2.0.8/lib/loop.c mosquitto-2.0.9/lib/loop.c --- mosquitto-2.0.8/lib/loop.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/loop.c 2021-03-11 22:37:20.000000000 +0000 @@ -203,6 +203,13 @@ 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; diff -Nru mosquitto-2.0.8/lib/mosquitto.c mosquitto-2.0.9/lib/mosquitto.c --- mosquitto-2.0.8/lib/mosquitto.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/mosquitto.c 2021-03-11 22:37:20.000000000 +0000 @@ -196,6 +196,7 @@ #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 -Nru mosquitto-2.0.8/lib/mosquitto_internal.h mosquitto-2.0.9/lib/mosquitto_internal.h --- mosquitto-2.0.8/lib/mosquitto_internal.h 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/mosquitto_internal.h 2021-03-11 22:37:20.000000000 +0000 @@ -190,8 +190,8 @@ #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 -Nru mosquitto-2.0.8/man/libmosquitto.3 mosquitto-2.0.9/man/libmosquitto.3 --- mosquitto-2.0.8/man/libmosquitto.3 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/libmosquitto.3 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: libmosquitto .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Library calls .\" Source: Mosquitto Project .\" Language: English .\" -.TH "LIBMOSQUITTO" "3" "02/25/2021" "Mosquitto Project" "Library calls" +.TH "LIBMOSQUITTO" "3" "03/11/2021" "Mosquitto Project" "Library calls" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto.8 mosquitto-2.0.9/man/mosquitto.8 --- mosquitto-2.0.8/man/mosquitto.8 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto.8 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: System management commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO" "8" "02/25/2021" "Mosquitto Project" "System management commands" +.TH "MOSQUITTO" "8" "03/11/2021" "Mosquitto Project" "System management commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto.conf.5 mosquitto-2.0.9/man/mosquitto.conf.5 --- mosquitto-2.0.8/man/mosquitto.conf.5 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto.conf.5 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto.conf .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: File formats and conventions .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO\&.CONF" "5" "02/25/2021" "Mosquitto Project" "File formats and conventions" +.TH "MOSQUITTO\&.CONF" "5" "03/11/2021" "Mosquitto Project" "File formats and conventions" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto_ctrl.1 mosquitto-2.0.9/man/mosquitto_ctrl.1 --- mosquitto-2.0.8/man/mosquitto_ctrl.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_ctrl.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_ctrl .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_CTRL" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_CTRL" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto_ctrl_dynsec.1 mosquitto-2.0.9/man/mosquitto_ctrl_dynsec.1 --- mosquitto-2.0.8/man/mosquitto_ctrl_dynsec.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_ctrl_dynsec.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_ctrl_dynsec .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_CTRL_DYNSE" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_CTRL_DYNSE" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto_passwd.1 mosquitto-2.0.9/man/mosquitto_passwd.1 --- mosquitto-2.0.8/man/mosquitto_passwd.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_passwd.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_passwd .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_PASSWD" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_PASSWD" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto_pub.1 mosquitto-2.0.9/man/mosquitto_pub.1 --- mosquitto-2.0.8/man/mosquitto_pub.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_pub.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_pub .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_PUB" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_PUB" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto_rr.1 mosquitto-2.0.9/man/mosquitto_rr.1 --- mosquitto-2.0.8/man/mosquitto_rr.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_rr.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_rr .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_RR" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_RR" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -437,7 +437,7 @@ \fBmqttv5\fR, \fBmqttv311\fR, or \fBmqttv31\fR\&. Defaults to -\fB311\fR\&. +\fB5\fR\&. .RE .PP \fB\-\-will\-payload\fR diff -Nru mosquitto-2.0.8/man/mosquitto_rr.1.xml mosquitto-2.0.9/man/mosquitto_rr.1.xml --- mosquitto-2.0.8/man/mosquitto_rr.1.xml 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_rr.1.xml 2021-03-11 22:37:20.000000000 +0000 @@ -632,7 +632,7 @@ <option>31</option>, or the more verbose <option>mqttv5</option>, <option>mqttv311</option>, or <option>mqttv31</option>. - Defaults to <option>311</option>.</para> + Defaults to <option>5</option>.</para> </listitem> </varlistentry> <varlistentry> diff -Nru mosquitto-2.0.8/man/mosquitto_sub.1 mosquitto-2.0.9/man/mosquitto_sub.1 --- mosquitto-2.0.8/man/mosquitto_sub.1 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto_sub.1 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto_sub .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Commands .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO_SUB" "1" "02/25/2021" "Mosquitto Project" "Commands" +.TH "MOSQUITTO_SUB" "1" "03/11/2021" "Mosquitto Project" "Commands" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mosquitto-tls.7 mosquitto-2.0.9/man/mosquitto-tls.7 --- mosquitto-2.0.8/man/mosquitto-tls.7 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mosquitto-tls.7 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mosquitto-tls .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Conventions and miscellaneous .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MOSQUITTO\-TLS" "7" "02/25/2021" "Mosquitto Project" "Conventions and miscellaneous" +.TH "MOSQUITTO\-TLS" "7" "03/11/2021" "Mosquitto Project" "Conventions and miscellaneous" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/man/mqtt.7 mosquitto-2.0.9/man/mqtt.7 --- mosquitto-2.0.8/man/mqtt.7 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/man/mqtt.7 2021-03-11 22:37:20.000000000 +0000 @@ -1,13 +1,13 @@ '\" t .\" Title: mqtt .\" Author: [see the "Author" section] -.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/> -.\" Date: 02/25/2021 +.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> +.\" Date: 03/11/2021 .\" Manual: Conventions and miscellaneous .\" Source: Mosquitto Project .\" Language: English .\" -.TH "MQTT" "7" "02/25/2021" "Mosquitto Project" "Conventions and miscellaneous" +.TH "MQTT" "7" "03/11/2021" "Mosquitto Project" "Conventions and miscellaneous" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru mosquitto-2.0.8/snap/snapcraft.yaml mosquitto-2.0.9/snap/snapcraft.yaml --- mosquitto-2.0.8/snap/snapcraft.yaml 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/snap/snapcraft.yaml 2021-03-11 22:37:20.000000000 +0000 @@ -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 -Nru mosquitto-2.0.8/src/bridge.c mosquitto-2.0.9/src/bridge.c --- mosquitto-2.0.8/src/bridge.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/bridge.c 2021-03-11 22:37:20.000000000 +0000 @@ -112,6 +112,7 @@ 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; @@ -313,10 +314,8 @@ 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 +453,8 @@ 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 +559,8 @@ } } + bridge__backoff_reset(context); + return MOSQ_ERR_SUCCESS; } @@ -646,11 +645,11 @@ 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) @@ -685,6 +684,33 @@ } } + +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; @@ -703,6 +729,7 @@ 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. */ diff -Nru mosquitto-2.0.8/src/CMakeLists.txt mosquitto-2.0.9/src/CMakeLists.txt --- mosquitto-2.0.8/src/CMakeLists.txt 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/CMakeLists.txt 2021-03-11 22:37:20.000000000 +0000 @@ -77,6 +77,11 @@ 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) diff -Nru mosquitto-2.0.8/src/database.c mosquitto-2.0.9/src/database.c --- mosquitto-2.0.8/src/database.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/database.c 2021-03-11 22:37:20.000000000 +0000 @@ -53,7 +53,7 @@ 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 @@ { 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; @@ -893,6 +893,26 @@ } +int db__message_remove_incoming(struct mosquitto* context, uint16_t mid) +{ + struct mosquitto_client_msg *tail, *tmp; + + 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); + return MOSQ_ERR_SUCCESS; + } + } + + return MOSQ_ERR_NOT_FOUND; +} + + int db__message_release_incoming(struct mosquitto *context, uint16_t mid) { struct mosquitto_client_msg *tail, *tmp; diff -Nru mosquitto-2.0.8/src/handle_connect.c mosquitto-2.0.9/src/handle_connect.c --- mosquitto-2.0.8/src/handle_connect.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/handle_connect.c 2021-03-11 22:37:20.000000000 +0000 @@ -244,7 +244,9 @@ 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; diff -Nru mosquitto-2.0.8/src/handle_publish.c mosquitto-2.0.9/src/handle_publish.c --- mosquitto-2.0.8/src/handle_publish.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/handle_publish.c 2021-03-11 22:37:20.000000000 +0000 @@ -285,6 +285,18 @@ if(msg->qos > 0){ 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) )){ + + 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; + } + if(!stored){ if(msg->qos == 0 || db__ready_for_flight(&context->msgs_in, msg->qos) diff -Nru mosquitto-2.0.8/src/mosquitto_broker_internal.h mosquitto-2.0.9/src/mosquitto_broker_internal.h --- mosquitto-2.0.8/src/mosquitto_broker_internal.h 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/mosquitto_broker_internal.h 2021-03-11 22:37:20.000000000 +0000 @@ -642,6 +642,7 @@ 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); diff -Nru mosquitto-2.0.8/src/net.c mosquitto-2.0.9/src/net.c --- mosquitto-2.0.8/src/net.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/net.c 2021-03-11 22:37:20.000000000 +0000 @@ -335,14 +335,14 @@ }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); @@ -624,23 +624,44 @@ && 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 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, + 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 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, + sizeof(struct in6_addr)); + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } } } } 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 configuration.", + listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); return MOSQ_ERR_NOT_FOUND; } #endif @@ -654,6 +675,9 @@ char service[10]; int rc; int ss_opt = 1; +#ifndef WIN32 + bool interface_bound = false; +#endif if(!listener) return MOSQ_ERR_INVAL; @@ -718,12 +742,14 @@ #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 +771,13 @@ } freeaddrinfo(ainfo); +#ifndef WIN32 + if(listener->bind_interface && !interface_bound){ + mosquitto__free(listener->socks); + return 1; + } +#endif + return 0; } diff -Nru mosquitto-2.0.8/src/retain.c mosquitto-2.0.9/src/retain.c --- mosquitto-2.0.8/src/retain.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/retain.c 2021-03-11 22:37:20.000000000 +0000 @@ -83,7 +83,10 @@ 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]); diff -Nru mosquitto-2.0.8/test/broker/02-subpub-qos0-queued-bytes.py mosquitto-2.0.9/test/broker/02-subpub-qos0-queued-bytes.py --- mosquitto-2.0.8/test/broker/02-subpub-qos0-queued-bytes.py 1970-01-01 01:00:00.000000000 +0100 +++ mosquitto-2.0.9/test/broker/02-subpub-qos0-queued-bytes.py 2021-03-11 22:37:20.000000000 +0000 @@ -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 -Nru mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos1.py mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos1.py --- mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos1.py 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos1.py 1970-01-01 01:00:00.000000000 +0100 @@ -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 -Nru mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos2.py mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos2.py --- mosquitto-2.0.8/test/broker/03-publish-b2c-timeout-qos2.py 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/test/broker/03-publish-b2c-timeout-qos2.py 1970-01-01 01:00:00.000000000 +0100 @@ -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 -Nru mosquitto-2.0.8/test/broker/03-publish-c2b-timeout-qos2.py mosquitto-2.0.9/test/broker/03-publish-c2b-timeout-qos2.py --- mosquitto-2.0.8/test/broker/03-publish-c2b-timeout-qos2.py 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/test/broker/03-publish-c2b-timeout-qos2.py 1970-01-01 01:00:00.000000000 +0100 @@ -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) - diff -Nru mosquitto-2.0.8/test/broker/Makefile mosquitto-2.0.9/test/broker/Makefile --- mosquitto-2.0.8/test/broker/Makefile 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/test/broker/Makefile 2021-03-11 22:37:20.000000000 +0000 @@ -45,6 +45,7 @@ ./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 -Nru mosquitto-2.0.8/test/broker/test.py mosquitto-2.0.9/test/broker/test.py --- mosquitto-2.0.8/test/broker/test.py 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/test/broker/test.py 2021-03-11 22:37:20.000000000 +0000 @@ -28,6 +28,7 @@ (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'),
diff -Nru mosquitto-2.0.8/lib/loop.c mosquitto-2.0.9/lib/loop.c --- mosquitto-2.0.8/lib/loop.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/loop.c 2021-03-11 22:37:20.000000000 +0000 @@ -203,6 +203,13 @@ 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; diff -Nru mosquitto-2.0.8/lib/mosquitto.c mosquitto-2.0.9/lib/mosquitto.c --- mosquitto-2.0.8/lib/mosquitto.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/mosquitto.c 2021-03-11 22:37:20.000000000 +0000 @@ -196,6 +196,7 @@ #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 -Nru mosquitto-2.0.8/lib/mosquitto_internal.h mosquitto-2.0.9/lib/mosquitto_internal.h --- mosquitto-2.0.8/lib/mosquitto_internal.h 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/lib/mosquitto_internal.h 2021-03-11 22:37:20.000000000 +0000 @@ -190,8 +190,8 @@ #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 -Nru mosquitto-2.0.8/src/bridge.c mosquitto-2.0.9/src/bridge.c --- mosquitto-2.0.8/src/bridge.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/bridge.c 2021-03-11 22:37:20.000000000 +0000 @@ -112,6 +112,7 @@ 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; @@ -313,10 +314,8 @@ 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 +453,8 @@ 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 +559,8 @@ } } + bridge__backoff_reset(context); + return MOSQ_ERR_SUCCESS; } @@ -646,11 +645,11 @@ 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) @@ -685,6 +684,33 @@ } } + +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; @@ -703,6 +729,7 @@ 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. */ diff -Nru mosquitto-2.0.8/src/CMakeLists.txt mosquitto-2.0.9/src/CMakeLists.txt --- mosquitto-2.0.8/src/CMakeLists.txt 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/CMakeLists.txt 2021-03-11 22:37:20.000000000 +0000 @@ -77,6 +77,11 @@ 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) diff -Nru mosquitto-2.0.8/src/database.c mosquitto-2.0.9/src/database.c --- mosquitto-2.0.8/src/database.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/database.c 2021-03-11 22:37:20.000000000 +0000 @@ -53,7 +53,7 @@ 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 @@ { 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; @@ -893,6 +893,26 @@ } +int db__message_remove_incoming(struct mosquitto* context, uint16_t mid) +{ + struct mosquitto_client_msg *tail, *tmp; + + 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); + return MOSQ_ERR_SUCCESS; + } + } + + return MOSQ_ERR_NOT_FOUND; +} + + int db__message_release_incoming(struct mosquitto *context, uint16_t mid) { struct mosquitto_client_msg *tail, *tmp; diff -Nru mosquitto-2.0.8/src/handle_connect.c mosquitto-2.0.9/src/handle_connect.c --- mosquitto-2.0.8/src/handle_connect.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/handle_connect.c 2021-03-11 22:37:20.000000000 +0000 @@ -244,7 +244,9 @@ 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; diff -Nru mosquitto-2.0.8/src/handle_publish.c mosquitto-2.0.9/src/handle_publish.c --- mosquitto-2.0.8/src/handle_publish.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/handle_publish.c 2021-03-11 22:37:20.000000000 +0000 @@ -285,6 +285,18 @@ if(msg->qos > 0){ 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) )){ + + 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; + } + if(!stored){ if(msg->qos == 0 || db__ready_for_flight(&context->msgs_in, msg->qos) diff -Nru mosquitto-2.0.8/src/mosquitto_broker_internal.h mosquitto-2.0.9/src/mosquitto_broker_internal.h --- mosquitto-2.0.8/src/mosquitto_broker_internal.h 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/mosquitto_broker_internal.h 2021-03-11 22:37:20.000000000 +0000 @@ -642,6 +642,7 @@ 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); diff -Nru mosquitto-2.0.8/src/net.c mosquitto-2.0.9/src/net.c --- mosquitto-2.0.8/src/net.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/net.c 2021-03-11 22:37:20.000000000 +0000 @@ -335,14 +335,14 @@ }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); @@ -624,23 +624,44 @@ && 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 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, + 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 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, + sizeof(struct in6_addr)); + freeifaddrs(ifaddr); + return MOSQ_ERR_SUCCESS; + } } } } 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 configuration.", + listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); return MOSQ_ERR_NOT_FOUND; } #endif @@ -654,6 +675,9 @@ char service[10]; int rc; int ss_opt = 1; +#ifndef WIN32 + bool interface_bound = false; +#endif if(!listener) return MOSQ_ERR_INVAL; @@ -718,12 +742,14 @@ #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 +771,13 @@ } freeaddrinfo(ainfo); +#ifndef WIN32 + if(listener->bind_interface && !interface_bound){ + mosquitto__free(listener->socks); + return 1; + } +#endif + return 0; } diff -Nru mosquitto-2.0.8/src/retain.c mosquitto-2.0.9/src/retain.c --- mosquitto-2.0.8/src/retain.c 2021-02-25 17:28:19.000000000 +0000 +++ mosquitto-2.0.9/src/retain.c 2021-03-11 22:37:20.000000000 +0000 @@ -83,7 +83,10 @@ 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]);