mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-09-21 07:13:46 +08:00
Merge branch 'master' into develop
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
# Configuration for Lock Threads - https://github.com/dessant/lock-threads
|
||||
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 90
|
||||
|
||||
# Skip issues and pull requests created before a given timestamp. Timestamp must
|
||||
# follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
|
||||
skipCreatedBefore: false
|
||||
|
||||
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
|
||||
exemptLabels: []
|
||||
|
||||
# Label to add before locking, such as `outdated`. Set to `false` to disable
|
||||
lockLabel: false
|
||||
|
||||
# Comment to post before locking. Set to `false` to disable
|
||||
lockComment: false
|
||||
|
||||
# Assign `resolved` as the reason for locking. Set to `false` to disable
|
||||
setLockReason: true
|
||||
|
||||
# Limit to only `issues` or `pulls`
|
||||
only: issues
|
||||
|
||||
# Optionally, specify configuration settings just for `issues` or `pulls`
|
||||
# issues:
|
||||
# exemptLabels:
|
||||
# - help-wanted
|
||||
# lockLabel: outdated
|
||||
|
||||
# pulls:
|
||||
# daysUntilLock: 30
|
||||
|
||||
# Repository to extend settings from
|
||||
# _extends: repo
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Coverity Scan develop branch on a weekly basis
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "7 3 * * 0"
|
||||
|
||||
jobs:
|
||||
coverity:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: develop
|
||||
|
||||
- name: Dependencies
|
||||
run: sudo apt-get install -y libcjson-dev libsqlite3-dev libssl-dev uthash-dev
|
||||
|
||||
- uses: vapier/coverity-scan-action@v1
|
||||
with:
|
||||
build_language: 'cxx'
|
||||
project: "eclipse/mosquitto"
|
||||
token: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
email: ${{ secrets.COVERITY_SCAN_EMAIL }}
|
||||
command: "make binary"
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Coverity Scan fixes branch on a weekly basis
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "7 3 * * 3"
|
||||
|
||||
jobs:
|
||||
coverity:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: fixes
|
||||
|
||||
- name: Dependencies
|
||||
run: sudo apt-get install -y libcjson-dev libsqlite3-dev libssl-dev uthash-dev
|
||||
|
||||
- uses: vapier/coverity-scan-action@v1
|
||||
with:
|
||||
build_language: 'cxx'
|
||||
project: "eclipse/mosquitto"
|
||||
token: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
email: ${{ secrets.COVERITY_SCAN_EMAIL }}
|
||||
command: "make binary"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
name: 'Lock Threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: lock
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v3
|
||||
with:
|
||||
issue-inactive-days: '90'
|
||||
+1
-1
@@ -13,7 +13,7 @@ project(mosquitto
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
|
||||
add_definitions (-DCMAKE -DVERSION=\"${VERSION}\")
|
||||
|
||||
|
||||
@@ -161,6 +161,73 @@ Build:
|
||||
- Add an CMake option `WITH_LTO` to enable/disable link time optimization.
|
||||
|
||||
|
||||
2.0.15 - 2022-08-16
|
||||
===================
|
||||
|
||||
Security:
|
||||
- Deleting the group configured as the anonymous group in the Dynamic Security
|
||||
plugin, would leave a dangling pointer that could lead to a single crash.
|
||||
This is considered a minor issue - only administrative users should have
|
||||
access to dynsec, the impact on availability is one-off, and there is no
|
||||
associated loss of data. It is now forbidden to delete the group configured
|
||||
as the anonymous group.
|
||||
|
||||
Broker:
|
||||
- Fix memory leak when a plugin modifies the topic of a message in
|
||||
MOSQ_EVT_MESSAGE.
|
||||
- Fix bridge `restart_timeout` not being honoured.
|
||||
- Fix potential memory leaks if a plugin modifies the message in the
|
||||
MOSQ_EVT_MESSAGE event.
|
||||
- Fix unused flags in CONNECT command being forced to be 0, which is not
|
||||
required for MQTT v3.1. Closes #2522.
|
||||
- Improve documentation of `persistent_client_expiration` option.
|
||||
Closes #2404.
|
||||
- Add clients to session expiry check list when restarting and reloading from
|
||||
persistence. Closes #2546.
|
||||
- Fix bridges not sending failure notification messages to the local broker if
|
||||
the remote bridge connection fails. Closes #2467. Closes #1488.
|
||||
- Fix some PUBLISH messages not being counted in $SYS stats. Closes #2448.
|
||||
- Fix incorrect return code being sent in DISCONNECT when a client session is
|
||||
taken over. Closes #2607.
|
||||
- Fix confusing "out of memory" error when a client is kicked in the dynamic
|
||||
security plugin. Closes #2525.
|
||||
- Fix confusing error message when dynamic security config file was a
|
||||
directory. Closes #2520.
|
||||
- Fix bridge queued messages not being persisted when local_cleansession is
|
||||
set to false and cleansession is set to true. Closes #2604.
|
||||
- Dynamic security: Fix modifyClient and modifyGroup commands to not modify
|
||||
the client/group if a new group/client being added is not valid.
|
||||
Closes #2598.
|
||||
- Dynamic security: Fix the plugin being able to be loaded twice. Currently
|
||||
only a single plugin can interact with a unique $CONTROL topic. Using
|
||||
multiple instances of the plugin would produce duplicate entries in the
|
||||
config file. Closes #2601. Closes #2470.
|
||||
- Fix case where expired messages were causing queued messages not to be
|
||||
delivered. Closes #2609.
|
||||
- Fix websockets not passing on the X-Forwarded-For header.
|
||||
|
||||
Client library:
|
||||
- Fix threads library detection on Windows under cmake. Bumps the minimum
|
||||
cmake version to 3.1, which is still ancient.
|
||||
- Fix use of `MOSQ_OPT_TLS_ENGINE` being unable to be used due to the openssl
|
||||
ctx not being initialised until starting to connect. Closes #2537.
|
||||
- Fix incorrect use of SSL_connect. Closes #2594.
|
||||
- Don't set SIGPIPE to ignore, use MSG_NOSIGNAL instead. Closes #2564.
|
||||
- Add documentation of struct mosquitto_message to header. Closes #2561.
|
||||
- Fix documentation omission around mosquitto_reinitialise. Closes #2489.
|
||||
- Fix use of MOSQ_OPT_SSL_CTX when used in conjunction with
|
||||
MOSQ_OPT_SSL_CTX_DEFAULTS. Closes #2463.
|
||||
- Fix failure to close thread in some situations. Closes #2545.
|
||||
|
||||
Clients:
|
||||
- Fix mosquitto_pub incorrectly reusing topic aliases when reconnecting.
|
||||
Closes #2494.
|
||||
|
||||
Apps:
|
||||
- Fix `-o` not working in `mosquitto_ctrl`, and typo in related documentation.
|
||||
Closes #2471.
|
||||
|
||||
|
||||
2.0.14 - 2021-11-17
|
||||
===================
|
||||
|
||||
@@ -188,6 +255,9 @@ Broker:
|
||||
- Fix broker sending duplicate CONNACK on failed MQTT v5 reauthentication.
|
||||
Closes #2339.
|
||||
- Fix mosquitto_plugin.h not including mosquitto_broker.h. Closes #2350.
|
||||
- Fix unlimited message quota not being properly checked for incoming
|
||||
messages. Closes #2593.
|
||||
- Fixed build for openssl compiled with OPENSSL_NO_ENGINE. Closes #2589.
|
||||
|
||||
Client library:
|
||||
- Initialise sockpairR/W to invalid in `mosquitto_reinitialise()` to avoid
|
||||
|
||||
@@ -152,3 +152,10 @@ void db__msg_add_to_queued_stats(struct mosquitto_msg_data *msg_data, struct mos
|
||||
UNUSED(msg_data);
|
||||
UNUSED(msg);
|
||||
}
|
||||
|
||||
int session_expiry__add_from_persistence(struct mosquitto *context, time_t expiry_time)
|
||||
{
|
||||
UNUSED(context);
|
||||
UNUSED(expiry_time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ Contributors:
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mosquitto_ctrl.h"
|
||||
#include "mosquitto.h"
|
||||
#include "base64_mosq.h"
|
||||
|
||||
@@ -22,6 +22,10 @@ Contributors:
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mosquitto.h"
|
||||
#include "mosquitto_ctrl.h"
|
||||
#include "password_mosq.h"
|
||||
|
||||
@@ -22,6 +22,10 @@ Contributors:
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mosquitto_ctrl.h"
|
||||
|
||||
void ctrl_help(void)
|
||||
|
||||
@@ -24,6 +24,10 @@ Contributors:
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "lib_load.h"
|
||||
#include "mosquitto.h"
|
||||
#include "mosquitto_ctrl.h"
|
||||
|
||||
@@ -90,13 +90,14 @@ int ctrl_config_parse(struct mosq_config *cfg, int *argc, char **argv[])
|
||||
|
||||
init_config(cfg);
|
||||
|
||||
rc = client_config_load(cfg);
|
||||
if(rc) return rc;
|
||||
|
||||
/* Deal with real argc/argv */
|
||||
rc = client_config_line_proc(cfg, argc, argv);
|
||||
if(rc) return rc;
|
||||
|
||||
/* Load options from config file - this must be after `-o` has been processed */
|
||||
rc = client_config_load(cfg);
|
||||
if(rc) return rc;
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if((cfg->certfile && !cfg->keyfile) || (cfg->keyfile && !cfg->certfile)){
|
||||
fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is set.\n");
|
||||
@@ -541,7 +542,7 @@ int client_config_load(struct mosq_config *cfg)
|
||||
fclose(fptr);
|
||||
return 1;
|
||||
}
|
||||
while(fgets(line, 1024, fptr)){
|
||||
while(fgets(line, sizeof(line), fptr)){
|
||||
if(line[0] == '#') continue; /* Comments */
|
||||
|
||||
while(line[strlen(line)-1] == 10 || line[strlen(line)-1] == 13){
|
||||
|
||||
@@ -135,6 +135,7 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result, int flag
|
||||
connack_result = result;
|
||||
|
||||
if(!result){
|
||||
first_publish = true;
|
||||
switch(cfg.pub_mode){
|
||||
case MSGMODE_CMD:
|
||||
case MSGMODE_FILE:
|
||||
|
||||
@@ -272,6 +272,7 @@ ifeq ($(WITH_THREADING),yes)
|
||||
BROKER_CFLAGS:=$(BROKER_CFLAGS) -pthread
|
||||
BROKER_LDFLAGS:=$(BROKER_LDFLAGS) -pthread
|
||||
LIB_CFLAGS:=$(LIB_CFLAGS) -pthread
|
||||
LIB_LDFLAGS:=$(LIB_LDFLAGS) -pthread
|
||||
LIB_CPPFLAGS:=$(LIB_CPPFLAGS) -DWITH_THREADING
|
||||
LIB_LDFLAGS:=$(LIB_LDFLAGS) -pthread
|
||||
CLIENT_CFLAGS:=$(CLIENT_CFLAGS) -pthread
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.12
|
||||
FROM alpine:3.14
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
@@ -40,9 +40,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
htps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
@@ -42,9 +42,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
@@ -65,7 +64,7 @@ RUN set -x && \
|
||||
WITH_SHARED_LIBRARIES=yes \
|
||||
WITH_SRV=no \
|
||||
WITH_STRIP=yes \
|
||||
WITH_TLS_PSK=no \
|
||||
WITH_TLS_PSK=no \
|
||||
WITH_WEBSOCKETS=yes \
|
||||
prefix=/usr \
|
||||
binary && \
|
||||
@@ -82,8 +81,8 @@ RUN set -x && \
|
||||
chown -R mosquitto:mosquitto /mosquitto && \
|
||||
apk --no-cache add \
|
||||
ca-certificates \
|
||||
libressl \
|
||||
libuuid && \
|
||||
libressl \
|
||||
libuuid && \
|
||||
apk del build-deps && \
|
||||
rm -rf /build
|
||||
|
||||
|
||||
@@ -45,9 +45,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
@@ -45,9 +45,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.16
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
ENV VERSION=2.0.14 \
|
||||
DOWNLOAD_SHA256=d0dde8fdb12caf6e2426b4f28081919a2fce3448773bdb8af0d3cd5fe5776925 \
|
||||
ENV VERSION=2.0.15 \
|
||||
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
|
||||
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
|
||||
LWS_VERSION=4.2.1 \
|
||||
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
|
||||
@@ -46,9 +46,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
FROM alpine:3.14
|
||||
FROM alpine:3.16
|
||||
|
||||
LABEL maintainer="Roger Light <roger@atchoo.org>" \
|
||||
description="Eclipse Mosquitto MQTT Broker"
|
||||
|
||||
ENV VERSION=2.0.14 \
|
||||
DOWNLOAD_SHA256=d0dde8fdb12caf6e2426b4f28081919a2fce3448773bdb8af0d3cd5fe5776925 \
|
||||
ENV VERSION=2.0.15 \
|
||||
DOWNLOAD_SHA256=4735b1d32e3f91c7a8896741d88a3022e89730a1ee897946decfa0df27039ac6 \
|
||||
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
|
||||
LWS_VERSION=4.2.1 \
|
||||
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51
|
||||
@@ -46,9 +46,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
@@ -63,9 +63,8 @@ RUN set -x && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
found=''; \
|
||||
for server in \
|
||||
ha.pool.sks-keyservers.net \
|
||||
hkps://keys.openpgp.org \
|
||||
hkp://keyserver.ubuntu.com:80 \
|
||||
hkp://p80.pool.sks-keyservers.net:80 \
|
||||
pgp.mit.edu \
|
||||
; do \
|
||||
echo "Fetching GPG key $GPG_KEYS from $server"; \
|
||||
|
||||
+33
-5
@@ -85,7 +85,8 @@ extern "C" {
|
||||
#define MOSQ_LOG_INTERNAL 0x80000000U
|
||||
#define MOSQ_LOG_ALL 0xFFFFFFFFU
|
||||
|
||||
/* Error values */
|
||||
/* Enum: mosq_err_t
|
||||
* Integer values returned from many libmosquitto functions. */
|
||||
enum mosq_err_t {
|
||||
MOSQ_ERR_QUOTA_EXCEEDED = -6,
|
||||
MOSQ_ERR_AUTH_DELAYED = -5,
|
||||
@@ -142,7 +143,12 @@ enum mosq_err_t {
|
||||
MOSQ_ERR_CONNECTION_RATE_EXCEEDED = 159,
|
||||
};
|
||||
|
||||
/* Option values */
|
||||
/* Enum: mosq_opt_t
|
||||
*
|
||||
* Client options.
|
||||
*
|
||||
* See <mosquitto_int_option>, <mosquitto_string_option>, and <mosquitto_void_option>.
|
||||
*/
|
||||
enum mosq_opt_t {
|
||||
MOSQ_OPT_PROTOCOL_VERSION = 1,
|
||||
MOSQ_OPT_SSL_CTX = 2,
|
||||
@@ -175,6 +181,24 @@ enum mosq_transport_t {
|
||||
#define MQTT_PROTOCOL_V311 4
|
||||
#define MQTT_PROTOCOL_V5 5
|
||||
|
||||
/* Struct: mosquitto_message
|
||||
*
|
||||
* Contains details of a PUBLISH message.
|
||||
*
|
||||
* int mid - the message/packet ID of the PUBLISH message, assuming this is a
|
||||
* QoS 1 or 2 message. Will be set to 0 for QoS 0 messages.
|
||||
*
|
||||
* char *topic - the topic the message was delivered on.
|
||||
*
|
||||
* void *payload - the message payload. This will be payloadlen bytes long, and
|
||||
* may be NULL if a zero length payload was sent.
|
||||
*
|
||||
* int payloadlen - the length of the payload, in bytes.
|
||||
*
|
||||
* int qos - the quality of service of the message, 0, 1, or 2.
|
||||
*
|
||||
* bool retain - set to true for stale retained messages.
|
||||
*/
|
||||
struct mosquitto_message{
|
||||
int mid;
|
||||
char *topic;
|
||||
@@ -359,9 +383,10 @@ libmosq_EXPORT void mosquitto_destroy(struct mosquitto *mosq);
|
||||
* callbacks that are specified.
|
||||
*
|
||||
* Returns:
|
||||
* MOSQ_ERR_SUCCESS - on success.
|
||||
* MOSQ_ERR_INVAL - if the input parameters were invalid.
|
||||
* MOSQ_ERR_NOMEM - if an out of memory condition occurred.
|
||||
* MOSQ_ERR_SUCCESS - on success.
|
||||
* MOSQ_ERR_INVAL - if the input parameters were invalid.
|
||||
* MOSQ_ERR_NOMEM - if an out of memory condition occurred.
|
||||
* MOSQ_ERR_MALFORMED_UTF8 - if the client id is not valid UTF-8.
|
||||
*
|
||||
* See Also:
|
||||
* <mosquitto_new>, <mosquitto_destroy>
|
||||
@@ -1623,6 +1648,9 @@ libmosq_EXPORT int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t
|
||||
* 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>.
|
||||
* Must be a valid engine, and note that the string will not be used
|
||||
* until a connection attempt is made so this function will return
|
||||
* success even if an invalid engine string is passed.
|
||||
*
|
||||
* MOSQ_OPT_TLS_KEYFORM - Configure the client to treat the keyfile
|
||||
* differently depending on its type. Must be set
|
||||
|
||||
@@ -78,6 +78,7 @@ static int mosquitto__connect_init(struct mosquitto *mosq, const char *host, int
|
||||
mosq->msgs_in.inflight_quota = mosq->msgs_in.inflight_maximum;
|
||||
mosq->msgs_out.inflight_quota = mosq->msgs_out.inflight_maximum;
|
||||
mosq->retain_available = 1;
|
||||
mosquitto__set_request_disconnect(mosq, false);
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
@@ -265,6 +266,7 @@ int mosquitto_disconnect_v5(struct mosquitto *mosq, int reason_code, const mosqu
|
||||
}
|
||||
|
||||
mosquitto__set_state(mosq, mosq_cs_disconnected);
|
||||
mosquitto__set_request_disconnect(mosq, true);
|
||||
if(!net__is_connected(mosq)){
|
||||
return MOSQ_ERR_NO_CONN;
|
||||
}else{
|
||||
|
||||
+4
-6
@@ -108,9 +108,11 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
}
|
||||
|
||||
now = mosquitto_time();
|
||||
pthread_mutex_lock(&mosq->msgtime_mutex);
|
||||
if(mosq->next_msg_out && now + timeout_ms/1000 > mosq->next_msg_out){
|
||||
timeout_ms = (mosq->next_msg_out - now)*1000;
|
||||
}
|
||||
pthread_mutex_unlock(&mosq->msgtime_mutex);
|
||||
|
||||
if(timeout_ms < 0){
|
||||
/* There has been a delay somewhere which means we should have already
|
||||
@@ -161,7 +163,6 @@ int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
FD_SET(mosq->sock, &writefds);
|
||||
}
|
||||
}
|
||||
|
||||
if(net__is_connected(mosq) && FD_ISSET(mosq->sock, &writefds)){
|
||||
rc = mosquitto_loop_write(mosq, max_packets);
|
||||
if(rc || !net__is_connected(mosq)){
|
||||
@@ -242,7 +243,6 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
int run = 1;
|
||||
int rc = MOSQ_ERR_SUCCESS;
|
||||
unsigned long reconnect_delay;
|
||||
enum mosquitto_client_state state;
|
||||
|
||||
if(!mosq) return MOSQ_ERR_INVAL;
|
||||
|
||||
@@ -281,8 +281,7 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
pthread_testcancel();
|
||||
#endif
|
||||
rc = MOSQ_ERR_SUCCESS;
|
||||
state = mosquitto__get_state(mosq);
|
||||
if(state == mosq_cs_disconnecting || state == mosq_cs_disconnected){
|
||||
if(mosquitto__get_request_disconnect(mosq)){
|
||||
run = 0;
|
||||
}else{
|
||||
if(mosq->reconnect_delay_max > mosq->reconnect_delay){
|
||||
@@ -304,8 +303,7 @@ int mosquitto_loop_forever(struct mosquitto *mosq, int timeout, int max_packets)
|
||||
rc = interruptible_sleep(mosq, (time_t)reconnect_delay);
|
||||
if(rc) return rc;
|
||||
|
||||
state = mosquitto__get_state(mosq);
|
||||
if(state == mosq_cs_disconnecting || state == mosq_cs_disconnected){
|
||||
if(mosquitto__get_request_disconnect(mosq)){
|
||||
run = 0;
|
||||
}else{
|
||||
rc = mosquitto_reconnect(mosq);
|
||||
|
||||
+3
-4
@@ -109,10 +109,6 @@ struct mosquitto *mosquitto_new(const char *id, bool clean_start, void *userdata
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
mosq = (struct mosquitto *)mosquitto__calloc(1, sizeof(struct mosquitto));
|
||||
if(mosq){
|
||||
mosq->sock = INVALID_SOCKET;
|
||||
@@ -179,6 +175,9 @@ int mosquitto_reinitialise(struct mosquitto *mosq, const char *id, bool clean_st
|
||||
return MOSQ_ERR_MALFORMED_UTF8;
|
||||
}
|
||||
mosq->id = mosquitto__strdup(id);
|
||||
if(!mosq->id){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
packet__cleanup(&mosq->in_packet);
|
||||
mosq->out_packet = NULL;
|
||||
|
||||
@@ -404,8 +404,9 @@ struct mosquitto {
|
||||
unsigned int reconnect_delay_max;
|
||||
int callback_depth;
|
||||
uint16_t port;
|
||||
bool reconnect_exponential_backoff;
|
||||
bool disable_socketpair;
|
||||
bool reconnect_exponential_backoff;
|
||||
bool request_disconnect;
|
||||
char threaded;
|
||||
struct mosquitto__packet *out_packet_last;
|
||||
mosquitto_property *connect_properties;
|
||||
|
||||
+2
-6
@@ -674,8 +674,8 @@ static int net__init_ssl_ctx(struct mosquitto *mosq)
|
||||
* has not been set, or if both of MOSQ_OPT_SSL_CTX and
|
||||
* MOSQ_OPT_SSL_CTX_WITH_DEFAULTS are set. */
|
||||
if(mosq->tls_cafile || mosq->tls_capath || mosq->tls_psk || mosq->tls_use_os_certs){
|
||||
net__init_tls();
|
||||
if(!mosq->ssl_ctx){
|
||||
net__init_tls();
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
mosq->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
@@ -1042,11 +1042,7 @@ ssize_t net__write(struct mosquitto *mosq, const void *buf, size_t count)
|
||||
/* Call normal write/send */
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
return write(mosq->sock, buf, count);
|
||||
#else
|
||||
return send(mosq->sock, buf, count, 0);
|
||||
#endif
|
||||
return send(mosq->sock, buf, count, MSG_NOSIGNAL);
|
||||
|
||||
#ifdef WITH_TLS
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ Contributors:
|
||||
#define NET_MOSQ_H
|
||||
|
||||
#ifndef WIN32
|
||||
# include <sys/socket.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <winsock2.h>
|
||||
@@ -51,6 +52,10 @@ typedef SSIZE_T ssize_t;
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
# define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
/* Macros for accessing the MSB and LSB of a uint16_t */
|
||||
#define MOSQ_MSB(A) (uint8_t)((A & 0xFF00) >> 8)
|
||||
#define MOSQ_LSB(A) (uint8_t)(A & 0x00FF)
|
||||
|
||||
+11
-8
@@ -274,14 +274,17 @@ int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, cons
|
||||
switch(option){
|
||||
case MOSQ_OPT_TLS_ENGINE:
|
||||
#if defined(WITH_TLS) && !defined(OPENSSL_NO_ENGINE)
|
||||
eng = ENGINE_by_id(value);
|
||||
if(!eng){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
ENGINE_free(eng); /* release the structural reference from ENGINE_by_id() */
|
||||
mosq->tls_engine = mosquitto__strdup(value);
|
||||
if(!mosq->tls_engine){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
mosquitto__free(mosq->tls_engine);
|
||||
if(value){
|
||||
eng = ENGINE_by_id(value);
|
||||
if(!eng){
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
ENGINE_free(eng); /* release the structural reference from ENGINE_by_id() */
|
||||
mosq->tls_engine = mosquitto__strdup(value);
|
||||
if(!mosq->tls_engine){
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
#else
|
||||
|
||||
+1
-1
@@ -558,7 +558,7 @@ int packet__read(struct mosquitto *mosq)
|
||||
mosq->in_packet.pos = 0;
|
||||
#ifdef WITH_BROKER
|
||||
G_MSGS_RECEIVED_INC(1);
|
||||
if(((mosq->in_packet.command)&0xF5) == CMD_PUBLISH){
|
||||
if(((mosq->in_packet.command)&0xF0) == CMD_PUBLISH){
|
||||
G_PUB_MSGS_RECEIVED_INC(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1206,6 +1206,7 @@ BROKER_EXPORT int mosquitto_property_copy_all(mosquitto_property **dest, const m
|
||||
}
|
||||
plast = pnew;
|
||||
|
||||
pnew->client_generated = src->client_generated;
|
||||
pnew->identifier = src->identifier;
|
||||
switch(pnew->identifier){
|
||||
case MQTT_PROP_PAYLOAD_FORMAT_INDICATOR:
|
||||
|
||||
@@ -21,6 +21,10 @@ Contributors:
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mosquitto.h"
|
||||
#include "mqtt_protocol.h"
|
||||
|
||||
|
||||
@@ -106,6 +106,11 @@ int mosquitto__check_keepalive(struct mosquitto *mosq)
|
||||
pthread_mutex_unlock(&mosq->msgtime_mutex);
|
||||
}else{
|
||||
#ifdef WITH_BROKER
|
||||
# ifdef WITH_BRIDGE
|
||||
if(mosq->bridge){
|
||||
context__send_will(mosq);
|
||||
}
|
||||
# endif
|
||||
net__socket_close(mosq);
|
||||
#else
|
||||
net__socket_close(mosq);
|
||||
@@ -288,3 +293,23 @@ enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq)
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
#ifndef WITH_BROKER
|
||||
void mosquitto__set_request_disconnect(struct mosquitto *mosq, bool request_disconnect)
|
||||
{
|
||||
pthread_mutex_lock(&mosq->state_mutex);
|
||||
mosq->request_disconnect = request_disconnect;
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
}
|
||||
|
||||
bool mosquitto__get_request_disconnect(struct mosquitto *mosq)
|
||||
{
|
||||
bool request_disconnect;
|
||||
|
||||
pthread_mutex_lock(&mosq->state_mutex);
|
||||
request_disconnect = mosq->request_disconnect;
|
||||
pthread_mutex_unlock(&mosq->state_mutex);
|
||||
|
||||
return request_disconnect;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -32,6 +32,10 @@ uint16_t mosquitto__mid_generate(struct mosquitto *mosq);
|
||||
|
||||
int mosquitto__set_state(struct mosquitto *mosq, enum mosquitto_client_state state);
|
||||
enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq);
|
||||
#ifndef WITH_BROKER
|
||||
void mosquitto__set_request_disconnect(struct mosquitto *mosq, bool request_disconnect);
|
||||
bool mosquitto__get_request_disconnect(struct mosquitto *mosq);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_TLS
|
||||
int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin);
|
||||
|
||||
+4
-4
@@ -8,10 +8,10 @@ if(NOT WIN32)
|
||||
find_program(XSLTPROC xsltproc OPTIONAL)
|
||||
if(XSLTPROC)
|
||||
function(compile_manpage page)
|
||||
add_custom_command(OUTPUT "${CMAKE_SOURCE_DIR}/man/${page}"
|
||||
COMMAND xsltproc "${CMAKE_SOURCE_DIR}/man/${page}.xml" -o "${CMAKE_SOURCE_DIR}/man/"
|
||||
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/man/${page}.xml")
|
||||
add_custom_target(${page} ALL DEPENDS "${CMAKE_SOURCE_DIR}/man/${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")
|
||||
|
||||
+19
-10
@@ -925,15 +925,21 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
|
||||
<varlistentry>
|
||||
<term><option>persistent_client_expiration</option> <replaceable>duration</replaceable></term>
|
||||
<listitem>
|
||||
<para>This option allows persistent clients (those with
|
||||
clean session set to false) to be removed if they do
|
||||
not reconnect within a certain time frame. This is a
|
||||
non-standard option. As far as the MQTT spec is
|
||||
concerned, persistent clients persist forever.</para>
|
||||
<para>Badly designed clients may set clean session to false
|
||||
whilst using a randomly generated client id. This leads
|
||||
to persistent clients that will never reconnect. This
|
||||
option allows these clients to be removed.</para>
|
||||
<para>
|
||||
This option allows the session of persistent clients (those with clean
|
||||
session set to false) <emphasis>that are not currently connected</emphasis> to be removed if they
|
||||
do not reconnect within a certain time frame. This is a non-standard option
|
||||
in MQTT v3.1. MQTT v3.1.1 and v5.0 allow brokers to remove client sessions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Badly designed clients may set clean session to false whilst using a randomly
|
||||
generated client id. This leads to persistent clients that connect once and
|
||||
never reconnect. This option allows these clients to be removed. This option
|
||||
allows persistent clients (those with clean session set to false) to be
|
||||
removed if they do not reconnect within a certain time frame.
|
||||
</para>
|
||||
|
||||
<para>The expiration period should be an integer followed
|
||||
by one of h d w m y for hour, day, week, month and year
|
||||
respectively. For example:</para>
|
||||
@@ -1043,7 +1049,9 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
|
||||
<listitem>
|
||||
<para>Set to <replaceable>true</replaceable> to queue
|
||||
messages with QoS 0 when a persistent client is
|
||||
disconnected. These messages are included in the limit
|
||||
disconnected. When bridges topics are configured with QoS level 1 or 2 incoming
|
||||
QoS 0 messages for these topics are also queued.
|
||||
These messages are included in the limit
|
||||
imposed by max_queued_messages. Defaults to
|
||||
<replaceable>false</replaceable>.</para>
|
||||
<para>Note that the MQTT v3.1.1 spec states that only QoS 1
|
||||
@@ -1398,6 +1406,7 @@ accept_protocol_versions 3, 4</programlisting>
|
||||
disconnected as not authorised when this option is
|
||||
set to true. Do not use in conjunction with
|
||||
<option>clientid_prefixes</option>.</para>
|
||||
<para>This does not apply globally, but on a per-listener basis.</para>
|
||||
<para>See also
|
||||
<option>use_identity_as_username</option>.</para>
|
||||
<para>Not reloaded on reload signal.</para>
|
||||
|
||||
+9
-6
@@ -160,14 +160,16 @@
|
||||
# accepted. MQTT imposes a maximum payload size of 268435455 bytes.
|
||||
#message_size_limit 0
|
||||
|
||||
# This option allows persistent clients (those with clean session set to false)
|
||||
# to be removed if they do not reconnect within a certain time frame.
|
||||
#
|
||||
# This is a non-standard option in MQTT V3.1 but allowed in MQTT v3.1.1.
|
||||
# This option allows the session of persistent clients (those with clean
|
||||
# session set to false) that are not currently connected to be removed if they
|
||||
# do not reconnect within a certain time frame. This is a non-standard option
|
||||
# in MQTT v3.1. MQTT v3.1.1 and v5.0 allow brokers to remove client sessions.
|
||||
#
|
||||
# Badly designed clients may set clean session to false whilst using a randomly
|
||||
# generated client id. This leads to persistent clients that will never
|
||||
# reconnect. This option allows these clients to be removed.
|
||||
# generated client id. This leads to persistent clients that connect once and
|
||||
# never reconnect. This option allows these clients to be removed. This option
|
||||
# allows persistent clients (those with clean session set to false) to be
|
||||
# removed if they do not reconnect within a certain time frame.
|
||||
#
|
||||
# The expiration period should be an integer followed by one of h d w m y for
|
||||
# hour, day, week, month and year respectively. For example
|
||||
@@ -324,6 +326,7 @@
|
||||
# authorised when this option is set to true.
|
||||
# Do not use in conjunction with clientid_prefixes.
|
||||
# See also use_identity_as_username.
|
||||
# This does not apply globally, but on a per-listener basis.
|
||||
#use_username_as_clientid
|
||||
|
||||
# Change the websockets headers size. This is a global option, it is not
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
set (PLUGIN_NAME mosquitto_deny_protocol_version)
|
||||
|
||||
add_library(${PLUGIN_NAME} MODULE
|
||||
${PLUGIN_NAME}.c
|
||||
)
|
||||
|
||||
target_include_directories(${PLUGIN_NAME} PRIVATE
|
||||
"${OPENSSL_INCLUDE_DIR}"
|
||||
"${STDBOOL_H_PATH} ${STDINT_H_PATH}"
|
||||
"${mosquitto_SOURCE_DIR}"
|
||||
"${mosquitto_SOURCE_DIR}/include"
|
||||
)
|
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
POSITION_INDEPENDENT_CODE 1
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE mosquitto)
|
||||
endif()
|
||||
|
||||
# Don't install, these are example plugins only.
|
||||
#install(TARGETS ${PLUGIN_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
@@ -0,0 +1,29 @@
|
||||
R=../..
|
||||
include ${R}/config.mk
|
||||
|
||||
.PHONY : all binary check clean reallyclean test install uninstall
|
||||
|
||||
PLUGIN_NAME=mosquitto_deny_protocol_version
|
||||
PLUGIN_CFLAGS+=-I${R}/include -I${R}/
|
||||
|
||||
all : binary
|
||||
|
||||
binary : ${PLUGIN_NAME}.so
|
||||
|
||||
${PLUGIN_NAME}.so : ${PLUGIN_NAME}.c
|
||||
$(CROSS_COMPILE)$(CC) $(PLUGIN_CPPFLAGS) $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) -fPIC -shared $< -o $@
|
||||
|
||||
reallyclean : clean
|
||||
clean:
|
||||
-rm -f *.o ${PLUGIN_NAME}.so *.gcda *.gcno
|
||||
|
||||
check: test
|
||||
test:
|
||||
|
||||
install: ${PLUGIN_NAME}.so
|
||||
# Don't install, these are examples only.
|
||||
#$(INSTALL) -d "${DESTDIR}$(libdir)"
|
||||
#$(INSTALL) ${STRIP_OPTS} ${PLUGIN_NAME}.so "${DESTDIR}${libdir}/${PLUGIN_NAME}.so"
|
||||
|
||||
uninstall :
|
||||
-rm -f "${DESTDIR}${libdir}/${PLUGIN_NAME}.so"
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Copyright (c) 2022 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License 2.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
SPDX-License-Identifier: EPL-2.0 OR EDL-1.0
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an example plugin showing how to deny access based on the version of
|
||||
* the protocol spec a client connects with. It does no other authentication
|
||||
* checks.
|
||||
*
|
||||
* It could be used with other authentication plugins by specifying it in the
|
||||
* config file before another plugin, for example:
|
||||
*
|
||||
* plugin /usr/lib/mosquitto_deny_protocol_version.so
|
||||
* plugin /usr/lib/mosquitto_dynamic_security.so
|
||||
*
|
||||
* or:
|
||||
*
|
||||
* plugin /usr/lib/mosquitto_deny_protocol_version.so
|
||||
* password_file pwfile
|
||||
*
|
||||
* It will *not* work on its own.
|
||||
*
|
||||
* In Mosquitto 2.1, this can be achieved with the `accept_protocol_version`
|
||||
* option instead.
|
||||
*
|
||||
*
|
||||
* To compile:
|
||||
*
|
||||
* gcc -I<path to mosquitto-repo/include> -fPIC -shared mosquitto_deny_protocol_version.c -o mosquitto_deny_protocol_version.so
|
||||
*
|
||||
* Note that this only works on Mosquitto 2.0 or later.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mosquitto_broker.h"
|
||||
#include "mosquitto_plugin.h"
|
||||
#include "mosquitto.h"
|
||||
#include "mqtt_protocol.h"
|
||||
|
||||
static mosquitto_plugin_id_t *mosq_pid = NULL;
|
||||
|
||||
int mosquitto_plugin_version(int supported_version_count, const int *supported_versions)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<supported_version_count; i++){
|
||||
if(supported_versions[i] == 5){
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int basic_auth_callback(int event, void *event_data, void *userdata)
|
||||
{
|
||||
struct mosquitto_evt_basic_auth *ed = event_data;
|
||||
int protocol_version;
|
||||
|
||||
UNUSED(event);
|
||||
UNUSED(userdata);
|
||||
|
||||
protocol_version = mosquitto_client_protocol_version(ed->client);
|
||||
|
||||
if(protocol_version == 5 || protocol_version == 4){
|
||||
/* Allow access to MQTT v5.0 and v3.1.1 - this passes on responsibility
|
||||
* for the actual auth checks to the next plugin/password file in the
|
||||
* config list. If no other plugins/password file is defined, then
|
||||
* access will be denied. */
|
||||
return MOSQ_ERR_PLUGIN_DEFER;
|
||||
}else{
|
||||
/* Deny access to all others */
|
||||
return MOSQ_ERR_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, struct mosquitto_opt *opts, int opt_count)
|
||||
{
|
||||
UNUSED(user_data);
|
||||
UNUSED(opts);
|
||||
UNUSED(opt_count);
|
||||
|
||||
mosq_pid = identifier;
|
||||
return mosquitto_callback_register(mosq_pid, MOSQ_EVT_BASIC_AUTH, basic_auth_callback, NULL, NULL);
|
||||
}
|
||||
|
||||
int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count)
|
||||
{
|
||||
UNUSED(user_data);
|
||||
UNUSED(opts);
|
||||
UNUSED(opt_count);
|
||||
|
||||
return mosquitto_callback_unregister(mosq_pid, MOSQ_EVT_MESSAGE, basic_auth_callback, NULL);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
listener 1883
|
||||
|
||||
plugin ./mosquitto_deny_protocol_version.so
|
||||
password_file pwfile
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
../../apps/mosquitto_passwd/mosquitto_passwd -c -b pwfile username password
|
||||
../../src/mosquitto -c test.conf -v
|
||||
@@ -718,10 +718,12 @@ static void client__remove_all_roles(struct dynsec__client *client)
|
||||
int dynsec_clients__process_modify(struct dynsec__data *data, struct plugin_cmd *cmd, struct mosquitto *context)
|
||||
{
|
||||
char *username;
|
||||
char *clientid;
|
||||
char *password;
|
||||
char *text_name, *text_description;
|
||||
char *clientid = NULL;
|
||||
char *password = NULL;
|
||||
char *text_name = NULL, *text_description = NULL;
|
||||
bool have_clientid = false, have_text_name = false, have_text_description = false, have_rolelist = false, have_password = false;
|
||||
struct dynsec__client *client;
|
||||
struct dynsec__group *group;
|
||||
struct dynsec__rolelist *rolelist = NULL;
|
||||
char *str;
|
||||
int rc;
|
||||
@@ -744,81 +746,87 @@ int dynsec_clients__process_modify(struct dynsec__data *data, struct plugin_cmd
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "clientid", &clientid, false) == MOSQ_ERR_SUCCESS){
|
||||
if(clientid && strlen(clientid) > 0){
|
||||
str = mosquitto_strdup(clientid);
|
||||
if(str == NULL){
|
||||
if(json_get_string(cmd->j_command, "clientid", &str, false) == MOSQ_ERR_SUCCESS){
|
||||
have_clientid = true;
|
||||
if(str && strlen(str) > 0){
|
||||
clientid = mosquitto_strdup(str);
|
||||
if(clientid == NULL){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
}else{
|
||||
str = NULL;
|
||||
clientid = NULL;
|
||||
}
|
||||
mosquitto_free(client->clientid);
|
||||
client->clientid = str;
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "password", &password, false) == MOSQ_ERR_SUCCESS){
|
||||
if(strlen(password) > 0){
|
||||
/* If password == "", we just ignore it */
|
||||
rc = client__set_password(client, password);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
dynsec_kicklist__add(data, username);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
}
|
||||
have_password = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "textname", &text_name, false) == MOSQ_ERR_SUCCESS){
|
||||
str = mosquitto_strdup(text_name);
|
||||
if(str == NULL){
|
||||
if(json_get_string(cmd->j_command, "textname", &str, false) == MOSQ_ERR_SUCCESS){
|
||||
have_text_name = true;
|
||||
text_name = mosquitto_strdup(str);
|
||||
if(text_name == NULL){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
dynsec_kicklist__add(data, username);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
mosquitto_free(client->text_name);
|
||||
client->text_name = str;
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "textdescription", &text_description, false) == MOSQ_ERR_SUCCESS){
|
||||
str = mosquitto_strdup(text_description);
|
||||
if(str == NULL){
|
||||
if(json_get_string(cmd->j_command, "textdescription", &str, false) == MOSQ_ERR_SUCCESS){
|
||||
have_text_description = true;
|
||||
text_description = mosquitto_strdup(str);
|
||||
if(text_description == NULL){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
dynsec_kicklist__add(data, username);
|
||||
return MOSQ_ERR_NOMEM;
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
mosquitto_free(client->text_description);
|
||||
client->text_description = str;
|
||||
}
|
||||
|
||||
rc = dynsec_rolelist__load_from_json(data, cmd->j_command, &rolelist);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
client__remove_all_roles(client);
|
||||
client__add_new_roles(client, rolelist);
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
have_rolelist = true;
|
||||
}else if(rc == ERR_LIST_NOT_FOUND){
|
||||
/* There was no list in the JSON, so no modification */
|
||||
}else if(rc == MOSQ_ERR_NOT_FOUND){
|
||||
plugin__command_reply(cmd, "Role not found");
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
dynsec_kicklist__add(data, username);
|
||||
return MOSQ_ERR_INVAL;
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}else{
|
||||
if(rc == MOSQ_ERR_INVAL){
|
||||
plugin__command_reply(cmd, "'roles' not an array or missing/invalid rolename");
|
||||
}else{
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
}
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
dynsec_kicklist__add(data, username);
|
||||
return MOSQ_ERR_INVAL;
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
j_groups = cJSON_GetObjectItem(cmd->j_command, "groups");
|
||||
if(j_groups && cJSON_IsArray(j_groups)){
|
||||
dynsec__remove_client_from_all_groups(data, username);
|
||||
/* Iterate through list to check all groups are valid */
|
||||
cJSON_ArrayForEach(j_group, j_groups){
|
||||
if(cJSON_IsObject(j_group)){
|
||||
jtmp = cJSON_GetObjectItem(j_group, "groupname");
|
||||
if(jtmp && cJSON_IsString(jtmp)){
|
||||
group = dynsec_groups__find(data, jtmp->valuestring);
|
||||
if(group == NULL){
|
||||
plugin__command_reply(cmd, "'groups' contains an object with a 'groupname' that does not exist");
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
}else{
|
||||
plugin__command_reply(cmd, "'groups' contains an object with an invalid 'groupname'");
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dynsec__remove_client_from_all_groups(data, username);
|
||||
cJSON_ArrayForEach(j_group, j_groups){
|
||||
if(cJSON_IsObject(j_group)){
|
||||
jtmp = cJSON_GetObjectItem(j_group, "groupname");
|
||||
@@ -830,6 +838,44 @@ int dynsec_clients__process_modify(struct dynsec__data *data, struct plugin_cmd
|
||||
}
|
||||
}
|
||||
|
||||
if(have_password){
|
||||
/* FIXME - This is the one call that will result in modification on internal error - note that groups have already been modified */
|
||||
rc = client__set_password(client, password);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
mosquitto_kick_client_by_username(username, false);
|
||||
/* If this fails we have the situation that the password is set as
|
||||
* invalid, but the config isn't saved, so restarting the broker
|
||||
* *now* will mean the client can log in again. This might be
|
||||
* "good", but is inconsistent, so save the config to be
|
||||
* consistent. */
|
||||
dynsec__config_save(data);
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if(have_clientid){
|
||||
mosquitto_free(client->clientid);
|
||||
client->clientid = clientid;
|
||||
}
|
||||
|
||||
if(have_text_name){
|
||||
mosquitto_free(client->text_name);
|
||||
client->text_name = text_name;
|
||||
}
|
||||
|
||||
if(have_text_description){
|
||||
mosquitto_free(client->text_description);
|
||||
client->text_description = text_description;
|
||||
}
|
||||
|
||||
if(have_rolelist){
|
||||
client__remove_all_roles(client);
|
||||
client__add_new_roles(client, rolelist);
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
}
|
||||
|
||||
dynsec__config_save(data);
|
||||
plugin__command_reply(cmd, NULL);
|
||||
|
||||
@@ -841,6 +887,12 @@ int dynsec_clients__process_modify(struct dynsec__data *data, struct plugin_cmd
|
||||
mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | modifyClient | username=%s",
|
||||
admin_clientid, admin_username, username);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
error:
|
||||
mosquitto_free(clientid);
|
||||
mosquitto_free(text_name);
|
||||
mosquitto_free(text_description);
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -305,5 +305,6 @@ cJSON *dynsec_rolelist__all_to_json(struct dynsec__rolelist *base_rolelist);
|
||||
int dynsec_kicklist__add(struct dynsec__data *data, const char *username);
|
||||
void dynsec_kicklist__kick(struct dynsec__data *data);
|
||||
int dynsec__tick_callback(int event, void *event_data, void *userdata);
|
||||
void dynsec_kicklist__cleanup(struct dynsec__data *data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -909,10 +909,12 @@ int dynsec_groups__process_remove_role(struct dynsec__data *data, struct plugin_
|
||||
|
||||
int dynsec_groups__process_modify(struct dynsec__data *data, struct plugin_cmd *cmd, struct mosquitto *context)
|
||||
{
|
||||
char *groupname;
|
||||
char *text_name, *text_description;
|
||||
struct dynsec__group *group;
|
||||
char *groupname = NULL;
|
||||
char *text_name = NULL, *text_description = NULL;
|
||||
struct dynsec__client *client = NULL;
|
||||
struct dynsec__group *group = NULL;
|
||||
struct dynsec__rolelist *rolelist = NULL;
|
||||
bool have_text_name = false, have_text_description = false, have_rolelist = false;
|
||||
char *str;
|
||||
int rc;
|
||||
int priority;
|
||||
@@ -934,52 +936,73 @@ int dynsec_groups__process_modify(struct dynsec__data *data, struct plugin_cmd *
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "textname", &text_name, false) == MOSQ_ERR_SUCCESS){
|
||||
str = mosquitto_strdup(text_name);
|
||||
if(str == NULL){
|
||||
if(json_get_string(cmd->j_command, "textname", &str, false) == MOSQ_ERR_SUCCESS){
|
||||
have_text_name = true;
|
||||
text_name = mosquitto_strdup(str);
|
||||
if(text_name == NULL){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
mosquitto_free(group->text_name);
|
||||
group->text_name = str;
|
||||
}
|
||||
|
||||
if(json_get_string(cmd->j_command, "textdescription", &text_description, false) == MOSQ_ERR_SUCCESS){
|
||||
str = mosquitto_strdup(text_description);
|
||||
if(str == NULL){
|
||||
if(json_get_string(cmd->j_command, "textdescription", &str, false) == MOSQ_ERR_SUCCESS){
|
||||
have_text_description = true;
|
||||
text_description = mosquitto_strdup(str);
|
||||
if(text_description == NULL){
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
return MOSQ_ERR_NOMEM;
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto error;
|
||||
}
|
||||
mosquitto_free(group->text_description);
|
||||
group->text_description = str;
|
||||
}
|
||||
|
||||
rc = dynsec_rolelist__load_from_json(data, cmd->j_command, &rolelist);
|
||||
if(rc == MOSQ_ERR_SUCCESS){
|
||||
dynsec_rolelist__cleanup(&group->rolelist);
|
||||
group->rolelist = rolelist;
|
||||
/* Apply changes below */
|
||||
have_rolelist = true;
|
||||
}else if(rc == ERR_LIST_NOT_FOUND){
|
||||
/* There was no list in the JSON, so no modification */
|
||||
rolelist = NULL;
|
||||
}else if(rc == MOSQ_ERR_NOT_FOUND){
|
||||
plugin__command_reply(cmd, "Role not found");
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
group__kick_all(data, group);
|
||||
return MOSQ_ERR_INVAL;
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}else{
|
||||
if(rc == MOSQ_ERR_INVAL){
|
||||
plugin__command_reply(cmd, "'roles' not an array or missing/invalid rolename");
|
||||
}else{
|
||||
plugin__command_reply(cmd, "Internal error");
|
||||
}
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
group__kick_all(data, group);
|
||||
return MOSQ_ERR_INVAL;
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
j_clients = cJSON_GetObjectItem(cmd->j_command, "clients");
|
||||
if(j_clients && cJSON_IsArray(j_clients)){
|
||||
/* Iterate over array to check clients are valid before proceeding */
|
||||
cJSON_ArrayForEach(j_client, j_clients){
|
||||
if(cJSON_IsObject(j_client)){
|
||||
jtmp = cJSON_GetObjectItem(j_client, "username");
|
||||
if(jtmp && cJSON_IsString(jtmp)){
|
||||
client = dynsec_clients__find(data, jtmp->valuestring);
|
||||
if(client == NULL){
|
||||
plugin__command_reply(cmd, "'clients' contains an object with a 'username' that does not exist");
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
}else{
|
||||
plugin__command_reply(cmd, "'clients' contains an object with an invalid 'username'");
|
||||
rc = MOSQ_ERR_INVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Kick all clients in the *current* group */
|
||||
group__kick_all(data, group);
|
||||
dynsec__remove_all_clients_from_group(group);
|
||||
|
||||
/* Now we can add the new clients to the group */
|
||||
cJSON_ArrayForEach(j_client, j_clients){
|
||||
if(cJSON_IsObject(j_client)){
|
||||
jtmp = cJSON_GetObjectItem(j_client, "username");
|
||||
@@ -991,11 +1014,28 @@ int dynsec_groups__process_modify(struct dynsec__data *data, struct plugin_cmd *
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply remaining changes to group, note that user changes are already applied */
|
||||
if(have_text_name){
|
||||
mosquitto_free(group->text_name);
|
||||
group->text_name = text_name;
|
||||
}
|
||||
|
||||
if(have_text_description){
|
||||
mosquitto_free(group->text_description);
|
||||
group->text_description = text_description;
|
||||
}
|
||||
|
||||
if(have_rolelist){
|
||||
dynsec_rolelist__cleanup(&group->rolelist);
|
||||
group->rolelist = rolelist;
|
||||
}
|
||||
|
||||
/* And save */
|
||||
dynsec__config_save(data);
|
||||
|
||||
plugin__command_reply(cmd, NULL);
|
||||
|
||||
/* Enforce any changes */
|
||||
/* Enforce any changes - kick any clients in the *new* group */
|
||||
group__kick_all(data, group);
|
||||
|
||||
admin_clientid = mosquitto_client_id(context);
|
||||
@@ -1004,6 +1044,17 @@ int dynsec_groups__process_modify(struct dynsec__data *data, struct plugin_cmd *
|
||||
admin_clientid, admin_username, groupname);
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
error:
|
||||
mosquitto_free(text_name);
|
||||
mosquitto_free(text_description);
|
||||
dynsec_rolelist__cleanup(&rolelist);
|
||||
|
||||
admin_clientid = mosquitto_client_id(context);
|
||||
admin_username = mosquitto_client_username(context);
|
||||
mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | modifyGroup | groupname=%s",
|
||||
admin_clientid, admin_username, groupname);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,3 +64,13 @@ void dynsec_kicklist__kick(struct dynsec__data *data)
|
||||
free(kick);
|
||||
}
|
||||
}
|
||||
|
||||
void dynsec_kicklist__cleanup(struct dynsec__data *data)
|
||||
{
|
||||
struct dynsec__kicklist *kick, *tmp;
|
||||
|
||||
DL_FOREACH_SAFE(data->kicklist, kick, tmp){
|
||||
DL_DELETE(data->kicklist, kick);
|
||||
free(kick);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ Contributors:
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "json_help.h"
|
||||
#include "mosquitto.h"
|
||||
#include "mosquitto_broker.h"
|
||||
#include "mosquitto_plugin.h"
|
||||
@@ -39,6 +44,7 @@ static mosquitto_plugin_id_t *plg_id = NULL;
|
||||
int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, struct mosquitto_opt *options, int option_count)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
UNUSED(user_data);
|
||||
|
||||
@@ -66,12 +72,54 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s
|
||||
mosquitto_plugin_set_info(identifier, "dynamic-security", NULL);
|
||||
|
||||
dynsec__config_load(&dynsec_data);
|
||||
mosquitto_callback_register(plg_id, MOSQ_EVT_CONTROL, dynsec_control_callback, "$CONTROL/dynamic-security/v1", &dynsec_data);
|
||||
mosquitto_callback_register(plg_id, MOSQ_EVT_BASIC_AUTH, dynsec_auth__basic_auth_callback, NULL, &dynsec_data);
|
||||
mosquitto_callback_register(plg_id, MOSQ_EVT_ACL_CHECK, dynsec__acl_check_callback, NULL, &dynsec_data);
|
||||
mosquitto_callback_register(plg_id, MOSQ_EVT_TICK, dynsec__tick_callback, NULL, &dynsec_data);
|
||||
|
||||
rc = mosquitto_callback_register(plg_id, MOSQ_EVT_CONTROL, dynsec_control_callback, "$CONTROL/dynamic-security/v1", &dynsec_data);
|
||||
if(rc == MOSQ_ERR_ALREADY_EXISTS){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can currently only be loaded once.");
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Note that this was previously incorrectly allowed but could cause problems with duplicate entries in the config.");
|
||||
goto error;
|
||||
}else if(rc == MOSQ_ERR_NOMEM){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
goto error;
|
||||
}else if(rc != MOSQ_ERR_SUCCESS){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mosquitto_callback_register(plg_id, MOSQ_EVT_BASIC_AUTH, dynsec_auth__basic_auth_callback, NULL, &dynsec_data);
|
||||
if(rc == MOSQ_ERR_ALREADY_EXISTS){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can only be loaded once.");
|
||||
goto error;
|
||||
}else if(rc == MOSQ_ERR_NOMEM){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
goto error;
|
||||
}else if(rc != MOSQ_ERR_SUCCESS){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mosquitto_callback_register(plg_id, MOSQ_EVT_ACL_CHECK, dynsec__acl_check_callback, NULL, &dynsec_data);
|
||||
if(rc == MOSQ_ERR_ALREADY_EXISTS){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can only be loaded once.");
|
||||
goto error;
|
||||
}else if(rc == MOSQ_ERR_NOMEM){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
goto error;
|
||||
}else if(rc != MOSQ_ERR_SUCCESS){
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = mosquitto_callback_register(plg_id, MOSQ_EVT_TICK, dynsec__tick_callback, NULL, &dynsec_data);
|
||||
if(rc == MOSQ_ERR_NOMEM){
|
||||
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||
goto error;
|
||||
}else if(rc != MOSQ_ERR_SUCCESS){
|
||||
goto error;
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
error:
|
||||
mosquitto_free(dynsec_data.config_file);
|
||||
dynsec_data.config_file = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *options, int option_count)
|
||||
@@ -83,6 +131,7 @@ int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *options, int
|
||||
dynsec_groups__cleanup(&dynsec_data);
|
||||
dynsec_clients__cleanup(&dynsec_data);
|
||||
dynsec_roles__cleanup(&dynsec_data);
|
||||
dynsec_kicklist__cleanup(&dynsec_data);
|
||||
|
||||
mosquitto_free(dynsec_data.config_file);
|
||||
dynsec_data.config_file = NULL;
|
||||
|
||||
@@ -24,6 +24,10 @@ Contributors:
|
||||
#include <uthash.h>
|
||||
#include <utlist.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "dynamic_security.h"
|
||||
#include "json_help.h"
|
||||
#include "mosquitto.h"
|
||||
|
||||
@@ -11,9 +11,9 @@ ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto /var/log/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto:mosquitto /var/log/mosquitto
|
||||
ExecStartPre=/bin/mkdir -m 740 -p /run/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto /run/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto:mosquitto /run/mosquitto
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -9,9 +9,9 @@ ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
Restart=on-failure
|
||||
ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto /var/log/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto:mosquitto /var/log/mosquitto
|
||||
ExecStartPre=/bin/mkdir -m 740 -p /run/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto /run/mosquitto
|
||||
ExecStartPre=/bin/chown mosquitto:mosquitto /run/mosquitto
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user