Fix possible crash when using pattern ACLs.

Crash may occur for ACLs that do not include a %u and clients that
connect without a username.

Thanks to Karl Palsson.
This commit is contained in:
Roger Light 2014-05-08 23:03:15 +01:00
parent 9ff56eefd0
commit ab15557931
3 changed files with 36 additions and 25 deletions

View File

@ -3,6 +3,10 @@
Broker: Broker:
- Ensure that bridges verify certificates by default when using TLS. - Ensure that bridges verify certificates by default when using TLS.
- Fix possible crash when using pattern ACLs that do not include a %u and
clients that connect without a username.
Client library: Client library:
- Fix topic matching edge case. - Fix topic matching edge case.

View File

@ -164,6 +164,8 @@ struct _mosquitto_acl{
struct _mosquitto_acl *next; struct _mosquitto_acl *next;
char *topic; char *topic;
int access; int access;
int ucount;
int ccount;
}; };
struct _mosquitto_acl_user{ struct _mosquitto_acl_user{

View File

@ -165,6 +165,7 @@ int _add_acl_pattern(struct mosquitto_db *db, const char *topic, int access)
{ {
struct _mosquitto_acl *acl, *acl_tail; struct _mosquitto_acl *acl, *acl_tail;
char *local_topic; char *local_topic;
char *s;
if(!db || !topic) return MOSQ_ERR_INVAL; if(!db || !topic) return MOSQ_ERR_INVAL;
@ -179,6 +180,26 @@ int _add_acl_pattern(struct mosquitto_db *db, const char *topic, int access)
acl->topic = local_topic; acl->topic = local_topic;
acl->next = NULL; acl->next = NULL;
acl->ccount = 0;
s = local_topic;
while(s){
s = strstr(s, "%c");
if(s){
acl->ccount++;
s+=2;
}
}
acl->ccount = 0;
s = local_topic;
while(s){
s = strstr(s, "%u");
if(s){
acl->ucount++;
s+=2;
}
}
if(db->acl_patterns){ if(db->acl_patterns){
acl_tail = db->acl_patterns; acl_tail = db->acl_patterns;
while(acl_tail->next){ while(acl_tail->next){
@ -199,7 +220,6 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
bool result; bool result;
int i; int i;
int len, tlen, clen, ulen; int len, tlen, clen, ulen;
int ccount, ucount;
char *s; char *s;
if(!db || !context || !topic) return MOSQ_ERR_INVAL; if(!db || !context || !topic) return MOSQ_ERR_INVAL;
@ -238,32 +258,17 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
while(acl_root){ while(acl_root){
tlen = strlen(acl_root->topic); tlen = strlen(acl_root->topic);
ccount = 0; if(acl_root->ucount && !context->username){
s = acl_root->topic;
while(s){
s = strstr(s, "%c");
if(s){
ccount++;
s+=2;
}
}
ucount = 0;
s = acl_root->topic;
while(s){
s = strstr(s, "%u");
if(s){
ucount++;
s+=2;
}
}
if(ucount && !context->username){
continue; continue;
} }
ulen = strlen(context->username); if(context->username){
len = tlen + ccount*(clen-2) + ucount*(ulen-2); ulen = strlen(context->username);
len = tlen + acl_root->ccount*(clen-2) + acl_root->ucount*(ulen-2);
}else{
ulen = 0;
len = tlen + acl_root->ccount*(clen-2);
}
local_acl = malloc(len+1); local_acl = malloc(len+1);
if(!local_acl) return 1; // FIXME if(!local_acl) return 1; // FIXME
s = local_acl; s = local_acl;
@ -274,7 +279,7 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
strncpy(s, context->id, clen); strncpy(s, context->id, clen);
s+=clen; s+=clen;
continue; continue;
}else if(acl_root->topic[i+1] == 'u'){ }else if(context->username && acl_root->topic[i+1] == 'u'){
i++; i++;
strncpy(s, context->username, ulen); strncpy(s, context->username, ulen);
s+=ulen; s+=ulen;