Fix password length not being passed to MOSQ_EVT_BASIC_AUTH events.

Closes #3490. Thanks to thehouseisonfire.
This commit is contained in:
Roger A. Light 2026-02-13 12:18:47 +00:00 committed by Roger Light
parent 33d14397c4
commit 43c2715042
8 changed files with 51 additions and 11 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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;
}

View file

@ -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 */

View file

@ -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:

View file

@ -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:

View file

@ -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;