From 43c271504277941a4423a7e8c6b07bbcb611080b Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Fri, 13 Feb 2026 12:18:47 +0000 Subject: [PATCH] Fix password length not being passed to MOSQ_EVT_BASIC_AUTH events. Closes #3490. Thanks to thehouseisonfire. --- ChangeLog.txt | 2 ++ include/mosquitto/broker.h | 7 ++++++- lib/mosquitto_internal.h | 1 + src/handle_connect.c | 16 +++++++++------- src/plugin_basic_auth.c | 1 + test/broker/09-plugin-auth-unpwd-fail.py | 11 ++++++++++- test/broker/09-plugin-auth-unpwd-success.py | 7 ++++++- test/broker/c/auth_plugin_v5.c | 17 ++++++++++++++++- 8 files changed, 51 insertions(+), 11 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 0e229e98f..941f80c3c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -4,6 +4,8 @@ # Broker - Fix MOSQ_EVT_DISCONNECT being called before MOSQ_EVT_ACL_CHECK for the will of that client. Closes #3487. +- Fix password length not being passed to MOSQ_EVT_BASIC_AUTH events. + Closes #3490. # Common lib: - Fix potential crash if reading a file in restricted mode and the group id diff --git a/include/mosquitto/broker.h b/include/mosquitto/broker.h index 9a4cd1f19..00be4b5e7 100644 --- a/include/mosquitto/broker.h +++ b/include/mosquitto/broker.h @@ -198,7 +198,12 @@ struct mosquitto_evt_basic_auth { struct mosquitto *client; char *username; char *password; - void *future2[4]; + union{ + void *future2[4]; + struct { + uint16_t password_len; + }; + }; }; /* Data for the MOSQ_EVT_PSK_KEY event */ diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index 0dd27b315..933238915 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -322,6 +322,7 @@ struct mosquitto { unsigned id_hashv; uint16_t keepalive; uint16_t last_mid; + uint16_t password_len; enum mosquitto_client_state state; uint8_t transport; time_t last_msg_in; diff --git a/src/handle_connect.c b/src/handle_connect.c index 47bb12c0b..9a5b9f141 100644 --- a/src/handle_connect.c +++ b/src/handle_connect.c @@ -776,11 +776,11 @@ static int set_username_from_packet(struct mosquitto *context, char **username, } -static int set_password_from_packet(struct mosquitto *context, char **password, const char *clientid) +static int set_password_from_packet(struct mosquitto *context, char **password, uint16_t *password_len, const char *clientid) { int rc; - rc = packet__read_binary(&context->in_packet, (uint8_t **)password, &(uint16_t){0}); + rc = packet__read_binary(&context->in_packet, (uint8_t **)password, password_len); if(rc == MOSQ_ERR_NOMEM){ return MOSQ_ERR_NOMEM; } @@ -801,7 +801,7 @@ static int set_password_from_packet(struct mosquitto *context, char **password, static int read_and_verify_client_credentials_from_packet(struct mosquitto *context, char **username, uint8_t username_flag, - char **password, uint8_t password_flag, + char **password, uint16_t *password_len, uint8_t password_flag, const char *clientid) { int rc; @@ -821,7 +821,7 @@ static int read_and_verify_client_credentials_from_packet(struct mosquitto *cont } } if(password_flag){ - rc = set_password_from_packet(context, password, clientid); + rc = set_password_from_packet(context, password, password_len, clientid); if(rc != MOSQ_ERR_SUCCESS){ return rc; } @@ -971,7 +971,7 @@ static int set_username_from_cert_subject_name(struct mosquitto *context) #endif -static int handle_username_from_cert_options(struct mosquitto *context, char **username, char **password) +static int handle_username_from_cert_options(struct mosquitto *context, char **username, char **password, uint16_t password_len) { int rc; @@ -1020,6 +1020,7 @@ static int handle_username_from_cert_options(struct mosquitto *context, char **u * mosquitto_client_username() functions work, but is hacky */ context->username = *username; context->password = *password; + context->password_len = password_len; *username = NULL; /* Avoid free() in error: below. */ *password = NULL; } @@ -1059,6 +1060,7 @@ int handle__connect(struct mosquitto *context) uint8_t will, will_retain, will_qos, clean_start; uint8_t username_flag, password_flag; char *username = NULL, *password = NULL; + uint16_t password_len = 0; int rc; mosquitto_property *properties = NULL; void *auth_data = NULL; @@ -1176,7 +1178,7 @@ int handle__connect(struct mosquitto *context) // Client credentials password_flag = connect_flags & 0x40; username_flag = connect_flags & 0x80; - rc = read_and_verify_client_credentials_from_packet(context, &username, username_flag, &password, password_flag, clientid); + rc = read_and_verify_client_credentials_from_packet(context, &username, username_flag, &password, &password_len, password_flag, clientid); if(rc != MOSQ_ERR_SUCCESS){ goto handle_connect_error; } @@ -1193,7 +1195,7 @@ int handle__connect(struct mosquitto *context) clientid = NULL; /* use_identity_as_username or use_subject_as_username */ - rc = handle_username_from_cert_options(context, &username, &password); + rc = handle_username_from_cert_options(context, &username, &password, password_len); if(rc != MOSQ_ERR_SUCCESS){ goto handle_connect_error; } diff --git a/src/plugin_basic_auth.c b/src/plugin_basic_auth.c index dfc0a57dd..49d4f5084 100644 --- a/src/plugin_basic_auth.c +++ b/src/plugin_basic_auth.c @@ -40,6 +40,7 @@ static int plugin__basic_auth(struct mosquitto__security_options *opts, struct m event_data.client = context; event_data.username = context->username; event_data.password = context->password; + event_data.password_len = context->password_len; rc = cb_base->cb(MOSQ_EVT_BASIC_AUTH, &event_data, cb_base->userdata); if(rc == MOSQ_ERR_PLUGIN_IGNORE){ /* Do nothing, this is as if the plugin doesn't exist */ diff --git a/test/broker/09-plugin-auth-unpwd-fail.py b/test/broker/09-plugin-auth-unpwd-fail.py index bdbf8b546..14520aa57 100755 --- a/test/broker/09-plugin-auth-unpwd-fail.py +++ b/test/broker/09-plugin-auth-unpwd-fail.py @@ -20,13 +20,22 @@ def do_test(plugin_ver): connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", username="test-username", password="wrong") connack_packet = mosq_test.gen_connack(rc=5) + connect_packet_binary_pw1 = mosq_test.gen_connect("connect-uname-pwd-test", username="binary-password", password="\x00\x01\x02\x03\x04\x05\x06\x08") + connect_packet_binary_pw2 = mosq_test.gen_connect("connect-uname-pwd-test", username="binary-password", password="\x00\x01\x02\x03\x04\x05\x06") + broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port) try: sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20, port=port) + sock.close() + + if plugin_ver == 5: + sock = mosq_test.do_client_connect(connect_packet_binary_pw1, connack_packet, port=port) + sock.close() + sock = mosq_test.do_client_connect(connect_packet_binary_pw2, connack_packet, port=port) + sock.close() rc = 0 - sock.close() except mosq_test.TestError: pass finally: diff --git a/test/broker/09-plugin-auth-unpwd-success.py b/test/broker/09-plugin-auth-unpwd-success.py index 1eaf4e5f9..91c7b80c7 100755 --- a/test/broker/09-plugin-auth-unpwd-success.py +++ b/test/broker/09-plugin-auth-unpwd-success.py @@ -20,12 +20,17 @@ def do_test(plugin_ver): connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", username="test-username", password="cnwTICONIURW") connack_packet = mosq_test.gen_connack(rc=0) + connect_packet_binary_pw = mosq_test.gen_connect("connect-uname-pwd-test", username="binary-password", password="\x00\x01\x02\x03\x04\x05\x06\x07") + broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port) try: sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20, port=port) - rc = 0 sock.close() + if plugin_ver == 5: + sock = mosq_test.do_client_connect(connect_packet_binary_pw, connack_packet, port=port) + sock.close() + rc = 0 except mosq_test.TestError: pass finally: diff --git a/test/broker/c/auth_plugin_v5.c b/test/broker/c/auth_plugin_v5.c index 4fbb622cc..0f72a0dae 100644 --- a/test/broker/c/auth_plugin_v5.c +++ b/test/broker/c/auth_plugin_v5.c @@ -82,6 +82,7 @@ int mosquitto_auth_acl_check_v5(int event, void *event_data, void *user_data) int mosquitto_auth_unpwd_check_v5(int event, void *event_data, void *user_data) { struct mosquitto_evt_basic_auth *ed = event_data; + const char binary_pw[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; (void)user_data; @@ -89,7 +90,21 @@ int mosquitto_auth_unpwd_check_v5(int event, void *event_data, void *user_data) abort(); } - if(ed->username && !strcmp(ed->username, "test-username") && ed->password && !strcmp(ed->password, "cnwTICONIURW")){ + if(ed->username + && !strcmp(ed->username, "test-username") + && ed->password + && !strcmp(ed->password, "cnwTICONIURW") + && strlen("cnwTICONIURW") == ed->password_len + ){ + + return MOSQ_ERR_SUCCESS; + }else if(ed->username + && !strcmp(ed->username, "binary-password") + && ed->password + && ed->password_len == sizeof(binary_pw) + && !memcmp(ed->password, binary_pw, ed->password_len) + ){ + return MOSQ_ERR_SUCCESS; }else if(ed->username && (!strcmp(ed->username, "readonly") || !strcmp(ed->username, "readwrite"))){ return MOSQ_ERR_SUCCESS;