Merge branch 'master' into develop

This commit is contained in:
Roger A. Light
2023-09-09 15:20:40 +01:00
75 changed files with 1075 additions and 305 deletions
@@ -0,0 +1,18 @@
name: Delete old workflow runs
on:
workflow_dispatch:
schedule:
- cron: '0 0 1 * *'
# Run monthly, at 00:00 on the 1st day of month.
jobs:
del_runs:
runs-on: ubuntu-latest
steps:
- name: Delete workflow runs
uses: Mattraks/delete-workflow-runs@v2
with:
token: ${{ github.token }}
repository: ${{ github.repository }}
retain_days: 30
keep_minimum_runs: 6
+18 -1
View File
@@ -1,3 +1,4 @@
# .gitignore
*.a
*.db
*.gcda
@@ -112,9 +113,25 @@ test/unit/lib/lib_test
test/unit/broker/persist_read_test
test/unit/broker/persist_write_test
test/unit/broker/subs_test
test/unit/tls_test
test/unit/out/
www/cache/
__pycache__
*.sync-conflict-*
# Debian generated files
debian/.debhelper/
debian/debhelper-build-stamp
debian/files
debian/*.log
debian/*.substvars
debian/*mosquitto*/
debian/*.debhelper
debian/tmp/
obj-*/
# Emacs generated files
*~
# Others
tmp/
+1 -1
View File
@@ -13,7 +13,7 @@ project(mosquitto
LANGUAGES C CXX
)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
+71
View File
@@ -189,6 +189,77 @@ Build:
- cJSON is now a required dependency.
2.0.17 - 2023-08-22
===================
Broker:
- Fix `max_queued_messages 0` stopping clients from receiving messages.
Closes #2879.
- Fix `max_inflight_messages` not being set correctly. Closes #2876.
Apps:
- Fix `mosquitto_passwd -U` backup file creation. Closes #2873.
2.0.16 - 2023-08-16
===================
Security:
- CVE-2023-28366: Fix memory leak in broker when clients send multiple QoS 2
messages with the same message ID, but then never respond to the PUBREC
commands.
- CVE-2023-0809: Fix excessive memory being allocated based on malicious
initial packets that are not CONNECT packets.
- CVE-2023-3592: Fix memory leak when clients send v5 CONNECT packets with a
will message that contains invalid property types.
- Broker will now reject Will messages that attempt to publish to $CONTROL/.
- Broker now validates usernames provided in a TLS certificate or TLS-PSK
identity are valid UTF-8.
- Fix potential crash when loading invalid persistence file.
- Library will no longer allow single level wildcard certificates, e.g. *.com
Broker:
- Fix $SYS messages being expired after 60 seconds and hence unchanged values
disappearing.
- Fix some retained topic memory not being cleared immediately after used.
- Fix error handling related to the `bind_interface` option.
- Fix std* files not being redirected when daemonising, when built with
assertions removed. Closes #2708.
- Fix default settings incorrectly allowing TLS v1.1. Closes #2722.
- Use line buffered mode for stdout. Closes #2354. Closes #2749.
- Fix bridges with non-matching cleansession/local_cleansession being expired
on start after restoring from persistence. Closes #2634.
- Fix connections being limited to 2048 on Windows. The limit is now 8192,
where supported. Closes #2732.
- Broker will log warnings if sensitive files are world readable/writable, or
if the owner/group is not the same as the user/group the broker is running
as. In future versions the broker will refuse to open these files.
- mosquitto_memcmp_const is now more constant time.
- Only register with DLT if DLT logging is enabled.
- Fix any possible case where a json string might be incorrectly loaded. This
could have caused a crash if a textname or textdescription field of a role was
not a string, when loading the dynsec config from file only.
- Dynsec plugin will not allow duplicate clients/groups/roles when loading
config from file, which matches the behaviour for when creating them.
- Fix heap overflow when reading corrupt config with "log_dest file".
Client library:
- Use CLOCK_BOOTTIME when available, to keep track of time. This solves the
problem of the client OS sleeping and the client hence not being able to
calculate the actual time for keepalive purposes. Closes #2760.
- Fix default settings incorrectly allowing TLS v1.1. Closes #2722.
- Fix high CPU use on slow TLS connect. Closes #2794.
Clients:
- Fix incorrect topic-alias property value in mosquitto_sub json output.
- Fix confusing message on TLS certificate verification. Closes #2746.
Apps:
- mosquitto_passwd uses mkstemp() for backup files.
- `mosquitto_ctrl dynsec init` will refuse to overwrite an existing file,
without a race-condition.
2.0.15 - 2022-08-16
===================
-1
View File
@@ -16,7 +16,6 @@ Contributors:
Roger Light - initial implementation and documentation.
*/
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+1
View File
@@ -11,6 +11,7 @@ if(WITH_TLS AND CJSON_FOUND)
dynsec_role.c
../mosquitto_passwd/get_password.c ../mosquitto_passwd/get_password.h
../../lib/memory_mosq.c ../../lib/memory_mosq.h
../../lib/misc_mosq.c ../../lib/misc_mosq.h
../../src/memory_public.c
options.c
../../common/json_help.c ../../common/json_help.h
+14 -8
View File
@@ -23,6 +23,8 @@ Contributors:
#include <string.h>
#ifndef WIN32
# include <errno.h>
# include <fcntl.h>
# include <strings.h>
#endif
@@ -32,6 +34,7 @@ Contributors:
#include "json_help.h"
#include "password_mosq.h"
#include "get_password.h"
#include "misc_mosq.h"
#define MAX_STRING_LEN 4096
@@ -709,13 +712,6 @@ static int dynsec_init(int argc, char *argv[])
admin_password = password;
}
fptr = fopen(filename, "rb");
if(fptr){
fclose(fptr);
fprintf(stderr, "dynsec init: '%s' already exists. Remove the file or use a different location..\n", filename);
return -1;
}
tree = init_create(admin_user, admin_password, "admin");
if(tree == NULL){
fprintf(stderr, "dynsec init: Out of memory.\n");
@@ -724,7 +720,17 @@ static int dynsec_init(int argc, char *argv[])
json_str = cJSON_Print(tree);
cJSON_Delete(tree);
fptr = fopen(filename, "wb");
#ifdef WIN32
fptr = mosquitto__fopen(filename, "wb", true);
#else
int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0640);
if(fd < 0){
free(json_str);
fprintf(stderr, "dynsec init: Unable to open '%s' for writing (%s).\n", filename, strerror(errno));
return -1;
}
fptr = fdopen(fd, "wb");
#endif
if(fptr){
fprintf(fptr, "%s", json_str);
free(json_str);
+5 -5
View File
@@ -611,6 +611,11 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
return 1;
}
#ifdef WITH_TLS
if(cfg->keyform && mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, cfg->keyform)){
fprintf(stderr, "Error: Problem setting key form, it must be one of 'pem' or 'engine'.\n");
mosquitto_lib_cleanup();
return 1;
}
if(cfg->cafile || cfg->capath){
rc = mosquitto_tls_set(mosq, cfg->cafile, cfg->capath, cfg->certfile, cfg->keyfile, NULL);
if(rc){
@@ -633,11 +638,6 @@ int client_opts_set(struct mosquitto *mosq, struct mosq_config *cfg)
mosquitto_lib_cleanup();
return 1;
}
if(cfg->keyform && mosquitto_string_option(mosq, MOSQ_OPT_TLS_KEYFORM, cfg->keyform)){
fprintf(stderr, "Error: Problem setting key form, it must be one of 'pem' or 'engine'.\n");
mosquitto_lib_cleanup();
return 1;
}
if(cfg->tls_engine_kpass_sha1 && mosquitto_string_option(mosq, MOSQ_OPT_TLS_ENGINE_KPASS_SHA1, cfg->tls_engine_kpass_sha1)){
fprintf(stderr, "Error: Problem setting TLS engine key pass sha, is it a 40 character hex string?\n");
mosquitto_lib_cleanup();
+19 -6
View File
@@ -364,15 +364,27 @@ static int copy_contents(FILE *src, FILE *dest)
return 0;
}
static int create_backup(const char *backup_file, FILE *fptr)
static int create_backup(char *backup_file, FILE *fptr)
{
FILE *fbackup;
fbackup = fopen(backup_file, "wt");
#ifdef WIN32
fbackup = mosquitto__fopen(backup_file, "wt", true);
#else
int fd;
umask(077);
fd = mkstemp(backup_file);
if(fd < 0){
fprintf(stderr, "Error creating backup password file \"%s\", not continuing.\n", backup_file);
return 1;
}
fbackup = fdopen(fd, "wt");
#endif
if(!fbackup){
fprintf(stderr, "Error creating backup password file \"%s\", not continuing.\n", backup_file);
return 1;
}
if(copy_contents(fptr, fbackup)){
fprintf(stderr, "Error copying data to backup password file \"%s\", not continuing.\n", backup_file);
fclose(fbackup);
@@ -597,7 +609,7 @@ int main(int argc, char *argv[])
}
password_cmd = password;
}
fptr = fopen(password_file, "wt");
fptr = mosquitto__fopen(password_file, "wt", true);
if(!fptr){
fprintf(stderr, "Error: Unable to open file %s for writing. %s.\n", password_file, strerror(errno));
free(password_file);
@@ -609,20 +621,21 @@ int main(int argc, char *argv[])
fclose(fptr);
return rc;
}else{
fptr = fopen(password_file, "r+t");
fptr = mosquitto__fopen(password_file, "r+t", true);
if(!fptr){
fprintf(stderr, "Error: Unable to open password file %s. %s.\n", password_file, strerror(errno));
free(password_file);
return 1;
}
backup_file = malloc((size_t)strlen(password_file)+5);
size_t len = strlen(password_file) + strlen(".backup.XXXXXX") + 1;
backup_file = malloc(len);
if(!backup_file){
fprintf(stderr, "Error: Out of memory.\n");
free(password_file);
return 1;
}
snprintf(backup_file, strlen(password_file)+5, "%s.tmp", password_file);
snprintf(backup_file, len, "%s.backup.XXXXXX", password_file);
free(password_file);
password_file = NULL;
+56
View File
@@ -38,6 +38,8 @@ Contributors:
# define PATH_MAX MAX_PATH
#else
# include <sys/stat.h>
# include <pwd.h>
# include <grp.h>
# include <unistd.h>
#endif
@@ -149,6 +151,60 @@ FILE *mosquitto__fopen(const char *path, const char *mode, bool restrict_read)
return NULL;
}
if(restrict_read){
if(statbuf.st_mode & S_IRWXO){
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_WARNING,
#else
fprintf(stderr,
#endif
"Warning: File %s has world readable permissions. Future versions will refuse to load this file.",
path);
#if 0
return NULL;
#endif
}
if(statbuf.st_uid != getuid()){
char buf[4096];
struct passwd pw, *result;
getpwuid_r(getuid(), &pw, buf, sizeof(buf), &result);
if(result){
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_WARNING,
#else
fprintf(stderr,
#endif
"Warning: File %s owner is not %s. Future versions will refuse to load this file.",
path, result->pw_name);
}
#if 0
// Future version
return NULL;
#endif
}
if(statbuf.st_gid != getgid()){
char buf[4096];
struct group grp, *result;
getgrgid_r(getgid(), &grp, buf, sizeof(buf), &result);
if(result){
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_WARNING,
#else
fprintf(stderr,
#endif
"Warning: File %s group is not %s. Future versions will refuse to load this file.",
path, result->gr_name);
}
#if 0
// Future version
return NULL
#endif
}
}
if(!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)){
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_ERR, "Error: %s is not a file.", path);
+1 -3
View File
@@ -124,9 +124,7 @@ int pw__memcmp_const(const void *a, const void *b, size_t len)
if(!a || !b) return 1;
for(i=0; i<len; i++){
if( ((char *)a)[i] != ((char *)b)[i] ){
rc = 1;
}
rc |= ((char *)a)[i] ^ ((char *)b)[i];
}
return rc;
}
+4
View File
@@ -44,7 +44,11 @@ time_t mosquitto_time(void)
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
struct timespec tp;
#ifdef CLOCK_BOOTTIME
clock_gettime(CLOCK_BOOTTIME, &tp);
#else
clock_gettime(CLOCK_MONOTONIC, &tp);
#endif
return tp.tv_sec;
#elif defined(__APPLE__)
static mach_timebase_info_data_t tb;
+7 -2
View File
@@ -1,4 +1,4 @@
FROM alpine:3.14
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
@@ -6,16 +6,19 @@ LABEL maintainer="Roger Light <roger@atchoo.org>" \
ENV VERSION=1.5.11 \
DOWNLOAD_SHA256=4a3b8a8f5505d27a7a966dd68bfd76f1e69feb51796d1b46b7271d1bb5a1a299 \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=2.4.2
LWS_VERSION=4.2.1 \
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
RUN set -x && \
apk --no-cache add --virtual build-deps \
build-base \
cmake \
gnupg \
linux-headers \
openssl-dev \
util-linux-dev && \
wget https://github.com/warmcat/libwebsockets/archive/v${LWS_VERSION}.tar.gz -O /tmp/lws.tar.gz && \
echo "$LWS_SHA256 /tmp/lws.tar.gz" | sha256sum -c - && \
mkdir -p /build/lws && \
tar --strip=1 -xf /tmp/lws.tar.gz -C /build/lws && \
rm /tmp/lws.tar.gz && \
@@ -23,11 +26,13 @@ RUN set -x && \
cmake . \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX=/usr \
-DDISABLE_WERROR=ON \
-DLWS_IPV6=ON \
-DLWS_WITHOUT_BUILTIN_GETIFADDRS=ON \
-DLWS_WITHOUT_CLIENT=ON \
-DLWS_WITHOUT_EXTENSIONS=ON \
-DLWS_WITHOUT_TESTAPPS=ON \
-DLWS_WITH_EXTERNAL_POLL=ON \
-DLWS_WITH_HTTP2=OFF \
-DLWS_WITH_SHARED=OFF \
-DLWS_WITH_ZIP_FOPS=OFF \
+1 -1
View File
@@ -1,4 +1,4 @@
FROM alpine:3.14
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
+3 -3
View File
@@ -1,10 +1,10 @@
FROM alpine:3.16
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=2.0.15 \
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
ENV VERSION=2.0.17 \
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=4.2.1 \
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
+3 -3
View File
@@ -1,10 +1,10 @@
FROM alpine:3.16
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=2.0.15 \
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
ENV VERSION=2.0.17 \
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=4.2.1 \
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
+1 -1
View File
@@ -1,4 +1,4 @@
FROM alpine:3.14
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM alpine:3.16
FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
+12 -12
View File
@@ -535,8 +535,8 @@ libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char
* mosq - a valid mosquitto instance.
* host - the hostname or ip address of the broker to connect to.
* port - the network port to connect to. Usually 1883.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
*
* Returns:
@@ -567,8 +567,8 @@ libmosq_EXPORT int mosquitto_connect(struct mosquitto *mosq, const char *host, i
* mosq - a valid mosquitto instance.
* host - the hostname or ip address of the broker to connect to.
* port - the network port to connect to. Usually 1883.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
* bind_address - the hostname or ip address of the local network interface to
* bind to. If you do not want to bind to a specific interface,
@@ -611,8 +611,8 @@ libmosq_EXPORT int mosquitto_connect_bind(struct mosquitto *mosq, const char *ho
* mosq - a valid mosquitto instance.
* host - the hostname or ip address of the broker to connect to.
* port - the network port to connect to. Usually 1883.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
* bind_address - the hostname or ip address of the local network interface to
* bind to. If you do not want to bind to a specific interface,
@@ -652,8 +652,8 @@ libmosq_EXPORT int mosquitto_connect_bind_v5(struct mosquitto *mosq, const char
* mosq - a valid mosquitto instance.
* host - the hostname or ip address of the broker to connect to.
* port - the network port to connect to. Usually 1883.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
*
* Returns:
@@ -687,8 +687,8 @@ libmosq_EXPORT int mosquitto_connect_async(struct mosquitto *mosq, const char *h
* mosq - a valid mosquitto instance.
* host - the hostname or ip address of the broker to connect to.
* port - the network port to connect to. Usually 1883.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
* bind_address - the hostname or ip address of the local network interface to
* bind to. If you do not want to bind to a specific interface,
@@ -726,8 +726,8 @@ libmosq_EXPORT int mosquitto_connect_bind_async(struct mosquitto *mosq, const ch
* Parameters:
* mosq - a valid mosquitto instance.
* host - the hostname to search for an SRV record.
* keepalive - the number of seconds after which the broker should send a PING
* message to the client if no other messages have been exchanged
* keepalive - the number of seconds after which the client should send a PING
* message to the broker if no other messages have been exchanged
* in that time.
* bind_address - the hostname or ip address of the local network interface to
* bind to. If you do not want to bind to a specific interface,
+1 -1
View File
@@ -112,7 +112,7 @@ struct mosquitto_client_msg {
uint16_t mid;
uint8_t qos;
bool retain;
bool dup;
uint8_t dup;
uint8_t direction;
uint8_t state;
uint8_t padding[5];
+10 -8
View File
@@ -65,18 +65,20 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
if(net__is_connected(mosq)){
maxfd = mosq->sock;
FD_SET(mosq->sock, &readfds);
pthread_mutex_lock(&mosq->out_packet_mutex);
if(mosq->out_packet){
if(mosq->want_write){
FD_SET(mosq->sock, &writefds);
}
}else{
#ifdef WITH_TLS
if(mosq->ssl){
if(mosq->want_write){
FD_SET(mosq->sock, &writefds);
if(mosq->ssl == NULL || SSL_is_init_finished(mosq->ssl))
#endif
{
pthread_mutex_lock(&mosq->out_packet_mutex);
if(mosq->out_packet){
FD_SET(mosq->sock, &writefds);
}
pthread_mutex_unlock(&mosq->out_packet_mutex);
}
}
#endif
pthread_mutex_unlock(&mosq->out_packet_mutex);
}else{
#ifdef WITH_SRV
if(mosq->achan){
+5 -13
View File
@@ -61,8 +61,11 @@ int mosquitto_lib_init(void)
srand((unsigned int)GetTickCount64());
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK)
struct timespec tp;
#ifdef CLOCK_BOOTTIME
clock_gettime(CLOCK_BOOTTIME, &tp);
#else
clock_gettime(CLOCK_MONOTONIC, &tp);
#endif
srand((unsigned int)tp.tv_nsec);
#elif defined(__APPLE__)
uint64_t ticks;
@@ -332,18 +335,7 @@ int mosquitto_socket(struct mosquitto *mosq)
bool mosquitto_want_write(struct mosquitto *mosq)
{
bool result = false;
if(mosq->out_packet){
result = true;
}
#ifdef WITH_TLS
if(mosq->ssl){
if (mosq->want_write) {
result = true;
}
}
#endif
return result;
return mosq->out_packet || mosq->want_write;
}
+4
View File
@@ -181,6 +181,10 @@ void net__init_tls(void)
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
# else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS \
| OPENSSL_INIT_LOAD_CONFIG, NULL);
# endif
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
ENGINE_load_builtin_engines();
+28 -8
View File
@@ -168,14 +168,21 @@ int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *ca
mosquitto__FREE(mosq->tls_keyfile);
if(keyfile){
fptr = mosquitto__fopen(keyfile, "rt", false);
if(fptr){
fclose(fptr);
}else{
mosquitto__FREE(mosq->tls_cafile);
mosquitto__FREE(mosq->tls_capath);
mosquitto__FREE(mosq->tls_certfile);
return MOSQ_ERR_INVAL;
if(mosq->tls_keyform == mosq_k_pem){
fptr = mosquitto__fopen(keyfile, "rt", false);
if(fptr){
fclose(fptr);
}else{
mosquitto__FREE(mosq->tls_cafile);
mosq->tls_cafile = NULL;
mosquitto__FREE(mosq->tls_capath);
mosq->tls_capath = NULL;
mosquitto__FREE(mosq->tls_certfile);
mosq->tls_certfile = NULL;
return MOSQ_ERR_INVAL;
}
}
mosq->tls_keyfile = mosquitto__strdup(keyfile);
if(!mosq->tls_keyfile){
@@ -223,6 +230,14 @@ int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tl
mosq->tls_version = mosquitto__strdup("tlsv1.2");
if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
}
if(ciphers){
mosquitto__FREE(mosq->tls_ciphers);
mosq->tls_ciphers = mosquitto__strdup(ciphers);
if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
}else{
mosquitto__FREE(mosq->tls_ciphers);
mosq->tls_ciphers = NULL;
}
mosquitto__FREE(mosq->tls_ciphers);
mosquitto__FREE(mosq->tls_13_ciphers);
@@ -278,6 +293,11 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
#if defined(WITH_TLS) && !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
mosquitto__FREE(mosq->tls_engine);
if(value){
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
/* The "Dynamic" OpenSSL engine is not initialized by default but
is required by ENGINE_by_id() to find dynamically loadable engines */
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DYNAMIC, NULL);
#endif
eng = ENGINE_by_id(value);
if(!eng){
return MOSQ_ERR_INVAL;
+17 -1
View File
@@ -137,6 +137,20 @@ void packet__cleanup_all(struct mosquitto *mosq)
static void packet__queue_append(struct mosquitto *mosq, struct mosquitto__packet *packet)
{
#ifdef WITH_BROKER
if(db.config->max_queued_messages > 0 && mosq->out_packet_count >= db.config->max_queued_messages){
mosquitto__free(packet);
if(mosq->is_dropping == false){
mosq->is_dropping = true;
log__printf(NULL, MOSQ_LOG_NOTICE,
"Outgoing messages are being dropped for client %s.",
mosq->id);
}
metrics__int_inc(mosq_counter_mqtt_publish_dropped, 1);
return;
}
#endif
pthread_mutex_lock(&mosq->out_packet_mutex);
if(mosq->out_packet){
mosq->out_packet_last->next = packet;
@@ -296,6 +310,8 @@ int packet__write(struct mosquitto *mosq)
return MOSQ_ERR_CONN_LOST;
case COMPAT_EINTR:
return MOSQ_ERR_SUCCESS;
case EPROTO:
return MOSQ_ERR_TLS;
default:
return MOSQ_ERR_ERRNO;
}
@@ -383,7 +399,7 @@ int packet__read(struct mosquitto *mosq)
#ifdef WITH_BROKER
metrics__int_inc(mosq_counter_bytes_received, 1);
/* Clients must send CONNECT as their first command. */
if(!(mosq->bridge) && state == mosq_cs_connected && (byte&0xF0) != CMD_CONNECT){
if(!(mosq->bridge) && state == mosq_cs_new && (byte&0xF0) != CMD_CONNECT){
return MOSQ_ERR_PROTOCOL;
}
#endif
+19 -18
View File
@@ -26,6 +26,7 @@ Contributors:
# include <strings.h>
#endif
#include "logging_mosq.h"
#include "memory_mosq.h"
#include "mqtt_protocol.h"
#include "packet_mosq.h"
@@ -147,6 +148,9 @@ static int property__read(struct mosquitto__packet_in *packet, uint32_t *len, mo
break;
default:
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property_identifier);
#endif
return MOSQ_ERR_MALFORMED_PACKET;
}
@@ -352,6 +356,9 @@ static int property__write(struct mosquitto__packet *packet, const mosquitto_pro
break;
default:
#ifdef WITH_BROKER
log__printf(NULL, MOSQ_LOG_DEBUG, "Unsupported property type: %d", property->identifier);
#endif
return MOSQ_ERR_INVAL;
}
@@ -1223,12 +1230,10 @@ BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const m
case MQTT_PROP_TYPE_STRING:
pnew->value.s.len = src->value.s.len;
if(src->value.s.v){
pnew->value.s.v = strdup(src->value.s.v);
if(!pnew->value.s.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1);
if(!pnew->value.s.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
break;
@@ -1246,21 +1251,17 @@ BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const m
case MQTT_PROP_TYPE_STRING_PAIR:
pnew->value.s.len = src->value.s.len;
if(src->value.s.v){
pnew->value.s.v = strdup(src->value.s.v);
if(!pnew->value.s.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
pnew->value.s.v = src->value.s.v ? strdup(src->value.s.v) : (char*)calloc(1,1);
if(!pnew->value.s.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
pnew->name.len = src->name.len;
if(src->name.v){
pnew->name.v = strdup(src->name.v);
if(!pnew->name.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
pnew->name.v = src->name.v ? strdup(src->name.v) : (char*)calloc(1,1);
if(!pnew->name.v){
mosquitto_property_free_all(dest);
return MOSQ_ERR_NOMEM;
}
break;
+1 -1
View File
@@ -84,7 +84,7 @@ const char *mosquitto_strerror(int mosq_errno)
case MOSQ_ERR_KEEPALIVE:
return "Keepalive exceeded";
case MOSQ_ERR_LOOKUP:
return "Lookup failed";
return "DNS Lookup failed";
case MOSQ_ERR_MALFORMED_PACKET:
return "Malformed packet";
case MOSQ_ERR_DUPLICATE_PROPERTY:
+11
View File
@@ -105,6 +105,17 @@ static int mosquitto__cmp_hostname_wildcard(char *certname, const char *hostname
break;
}
}
len = strlen(hostname);
int dotcount = 0;
for(i=0; i<len-1; i++){
if(hostname[i] == '.'){
dotcount++;
}
}
if(dotcount < 1){
/* Exclude e.g. *.com, allow e.g. *.example.com */
return 1;
}
return strcasecmp(certname, hostname);
}else{
return strcasecmp(certname, hostname);
+38 -38
View File
@@ -4,44 +4,44 @@
# could not be found, then the man pages will not be built or installed -
# because the install is optional.
if(NOT WIN32)
find_program(XSLTPROC xsltproc OPTIONAL)
if(XSLTPROC)
function(compile_manpage page)
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${page}
COMMAND xsltproc ${PROJECT_SOURCE_DIR}/man/${page}.xml -o ${PROJECT_SOURCE_DIR}/man/
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/man/${page}.xml)
add_custom_target(${page} ALL DEPENDS ${PROJECT_SOURCE_DIR}/man/${page})
endfunction()
find_program(XSLTPROC xsltproc OPTIONAL)
if(XSLTPROC)
function(compile_manpage page)
add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/man/${page}
COMMAND xsltproc ${PROJECT_SOURCE_DIR}/man/${page}.xml -o ${PROJECT_SOURCE_DIR}/man/
MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/man/${page}.xml)
add_custom_target(${page} ALL DEPENDS ${PROJECT_SOURCE_DIR}/man/${page})
endfunction()
compile_manpage("libmosquitto.3")
compile_manpage("mosquitto-tls.7")
compile_manpage("mosquitto.8")
compile_manpage("mosquitto.conf.5")
compile_manpage("mosquitto_ctrl.1")
compile_manpage("mosquitto_ctrl_dynsec.1")
compile_manpage("mosquitto_passwd.1")
compile_manpage("mosquitto_pub.1")
compile_manpage("mosquitto_rr.1")
compile_manpage("mosquitto_sub.1")
compile_manpage("mqtt.7")
else()
message(FATAL_ERROR "xsltproc not found: manpages cannot be built")
endif()
compile_manpage("mosquitto_ctrl.1")
compile_manpage("mosquitto_ctrl_dynsec.1")
compile_manpage("mosquitto_passwd.1")
compile_manpage("mosquitto_pub.1")
compile_manpage("mosquitto_sub.1")
compile_manpage("mosquitto_rr.1")
compile_manpage("libmosquitto.3")
compile_manpage("mosquitto.conf.5")
compile_manpage("mosquitto-tls.7")
compile_manpage("mqtt.7")
compile_manpage("mosquitto.8")
install(FILES
mosquitto_ctrl.1
mosquitto_ctrl_dynsec.1
mosquitto_passwd.1
mosquitto_pub.1
mosquitto_sub.1
mosquitto_rr.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
OPTIONAL)
install(FILES libmosquitto.3 DESTINATION ${CMAKE_INSTALL_MANDIR}/man3 OPTIONAL)
install(FILES mosquitto.conf.5 DESTINATION ${CMAKE_INSTALL_MANDIR}/man5 OPTIONAL)
install(FILES mosquitto-tls.7 mqtt.7 DESTINATION ${CMAKE_INSTALL_MANDIR}/man7 OPTIONAL)
install(FILES mosquitto.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8 OPTIONAL)
elseif(WIN32)
message(WARNING "xsltproc not found: manpages cannot be built")
else()
message(FATAL_ERROR "xsltproc not found: manpages cannot be built")
endif()
install(FILES
mosquitto_ctrl.1
mosquitto_ctrl_dynsec.1
mosquitto_passwd.1
mosquitto_pub.1
mosquitto_rr.1
mosquitto_sub.1
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
OPTIONAL)
install(FILES libmosquitto.3 DESTINATION "${CMAKE_INSTALL_MANDIR}/man3" OPTIONAL)
install(FILES mosquitto.conf.5 DESTINATION "${CMAKE_INSTALL_MANDIR}/man5" OPTIONAL)
install(FILES mosquitto-tls.7 mqtt.7 DESTINATION "${CMAKE_INSTALL_MANDIR}/man7" OPTIONAL)
install(FILES mosquitto.8 DESTINATION "${CMAKE_INSTALL_MANDIR}/man8" OPTIONAL)
+2 -2
View File
@@ -47,7 +47,7 @@
<title>Server</title>
<para>Generate a server key.</para>
<itemizedlist mark="circle">
<listitem><para>openssl genrsa -des3 -out server.key 2048</para></listitem>
<listitem><para>openssl genrsa -aes256 -out server.key 2048</para></listitem>
</itemizedlist>
<para>Generate a server key without encryption.</para>
@@ -71,7 +71,7 @@
<title>Client</title>
<para>Generate a client key.</para>
<itemizedlist mark="circle">
<listitem><para>openssl genrsa -des3 -out client.key 2048</para></listitem>
<listitem><para>openssl genrsa -aes256 -out client.key 2048</para></listitem>
</itemizedlist>
<para>Generate a certificate signing request to send to the CA.</para>
+6 -3
View File
@@ -1638,9 +1638,12 @@ openssl dhparam -out dhparam.pem 2048</programlisting>
<term><option>keyfile</option> <replaceable>file path</replaceable></term>
<listitem>
<para>
Path to the PEM encoded server key. This
option and <option>certfile</option> must be present
to enable certificate based TLS encryption.
If <option>tls_keyform</option> equals "pem" this is the
path to the PEM encoded server key. This option
and <option>certfile</option> must be present
to enable certificate based TLS encryption. If
<option>tls_keyform</option> is "engine" this represents
the engine handle of the private key.
</para>
<para>
The private key pointed to by this option will be
+1 -1
View File
@@ -319,7 +319,7 @@
<listitem>
<para>Disable Nagle's algorithm for the socket. This means
that latency of sent messages is reduced, which is
particularly noticable for small, reasonably infrequent
particularly noticeable for small, reasonably infrequent
messages. Using this option may result in more packets
being sent than would normally be necessary.</para>
</listitem>
+10
View File
@@ -715,6 +715,16 @@
Defaults to <option>5</option>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-W</option></term>
<listitem>
<para>Provide a timeout as an integer number of seconds.
mosquitto_sub will stop processing messages and
disconnect after this number of seconds has
passed. The timeout starts just after the client has
connected to the broker.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--will-payload</option></term>
<listitem>
-1
View File
@@ -1069,7 +1069,6 @@ mosquitto_sub -t 'bbc/#' -T bbc/bbc1 --remove-retained</programlisting>
<para>If the payload is not valid JSON, then the error message "Error: Message payload is not valid JSON on topic
&lt;topic&gt;" will be printed to stderr.</para></listitem>
<listitem><para><option>%I</option> ISO-8601 format date and time, e.g. 2016-08-10T09:47:38+0100</para></listitem>
<listitem><para><option>%U</option> Unix timestamp with nanoseconds, e.g. 1470818943.786368637</para></listitem>
</itemizedlist>
</refsect2>
+13 -11
View File
@@ -17,17 +17,19 @@ MY_DOMAIN=example.com
# Set the directory that the certificates will be copied to.
CERTIFICATE_DIR=/etc/mosquitto/certs
if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then
# Copy new certificate to Mosquitto directory
cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key
for D in ${RENEWED_DOMAINS}; do
if [ "${D}" = "${MY_DOMAIN}" ]; then
# Copy new certificate to Mosquitto directory
cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key
# Set ownership to Mosquitto
chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Set ownership to Mosquitto
chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Ensure permissions are restrictive
chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Ensure permissions are restrictive
chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key
# Tell Mosquitto to reload certificates and configuration
pkill -HUP -x mosquitto
fi
# Tell Mosquitto to reload certificates and configuration
pkill -HUP -x mosquitto
fi
done
+3 -3
View File
@@ -61,7 +61,7 @@ Command:
{
"commands":[
{
"command": "getDefaultACLAccess",
"command": "getDefaultACLAccess"
}
]
}
@@ -244,7 +244,7 @@ Command:
mosquitto_ctrl example:
```
mosquitto_ctrl dynsec setClientPassword username password
mosquitto_ctrl dynsec setClientId username clientId
```
## Set Client Password
@@ -523,7 +523,7 @@ Command:
{
"commands":[
{
"command": "getAnonymousGroup",
"command": "getAnonymousGroup"
}
]
}
+1 -3
View File
@@ -42,9 +42,7 @@ static int memcmp_const(const void *a, const void *b, size_t len)
if(!a || !b) return 1;
for(i=0; i<len; i++){
if( ((char *)a)[i] != ((char *)b)[i] ){
rc = 1;
}
rc |= ((char *)a)[i] ^ ((char *)b)[i];
}
return rc;
}
+9 -10
View File
@@ -107,17 +107,12 @@ void dynsec_clients__cleanup(struct dynsec__data *data)
int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
{
cJSON *j_clients, *j_client = NULL, *jtmp, *j_roles, *j_role;
cJSON *j_clients, *j_client = NULL, *j_roles, *j_role;
struct dynsec__client *client;
struct dynsec__role *role;
unsigned char *buf;
unsigned int buf_len;
int priority;
int iterations;
const char *username;
size_t username_len;
const char *salt;
const char *password;
j_clients = cJSON_GetObjectItem(tree, "clients");
if(j_clients == NULL){
@@ -130,10 +125,11 @@ int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
cJSON_ArrayForEach(j_client, j_clients){
if(cJSON_IsObject(j_client) == true){
/* Username */
const char *username;
if(json_get_string(j_client, "username", &username, false) != MOSQ_ERR_SUCCESS){
continue;
}
username_len = strlen(username);
size_t username_len = strlen(username);
if(username_len == 0){
continue;
}
@@ -147,11 +143,14 @@ int dynsec_clients__config_load(struct dynsec__data *data, cJSON *tree)
}
strncpy(client->username, username, username_len);
jtmp = cJSON_GetObjectItem(j_client, "disabled");
if(jtmp && cJSON_IsBool(jtmp)){
client->disabled = cJSON_IsTrue(jtmp);
bool disabled;
if(json_get_bool(j_client, "disabled", &disabled, false, false) == MOSQ_ERR_SUCCESS){
client->disabled = disabled;
}
int iterations;
const char *salt;
const char *password;
json_get_int(j_client, "iterations", &iterations, 0, true);
if(json_get_string(j_client, "salt", &salt, false) == MOSQ_ERR_SUCCESS
&& json_get_string(j_client, "password", &password, false) == MOSQ_ERR_SUCCESS
+3 -1
View File
@@ -195,7 +195,6 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
struct dynsec__group *group;
struct dynsec__role *role;
int priority;
const char *textname, *textdescription;
const char *groupname;
size_t groupname_len;
@@ -211,6 +210,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
cJSON_ArrayForEach(j_group, j_groups){
if(cJSON_IsObject(j_group) == true){
/* Group name */
const char *groupname;
if(json_get_string(j_group, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){
continue;
}
@@ -229,6 +229,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
strncpy(group->groupname, groupname, groupname_len+1);
/* Text name */
const char *textname;
if(json_get_string(j_group, "textname", &textname, false) == MOSQ_ERR_SUCCESS){
if(textname){
group->text_name = strdup(textname);
@@ -240,6 +241,7 @@ int dynsec_groups__config_load(struct dynsec__data *data, cJSON *tree)
}
/* Text description */
const char *textdescription;
if(json_get_string(j_group, "textdescription", &textdescription, false) == MOSQ_ERR_SUCCESS){
if(textdescription){
group->text_description = strdup(textdescription);
+15 -14
View File
@@ -204,13 +204,14 @@ static int insert_acl_cmp(struct dynsec__acl *a, struct dynsec__acl *b)
static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec__acl **acllist)
{
cJSON *j_acl, *jtmp;
cJSON *j_acl;
struct dynsec__acl *acl;
size_t topic_len;
const char *acltype;
const char *topic;
cJSON_ArrayForEach(j_acl, j_acls){
const char *acltype;
const char *topic;
size_t topic_len;
if(json_get_string(j_acl, "acltype", &acltype, false) != MOSQ_ERR_SUCCESS){
continue;
}
@@ -226,6 +227,11 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
continue;
}
HASH_FIND(hh, *acllist, topic, strlen(topic), acl);
if(acl){
continue;
}
acl = mosquitto_calloc(1, sizeof(struct dynsec__acl) + topic_len + 1);
if(acl == NULL){
return 1;
@@ -235,9 +241,9 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
json_get_int(j_acl, "priority", &acl->priority, true, 0);
json_get_bool(j_acl, "allow", &acl->allow, true, false);
jtmp = cJSON_GetObjectItem(j_acl, "allow");
if(jtmp && cJSON_IsBool(jtmp)){
acl->allow = cJSON_IsTrue(jtmp);
bool allow;
if(json_get_bool(j_acl, "allow", &allow, false, false) == MOSQ_ERR_SUCCESS){
acl->allow = allow;
}
HASH_ADD_INORDER(hh, *acllist, topic, topic_len, acl, insert_acl_cmp);
@@ -249,7 +255,7 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
int dynsec_roles__config_load(struct dynsec__data *data, cJSON *tree)
{
cJSON *j_roles, *j_role, *jtmp, *j_acls;
cJSON *j_roles, *j_role, *j_acls;
struct dynsec__role *role;
size_t rolename_len;
@@ -305,12 +311,7 @@ int dynsec_roles__config_load(struct dynsec__data *data, cJSON *tree)
}
/* Allow wildcard subs */
jtmp = cJSON_GetObjectItem(j_role, "allowwildcardsubs");
if(jtmp != NULL && cJSON_IsBool(jtmp)){
role->allow_wildcard_subs = cJSON_IsTrue(jtmp);
}else{
role->allow_wildcard_subs = true;
}
json_get_bool(j_role, "allowwildcardsubs", &role->allow_wildcard_subs, true, true);
/* ACLs */
j_acls = cJSON_GetObjectItem(j_role, "acls");
@@ -107,5 +107,5 @@ int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int op
UNUSED(opts);
UNUSED(opt_count);
return MOSQ_ERR_SUCCESS;
return mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_BASIC_AUTH, basic_auth_callback, NULL);
}
+1 -1
View File
@@ -372,7 +372,7 @@ static int client_msg_restore(struct mosquitto_sqlite *ms)
client_msg.clientid = (const char *)sqlite3_column_text(stmt, 0);
client_msg.cmsg_id = (uint64_t)sqlite3_column_int64(stmt, 1);
client_msg.store_id = (uint64_t)sqlite3_column_int64(stmt, 2);
client_msg.dup = sqlite3_column_int(stmt, 3);
client_msg.dup = (uint8_t)sqlite3_column_int(stmt, 3);
client_msg.direction = (uint8_t)sqlite3_column_int(stmt, 4);
client_msg.mid = (uint16_t)sqlite3_column_int(stmt, 5);
client_msg.qos = (uint8_t)sqlite3_column_int(stmt, 6);
+2
View File
@@ -298,6 +298,7 @@ static void config__init_reload(struct mosquitto__config *config)
mosquitto__FREE(config->log_timestamp_format);
config->global_max_clients = -1;
config->global_max_connections = -1;
config->log_timestamp_format = NULL;
config->max_keepalive = 0;
config->max_packet_size = 0;
config->max_inflight_messages = 20;
@@ -1859,6 +1860,7 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
return MOSQ_ERR_NOMEM;
}
cr->log_dest |= MQTT3_LOG_FILE;
}else{
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty \"log_dest file\" value in configuration.");
return MOSQ_ERR_INVAL;
+21 -12
View File
@@ -105,8 +105,8 @@ struct mosquitto *context__init(void)
context->address = NULL;
context->bridge = NULL;
context->msgs_in.inflight_maximum = db.config->max_inflight_messages;
context->msgs_out.inflight_maximum = db.config->max_inflight_messages;
context->msgs_in.inflight_quota = db.config->max_inflight_messages;
context->msgs_out.inflight_maximum = db.config->max_inflight_messages;
context->msgs_out.inflight_quota = db.config->max_inflight_messages;
context->max_qos = 2;
#ifdef WITH_TLS
@@ -116,6 +116,24 @@ struct mosquitto *context__init(void)
return context;
}
static void context__cleanup_out_packets(struct mosquitto *context)
{
struct mosquitto__packet *packet;
if(!context) return;
while(context->out_packet){
packet = context->out_packet;
context->out_packet = context->out_packet->next;
mosquitto__free(packet);
}
metrics__int_dec(mosq_gauge_out_packets, context->out_packet_count);
metrics__int_dec(mosq_gauge_out_packet_bytes, context->out_packet_bytes);
context->out_packet_count = 0;
context->out_packet_bytes = 0;
}
/*
* This will result in any outgoing packets going unsent. If we're disconnected
* forcefully then it is usually an error condition and shouldn't be a problem,
@@ -124,8 +142,6 @@ struct mosquitto *context__init(void)
*/
void context__cleanup(struct mosquitto *context, bool force_free)
{
struct mosquitto__packet *packet;
if(!context) return;
if(force_free){
@@ -140,6 +156,7 @@ void context__cleanup(struct mosquitto *context, bool force_free)
alias__free_all(context);
keepalive__remove(context);
context__cleanup_out_packets(context);
mosquitto__FREE(context->auth_method);
mosquitto__FREE(context->username);
@@ -160,15 +177,7 @@ void context__cleanup(struct mosquitto *context, bool force_free)
mosquitto__FREE(context->id);
}
packet__cleanup(&(context->in_packet));
while(context->out_packet){
packet = context->out_packet;
context->out_packet = context->out_packet->next;
mosquitto__FREE(packet);
}
metrics__int_dec(mosq_gauge_out_packets, context->out_packet_count);
metrics__int_dec(mosq_gauge_out_packet_bytes, context->out_packet_bytes);
context->out_packet_count = 0;
context->out_packet_bytes = 0;
context__cleanup_out_packets(context);
#if defined(WITH_BROKER) && defined(__GLIBC__) && defined(WITH_ADNS)
if(context->adns){
gai_cancel(context->adns);
+12 -9
View File
@@ -964,23 +964,24 @@ int db__message_store(const struct mosquitto *source, struct mosquitto__base_msg
return MOSQ_ERR_SUCCESS;
}
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__base_msg **base_msg)
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__client_msg **client_msg)
{
struct mosquitto__client_msg *client_msg;
struct mosquitto__client_msg *cmsg;
*client_msg = NULL;
if(!context) return MOSQ_ERR_INVAL;
*base_msg = NULL;
DL_FOREACH(context->msgs_in.inflight, client_msg){
if(client_msg->base_msg->data.source_mid == mid){
*base_msg = client_msg->base_msg;
DL_FOREACH(context->msgs_in.inflight, cmsg){
if(cmsg->base_msg->data.source_mid == mid){
*client_msg = cmsg;
return MOSQ_ERR_SUCCESS;
}
}
DL_FOREACH(context->msgs_in.queued, client_msg){
if(client_msg->base_msg->data.source_mid == mid){
*base_msg = client_msg->base_msg;
DL_FOREACH(context->msgs_in.queued, cmsg){
if(cmsg->base_msg->data.source_mid == mid){
*client_msg = cmsg;
return MOSQ_ERR_SUCCESS;
}
}
@@ -1084,6 +1085,7 @@ static int db__message_reconnect_reset_incoming(struct mosquitto *context)
}else{
/* Message state can be preserved here because it should match
* whatever the client has got. */
client_msg->data.dup = 0;
}
}
@@ -1094,6 +1096,7 @@ static int db__message_reconnect_reset_incoming(struct mosquitto *context)
* will be sent out of order.
*/
DL_FOREACH_SAFE(context->msgs_in.queued, client_msg, tmp){
client_msg->data.dup = 0;
db__msg_add_to_queued_stats(&context->msgs_in, client_msg);
if(db__ready_for_flight(context, mosq_md_in, client_msg->data.qos)){
switch(client_msg->data.qos){
+5
View File
@@ -403,6 +403,10 @@ static int will__read(struct mosquitto *context, const char *clientid, struct mo
will_struct->msg.topic = will_topic_mount;
}
if(!strncmp(will_struct->msg.topic, "$CONTROL/", strlen("$CONTROL/"))){
rc = MOSQ_ERR_ACL_DENIED;
goto error_cleanup;
}
rc = mosquitto_pub_topic_check(will_struct->msg.topic);
if(rc) goto error_cleanup;
@@ -1065,6 +1069,7 @@ handle_connect_error:
mosquitto__FREE(context->will->msg.payload);
mosquitto__FREE(context->will->msg.topic);
mosquitto__FREE(context->will);
context->will = NULL;
}
/* We return an error here which means the client is freed later on. */
context->clean_start = true;
+24 -11
View File
@@ -42,6 +42,7 @@ int handle__publish(struct mosquitto *context)
uint8_t header = context->in_packet.command;
int res = 0;
struct mosquitto__base_msg *base_msg, *stored = NULL;
struct mosquitto__client_msg *cmsg_stored = NULL;
size_t len;
uint16_t slen;
char *topic_mount;
@@ -300,21 +301,21 @@ int handle__publish(struct mosquitto *context)
}
if(base_msg->data.qos > 0){
db__message_store_find(context, base_msg->data.source_mid, &stored);
db__message_store_find(context, base_msg->data.source_mid, &cmsg_stored);
}
if(stored && base_msg->data.source_mid != 0 &&
(stored->data.qos != base_msg->data.qos
|| stored->data.payloadlen != base_msg->data.payloadlen
|| strcmp(stored->data.topic, base_msg->data.topic)
|| memcmp(stored->data.payload, base_msg->data.payload, base_msg->data.payloadlen) )){
if(cmsg_stored && cmsg_stored->base_msg && base_msg->data.source_mid != 0 &&
(cmsg_stored->base_msg->data.qos != base_msg->data.qos
|| cmsg_stored->base_msg->data.payloadlen != base_msg->data.payloadlen
|| strcmp(cmsg_stored->base_msg->data.topic, base_msg->data.topic)
|| memcmp(cmsg_stored->base_msg->data.payload, base_msg->data.payload, base_msg->data.payloadlen) )){
log__printf(NULL, MOSQ_LOG_WARNING, "Reused message ID %u from %s detected. Clearing from storage.", base_msg->data.source_mid, context->id);
db__message_remove_incoming(context, base_msg->data.source_mid);
stored = NULL;
cmsg_stored = NULL;
}
if(!stored){
if(!cmsg_stored){
if(base_msg->data.qos > 0 && context->msgs_in.inflight_quota == 0){
/* Client isn't allowed any more incoming messages, so fail early */
db__msg_store_free(base_msg);
@@ -323,7 +324,7 @@ int handle__publish(struct mosquitto *context)
if(base_msg->data.qos == 0
|| db__ready_for_flight(context, mosq_md_in, base_msg->data.qos)
|| db__ready_for_queue(context, base_msg->data.qos, &context->msgs_in)){
){
dup = 0;
rc = db__message_store(context, base_msg, message_expiry_interval, mosq_mo_client);
@@ -335,10 +336,13 @@ int handle__publish(struct mosquitto *context)
}
stored = base_msg;
base_msg = NULL;
dup = 0;
}else{
db__msg_store_free(base_msg);
base_msg = NULL;
dup = 1;
stored = cmsg_stored->base_msg;
cmsg_stored->data.dup++;
dup = cmsg_stored->data.dup;
}
switch(stored->data.qos){
@@ -364,11 +368,17 @@ int handle__publish(struct mosquitto *context)
}else{
res = 0;
}
/* db__message_insert() returns 2 to indicate dropped message
* due to queue. This isn't an error so don't disconnect them. */
/* FIXME - this is no longer necessary due to failing early above */
if(!res){
if(send__pubrec(context, stored->data.source_mid, 0, NULL)) rc = 1;
if(dup == 0 || dup == 1){
rc2 = send__pubrec(context, stored->data.source_mid, 0, NULL);
if(rc2) rc = rc2;
}else{
return MOSQ_ERR_PROTOCOL;
}
}else if(res == 1){
rc = 1;
}
@@ -393,5 +403,8 @@ process_bad_message:
}
db__msg_store_free(base_msg);
}
if(context->out_packet_count >= db.config->max_queued_messages){
rc = MQTT_RC_QUOTA_EXCEEDED;
}
return rc;
}
+10 -4
View File
@@ -21,6 +21,7 @@ Contributors:
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#ifndef WIN32
#include <syslog.h>
#endif
@@ -135,11 +136,16 @@ int log__init(struct mosquitto__config *config)
log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open log file %s for writing.", config->log_file);
}
}
if(log_destinations & MQTT3_LOG_STDOUT){
setvbuf(stdout, NULL, _IOLBF, 0);
}
#ifdef WITH_DLT
dlt_fifo_check();
if(dlt_allowed){
DLT_REGISTER_APP("MQTT","mosquitto log");
dlt_register_context(&dltContext, "MQTT", "mosquitto DLT context");
if(log_destinations & MQTT3_LOG_DLT){
dlt_fifo_check();
if(dlt_allowed){
DLT_REGISTER_APP("MQTT","mosquitto log");
dlt_register_context(&dltContext, "MQTT", "mosquitto DLT context");
}
}
#endif
return rc;
+12 -4
View File
@@ -239,9 +239,18 @@ static void mosquitto__daemonise(void)
exit(1);
}
assert(freopen("/dev/null", "r", stdin));
assert(freopen("/dev/null", "w", stdout));
assert(freopen("/dev/null", "w", stderr));
if(!freopen("/dev/null", "r", stdin)){
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stdin", strerror(errno));
exit(1);
}
if(!freopen("/dev/null", "w", stdout)){
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stdout", strerror(errno));
exit(1);
}
if(!freopen("/dev/null", "w", stderr)){
log__printf(NULL, MOSQ_LOG_ERR, "Error whilst daemonising (%s): %s", "stderr", strerror(errno));
exit(1);
}
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Can't start in daemon mode in Windows.");
#endif
@@ -342,7 +351,6 @@ int main(int argc, char *argv[])
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Unable to increase maximum allowed connections. This session may be limited to 512 connections.");
}
}
#endif
memset(&db, 0, sizeof(struct mosquitto_db));
+1 -1
View File
@@ -720,7 +720,7 @@ int db__messages_delete_incoming(struct mosquitto *context);
int db__messages_delete_outgoing(struct mosquitto *context);
int db__messages_easy_queue(struct mosquitto *context, const char *topic, uint8_t qos, uint32_t payloadlen, const void *payload, int retain, uint32_t message_expiry_interval, mosquitto_property **properties);
int db__message_store(const struct mosquitto *source, struct mosquitto__base_msg *base_msg, uint32_t message_expiry_interval, enum mosquitto_msg_origin origin);
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__base_msg **base_msg);
int db__message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto__client_msg **client_msg);
int db__msg_store_add(struct mosquitto__base_msg *base_msg);
void db__msg_store_remove(struct mosquitto__base_msg *base_msg, bool notify);
void db__msg_store_ref_inc(struct mosquitto__base_msg *base_msg);

Some files were not shown because too many files have changed in this diff Show More