Fix any possible case where a json string might be incorrectly loaded.

This commit is contained in:
Roger A. Light 2023-06-13 13:50:09 +01:00
parent fa9979ce68
commit 8bc047511a
6 changed files with 150 additions and 148 deletions

View File

@ -25,6 +25,9 @@ Broker:
as. In future versions the broker will refuse to open these files.
- mosquitto_memcmp_const is now more constant time.
- Only register with DLT if DLT logging is enabled.
- 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.
Client library:
- Use CLOCK_BOOTTIME when available, to keep track of time. This solves the

View File

@ -106,14 +106,12 @@ void dynsec_clients__cleanup(void)
int dynsec_clients__config_load(cJSON *tree)
{
cJSON *j_clients, *j_client, *jtmp, *j_roles, *j_role;
cJSON *j_salt, *j_password, *j_iterations;
cJSON *j_clients, *j_client, *j_roles, *j_role;
struct dynsec__client *client;
struct dynsec__role *role;
unsigned char *buf;
int buf_len;
int priority;
int iterations;
j_clients = cJSON_GetObjectItem(tree, "clients");
if(j_clients == NULL){
@ -132,41 +130,34 @@ int dynsec_clients__config_load(cJSON *tree)
}
/* Username */
jtmp = cJSON_GetObjectItem(j_client, "username");
if(jtmp == NULL || !cJSON_IsString(jtmp)){
char *username;
json_get_string(j_client, "username", &username, false);
if(!username){
mosquitto_free(client);
continue;
}
client->username = mosquitto_strdup(jtmp->valuestring);
client->username = mosquitto_strdup(username);
if(client->username == NULL){
mosquitto_free(client);
continue;
}
jtmp = cJSON_GetObjectItem(j_client, "disabled");
if(jtmp && cJSON_IsBool(jtmp)){
client->disabled = cJSON_IsTrue(jtmp);
bool disabled;
if(json_get_bool(j_client, "disabled", &disabled, false, false) == MOSQ_ERR_SUCCESS){
client->disabled = disabled;
}
/* Salt */
j_salt = cJSON_GetObjectItem(j_client, "salt");
j_password = cJSON_GetObjectItem(j_client, "password");
j_iterations = cJSON_GetObjectItem(j_client, "iterations");
char *salt, *password;
int iterations;
json_get_string(j_client, "salt", &salt, false);
json_get_string(j_client, "password", &password, false);
json_get_int(j_client, "iterations", &iterations, false, -1);
if(j_salt && cJSON_IsString(j_salt)
&& j_password && cJSON_IsString(j_password)
&& j_iterations && cJSON_IsNumber(j_iterations)){
if(salt && password && iterations > 0){
client->pw.iterations = iterations;
iterations = (int)j_iterations->valuedouble;
if(iterations < 1){
mosquitto_free(client->username);
mosquitto_free(client);
continue;
}else{
client->pw.iterations = iterations;
}
if(dynsec_auth__base64_decode(j_salt->valuestring, &buf, &buf_len) != MOSQ_ERR_SUCCESS
if(dynsec_auth__base64_decode(salt, &buf, &buf_len) != MOSQ_ERR_SUCCESS
|| buf_len != sizeof(client->pw.salt)){
mosquitto_free(client->username);
@ -176,7 +167,7 @@ int dynsec_clients__config_load(cJSON *tree)
memcpy(client->pw.salt, buf, (size_t)buf_len);
mosquitto_free(buf);
if(dynsec_auth__base64_decode(j_password->valuestring, &buf, &buf_len) != MOSQ_ERR_SUCCESS
if(dynsec_auth__base64_decode(password, &buf, &buf_len) != MOSQ_ERR_SUCCESS
|| buf_len != sizeof(client->pw.password_hash)){
mosquitto_free(client->username);
@ -191,9 +182,10 @@ int dynsec_clients__config_load(cJSON *tree)
}
/* Client id */
jtmp = cJSON_GetObjectItem(j_client, "clientid");
if(jtmp != NULL && cJSON_IsString(jtmp)){
client->clientid = mosquitto_strdup(jtmp->valuestring);
char *clientid;
json_get_string(j_client, "clientid", &clientid, false);
if(clientid){
client->clientid = mosquitto_strdup(clientid);
if(client->clientid == NULL){
mosquitto_free(client->username);
mosquitto_free(client);
@ -202,9 +194,10 @@ int dynsec_clients__config_load(cJSON *tree)
}
/* Text name */
jtmp = cJSON_GetObjectItem(j_client, "textname");
if(jtmp != NULL && cJSON_IsString(jtmp)){
client->text_name = mosquitto_strdup(jtmp->valuestring);
char *textname;
json_get_string(j_client, "textname", &textname, false);
if(textname){
client->text_name = mosquitto_strdup(textname);
if(client->text_name == NULL){
mosquitto_free(client->clientid);
mosquitto_free(client->username);
@ -214,9 +207,10 @@ int dynsec_clients__config_load(cJSON *tree)
}
/* Text description */
jtmp = cJSON_GetObjectItem(j_client, "textdescription");
if(jtmp != NULL && cJSON_IsString(jtmp)){
client->text_description = mosquitto_strdup(jtmp->valuestring);
char *textdescription;
json_get_string(j_client, "textdescription", &textdescription, false);
if(textdescription){
client->text_description = mosquitto_strdup(textdescription);
if(client->text_description == NULL){
mosquitto_free(client->text_name);
mosquitto_free(client->clientid);
@ -231,10 +225,11 @@ int dynsec_clients__config_load(cJSON *tree)
if(j_roles && cJSON_IsArray(j_roles)){
cJSON_ArrayForEach(j_role, j_roles){
if(cJSON_IsObject(j_role)){
jtmp = cJSON_GetObjectItem(j_role, "rolename");
if(jtmp && cJSON_IsString(jtmp)){
char *rolename;
json_get_string(j_role, "rolename", &rolename, false);
if(rolename){
json_get_int(j_role, "priority", &priority, true, -1);
role = dynsec_roles__find(jtmp->valuestring);
role = dynsec_roles__find(rolename);
dynsec_rolelist__client_add(client, role, priority);
}
}
@ -326,7 +321,7 @@ int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context
char *text_name, *text_description;
struct dynsec__client *client;
int rc;
cJSON *j_groups, *j_group, *jtmp;
cJSON *j_groups, *j_group;
int priority;
const char *admin_clientid, *admin_username;
@ -438,10 +433,11 @@ int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context
if(j_groups && cJSON_IsArray(j_groups)){
cJSON_ArrayForEach(j_group, j_groups){
if(cJSON_IsObject(j_group)){
jtmp = cJSON_GetObjectItem(j_group, "groupname");
if(jtmp && cJSON_IsString(jtmp)){
char *groupname;
json_get_string(j_group, "groupname", &groupname, false);
if(groupname){
json_get_int(j_group, "priority", &priority, true, -1);
rc = dynsec_groups__add_client(username, jtmp->valuestring, priority, false);
rc = dynsec_groups__add_client(username, groupname, priority, false);
if(rc == ERR_GROUP_NOT_FOUND){
dynsec__command_reply(j_responses, context, "createClient", "Group not found", correlation_data);
client__free_item(client);
@ -730,7 +726,7 @@ int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context
char *str;
int rc;
int priority;
cJSON *j_group, *j_groups, *jtmp;
cJSON *j_group, *j_groups;
const char *admin_clientid, *admin_username;
if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){
@ -812,9 +808,10 @@ int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context
/* Iterate through list to check all groups are valid */
cJSON_ArrayForEach(j_group, j_groups){
if(cJSON_IsObject(j_group)){
jtmp = cJSON_GetObjectItem(j_group, "groupname");
if(jtmp && cJSON_IsString(jtmp)){
group = dynsec_groups__find(jtmp->valuestring);
char *groupname;
json_get_string(j_group, "groupname", &groupname, false);
if(groupname){
group = dynsec_groups__find(groupname);
if(group == NULL){
dynsec__command_reply(j_responses, context, "modifyClient", "'groups' contains an object with a 'groupname' that does not exist", correlation_data);
rc = MOSQ_ERR_INVAL;
@ -831,10 +828,11 @@ int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context
dynsec__remove_client_from_all_groups(username);
cJSON_ArrayForEach(j_group, j_groups){
if(cJSON_IsObject(j_group)){
jtmp = cJSON_GetObjectItem(j_group, "groupname");
if(jtmp && cJSON_IsString(jtmp)){
char *groupname;
json_get_string(j_group, "groupname", &groupname, false);
if(groupname){
json_get_int(j_group, "priority", &priority, true, -1);
dynsec_groups__add_client(username, jtmp->valuestring, priority, false);
dynsec_groups__add_client(username, groupname, priority, false);
}
}
}

View File

@ -195,12 +195,12 @@ void dynsec_groups__cleanup(void)
int dynsec_groups__config_load(cJSON *tree)
{
cJSON *j_groups, *j_group;
cJSON *j_clientlist, *j_client, *j_username;
cJSON *j_roles, *j_role, *j_rolename;
cJSON *j_clientlist, *j_client;
cJSON *j_roles, *j_role;
struct dynsec__group *group;
struct dynsec__role *role;
char *str;
char *groupname;
int priority;
j_groups = cJSON_GetObjectItem(tree, "groups");
@ -220,20 +220,21 @@ int dynsec_groups__config_load(cJSON *tree)
}
/* Group name */
if(json_get_string(j_group, "groupname", &str, false) != MOSQ_ERR_SUCCESS){
if(json_get_string(j_group, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){
mosquitto_free(group);
continue;
}
group->groupname = strdup(str);
group->groupname = strdup(groupname);
if(group->groupname == NULL){
mosquitto_free(group);
continue;
}
/* Text name */
if(json_get_string(j_group, "textname", &str, false) == MOSQ_ERR_SUCCESS){
if(str){
group->text_name = strdup(str);
char *textname;
if(json_get_string(j_group, "textname", &textname, false) == MOSQ_ERR_SUCCESS){
if(textname){
group->text_name = strdup(textname);
if(group->text_name == NULL){
mosquitto_free(group->groupname);
mosquitto_free(group);
@ -243,9 +244,10 @@ int dynsec_groups__config_load(cJSON *tree)
}
/* Text description */
if(json_get_string(j_group, "textdescription", &str, false) == MOSQ_ERR_SUCCESS){
if(str){
group->text_description = strdup(str);
char *textdescription;
if(json_get_string(j_group, "textdescription", &textdescription, false) == MOSQ_ERR_SUCCESS){
if(textdescription){
group->text_description = strdup(textdescription);
if(group->text_description == NULL){
mosquitto_free(group->text_name);
mosquitto_free(group->groupname);
@ -260,10 +262,11 @@ int dynsec_groups__config_load(cJSON *tree)
if(j_roles && cJSON_IsArray(j_roles)){
cJSON_ArrayForEach(j_role, j_roles){
if(cJSON_IsObject(j_role)){
j_rolename = cJSON_GetObjectItem(j_role, "rolename");
if(j_rolename && cJSON_IsString(j_rolename)){
char *rolename;
json_get_string(j_role, "rolename", &rolename, false);
if(rolename){
json_get_int(j_role, "priority", &priority, true, -1);
role = dynsec_roles__find(j_rolename->valuestring);
role = dynsec_roles__find(rolename);
dynsec_rolelist__group_add(group, role, priority);
}
}
@ -278,10 +281,11 @@ int dynsec_groups__config_load(cJSON *tree)
if(j_clientlist && cJSON_IsArray(j_clientlist)){
cJSON_ArrayForEach(j_client, j_clientlist){
if(cJSON_IsObject(j_client)){
j_username = cJSON_GetObjectItem(j_client, "username");
if(j_username && cJSON_IsString(j_username)){
char *username;
json_get_string(j_client, "username", &username, false);
if(username){
json_get_int(j_client, "priority", &priority, true, -1);
dynsec_groups__add_client(j_username->valuestring, group->groupname, priority, false);
dynsec_groups__add_client(username, group->groupname, priority, false);
}
}
}
@ -290,9 +294,9 @@ int dynsec_groups__config_load(cJSON *tree)
}
HASH_SORT(local_groups, group_cmp);
j_group = cJSON_GetObjectItem(tree, "anonymousGroup");
if(j_group && cJSON_IsString(j_group)){
dynsec_anonymous_group = dynsec_groups__find(j_group->valuestring);
json_get_string(tree, "anonymousGroup", &groupname, false);
if(groupname){
dynsec_anonymous_group = dynsec_groups__find(groupname);
}
return 0;
@ -922,10 +926,12 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context,
struct dynsec__group *group = NULL;
struct dynsec__rolelist *rolelist = NULL;
bool have_text_name = false, have_text_description = false, have_rolelist = false;
char *str;
int rc;
int priority;
cJSON *j_client, *j_clients, *jtmp;
cJSON *j_client, *j_clients;
char *username;
char *textname;
char *textdescription;
const char *admin_clientid, *admin_username;
if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){
@ -943,9 +949,9 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context,
return MOSQ_ERR_INVAL;
}
if(json_get_string(command, "textname", &str, false) == MOSQ_ERR_SUCCESS){
if(json_get_string(command, "textname", &textname, false) == MOSQ_ERR_SUCCESS){
have_text_name = true;
text_name = mosquitto_strdup(str);
text_name = mosquitto_strdup(textname);
if(text_name == NULL){
dynsec__command_reply(j_responses, context, "modifyGroup", "Internal error", correlation_data);
rc = MOSQ_ERR_NOMEM;
@ -953,9 +959,9 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context,
}
}
if(json_get_string(command, "textdescription", &str, false) == MOSQ_ERR_SUCCESS){
if(json_get_string(command, "textdescription", &textdescription, false) == MOSQ_ERR_SUCCESS){
have_text_description = true;
text_description = mosquitto_strdup(str);
text_description = mosquitto_strdup(textdescription);
if(text_description == NULL){
dynsec__command_reply(j_responses, context, "modifyGroup", "Internal error", correlation_data);
rc = MOSQ_ERR_NOMEM;
@ -989,9 +995,9 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context,
/* Iterate over array to check clients are valid before proceeding */
cJSON_ArrayForEach(j_client, j_clients){
if(cJSON_IsObject(j_client)){
jtmp = cJSON_GetObjectItem(j_client, "username");
if(jtmp && cJSON_IsString(jtmp)){
client = dynsec_clients__find(jtmp->valuestring);
json_get_string(j_client, "username", &username, false);
if(username){
client = dynsec_clients__find(username);
if(client == NULL){
dynsec__command_reply(j_responses, context, "modifyGroup", "'clients' contains an object with a 'username' that does not exist", correlation_data);
rc = MOSQ_ERR_INVAL;
@ -1012,10 +1018,10 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context,
/* Now we can add the new clients to the group */
cJSON_ArrayForEach(j_client, j_clients){
if(cJSON_IsObject(j_client)){
jtmp = cJSON_GetObjectItem(j_client, "username");
if(jtmp && cJSON_IsString(jtmp)){
json_get_string(j_client, "username", &username, false);
if(username){
json_get_int(j_client, "priority", &priority, true, -1);
dynsec_groups__add_client(jtmp->valuestring, groupname, priority, false);
dynsec_groups__add_client(username, groupname, priority, false);
}
}
}

View File

@ -321,8 +321,7 @@ static int dynsec_control_callback(int event, void *event_data, void *userdata)
static int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data)
{
cJSON *j_actions, *j_action, *j_acltype, *j_allow;
bool allow;
cJSON *j_actions, *j_action;
const char *admin_clientid, *admin_username;
j_actions = cJSON_GetObjectItem(command, "acls");
@ -335,24 +334,23 @@ static int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mos
admin_username = mosquitto_client_username(context);
cJSON_ArrayForEach(j_action, j_actions){
j_acltype = cJSON_GetObjectItem(j_action, "acltype");
j_allow = cJSON_GetObjectItem(j_action, "allow");
if(j_acltype && cJSON_IsString(j_acltype)
&& j_allow && cJSON_IsBool(j_allow)){
char *acltype;
bool allow;
allow = cJSON_IsTrue(j_allow);
if(json_get_string(j_action, "acltype", &acltype, false) == MOSQ_ERR_SUCCESS
&& json_get_bool(j_action, "allow", &allow, false, false) == MOSQ_ERR_SUCCESS){
if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){
if(!strcasecmp(acltype, ACL_TYPE_PUB_C_SEND)){
default_access.publish_c_send = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){
}else if(!strcasecmp(acltype, ACL_TYPE_PUB_C_RECV)){
default_access.publish_c_recv = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_GENERIC)){
}else if(!strcasecmp(acltype, ACL_TYPE_SUB_GENERIC)){
default_access.subscribe = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_GENERIC)){
}else if(!strcasecmp(acltype, ACL_TYPE_UNSUB_GENERIC)){
default_access.unsubscribe = allow;
}
mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | setDefaultACLAccess | acltype=%s | allow=%s",
admin_clientid, admin_username, j_acltype->valuestring, allow?"true":"false");
admin_clientid, admin_username, acltype, allow?"true":"false");
}
}

View File

@ -164,7 +164,7 @@ int dynsec_rolelist__group_add(struct dynsec__group *group, struct dynsec__role
int dynsec_rolelist__load_from_json(cJSON *command, struct dynsec__rolelist **rolelist)
{
cJSON *j_roles, *j_role, *j_rolename;
cJSON *j_roles, *j_role;
int priority;
struct dynsec__role *role;
@ -172,10 +172,11 @@ int dynsec_rolelist__load_from_json(cJSON *command, struct dynsec__rolelist **ro
if(j_roles){
if(cJSON_IsArray(j_roles)){
cJSON_ArrayForEach(j_role, j_roles){
j_rolename = cJSON_GetObjectItem(j_role, "rolename");
if(j_rolename && cJSON_IsString(j_rolename)){
char *rolename;
json_get_string(j_role, "rolename", &rolename, false);
if(rolename){
json_get_int(j_role, "priority", &priority, true, -1);
role = dynsec_roles__find(j_rolename->valuestring);
role = dynsec_roles__find(rolename);
if(role){
dynsec_rolelist__add(rolelist, role, priority);
}else{

View File

@ -215,12 +215,13 @@ static int insert_acl_cmp(struct dynsec__acl *a, struct dynsec__acl *b)
static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec__acl **acllist)
{
cJSON *j_acl, *j_type, *jtmp;
cJSON *j_acl;
struct dynsec__acl *acl;
cJSON_ArrayForEach(j_acl, j_acls){
j_type = cJSON_GetObjectItem(j_acl, "acltype");
if(j_type == NULL || !cJSON_IsString(j_type) || strcasecmp(j_type->valuestring, key) != 0){
char *acltype;
json_get_string(j_acl, "acltype", &acltype, false);
if(!acltype || strcasecmp(acltype, key) != 0){
continue;
}
acl = mosquitto_calloc(1, sizeof(struct dynsec__acl));
@ -231,14 +232,14 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
json_get_int(j_acl, "priority", &acl->priority, true, 0);
json_get_bool(j_acl, "allow", &acl->allow, true, false);
jtmp = cJSON_GetObjectItem(j_acl, "allow");
if(jtmp && cJSON_IsBool(jtmp)){
acl->allow = cJSON_IsTrue(jtmp);
bool allow;
if(json_get_bool(j_acl, "allow", &allow, false, false) == MOSQ_ERR_SUCCESS){
acl->allow = allow;
}
jtmp = cJSON_GetObjectItem(j_acl, "topic");
if(jtmp && cJSON_IsString(jtmp)){
acl->topic = mosquitto_strdup(jtmp->valuestring);
char *topic;
if(json_get_string(j_acl, "topic", &topic, false) == MOSQ_ERR_SUCCESS){
acl->topic = mosquitto_strdup(topic);
}
if(acl->topic == NULL){
@ -255,7 +256,7 @@ static int dynsec_roles__acl_load(cJSON *j_acls, const char *key, struct dynsec_
int dynsec_roles__config_load(cJSON *tree)
{
cJSON *j_roles, *j_role, *jtmp, *j_acls;
cJSON *j_roles, *j_role, *j_acls;
struct dynsec__role *role;
j_roles = cJSON_GetObjectItem(tree, "roles");
@ -275,21 +276,21 @@ int dynsec_roles__config_load(cJSON *tree)
}
/* Role name */
jtmp = cJSON_GetObjectItem(j_role, "rolename");
if(jtmp == NULL){
char *rolename;
if(json_get_string(j_role, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){
mosquitto_free(role);
continue;
}
role->rolename = mosquitto_strdup(jtmp->valuestring);
role->rolename = mosquitto_strdup(rolename);
if(role->rolename == NULL){
mosquitto_free(role);
continue;
}
/* Text name */
jtmp = cJSON_GetObjectItem(j_role, "textname");
if(jtmp != NULL){
role->text_name = mosquitto_strdup(jtmp->valuestring);
char *textname;
if(json_get_string(j_role, "textname", &textname, false) == MOSQ_ERR_SUCCESS){
role->text_name = mosquitto_strdup(textname);
if(role->text_name == NULL){
mosquitto_free(role->rolename);
mosquitto_free(role);
@ -298,9 +299,9 @@ int dynsec_roles__config_load(cJSON *tree)
}
/* Text description */
jtmp = cJSON_GetObjectItem(j_role, "textdescription");
if(jtmp != NULL){
role->text_description = mosquitto_strdup(jtmp->valuestring);
char *textdescription;
if(json_get_string(j_role, "textdescription", &textdescription, false) == MOSQ_ERR_SUCCESS){
role->text_description = mosquitto_strdup(textdescription);
if(role->text_description == NULL){
mosquitto_free(role->text_name);
mosquitto_free(role->rolename);
@ -594,9 +595,9 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context,
char *rolename;
char *topic;
struct dynsec__role *role;
cJSON *jtmp, *j_acltype;
struct dynsec__acl **acllist, *acl;
int rc;
char *acltype;
const char *admin_clientid, *admin_username;
if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){
@ -614,44 +615,37 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context,
return MOSQ_ERR_SUCCESS;
}
j_acltype = cJSON_GetObjectItem(command, "acltype");
if(j_acltype == NULL || !cJSON_IsString(j_acltype)){
if(json_get_string(command, "acltype", &acltype, false) != MOSQ_ERR_SUCCESS){
dynsec__command_reply(j_responses, context, "addRoleACL", "Invalid/missing acltype", correlation_data);
return MOSQ_ERR_SUCCESS;
}
if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){
if(!strcasecmp(acltype, ACL_TYPE_PUB_C_SEND)){
acllist = &role->acls.publish_c_send;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){
}else if(!strcasecmp(acltype, ACL_TYPE_PUB_C_RECV)){
acllist = &role->acls.publish_c_recv;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_LITERAL)){
}else if(!strcasecmp(acltype, ACL_TYPE_SUB_LITERAL)){
acllist = &role->acls.subscribe_literal;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_PATTERN)){
}else if(!strcasecmp(acltype, ACL_TYPE_SUB_PATTERN)){
acllist = &role->acls.subscribe_pattern;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_LITERAL)){
}else if(!strcasecmp(acltype, ACL_TYPE_UNSUB_LITERAL)){
acllist = &role->acls.unsubscribe_literal;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_PATTERN)){
}else if(!strcasecmp(acltype, ACL_TYPE_UNSUB_PATTERN)){
acllist = &role->acls.unsubscribe_pattern;
}else{
dynsec__command_reply(j_responses, context, "addRoleACL", "Unknown acltype", correlation_data);
return MOSQ_ERR_SUCCESS;
}
jtmp = cJSON_GetObjectItem(command, "topic");
if(jtmp && cJSON_IsString(jtmp)){
if(mosquitto_validate_utf8(jtmp->valuestring, (int)strlen(jtmp->valuestring)) != MOSQ_ERR_SUCCESS){
if(json_get_string(command, "topic", &topic, false) == MOSQ_ERR_SUCCESS){
if(mosquitto_validate_utf8(topic, (int)strlen(topic)) != MOSQ_ERR_SUCCESS){
dynsec__command_reply(j_responses, context, "addRoleACL", "Topic not valid UTF-8", correlation_data);
return MOSQ_ERR_INVAL;
}
rc = mosquitto_sub_topic_check(jtmp->valuestring);
rc = mosquitto_sub_topic_check(topic);
if(rc != MOSQ_ERR_SUCCESS){
dynsec__command_reply(j_responses, context, "addRoleACL", "Invalid ACL topic", correlation_data);
return MOSQ_ERR_INVAL;
}
topic = mosquitto_strdup(jtmp->valuestring);
if(topic == NULL){
dynsec__command_reply(j_responses, context, "addRoleACL", "Internal error", correlation_data);
return MOSQ_ERR_SUCCESS;
}
}else{
dynsec__command_reply(j_responses, context, "addRoleACL", "Invalid/missing topic", correlation_data);
return MOSQ_ERR_SUCCESS;
@ -659,18 +653,21 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context,
HASH_FIND(hh, *acllist, topic, strlen(topic), acl);
if(acl){
mosquitto_free(topic);
dynsec__command_reply(j_responses, context, "addRoleACL", "ACL with this topic already exists", correlation_data);
return MOSQ_ERR_SUCCESS;
}
acl = mosquitto_calloc(1, sizeof(struct dynsec__acl));
if(acl == NULL){
mosquitto_free(topic);
dynsec__command_reply(j_responses, context, "addRoleACL", "Internal error", correlation_data);
return MOSQ_ERR_SUCCESS;
}
acl->topic = topic;
acl->topic = mosquitto_strdup(topic);
if(acl->topic == NULL){
mosquitto_free(acl);
dynsec__command_reply(j_responses, context, "addRoleACL", "Internal error", correlation_data);
return MOSQ_ERR_SUCCESS;
}
json_get_int(command, "priority", &acl->priority, true, 0);
json_get_bool(command, "allow", &acl->allow, true, false);
@ -684,7 +681,7 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context,
admin_clientid = mosquitto_client_id(context);
admin_username = mosquitto_client_username(context);
mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | addRoleACL | rolename=%s | acltype=%s | topic=%s | priority=%d | allow=%s",
admin_clientid, admin_username, rolename, j_acltype->valuestring, topic, acl->priority, acl->allow?"true":"false");
admin_clientid, admin_username, rolename, acltype, topic, acl->priority, acl->allow?"true":"false");
return MOSQ_ERR_SUCCESS;
}
@ -696,7 +693,7 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte
struct dynsec__role *role;
struct dynsec__acl **acllist, *acl;
char *topic;
cJSON *j_acltype;
char *acltype;
int rc;
const char *admin_clientid, *admin_username;
@ -715,22 +712,21 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte
return MOSQ_ERR_SUCCESS;
}
j_acltype = cJSON_GetObjectItem(command, "acltype");
if(j_acltype == NULL || !cJSON_IsString(j_acltype)){
if(json_get_string(command, "acltype", &acltype, false) != MOSQ_ERR_SUCCESS){
dynsec__command_reply(j_responses, context, "removeRoleACL", "Invalid/missing acltype", correlation_data);
return MOSQ_ERR_SUCCESS;
}
if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){
if(!strcasecmp(acltype, ACL_TYPE_PUB_C_SEND)){
acllist = &role->acls.publish_c_send;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){
}else if(!strcasecmp(acltype, ACL_TYPE_PUB_C_RECV)){
acllist = &role->acls.publish_c_recv;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_LITERAL)){
}else if(!strcasecmp(acltype, ACL_TYPE_SUB_LITERAL)){
acllist = &role->acls.subscribe_literal;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_PATTERN)){
}else if(!strcasecmp(acltype, ACL_TYPE_SUB_PATTERN)){
acllist = &role->acls.subscribe_pattern;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_LITERAL)){
}else if(!strcasecmp(acltype, ACL_TYPE_UNSUB_LITERAL)){
acllist = &role->acls.unsubscribe_literal;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_PATTERN)){
}else if(!strcasecmp(acltype, ACL_TYPE_UNSUB_PATTERN)){
acllist = &role->acls.unsubscribe_pattern;
}else{
dynsec__command_reply(j_responses, context, "removeRoleACL", "Unknown acltype", correlation_data);
@ -762,7 +758,7 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte
admin_clientid = mosquitto_client_id(context);
admin_username = mosquitto_client_username(context);
mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | removeRoleACL | rolename=%s | acltype=%s | topic=%s",
admin_clientid, admin_username, rolename, j_acltype->valuestring, topic);
admin_clientid, admin_username, rolename, acltype, topic);
}else{
dynsec__command_reply(j_responses, context, "removeRoleACL", "ACL not found", correlation_data);