Skip to content

Commit 65b58aa

Browse files
committed
feat(mosq): Add support for basic MQTT authentication
1 parent 318bca1 commit 65b58aa

File tree

5 files changed

+63
-1
lines changed

5 files changed

+63
-1
lines changed

components/mosquitto/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ if (CONFIG_MOSQ_ENABLE_SYS)
9090
endif()
9191
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
9292

93+
# Enable linker wrapping for mosquitto_unpwd_check to allow connection callback interception
94+
# without modifying upstream code
95+
target_link_options(${COMPONENT_LIB} PRIVATE "-Wl,--wrap=mosquitto_unpwd_check")
96+
9397
# Some mosquitto source unconditionally define `_GNU_SOURCE` which collides with IDF build system
9498
# producing warning: "_GNU_SOURCE" redefined
9599
# This workarounds this issue by undefining the macro for the selected files

components/mosquitto/api.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| Type | Name |
1616
| ---: | :--- |
1717
| struct | [**mosq\_broker\_config**](#struct-mosq_broker_config) <br>_Mosquitto configuration structure._ |
18+
| typedef int(\* | [**mosq\_connect\_cb\_t**](#typedef-mosq_connect_cb_t) <br> |
1819
| typedef void(\* | [**mosq\_message\_cb\_t**](#typedef-mosq_message_cb_t) <br> |
1920

2021
## Functions
@@ -35,6 +36,8 @@ ESP port of mosquittto supports only the options in this configuration structure
3536

3637
Variables:
3738

39+
- 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.
40+
3841
- void(\* handle_message_cb <br>On message callback. If configured, user function is called whenever mosquitto processes a message.
3942

4043
- const char \* host <br>Address on which the broker is listening for connections
@@ -43,6 +46,12 @@ Variables:
4346

4447
- 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`
4548

49+
### typedef `mosq_connect_cb_t`
50+
51+
```c
52+
typedef int(* mosq_connect_cb_t) (const char *client_id, const char *username, const char *password, int password_len);
53+
```
54+
4655
### typedef `mosq_message_cb_t`
4756
4857
```c

components/mosquitto/port/broker.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ void mosq_broker_stop(void)
102102
}
103103

104104
extern mosq_message_cb_t g_mosq_message_callback;
105+
extern mosq_connect_cb_t g_mosq_connect_callback;
105106

106107
int mosq_broker_run(struct mosq_broker_config *broker_config)
107108
{
@@ -130,6 +131,9 @@ int mosq_broker_run(struct mosq_broker_config *broker_config)
130131
if (broker_config->handle_message_cb) {
131132
g_mosq_message_callback = broker_config->handle_message_cb;
132133
}
134+
if (broker_config->handle_connect_cb) {
135+
g_mosq_connect_callback = broker_config->handle_connect_cb;
136+
}
133137

134138
db.config = &config;
135139

components/mosquitto/port/callbacks.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
*
44
* SPDX-License-Identifier: EPL-2.0
55
*
6-
* SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD
6+
* SPDX-FileContributor: 2024-2025 Espressif Systems (Shanghai) CO LTD
77
*/
8+
#include <string.h>
89
#include "mosquitto_internal.h"
910
#include "mosquitto_broker.h"
1011
#include "memory_mosq.h"
@@ -16,6 +17,7 @@
1617
#include "mosq_broker.h"
1718

1819
mosq_message_cb_t g_mosq_message_callback = NULL;
20+
mosq_connect_cb_t g_mosq_connect_callback = NULL;
1921

2022
int mosquitto_callback_register(
2123
mosquitto_plugin_id_t *identifier,
@@ -51,3 +53,39 @@ int plugin__handle_message(struct mosquitto *context, struct mosquitto_msg_store
5153
}
5254
return MOSQ_ERR_SUCCESS;
5355
}
56+
57+
int __real_mosquitto_unpwd_check(struct mosquitto *context);
58+
59+
/* Wrapper function to intercept mosquitto_unpwd_check calls via linker wrapping */
60+
int __wrap_mosquitto_unpwd_check(struct mosquitto *context)
61+
{
62+
int rc;
63+
int password_len = 0;
64+
65+
/* Call user's connect callback if set */
66+
if (g_mosq_connect_callback) {
67+
/* Extract password length if password is present.
68+
* Note: MQTT passwords are binary data, but mosquitto stores them as null-terminated strings.
69+
* If password contains null bytes, strlen() will not return the full length.
70+
* This matches how mosquitto itself handles passwords in some security functions. */
71+
if (context->password) {
72+
password_len = (int)strlen(context->password);
73+
}
74+
75+
/* Call user callback */
76+
rc = g_mosq_connect_callback(
77+
context->id ? context->id : "",
78+
context->username ? context->username : NULL,
79+
context->password ? context->password : NULL,
80+
password_len
81+
);
82+
83+
/* If callback rejects (returns non-zero), return AUTH error immediately */
84+
if (rc != 0) {
85+
return MOSQ_ERR_AUTH;
86+
}
87+
}
88+
89+
/* Call the original function */
90+
return __real_mosquitto_unpwd_check(context);
91+
}

components/mosquitto/port/include/mosq_broker.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ extern "C" {
1414
struct mosquitto__config;
1515

1616
typedef void (*mosq_message_cb_t)(char *client, char *topic, char *data, int len, int qos, int retain);
17+
18+
typedef int (*mosq_connect_cb_t)(const char *client_id, const char *username, const char *password, int password_len);
1719
/**
1820
* @brief Mosquitto configuration structure
1921
*
@@ -33,6 +35,11 @@ struct mosq_broker_config {
3335
* On message callback. If configured, user function is called
3436
* whenever mosquitto processes a message.
3537
*/
38+
mosq_connect_cb_t handle_connect_cb; /*!< On connect callback. If configured, user function is called
39+
* whenever a client attempts to connect. The callback receives
40+
* client_id, username, password, and password length. Return 0 to
41+
* accept the connection, non-zero to reject it.
42+
*/
3643
};
3744

3845
/**

0 commit comments

Comments
 (0)