diff --git a/ChangeLog.txt b/ChangeLog.txt index 412d3b4d..816ba8eb 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -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 diff --git a/plugins/dynamic-security/clients.c b/plugins/dynamic-security/clients.c index 78d53729..07ae7a42 100644 --- a/plugins/dynamic-security/clients.c +++ b/plugins/dynamic-security/clients.c @@ -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); } } } diff --git a/plugins/dynamic-security/groups.c b/plugins/dynamic-security/groups.c index f26a2ba5..601b06d1 100644 --- a/plugins/dynamic-security/groups.c +++ b/plugins/dynamic-security/groups.c @@ -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); } } } diff --git a/plugins/dynamic-security/plugin.c b/plugins/dynamic-security/plugin.c index b8943bd5..b5b81fc1 100644 --- a/plugins/dynamic-security/plugin.c +++ b/plugins/dynamic-security/plugin.c @@ -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"); } } diff --git a/plugins/dynamic-security/rolelist.c b/plugins/dynamic-security/rolelist.c index 2bc1f163..63654c6b 100644 --- a/plugins/dynamic-security/rolelist.c +++ b/plugins/dynamic-security/rolelist.c @@ -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{ diff --git a/plugins/dynamic-security/roles.c b/plugins/dynamic-security/roles.c index 6a393bc0..13f0a6bd 100644 --- a/plugins/dynamic-security/roles.c +++ b/plugins/dynamic-security/roles.c @@ -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);