Skip to content

Commit

Permalink
Added support for controlling UNSUBSCRIBE calls in v5 plugin ACL checks.
Browse files Browse the repository at this point in the history
  • Loading branch information
ralight committed Oct 9, 2020
1 parent 6c6542a commit 4472c1f
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 17 deletions.
1 change: 1 addition & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Broker:
- Add support for PBKDF2-SHA512 password hashing.
- Enabling certificate based TLS encryption is now through certfile and
keyfile, not capath or cafile.
- Added support for controlling UNSUBSCRIBE calls in v5 plugin ACL checks.

Client library:
- Client no longer generates random client ids for v3.1.1 clients, these are
Expand Down
1 change: 1 addition & 0 deletions include/mosquitto_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern "C" {
#define MOSQ_ACL_READ 0x01
#define MOSQ_ACL_WRITE 0x02
#define MOSQ_ACL_SUBSCRIBE 0x04
#define MOSQ_ACL_UNSUBSCRIBE 0x08

#include <stdbool.h>
#include <stdint.h>
Expand Down
29 changes: 17 additions & 12 deletions src/handle_subscribe.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int handle__subscribe(struct mosquitto_db *db, struct mosquitto *context)
int slen;
char *sub_mount;
mosquitto_property *properties = NULL;
bool allowed;

if(!context) return MOSQ_ERR_INVAL;

Expand Down Expand Up @@ -160,21 +161,25 @@ int handle__subscribe(struct mosquitto_db *db, struct mosquitto *context)
}
log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s (QoS %d)", sub, qos);

if(context->protocol != mosq_p_mqtt31){
rc2 = mosquitto_acl_check(db, context, sub, 0, NULL, qos, false, MOSQ_ACL_SUBSCRIBE);
switch(rc2){
case MOSQ_ERR_SUCCESS:
break;
case MOSQ_ERR_ACL_DENIED:
allowed = true;
rc2 = mosquitto_acl_check(db, context, sub, 0, NULL, qos, false, MOSQ_ACL_SUBSCRIBE);
switch(rc2){
case MOSQ_ERR_SUCCESS:
break;
case MOSQ_ERR_ACL_DENIED:
allowed = false;
if(context->protocol == mosq_p_mqtt5){
qos = MQTT_RC_NOT_AUTHORIZED;
}else if(context->protocol == mosq_p_mqtt311){
qos = 0x80;
break;
default:
mosquitto__free(sub);
return rc2;
}
}
break;
default:
mosquitto__free(sub);
return rc2;
}

if(qos != 0x80){
if(allowed){
rc2 = sub__add(db, context, sub, qos, subscription_identifier, subscription_options, &db->subs);
if(rc2 > 0){
mosquitto__free(sub);
Expand Down
20 changes: 19 additions & 1 deletion src/handle_unsubscribe.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ int handle__unsubscribe(struct mosquitto_db *db, struct mosquitto *context)
int reason_code_max;
uint8_t *reason_codes = NULL, *reason_tmp;
mosquitto_property *properties = NULL;
bool allowed;

if(!context) return MOSQ_ERR_INVAL;

Expand Down Expand Up @@ -105,8 +106,25 @@ int handle__unsubscribe(struct mosquitto_db *db, struct mosquitto *context)
return MOSQ_ERR_MALFORMED_PACKET;
}

/* ACL check */
allowed = true;
rc = mosquitto_acl_check(db, context, sub, 0, NULL, 0, false, MOSQ_ACL_UNSUBSCRIBE);
switch(rc){
case MOSQ_ERR_SUCCESS:
break;
case MOSQ_ERR_ACL_DENIED:
allowed = false;
reason = MQTT_RC_NOT_AUTHORIZED;
break;
default:
mosquitto__free(sub);
return rc;
}

log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", sub);
rc = sub__remove(db, context, sub, db->subs, &reason);
if(allowed){
rc = sub__remove(db, context, sub, db->subs, &reason);
}
log__printf(NULL, MOSQ_LOG_UNSUBSCRIBE, "%s %s", context->id, sub);
mosquitto__free(sub);
if(rc){
Expand Down
11 changes: 8 additions & 3 deletions src/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,11 +614,17 @@ static int acl__check_single(struct mosquitto__auth_plugin_config *auth_plugin,
}

if(auth_plugin->plugin.version == 4){
if(access == MOSQ_ACL_UNSUBSCRIBE){
return MOSQ_ERR_SUCCESS;
}
return auth_plugin->plugin.acl_check_v4(auth_plugin->plugin.user_data, access, context, msg);
}else if(auth_plugin->plugin.version == 3){
if(access == MOSQ_ACL_UNSUBSCRIBE){
return MOSQ_ERR_SUCCESS;
}
return auth_plugin->plugin.acl_check_v3(auth_plugin->plugin.user_data, access, context, msg);
}else if(auth_plugin->plugin.version == 2){
if(access == MOSQ_ACL_SUBSCRIBE){
if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE){
return MOSQ_ERR_SUCCESS;
}
return auth_plugin->plugin.acl_check_v2(auth_plugin->plugin.user_data, context->id, username, topic, access);
Expand Down Expand Up @@ -649,8 +655,7 @@ static int acl__check_dollar(const char *topic, int access)
}
}else if(!strncmp(topic, "$share", 6)){
/* Only allow sub/unsub to shared subscriptions */
if(access == MOSQ_ACL_SUBSCRIBE){
/* FIXME if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE){ */
if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE){
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_ACL_DENIED;
Expand Down
2 changes: 1 addition & 1 deletion src/security_default.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
return MOSQ_ERR_PLUGIN_DEFER;
}

if(access == MOSQ_ACL_SUBSCRIBE) return MOSQ_ERR_SUCCESS; /* FIXME - implement ACL subscription strings. */
if(access == MOSQ_ACL_SUBSCRIBE || access == MOSQ_ACL_UNSUBSCRIBE) return MOSQ_ERR_SUCCESS; /* FIXME - implement ACL subscription strings. */
if(!context->acl_list && !security_opts->acl_patterns) return MOSQ_ERR_ACL_DENIED;

if(context->acl_list){
Expand Down

0 comments on commit 4472c1f

Please sign in to comment.