Fix any possible case where a json string might be incorrectly loaded.
This commit is contained in:
parent
fa9979ce68
commit
8bc047511a
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user