Compare commits

...

7 Commits

Author SHA1 Message Date
Roger A. Light de93230ded Bump version. 5 years ago
Roger A. Light 03dac10d67 Fix TLS bridge/lib incorrectly connecting on invalid CA file.
Closes #2130. Thanks to becz.
5 years ago
CJ Lee ebc8b76d03 Add missing header for QNX
<arpa/inet.h> header is required to compile this source. Without it, WARNING is generated.

mosquitto/lib/socks_mosq.c: In function 'socks5__send':
mosquitto/lib/socks_mosq.c:156:22: warning: implicit declaration of function 'inet_pton' [-Wimplicit-function-declaration]
   ipv4_pton_result = inet_pton(AF_INET, mosq->host, &addr_ipv4);

Signed-off-by: ChangJoon Lee <changjoon.lee@lge.com>
5 years ago
Roger A. Light 32c8221d43 Bump version. 5 years ago
Roger A. Light 3190d29252 Fix memory leak on handling QoS 2 PUBLISH.
In some circumstances, Mosquitto could leak memory when handling PUBLISH messages. This is limited to incoming QoS 2 messages, and is related to the combination of the broker having persistence enabled, a clean session=false client, which was connected prior to the broker restarting, then has reconnected and has now sent messages at a sufficiently high rate that the incoming queue at the broker has filled up and hence messages are being dropped. This is more likely to have an effect where max_queued_messages is a small value. This has now been fixed.

Closes #1793.
5 years ago
Roger A. Light f47b565831 Bump version numbers, update changelog. 6 years ago
Roger A. Light 84681d9728 Restrict topic hierarchy to 200 levels to prevent possible stack overflow.
Closes #1412. Thanks to Ryan Shaw.
6 years ago

@ -11,7 +11,7 @@ project(mosquitto)
cmake_minimum_required(VERSION 2.8)
# Only for version 3 and up. cmake_policy(SET CMP0042 NEW)
set (VERSION 1.5.8)
set (VERSION 1.5.11)
add_definitions (-DCMAKE -DVERSION=\"${VERSION}\")

@ -1,3 +1,46 @@
1.5.11 - 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.
Client library:
- Fix encrypted connections incorrectly connecting when the CA file passed to
`mosquitto_tls_set()` is empty or invalid. Closes #2130.
1.5.10 - 2020-08-19
===================
Security:
- In some circumstances, Mosquitto could leak memory when handling PUBLISH
messages. This is limited to incoming QoS 2 messages, and is related
to the combination of the broker having persistence enabled, a clean
session=false client, which was connected prior to the broker restarting,
then has reconnected and has now sent messages at a sufficiently high rate
that the incoming queue at the broker has filled up and hence messages are
being dropped. This is more likely to have an effect where
max_queued_messages is a small value. This has now been fixed. Closes #1793.
1.5.9 - 20190917
================
Broker:
- Restrict topic hierarchy to 200 levels on publish/subscribe to prevent a
subscribe with 65535 '/' characters causing a stack overflow.
1.5.8 - 20190228
================

@ -105,7 +105,7 @@ WITH_BUNDLED_DEPS:=yes
# Also bump lib/mosquitto.h, CMakeLists.txt,
# installer/mosquitto.nsi, installer/mosquitto64.nsi
VERSION=1.5.8
VERSION=1.5.11
# Client library SO version. Bump if incompatible API/ABI changes are made.
SOVERSION=1

@ -9,7 +9,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "Eclipse Mosquitto"
!define VERSION 1.5.8
!define VERSION 1.5.11
OutFile "mosquitto-${VERSION}-install-windows-x86.exe"
InstallDir "$PROGRAMFILES\mosquitto"

@ -9,7 +9,7 @@
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
Name "Eclipse Mosquitto"
!define VERSION 1.5.8
!define VERSION 1.5.11
OutFile "mosquitto-${VERSION}-install-windows-x64.exe"
!include "x64.nsh"

@ -190,6 +190,7 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_se
#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;

@ -47,7 +47,7 @@ extern "C" {
#define LIBMOSQUITTO_MAJOR 1
#define LIBMOSQUITTO_MINOR 5
#define LIBMOSQUITTO_REVISION 8
#define LIBMOSQUITTO_REVISION 11
/* 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)

@ -23,6 +23,7 @@ Contributors:
# include <ws2tcpip.h>
#elif __QNX__
# include <sys/socket.h>
# include <arpa/inet.h>
# include <netinet/in.h>
#else
# include <arpa/inet.h>

@ -143,14 +143,25 @@ uint16_t mosquitto__mid_generate(struct mosquitto *mosq)
int mosquitto_pub_topic_check(const char *str)
{
int len = 0;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
while(str && str[0]){
if(str[0] == '+' || str[0] == '#'){
return MOSQ_ERR_INVAL;
}
#ifdef WITH_BROKER
else if(str[0] == '/'){
hier_count++;
}
#endif
len++;
str = &str[1];
}
if(len > 65535) return MOSQ_ERR_INVAL;
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
@ -158,6 +169,9 @@ int mosquitto_pub_topic_check(const char *str)
int mosquitto_pub_topic_check2(const char *str, size_t len)
{
int i;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(len > 65535) return MOSQ_ERR_INVAL;
@ -165,7 +179,15 @@ int mosquitto_pub_topic_check2(const char *str, size_t len)
if(str[i] == '+' || str[i] == '#'){
return MOSQ_ERR_INVAL;
}
#ifdef WITH_BROKER
else if(str[i] == '/'){
hier_count++;
}
#endif
}
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
@ -181,6 +203,10 @@ int mosquitto_sub_topic_check(const char *str)
{
char c = '\0';
int len = 0;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
while(str && str[0]){
if(str[0] == '+'){
if((c != '\0' && c != '/') || (str[1] != '\0' && str[1] != '/')){
@ -191,11 +217,19 @@ int mosquitto_sub_topic_check(const char *str)
return MOSQ_ERR_INVAL;
}
}
#ifdef WITH_BROKER
else if(str[0] == '/'){
hier_count++;
}
#endif
len++;
c = str[0];
str = &str[1];
}
if(len > 65535) return MOSQ_ERR_INVAL;
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}
@ -204,6 +238,9 @@ int mosquitto_sub_topic_check2(const char *str, size_t len)
{
char c = '\0';
int i;
#ifdef WITH_BROKER
int hier_count = 0;
#endif
if(len > 65535) return MOSQ_ERR_INVAL;
@ -217,8 +254,16 @@ int mosquitto_sub_topic_check2(const char *str, size_t len)
return MOSQ_ERR_INVAL;
}
}
#ifdef WITH_BROKER
else if(str[i] == '/'){
hier_count++;
}
#endif
c = str[i];
}
#ifdef WITH_BROKER
if(hier_count > TOPIC_HIERARCHY_LIMIT) return MOSQ_ERR_INVAL;
#endif
return MOSQ_ERR_SUCCESS;
}

@ -2,7 +2,7 @@
MAJOR=1
MINOR=5
REVISION=8
REVISION=11
sed -i "s/^VERSION=.*/VERSION=${MAJOR}.${MINOR}.${REVISION}/" config.mk

@ -1,5 +1,5 @@
name: mosquitto
version: 1.5.8
version: 1.5.11
summary: Eclipse Mosquitto MQTT broker
description: This is a message broker that supports version 3.1 and 3.1.1 of the MQTT
protocol.

@ -82,6 +82,7 @@ int bridge__new(struct mosquitto_db *db, struct mosquitto__bridge *bridge)
new_context->tls_cert_reqs = SSL_VERIFY_PEER;
new_context->tls_version = new_context->bridge->tls_version;
new_context->tls_insecure = new_context->bridge->tls_insecure;
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;

@ -36,7 +36,7 @@ static unsigned long max_queued_bytes = 0;
* @param qos qos for the packet of interest
* @return true if more in flight are allowed.
*/
static bool db__ready_for_flight(struct mosquitto *context, int qos)
bool db__ready_for_flight(struct mosquitto *context, int qos)
{
if(qos == 0 || (max_inflight == 0 && max_inflight_bytes == 0)){
return true;
@ -64,7 +64,7 @@ static bool db__ready_for_flight(struct mosquitto *context, int qos)
* @param qos destination qos for the packet of interest
* @return true if queuing is allowed, false if should be dropped
*/
static bool db__ready_for_queue(struct mosquitto *context, int qos)
bool db__ready_for_queue(struct mosquitto *context, int qos)
{
if(max_queued == 0 && max_queued_bytes == 0){
return true;

@ -184,10 +184,24 @@ int handle__publish(struct mosquitto_db *db, struct mosquitto *context)
db__message_store_find(context, mid, &stored);
}
if(!stored){
if(qos == 0
|| db__ready_for_flight(context, qos)
|| db__ready_for_queue(context, qos)){
dup = 0;
if(db__message_store(db, context, mid, topic, qos, payloadlen, &payload, retain, &stored, 0)){
return 1;
}
}else{
/* Client isn't allowed any more incoming messages, so fail early */
mosquitto__free(topic);
UHPA_FREE(payload, payloadlen);
if(qos == 1){
return send__puback(context, mid);
}else{
return send__pubrec(context, mid);
}
}
}else{
mosquitto__free(topic);
topic = stored->topic;

@ -70,6 +70,9 @@ Contributors:
#define WEBSOCKET_CLIENT -2
#define TOPIC_HIERARCHY_LIMIT 200
/* ========================================
* UHPA data types
* ======================================== */
@ -564,6 +567,8 @@ void db__msg_store_deref(struct mosquitto_db *db, struct mosquitto_msg_store **s
void db__msg_store_clean(struct mosquitto_db *db);
void db__msg_store_compact(struct mosquitto_db *db);
int db__message_reconnect_reset(struct mosquitto_db *db, struct mosquitto *context);
bool db__ready_for_flight(struct mosquitto *context, int qos);
bool db__ready_for_queue(struct mosquitto *context, int qos);
void sys_tree__init(struct mosquitto_db *db);
void sys_tree__update(struct mosquitto_db *db, int interval, time_t start_time);

@ -178,6 +178,7 @@ static int sub__topic_tokenise(const char *subtopic, struct sub__token **topics)
int start, stop, tlen;
int i;
mosquitto__topic_element_uhpa topic;
int count = 0;
assert(subtopic);
assert(topics);
@ -200,6 +201,7 @@ static int sub__topic_tokenise(const char *subtopic, struct sub__token **topics)
stop = 0;
for(i=start; i<len+1; i++){
count++;
if(subtopic[i] == '/' || subtopic[i] == '\0'){
stop = i;
@ -219,6 +221,11 @@ static int sub__topic_tokenise(const char *subtopic, struct sub__token **topics)
}
}
if(count > TOPIC_HIERARCHY_LIMIT){
/* Set limit on hierarchy levels, to restrict stack usage. */
goto cleanup;
}
return MOSQ_ERR_SUCCESS;
cleanup:

@ -0,0 +1,44 @@
#!/usr/bin/env python
# Test whether a SUBSCRIBE to a topic with 65535 hierarchy characters fails
# This needs checking with MOSQ_USE_VALGRIND=1 to detect memory failures
# https://github.com/eclipse/mosquitto/issues/1412
import time
import inspect, os, sys
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import mosq_test
rc = 1
mid = 1
keepalive = 60
connect_packet = mosq_test.gen_connect("subscribe-long-test", keepalive=keepalive)
connack_packet = mosq_test.gen_connack(rc=0)
subscribe_packet = mosq_test.gen_subscribe(mid, "/"*65535, 0)
suback_packet = mosq_test.gen_suback(mid, 0)
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, port=port)
mosq_test.do_send_receive(sock, subscribe_packet, b"", "suback")
rc = 0
sock.close()
finally:
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde.decode('utf-8'))
exit(rc)

@ -0,0 +1,45 @@
#!/usr/bin/env python
# Test whether a PUBLISH to a topic with 65535 hierarchy characters fails
# This needs checking with MOSQ_USE_VALGRIND=1 to detect memory failures
# https://github.com/eclipse/mosquitto/issues/1412
import time
import inspect, os, sys
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import mosq_test
rc = 1
mid = 19
keepalive = 60
connect_packet = mosq_test.gen_connect("pub-qos1-test", keepalive=keepalive)
connack_packet = mosq_test.gen_connack(rc=0)
publish_packet = mosq_test.gen_publish("/"*65535, qos=1, mid=mid, payload="message")
puback_packet = mosq_test.gen_puback(mid)
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, port=port)
mosq_test.do_send_receive(sock, publish_packet, b"", "puback")
rc = 0
sock.close()
finally:
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde.decode('utf-8'))
exit(rc)

@ -39,6 +39,7 @@ endif
02 :
./02-subscribe-long-topic.py
./02-subscribe-qos0.py
./02-subscribe-qos1.py
./02-subscribe-qos2.py
@ -67,6 +68,7 @@ endif
./03-pattern-matching.py
#./03-publish-qos1-queued-bytes.py
./03-publish-invalid-utf8.py
./03-publish-long-topic.py
./03-publish-dollar.py
04 :

@ -25,6 +25,7 @@ tests = [
(1, './02-subscribe-qos0.py'),
(1, './02-subscribe-qos1.py'),
(1, './02-subscribe-qos2.py'),
(1, './02-subscribe-long-topic.py'),
(1, './02-subpub-qos0.py'),
(1, './02-subpub-qos1.py'),
(1, './02-subpub-qos2.py'),
@ -46,6 +47,7 @@ tests = [
(1, './03-publish-b2c-disconnect-qos1.py'),
(1, './03-publish-c2b-disconnect-qos2.py'),
(1, './03-publish-b2c-disconnect-qos2.py'),
(1, './03-publish-long-topic.py'),
(1, './03-pattern-matching.py'),
#(1, './03-publish-qos1-queued-bytes.py'),
(1, './03-publish-invalid-utf8.py'),

@ -395,9 +395,13 @@ def gen_pubrel(mid, dup=False):
def gen_pubcomp(mid):
return struct.pack('!BBH', 112, 2, mid)
def gen_subscribe(mid, topic, qos):
pack_format = "!BBHH"+str(len(topic))+"sB"
return struct.pack(pack_format, 130, 2+2+len(topic)+1, mid, len(topic), topic, qos)
packet = struct.pack("!B", 130)
packet += bytes(pack_remaining_length(2+2+len(topic)+1))
pack_format = "!HH"+str(len(topic))+"sB"
return packet + struct.pack(pack_format, mid, len(topic), topic, qos)
def gen_suback(mid, qos):
return struct.pack('!BBHB', 144, 2+1, mid, qos)
@ -419,7 +423,7 @@ def gen_disconnect():
return struct.pack('!BB', 224, 0)
def pack_remaining_length(remaining_length):
s = ""
s = bytes("".encode('utf-8'))
while True:
byte = remaining_length % 128
remaining_length = remaining_length // 128

Loading…
Cancel
Save