diff --git a/ChangeLog.txt b/ChangeLog.txt index 816ba8eb8961b1aac7ea90bcca91e1a575cde4d4..45adc1dadb2ad52fb836fea48acf8c16f298c80e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -28,6 +28,8 @@ Broker: - Fix any possible case where a json string might be incorrectly loaded. This could have caused a crash if a textname or textdescription field of a role was not a string, when loading the dynsec config from file only. +- Dynsec plugin will not allow duplicate clients/groups/roles when loading + config from file, which matches the behaviour for when creating them. Client library: - Use CLOCK_BOOTTIME when available, to keep track of time. This solves the diff --git a/plugins/dynamic-security/clients.c b/plugins/dynamic-security/clients.c index 07ae7a4298454b85025204bf91f2ac9ab0532073..c21d56969945bf8f0f36b2512031d65e1c242bb7 100644 --- a/plugins/dynamic-security/clients.c +++ b/plugins/dynamic-security/clients.c @@ -124,18 +124,24 @@ int dynsec_clients__config_load(cJSON *tree) cJSON_ArrayForEach(j_client, j_clients){ if(cJSON_IsObject(j_client) == true){ - client = mosquitto_calloc(1, sizeof(struct dynsec__client)); - if(client == NULL){ - return MOSQ_ERR_NOMEM; - } - /* Username */ char *username; json_get_string(j_client, "username", &username, false); if(!username){ - mosquitto_free(client); continue; } + + client = dynsec_clients__find(username); + if(client){ + continue; + } + + client = mosquitto_calloc(1, sizeof(struct dynsec__client)); + if(client == NULL){ + return MOSQ_ERR_NOMEM; + } + + client->username = mosquitto_strdup(username); if(client->username == NULL){ mosquitto_free(client); diff --git a/plugins/dynamic-security/groups.c b/plugins/dynamic-security/groups.c index 601b06d19b8534e09907ac803cc4d482f18b5171..16fa76f3db11710062944326be39979be010cd65 100644 --- a/plugins/dynamic-security/groups.c +++ b/plugins/dynamic-security/groups.c @@ -214,16 +214,20 @@ int dynsec_groups__config_load(cJSON *tree) cJSON_ArrayForEach(j_group, j_groups){ if(cJSON_IsObject(j_group) == true){ + /* Group name */ + if(json_get_string(j_group, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ + continue; + } + group = dynsec_groups__find(groupname); + if(group){ + continue; + } + group = mosquitto_calloc(1, sizeof(struct dynsec__group)); if(group == NULL){ return MOSQ_ERR_NOMEM; } - /* Group name */ - if(json_get_string(j_group, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ - mosquitto_free(group); - continue; - } group->groupname = strdup(groupname); if(group->groupname == NULL){ mosquitto_free(group); diff --git a/plugins/dynamic-security/roles.c b/plugins/dynamic-security/roles.c index 13f0a6bde39777669fe0019251e2a8744638b54c..09b9fe3cd172d66b0765cbfe3cd2d2ffcdb227f8 100644 --- a/plugins/dynamic-security/roles.c +++ b/plugins/dynamic-security/roles.c @@ -220,10 +220,19 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_ cJSON_ArrayForEach(j_acl, j_acls){ char *acltype; + char *topic; + json_get_string(j_acl, "acltype", &acltype, false); - if(!acltype || strcasecmp(acltype, key) != 0){ + json_get_string(j_acl, "topic", &topic, false); + + if(!acltype || strcasecmp(acltype, key) != 0 || !topic){ continue; } + HASH_FIND(hh, *acllist, topic, strlen(topic), acl); + if(acl){ + continue; + } + acl = mosquitto_calloc(1, sizeof(struct dynsec__acl)); if(acl == NULL){ return 1; @@ -237,11 +246,7 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_ acl->allow = allow; } - char *topic; - if(json_get_string(j_acl, "topic", &topic, false) == MOSQ_ERR_SUCCESS){ - acl->topic = mosquitto_strdup(topic); - } - + acl->topic = mosquitto_strdup(topic); if(acl->topic == NULL){ mosquitto_free(acl); continue; @@ -270,17 +275,21 @@ int dynsec_roles__config_load(cJSON *tree) cJSON_ArrayForEach(j_role, j_roles){ if(cJSON_IsObject(j_role) == true){ - role = mosquitto_calloc(1, sizeof(struct dynsec__role)); - if(role == NULL){ - return MOSQ_ERR_NOMEM; - } - /* Role name */ char *rolename; if(json_get_string(j_role, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ - mosquitto_free(role); continue; } + role = dynsec_roles__find(rolename); + if(role){ + continue; + } + + role = mosquitto_calloc(1, sizeof(struct dynsec__role)); + if(role == NULL){ + return MOSQ_ERR_NOMEM; + } + role->rolename = mosquitto_strdup(rolename); if(role->rolename == NULL){ mosquitto_free(role);