feat(mosq): Add support for basic MQTT authentication

This commit is contained in:
David Cermak
2025-11-10 08:35:54 +01:00
parent 318bca1657
commit 65b58aa05a
5 changed files with 63 additions and 1 deletions

View File

@@ -90,6 +90,10 @@ if (CONFIG_MOSQ_ENABLE_SYS)
endif() endif()
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
# Enable linker wrapping for mosquitto_unpwd_check to allow connection callback interception
# without modifying upstream code
target_link_options(${COMPONENT_LIB} PRIVATE "-Wl,--wrap=mosquitto_unpwd_check")
# Some mosquitto source unconditionally define `_GNU_SOURCE` which collides with IDF build system # Some mosquitto source unconditionally define `_GNU_SOURCE` which collides with IDF build system
# producing warning: "_GNU_SOURCE" redefined # producing warning: "_GNU_SOURCE" redefined
# This workarounds this issue by undefining the macro for the selected files # This workarounds this issue by undefining the macro for the selected files

View File

@@ -15,6 +15,7 @@
| Type | Name | | Type | Name |
| ---: | :--- | | ---: | :--- |
| struct | [**mosq\_broker\_config**](#struct-mosq_broker_config) <br>_Mosquitto configuration structure._ | | struct | [**mosq\_broker\_config**](#struct-mosq_broker_config) <br>_Mosquitto configuration structure._ |
| typedef int(\* | [**mosq\_connect\_cb\_t**](#typedef-mosq_connect_cb_t) <br> |
| typedef void(\* | [**mosq\_message\_cb\_t**](#typedef-mosq_message_cb_t) <br> | | typedef void(\* | [**mosq\_message\_cb\_t**](#typedef-mosq_message_cb_t) <br> |
## Functions ## Functions
@@ -35,6 +36,8 @@ ESP port of mosquittto supports only the options in this configuration structure
Variables: Variables:
- mosq\_connect\_cb\_t handle_connect_cb <br>On connect callback. If configured, user function is called whenever a client attempts to connect. The callback receives client\_id, username, password, and password length. Return 0 to accept the connection, non-zero to reject it.
- void(\* handle_message_cb <br>On message callback. If configured, user function is called whenever mosquitto processes a message. - void(\* handle_message_cb <br>On message callback. If configured, user function is called whenever mosquitto processes a message.
- const char \* host <br>Address on which the broker is listening for connections - const char \* host <br>Address on which the broker is listening for connections
@@ -43,6 +46,12 @@ Variables:
- esp\_tls\_cfg\_server\_t \* tls_cfg <br>ESP-TLS configuration (if TLS transport used) Please refer to the ESP-TLS official documentation for more details on configuring the TLS options. You can open the respective docs with this idf.py command: `idf.py docs -sp api-reference/protocols/esp_tls.html` - esp\_tls\_cfg\_server\_t \* tls_cfg <br>ESP-TLS configuration (if TLS transport used) Please refer to the ESP-TLS official documentation for more details on configuring the TLS options. You can open the respective docs with this idf.py command: `idf.py docs -sp api-reference/protocols/esp_tls.html`
### typedef `mosq_connect_cb_t`
```c
typedef int(* mosq_connect_cb_t) (const char *client_id, const char *username, const char *password, int password_len);
```
### typedef `mosq_message_cb_t` ### typedef `mosq_message_cb_t`
```c ```c

View File

@@ -102,6 +102,7 @@ void mosq_broker_stop(void)
} }
extern mosq_message_cb_t g_mosq_message_callback; extern mosq_message_cb_t g_mosq_message_callback;
extern mosq_connect_cb_t g_mosq_connect_callback;
int mosq_broker_run(struct mosq_broker_config *broker_config) int mosq_broker_run(struct mosq_broker_config *broker_config)
{ {
@@ -130,6 +131,9 @@ int mosq_broker_run(struct mosq_broker_config *broker_config)
if (broker_config->handle_message_cb) { if (broker_config->handle_message_cb) {
g_mosq_message_callback = broker_config->handle_message_cb; g_mosq_message_callback = broker_config->handle_message_cb;
} }
if (broker_config->handle_connect_cb) {
g_mosq_connect_callback = broker_config->handle_connect_cb;
}
db.config = &config; db.config = &config;

View File

@@ -3,8 +3,9 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
*/ */
#include <string.h>
#include "mosquitto_internal.h" #include "mosquitto_internal.h"
#include "mosquitto_broker.h" #include "mosquitto_broker.h"
#include "memory_mosq.h" #include "memory_mosq.h"
@@ -16,6 +17,7 @@
#include "mosq_broker.h" #include "mosq_broker.h"
mosq_message_cb_t g_mosq_message_callback = NULL; mosq_message_cb_t g_mosq_message_callback = NULL;
mosq_connect_cb_t g_mosq_connect_callback = NULL;
int mosquitto_callback_register( int mosquitto_callback_register(
mosquitto_plugin_id_t *identifier, mosquitto_plugin_id_t *identifier,
@@ -51,3 +53,39 @@ int plugin__handle_message(struct mosquitto *context, struct mosquitto_msg_store
} }
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
int __real_mosquitto_unpwd_check(struct mosquitto *context);
/* Wrapper function to intercept mosquitto_unpwd_check calls via linker wrapping */
int __wrap_mosquitto_unpwd_check(struct mosquitto *context)
{
int rc;
int password_len = 0;
/* Call user's connect callback if set */
if (g_mosq_connect_callback) {
/* Extract password length if password is present.
* Note: MQTT passwords are binary data, but mosquitto stores them as null-terminated strings.
* If password contains null bytes, strlen() will not return the full length.
* This matches how mosquitto itself handles passwords in some security functions. */
if (context->password) {
password_len = (int)strlen(context->password);
}
/* Call user callback */
rc = g_mosq_connect_callback(
context->id ? context->id : "",
context->username ? context->username : NULL,
context->password ? context->password : NULL,
password_len
);
/* If callback rejects (returns non-zero), return AUTH error immediately */
if (rc != 0) {
return MOSQ_ERR_AUTH;
}
}
/* Call the original function */
return __real_mosquitto_unpwd_check(context);
}

View File

@@ -14,6 +14,8 @@ extern "C" {
struct mosquitto__config; struct mosquitto__config;
typedef void (*mosq_message_cb_t)(char *client, char *topic, char *data, int len, int qos, int retain); typedef void (*mosq_message_cb_t)(char *client, char *topic, char *data, int len, int qos, int retain);
typedef int (*mosq_connect_cb_t)(const char *client_id, const char *username, const char *password, int password_len);
/** /**
* @brief Mosquitto configuration structure * @brief Mosquitto configuration structure
* *
@@ -33,6 +35,11 @@ struct mosq_broker_config {
* On message callback. If configured, user function is called * On message callback. If configured, user function is called
* whenever mosquitto processes a message. * whenever mosquitto processes a message.
*/ */
mosq_connect_cb_t handle_connect_cb; /*!< On connect callback. If configured, user function is called
* whenever a client attempts to connect. The callback receives
* client_id, username, password, and password length. Return 0 to
* accept the connection, non-zero to reject it.
*/
}; };
/** /**