Skip to content

Commit a5dd99f

Browse files
committed
Fenrir broker fixes
1 parent 392a4e5 commit a5dd99f

2 files changed

Lines changed: 77 additions & 10 deletions

File tree

src/mqtt_broker.c

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@
3535

3636
#ifdef WOLFMQTT_BROKER
3737

38+
/* Secure memory zeroing - prevents compiler dead-store elimination */
39+
#ifdef ENABLE_MQTT_TLS
40+
#include <wolfssl/wolfcrypt/memory.h>
41+
#define BROKER_FORCE_ZERO(mem, len) wc_ForceZero(mem, (word32)(len))
42+
#else
43+
/* Local implementation matching wolfCrypt's ForceZero */
44+
static void BrokerForceZero(void* mem, word32 len)
45+
{
46+
volatile byte* p = (volatile byte*)mem;
47+
word32 i;
48+
for (i = 0; i < len; i++) {
49+
p[i] = 0;
50+
}
51+
}
52+
#define BROKER_FORCE_ZERO(mem, len) BrokerForceZero(mem, (word32)(len))
53+
#endif
54+
3855
/* -------------------------------------------------------------------------- */
3956
/* Platform includes */
4057
/* -------------------------------------------------------------------------- */
@@ -137,10 +154,14 @@ static int BrokerStrCompare(const char* a, const char* b)
137154
int result = 0;
138155
int len_a = (int)XSTRLEN(a);
139156
int len_b = (int)XSTRLEN(b);
140-
int len = (len_a < len_b) ? len_a : len_b;
157+
int max_len = (len_a > len_b) ? len_a : len_b;
141158
int i;
142-
for (i = 0; i < len; i++) {
143-
result |= (a[i] ^ b[i]);
159+
for (i = 0; i < max_len; i++) {
160+
/* Branchless index clamp: when i >= len, reads position 0.
161+
* Length mismatch is caught by the final XOR below. */
162+
int ia = i & ((i - len_a) >> (sizeof(int) * 8 - 1));
163+
int ib = i & ((i - len_b) >> (sizeof(int) * 8 - 1));
164+
result |= (a[ia] ^ b[ib]);
144165
}
145166
result |= (len_a ^ len_b);
146167
return result;
@@ -164,7 +185,7 @@ static void BrokerStore_StringSensitive(char* dst, int max_len,
164185
const char* src, word16 src_len)
165186
{
166187
/* Wipe old value before overwriting */
167-
XMEMSET(dst, 0, max_len);
188+
BROKER_FORCE_ZERO(dst, max_len);
168189
if (src_len >= (word16)max_len) {
169190
src_len = (word16)(max_len - 1);
170191
}
@@ -177,7 +198,7 @@ static void BrokerStore_String(char** dst_ptr,
177198
{
178199
if (*dst_ptr != NULL) {
179200
if (sensitive) {
180-
XMEMSET(*dst_ptr, 0, XSTRLEN(*dst_ptr) + 1);
201+
BROKER_FORCE_ZERO(*dst_ptr, XSTRLEN(*dst_ptr) + 1);
181202
}
182203
WOLFMQTT_FREE(*dst_ptr);
183204
*dst_ptr = NULL;
@@ -225,6 +246,9 @@ static int BrokerTls_Init(MqttBroker* broker)
225246
}
226247
else {
227248
ctx = wolfSSL_CTX_new(wolfSSLv23_server_method());
249+
if (ctx != NULL) {
250+
wolfSSL_CTX_SetMinVersion(ctx, WOLFSSL_TLSV1_2);
251+
}
228252
}
229253
if (ctx == NULL) {
230254
WBLOG_ERR(broker, "broker: wolfSSL_CTX_new failed");
@@ -1203,21 +1227,21 @@ static void BrokerClient_Free(BrokerClient* bc)
12031227
}
12041228
#ifdef WOLFMQTT_BROKER_AUTH
12051229
if (bc->username) {
1206-
XMEMSET(bc->username, 0, XSTRLEN(bc->username) + 1);
1230+
BROKER_FORCE_ZERO(bc->username, XSTRLEN(bc->username) + 1);
12071231
WOLFMQTT_FREE(bc->username);
12081232
}
12091233
if (bc->password) {
1210-
XMEMSET(bc->password, 0, XSTRLEN(bc->password) + 1);
1234+
BROKER_FORCE_ZERO(bc->password, XSTRLEN(bc->password) + 1);
12111235
WOLFMQTT_FREE(bc->password);
12121236
}
12131237
#endif
12141238
#ifdef WOLFMQTT_BROKER_WILL
12151239
if (bc->will_topic) {
1216-
XMEMSET(bc->will_topic, 0, XSTRLEN(bc->will_topic) + 1);
1240+
BROKER_FORCE_ZERO(bc->will_topic, XSTRLEN(bc->will_topic) + 1);
12171241
WOLFMQTT_FREE(bc->will_topic);
12181242
}
12191243
if (bc->will_payload) {
1220-
XMEMSET(bc->will_payload, 0, bc->will_payload_len);
1244+
BROKER_FORCE_ZERO(bc->will_payload, bc->will_payload_len);
12211245
WOLFMQTT_FREE(bc->will_payload);
12221246
}
12231247
#endif
@@ -2468,6 +2492,11 @@ static int BrokerTopicMatch(const char* filter, const char* topic)
24682492
return 0;
24692493
}
24702494

2495+
/* [MQTT-4.7.2] Wildcard filters must not match $-prefixed topics */
2496+
if (*t == '$' && (*f == '+' || *f == '#')) {
2497+
return 0;
2498+
}
2499+
24712500
while (*f && *t) {
24722501
if (*f == '#') {
24732502
return (f[1] == '\0');
@@ -3063,6 +3092,19 @@ static int BrokerHandle_Publish(BrokerClient* bc, int rx_len,
30633092
return rc;
30643093
}
30653094

3095+
/* [MQTT-3.3.2-2] PUBLISH topic must not contain wildcard characters */
3096+
if (pub.topic_name && pub.topic_name_len > 0) {
3097+
word16 i;
3098+
for (i = 0; i < pub.topic_name_len; i++) {
3099+
if (pub.topic_name[i] == '+' || pub.topic_name[i] == '#') {
3100+
WBLOG_ERR(broker,
3101+
"broker: PUBLISH topic contains wildcard sock=%d",
3102+
(int)bc->sock);
3103+
return MQTT_CODE_ERROR_BAD_ARG;
3104+
}
3105+
}
3106+
}
3107+
30663108
/* Create null-terminated topic copy for matching/logging */
30673109
if (pub.topic_name && pub.topic_name_len > 0) {
30683110
#ifdef WOLFMQTT_STATIC_MEMORY
@@ -3363,6 +3405,15 @@ static int BrokerClient_Process(MqttBroker* broker, BrokerClient* bc)
33633405
BrokerClient_Remove(broker, bc);
33643406
return 0;
33653407
}
3408+
/* [MQTT-3.1.0-2] Second CONNECT is a protocol violation */
3409+
if (type == MQTT_PACKET_TYPE_CONNECT && bc->connected) {
3410+
WBLOG_ERR(broker,
3411+
"broker: second CONNECT on sock=%d [MQTT-3.1.0-2]",
3412+
(int)bc->sock);
3413+
BrokerSubs_RemoveClient(broker, bc);
3414+
BrokerClient_Remove(broker, bc);
3415+
return 0;
3416+
}
33663417
switch (type) {
33673418
case MQTT_PACKET_TYPE_CONNECT:
33683419
{

src/mqtt_packet.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,9 @@ int MqttDecode_String(byte *buf, const char **pstr, word16 *pstr_len, word32 buf
338338
if (len < 0) {
339339
return len;
340340
}
341+
if ((word32)str_len > buf_len - (word32)len) {
342+
return MQTT_TRACE_ERROR(MQTT_CODE_ERROR_OUT_OF_BUFFER);
343+
}
341344
buf += len;
342345
if (pstr_len) {
343346
*pstr_len = str_len;
@@ -353,7 +356,13 @@ int MqttDecode_String(byte *buf, const char **pstr, word16 *pstr_len, word32 buf
353356
int MqttEncode_String(byte *buf, const char *str)
354357
{
355358
int str_len = (int)XSTRLEN(str);
356-
int len = MqttEncode_Num(buf, (word16)str_len);
359+
int len;
360+
361+
/* MQTT UTF-8 strings are limited to 65535 bytes [MQTT-1.5.3] */
362+
if (str_len > (int)0xFFFF) {
363+
return MQTT_TRACE_ERROR(MQTT_CODE_ERROR_BAD_ARG);
364+
}
365+
len = MqttEncode_Num(buf, (word16)str_len);
357366

358367
if (buf != NULL) {
359368
buf += len;
@@ -790,6 +799,10 @@ int MqttEncode_Connect(byte *tx_buf, int tx_buf_len, MqttConnect *mc_connect)
790799

791800
remain_len += (int)XSTRLEN(mc_connect->lwt_msg->topic_name);
792801
remain_len += MQTT_DATA_LEN_SIZE;
802+
/* LWT payload uses word16 length prefix, validate it fits */
803+
if (mc_connect->lwt_msg->total_len > (word32)0xFFFF) {
804+
return MQTT_TRACE_ERROR(MQTT_CODE_ERROR_BAD_ARG);
805+
}
793806
remain_len += mc_connect->lwt_msg->total_len;
794807
remain_len += MQTT_DATA_LEN_SIZE;
795808
#ifdef WOLFMQTT_V5
@@ -1466,6 +1479,9 @@ int MqttDecode_Publish(byte *rx_buf, int rx_buf_len, MqttPublish *publish)
14661479
#endif
14671480

14681481
/* Decode Payload */
1482+
if (variable_len > remain_len) {
1483+
return MQTT_TRACE_ERROR(MQTT_CODE_ERROR_OUT_OF_BUFFER);
1484+
}
14691485
payload_len = remain_len - variable_len;
14701486
publish->buffer = rx_payload;
14711487
publish->buffer_new = 1;

0 commit comments

Comments
 (0)