Compare commits

...

5 Commits

Author SHA1 Message Date
Dominik Kuhn
323a37331c adding wamo plugin 2024-08-18 12:56:58 +02:00
Roger A. Light
15292b20b0 Update security page 2023-10-06 16:20:43 +01:00
Roger Light
b9a842a394
Merge pull request #1571 from LocutusOfBorg/dynamic-symbols
Add dynamic symbols linking with cmake too
2023-09-28 23:58:40 +01:00
Gianfranco Costamagna
5b011ff112 Add dynamic symbols linking with cmake too
Signed-off-by: Gianfranco Costamagna <costamagnagianfranco@yahoo.it>
2023-09-26 23:40:50 +02:00
Roger A. Light
f4400fa422 Bump docker 2023-09-18 22:32:22 +01:00
13 changed files with 552 additions and 6 deletions

57
CMakeSettings.json Normal file
View File

@ -0,0 +1,57 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "clang_cl_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "WITH_TLS",
"value": "False",
"type": "BOOL"
},
{
"name": "WITH_CLIENTS",
"value": "False",
"type": "BOOL"
},
{
"name": "WITH_WEBSOCKETS",
"value": "False",
"type": "BOOL"
},
{
"name": "WITH_THREADING",
"value": "False",
"type": "BOOL"
},
{
"name": "DOCUMENTATION",
"value": "False",
"type": "BOOL"
},
{
"name": "CJSON_DIR",
"value": "C:/Users/d.kuhn/Projekte/cJSON/",
"type": "STRING"
},
{
"name": "CJSON_INCLUDE_DIR",
"value": "C:/Users/d.kuhn/Projekte/cJSON/",
"type": "PATH"
},
{
"name": "CJSON_LIBRARY",
"value": "C:/Users/d.kuhn/Projekte/cJSON/cjson/out/build/x64-Debug/cjson.lib",
"type": "FILEPATH"
}
]
}
]
}

View File

@ -67,7 +67,7 @@ WITH_SYSTEMD:=no
WITH_SRV:=no
# Build with websockets support on the broker.
WITH_WEBSOCKETS:=no
WITH_WEBSOCKETS:=yes
# Use elliptic keys in broker
WITH_EC:=yes

View File

@ -3,8 +3,8 @@ FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=2.0.17 \
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
ENV VERSION=2.0.18 \
DOWNLOAD_SHA256=d665fe7d0032881b1371a47f34169ee4edab67903b2cd2b4c083822823f4448a \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=4.2.1 \
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51

View File

@ -3,8 +3,8 @@ FROM alpine:3.18
LABEL maintainer="Roger Light <roger@atchoo.org>" \
description="Eclipse Mosquitto MQTT Broker"
ENV VERSION=2.0.17 \
DOWNLOAD_SHA256=3be7a911236567c1a9fbe25baf3e3167004ba4a0c151a448ef1f7fc077dba52f \
ENV VERSION=2.0.18 \
DOWNLOAD_SHA256=d665fe7d0032881b1371a47f34169ee4edab67903b2cd2b4c083822823f4448a \
GPG_KEYS=A0D6EEA1DCAE49A635A3B2F0779B22DFB3E717B7 \
LWS_VERSION=4.2.1 \
LWS_SHA256=842da21f73ccba2be59e680de10a8cce7928313048750eb6ad73b6fa50763c51

View File

@ -94,6 +94,8 @@ set_target_properties(libmosquitto PROPERTIES
OUTPUT_NAME mosquitto
VERSION ${VERSION}
SOVERSION 1
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.version
LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/linker.version"
)
install(TARGETS libmosquitto

View File

@ -902,3 +902,7 @@
# given multiple times, all of the files from the first instance will be
# processed before the next instance. See the man page for examples.
#include_dir
# plugin C:\Users\d.kuhn\Projekte\mosquitto\out\build\x64-Debug\plugins\payload-modification\mosquitto_payload_modification.dll
plugin C:\Users\d.kuhn\Projekte\mosquitto\out\build\x64-Debug\plugins\wamo\wamo.dll

View File

@ -3,3 +3,4 @@ if(NOT WIN32)
add_subdirectory(message-timestamp)
endif(NOT WIN32)
add_subdirectory(payload-modification)
add_subdirectory(wamo)

View File

@ -0,0 +1,51 @@
# include_directories(${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/include
# ${OPENSSL_INCLUDE_DIR} ${STDBOOL_H_PATH} ${STDINT_H_PATH})
# link_directories(${mosquitto_SOURCE_DIR})
#
# add_library(wamo MODULE wamo.c "json_help.c" "json_help.h")
# set_target_properties(wamo PROPERTIES
# POSITION_INDEPENDENT_CODE 1
# )
# set_target_properties(wamo PROPERTIES PREFIX "")
# if(WIN32)
# target_link_libraries(wamo mosquitto ${CJSON_LIBRARIES})
# endif(WIN32)
# Don't install, these are example plugins only.
#install(TARGETS wamo RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
if (CJSON_FOUND )
add_definitions("-DWITH_CJSON")
set( CLIENT_INC ${mosquitto_SOURCE_DIR} ${mosquitto_SOURCE_DIR}/include
${STDBOOL_H_PATH} ${STDINT_H_PATH} ${mosquitto_SOURCE_DIR}/deps
${mosquitto_SOURCE_DIR}/src ${CJSON_INCLUDE_DIRS} )
set( CLIENT_DIR ${mosquitto_BINARY_DIR}/lib ${CJSON_DIR})
include_directories(${CLIENT_INC})
link_directories(${CLIENT_DIR} ${mosquitto_SOURCE_DIR})
add_library(wamo MODULE
json_help.c
json_help.h
wamo.c)
set_target_properties(wamo PROPERTIES
POSITION_INDEPENDENT_CODE 1
)
set_target_properties(wamo PROPERTIES PREFIX "")
target_link_libraries(wamo ${CJSON_LIBRARIES})
if(WIN32)
target_link_libraries(wamo mosquitto)
install(TARGETS wamo
DESTINATION "${CMAKE_INSTALL_BINDIR}")
else()
install(TARGETS wamo
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()
endif()

53
plugins/wamo/Makefile Normal file
View File

@ -0,0 +1,53 @@
include ../../config.mk
.PHONY : all binary check clean reallyclean test install uninstall
PLUGIN_NAME=wamo
LOCAL_CPPFLAGS=-I../../src/ -DWITH_CJSON
OBJS= \
json_help.o \
wamo.o
ifeq ($(WITH_CJSON),yes)
ALL_DEPS:= binary
else
ALL_DEPS:=
endif
else
ALL_DEPS:=
endif
all : ${ALL_DEPS}
binary : ${PLUGIN_NAME}.so
${PLUGIN_NAME}.so : ${OBJS}
${CROSS_COMPILE}${CC} $(PLUGIN_LDFLAGS) -fPIC -shared $^ -o $@ -lcjson
json_help.o : json_help.c
${CROSS_COMPILE}${CC} $(LOCAL_CPPFLAGS) $(PLUGIN_CPPFLAGS) $(PLUGIN_CFLAGS) -c $< -o $@
wamo.o : wamo.c
${CROSS_COMPILE}${CC} $(LOCAL_CPPFLAGS) $(PLUGIN_CPPFLAGS) $(PLUGIN_CFLAGS) -c $< -o $@
reallyclean : clean
clean:
-rm -f *.o ${PLUGIN_NAME}.so *.gcda *.gcno
check: test
test:
install: all
ifeq ($(WITH_CJSON),yes)
$(INSTALL) -d "${DESTDIR}$(libdir)"
$(INSTALL) ${STRIP_OPTS} ${PLUGIN_NAME}.so "${DESTDIR}${libdir}/${PLUGIN_NAME}.so"
endif
endif
uninstall :
-rm -f "${DESTDIR}${libdir}/${PLUGIN_NAME}.so"

182
plugins/wamo/json_help.c Normal file
View File

@ -0,0 +1,182 @@
/*
Contributors:
Dominik Kuhn - initial implementation and documentation.
*/
#include "config.h"
#include <cjson/cJSON.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "json_help.h"
#include "mosquitto.h"
#include "mosquitto_broker.h"
int json_create_array(cJSON* json, const char* name) {
cJSON* jtmp;
jtmp = cJSON_GetObjectItem(json, name);
if (jtmp) {
if (cJSON_IsArray(jtmp) == true) {
return MOSQ_ERR_INVAL;
}
else {
cJSON_AddArrayToObject(json, name);
}
}
else {
cJSON_AddArrayToObject(json, name);
}
return MOSQ_ERR_SUCCESS;
}
int json_add_id_to_array(cJSON* json, const char* name, const char * id)
{
cJSON* jtmp;
cJSON* tid;
jtmp = cJSON_GetObjectItem(json, name);
if (jtmp) {
if (cJSON_IsArray(jtmp) == true) {
tid = cJSON_CreateString(id);
cJSON_AddItemToArray(jtmp, tid);
}
else {
return MOSQ_ERR_INVAL;
}
}
else {
return MOSQ_ERR_INVAL;
}
return MOSQ_ERR_SUCCESS;
}
int json_del_id_from_array(cJSON* json, const char* name, const char* id)
{
cJSON* jtmp = NULL;
cJSON* tid = NULL;
cJSON* detached_item = NULL;
int array_index = 0;
jtmp = cJSON_GetObjectItem(json, name);
if (jtmp) {
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 1");
if (cJSON_IsArray(jtmp) == true) {
// cJSON_DeleteItemFromObject(json, name);
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 2");
cJSON_ArrayForEach(tid, jtmp)
{
if ( strcmp( cJSON_GetStringValue(tid),id) == 0)
{
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 3");
detached_item = cJSON_DetachItemFromArray(jtmp, array_index);
}
else
{
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: deleting item from array .. debug 4");
}
array_index++;
}
// cJSON_ReplaceItemInObject(json, name, jtmp);
// cJSON_AddItemToObject(json, id, jtmp);
}
else {
return MOSQ_ERR_INVAL;
}
}
else {
return MOSQ_ERR_INVAL;
}
return MOSQ_ERR_SUCCESS;
}
int json_get_bool(cJSON *json, const char *name, bool *value, bool optional, bool default_value)
{
cJSON *jtmp;
if(optional == true){
*value = default_value;
}
jtmp = cJSON_GetObjectItem(json, name);
if(jtmp){
if(cJSON_IsBool(jtmp) == false){
return MOSQ_ERR_INVAL;
}
*value = cJSON_IsTrue(jtmp);
}else{
if(optional == false){
return MOSQ_ERR_INVAL;
}
}
return MOSQ_ERR_SUCCESS;
}
int json_get_int(cJSON *json, const char *name, int *value, bool optional, int default_value)
{
cJSON *jtmp;
if(optional == true){
*value = default_value;
}
jtmp = cJSON_GetObjectItem(json, name);
if(jtmp){
if(cJSON_IsNumber(jtmp) == false){
return MOSQ_ERR_INVAL;
}
*value = jtmp->valueint;
}else{
if(optional == false){
return MOSQ_ERR_INVAL;
}
}
return MOSQ_ERR_SUCCESS;
}
int json_get_string(cJSON *json, const char *name, char **value, bool optional)
{
cJSON *jtmp;
*value = NULL;
jtmp = cJSON_GetObjectItem(json, name);
if(jtmp){
if(cJSON_IsString(jtmp) == false){
return MOSQ_ERR_INVAL;
}
*value = jtmp->valuestring;
}else{
if(optional == false){
return MOSQ_ERR_INVAL;
}
}
return MOSQ_ERR_SUCCESS;
}
cJSON *cJSON_AddIntToObject(cJSON * const object, const char * const name, int number)
{
char buf[30];
snprintf(buf, sizeof(buf), "%d", number);
return cJSON_AddRawToObject(object, name, buf);
}

23
plugins/wamo/json_help.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef JSON_HELP_H
#define JSON_HELP_H
/*
Contributors:
Dominik Kuhn Light - initial implementation and documentation.
*/
#include <cjson/cJSON.h>
#include <stdbool.h>
int json_create_array(cJSON* json, const char* name);
int json_add_id_to_array(cJSON* json, const char* name, const char* id);
int json_del_id_from_array(cJSON* json, const char* name, const char* id);
/* "optional==false" can also be taken to mean "only return success if the key exists and is valid" */
int json_get_bool(cJSON *json, const char *name, bool *value, bool optional, bool default_value);
int json_get_int(cJSON *json, const char *name, int *value, bool optional, int default_value);
int json_get_string(cJSON *json, const char *name, char **value, bool optional);
cJSON *cJSON_AddIntToObject(cJSON * const object, const char * const name, int number);
cJSON *cJSON_CreateInt(int num);
#endif

167
plugins/wamo/wamo.c Normal file
View File

@ -0,0 +1,167 @@
/*
Copyright (c) 2020 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 BSD-3-Clause
Contributors:
Roger Light - initial implementation and documentation.
*/
/*
* This is an *example* plugin which demonstrates how to modify the payload of
* a message after it is received by the broker and before it is sent on to
* other clients.
*
* You should be very sure of what you are doing before making use of this feature.
*
* Compile with:
* gcc -I<path to mosquitto-repo/include> -fPIC -shared mosquitto_payload_modification.c -o mosquitto_payload_modification.so
*
* Use in config with:
*
* plugin /path/to/mosquitto_payload_modification.so
*
* Note that this only works on Mosquitto 2.0 or later.
*/
#include <stdio.h>
#include <string.h>
#include "mosquitto_broker.h"
#include "mosquitto_plugin.h"
#include "mosquitto.h"
#include "mqtt_protocol.h"
#include "json_help.h"
#define UNUSED(A) (void)(A)
static mosquitto_plugin_id_t* mosq_pid = NULL;
static cJSON* subscribedTopics = NULL;
static int callback_control(int event, void* event_data, void* userdata)
{
struct mosquitto_evt_acl_check* ed = event_data;
UNUSED(event);
UNUSED(userdata);
const char * client_id = mosquitto_client_id(ed->client);
const char* topic = ed->topic;
const int access = ed->access;
if (access == MOSQ_ACL_SUBSCRIBE) {
json_create_array(subscribedTopics, topic);
json_add_id_to_array(subscribedTopics, topic, client_id);
char* json_string = cJSON_Print(subscribedTopics);
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with id %s subscribed to topic %s", client_id, topic);
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string);
}
else if (access == MOSQ_ACL_UNSUBSCRIBE) {
json_del_id_from_array(subscribedTopics, topic, client_id);
char* json_string = cJSON_Print(subscribedTopics);
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: client with id %s unscribed to topic %s", client_id, topic);
mosquitto_log_printf(MOSQ_LOG_INFO, "wamo: subscribed topics %s", json_string);
}
return MOSQ_ERR_SUCCESS;
}
static int callback_message(int event, void* event_data, void* userdata)
{
struct mosquitto_evt_message* ed = event_data;
char* new_payload;
uint32_t new_payloadlen;
UNUSED(event);
UNUSED(userdata);
/* This simply adds "hello " to the front of every payload. You can of
* course do much more complicated message processing if needed. */
/* Calculate the length of our new payload */
new_payloadlen = ed->payloadlen + (uint32_t)strlen("hello ") + 1;
/* Allocate some memory - use
* mosquitto_calloc/mosquitto_malloc/mosquitto_strdup when allocating, to
* allow the broker to track memory usage */
new_payload = mosquitto_calloc(1, new_payloadlen);
if (new_payload == NULL) {
return MOSQ_ERR_NOMEM;
}
/* Print "hello " to the payload */
snprintf(new_payload, new_payloadlen, "hello ");
memcpy(new_payload + (uint32_t)strlen("hello "), ed->payload, ed->payloadlen);
/* Assign the new payload and payloadlen to the event data structure. You
* must *not* free the original payload, it will be handled by the
* broker. */
ed->payload = new_payload;
ed->payloadlen = new_payloadlen;
return MOSQ_ERR_SUCCESS;
}
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;
}
int mosquitto_plugin_init(mosquitto_plugin_id_t* identifier, void** user_data, struct mosquitto_opt* opts, int opt_count)
{
int rc;
UNUSED(user_data);
mosq_pid = identifier;
subscribedTopics = cJSON_CreateObject();
rc = mosquitto_callback_register(mosq_pid, MOSQ_EVT_ACL_CHECK, callback_control, NULL, NULL);
if (rc == MOSQ_ERR_ALREADY_EXISTS) {
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: WaMo 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.");
return rc;
}
else if (rc == MOSQ_ERR_NOMEM) {
mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory.");
return rc;
}
else if (rc != MOSQ_ERR_SUCCESS) {
return rc;
}
return MOSQ_ERR_SUCCESS;
}
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_ACL_CHECK, callback_control, NULL);
}

View File

@ -19,7 +19,13 @@ follow the steps on [Eclipse Security] page to report it.
Listed with most recent first. Further information on security related issues
can be found in the [security category].
* June 2023: [CVE-2023-28366]: Clients sending unacknowledged QoS 2 messages
* August 2023: [CVE-2023-0809]: Fix excessive memory being allocated based on
malicious initial packets that are not CONNECT packets. Affecting versions
**1.5.0** to **2.0.15**. Fixed in **2.0.16**.
* August 2023: [CVE-2023-3592]: Fix memory leak when clients send v5 CONNECT
packets with a will message that contains invalid property types. Affecting
version **1.6.0** to **2.0.15** Fixed in **2.0.16**.
* August 2023: [CVE-2023-28366]: Clients sending unacknowledged QoS 2 messages
with duplicate message ids cause a memory leak. Affecting versions **1.3.2**
to **2.0.15** inclusive, fixed in **2.0.16**.
* August 2022: Deleting the anonymous group in the dynamic security plugin