Simplify memory use for dynsec.

pull/2438/merge
Roger A. Light 4 years ago
parent 223d9eae66
commit 11c5cf039f

@ -213,9 +213,9 @@ static int acl_check(struct mosquitto_evt_acl_check *ed, MOSQ_FUNC_acl_check che
return rc;
}
}
}else if(dynsec_anonymous_group){
}else if(g_dynsec_data.anonymous_group){
/* If we have a group for anonymous users, use that for checking. */
rc = check(ed, dynsec_anonymous_group->rolelist);
rc = check(ed, g_dynsec_data.anonymous_group->rolelist);
if(rc != MOSQ_ERR_NOT_FOUND){
return rc;
}
@ -260,16 +260,16 @@ int dynsec__acl_check_callback(int event, void *event_data, void *userdata)
switch(ed->access){
case MOSQ_ACL_SUBSCRIBE:
return acl_check(event_data, acl_check_subscribe, default_access.subscribe);
return acl_check(event_data, acl_check_subscribe, g_dynsec_data.default_access.subscribe);
break;
case MOSQ_ACL_UNSUBSCRIBE:
return acl_check(event_data, acl_check_unsubscribe, default_access.unsubscribe);
return acl_check(event_data, acl_check_unsubscribe, g_dynsec_data.default_access.unsubscribe);
break;
case MOSQ_ACL_WRITE: /* Client to broker */
return acl_check(event_data, acl_check_publish_c_send, default_access.publish_c_send);
return acl_check(event_data, acl_check_publish_c_send, g_dynsec_data.default_access.publish_c_send);
break;
case MOSQ_ACL_READ:
return acl_check(event_data, acl_check_publish_c_recv, default_access.publish_c_recv);
return acl_check(event_data, acl_check_publish_c_recv, g_dynsec_data.default_access.publish_c_recv);
break;
default:
return MOSQ_ERR_PLUGIN_DEFER;

@ -43,9 +43,6 @@ static void client__remove_all_roles(struct dynsec__client *client);
* #
* ################################################################ */
static struct dynsec__client *local_clients = NULL;
/* ################################################################
* #
* # Utility functions
@ -65,7 +62,7 @@ struct dynsec__client *dynsec_clients__find(const char *username)
struct dynsec__client *client = NULL;
if(username){
HASH_FIND(hh, local_clients, username, strlen(username), client);
HASH_FIND(hh, g_dynsec_data.clients, username, strlen(username), client);
}
return client;
}
@ -78,7 +75,7 @@ static void client__free_item(struct dynsec__client *client)
client_found = dynsec_clients__find(client->username);
if(client_found){
HASH_DEL(local_clients, client_found);
HASH_DEL(g_dynsec_data.clients, client_found);
}
dynsec_rolelist__cleanup(&client->rolelist);
dynsec__remove_client_from_all_groups(client->username);
@ -93,7 +90,7 @@ void dynsec_clients__cleanup(void)
{
struct dynsec__client *client, *client_tmp;
HASH_ITER(hh, local_clients, client, client_tmp){
HASH_ITER(hh, g_dynsec_data.clients, client, client_tmp){
client__free_item(client);
}
}
@ -242,10 +239,10 @@ int dynsec_clients__config_load(cJSON *tree)
}
}
HASH_ADD_KEYPTR(hh, local_clients, client->username, strlen(client->username), client);
HASH_ADD_KEYPTR(hh, g_dynsec_data.clients, client->username, strlen(client->username), client);
}
}
HASH_SORT(local_clients, client_cmp);
HASH_SORT(g_dynsec_data.clients, client_cmp);
return 0;
}
@ -257,7 +254,7 @@ static int dynsec__config_add_clients(cJSON *j_clients)
cJSON *j_client, *j_roles, *jtmp;
char *buf;
HASH_ITER(hh, local_clients, client, client_tmp){
HASH_ITER(hh, g_dynsec_data.clients, client, client_tmp){
j_client = cJSON_CreateObject();
if(j_client == NULL) return 1;
cJSON_AddItemToArray(j_clients, j_client);
@ -433,7 +430,7 @@ int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context
}
/* Must add user before groups, otherwise adding groups will fail */
HASH_ADD_KEYPTR_INORDER(hh, local_clients, client->username, strlen(client->username), client, client_cmp);
HASH_ADD_KEYPTR_INORDER(hh, g_dynsec_data.clients, client->username, strlen(client->username), client, client_cmp);
j_groups = cJSON_GetObjectItem(command, "groups");
if(j_groups && cJSON_IsArray(j_groups)){
@ -983,7 +980,7 @@ int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context,
if(cJSON_AddStringToObject(tree, "command", "listClients") == NULL
|| (j_data = cJSON_AddObjectToObject(tree, "data")) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, local_clients)) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, g_dynsec_data.clients)) == NULL
|| (j_clients = cJSON_AddArrayToObject(j_data, "clients")) == NULL
|| (correlation_data && cJSON_AddStringToObject(tree, "correlationData", correlation_data) == NULL)
){
@ -994,7 +991,7 @@ int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context,
}
i = 0;
HASH_ITER(hh, local_clients, client, client_tmp){
HASH_ITER(hh, g_dynsec_data.clients, client, client_tmp){
if(i>=offset){
j_client = add_client_to_json(client, verbose);
if(j_client == NULL){

@ -41,30 +41,30 @@ static int dynsec__general_config_load(cJSON *tree)
if(j_default_access && cJSON_IsObject(j_default_access)){
jtmp = cJSON_GetObjectItem(j_default_access, ACL_TYPE_PUB_C_SEND);
if(jtmp && cJSON_IsBool(jtmp)){
default_access.publish_c_send = cJSON_IsTrue(jtmp);
g_dynsec_data.default_access.publish_c_send = cJSON_IsTrue(jtmp);
}else{
default_access.publish_c_send = false;
g_dynsec_data.default_access.publish_c_send = false;
}
jtmp = cJSON_GetObjectItem(j_default_access, ACL_TYPE_PUB_C_RECV);
if(jtmp && cJSON_IsBool(jtmp)){
default_access.publish_c_recv = cJSON_IsTrue(jtmp);
g_dynsec_data.default_access.publish_c_recv = cJSON_IsTrue(jtmp);
}else{
default_access.publish_c_recv = false;
g_dynsec_data.default_access.publish_c_recv = false;
}
jtmp = cJSON_GetObjectItem(j_default_access, ACL_TYPE_SUB_GENERIC);
if(jtmp && cJSON_IsBool(jtmp)){
default_access.subscribe = cJSON_IsTrue(jtmp);
g_dynsec_data.default_access.subscribe = cJSON_IsTrue(jtmp);
}else{
default_access.subscribe = false;
g_dynsec_data.default_access.subscribe = false;
}
jtmp = cJSON_GetObjectItem(j_default_access, ACL_TYPE_UNSUB_GENERIC);
if(jtmp && cJSON_IsBool(jtmp)){
default_access.unsubscribe = cJSON_IsTrue(jtmp);
g_dynsec_data.default_access.unsubscribe = cJSON_IsTrue(jtmp);
}else{
default_access.unsubscribe = false;
g_dynsec_data.default_access.unsubscribe = false;
}
}
return MOSQ_ERR_SUCCESS;
@ -80,10 +80,10 @@ static int dynsec__general_config_save(cJSON *tree)
}
cJSON_AddItemToObject(tree, "defaultACLAccess", j_default_access);
if(cJSON_AddBoolToObject(j_default_access, ACL_TYPE_PUB_C_SEND, default_access.publish_c_send) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_PUB_C_RECV, default_access.publish_c_recv) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_SUB_GENERIC, default_access.subscribe) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_UNSUB_GENERIC, default_access.unsubscribe) == NULL
if(cJSON_AddBoolToObject(j_default_access, ACL_TYPE_PUB_C_SEND, g_dynsec_data.default_access.publish_c_send) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_PUB_C_RECV, g_dynsec_data.default_access.publish_c_recv) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_SUB_GENERIC, g_dynsec_data.default_access.subscribe) == NULL
|| cJSON_AddBoolToObject(j_default_access, ACL_TYPE_UNSUB_GENERIC, g_dynsec_data.default_access.unsubscribe) == NULL
){
return 1;

@ -33,8 +33,6 @@ Contributors:
#include "dynamic_security.h"
struct dynsec__acl_default_access default_access = {false, false, false, false};
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;
@ -59,13 +57,13 @@ int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto
allow = cJSON_IsTrue(j_allow);
if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){
default_access.publish_c_send = allow;
g_dynsec_data.default_access.publish_c_send = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){
default_access.publish_c_recv = allow;
g_dynsec_data.default_access.publish_c_recv = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_GENERIC)){
default_access.subscribe = allow;
g_dynsec_data.default_access.subscribe = allow;
}else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_GENERIC)){
default_access.unsubscribe = allow;
g_dynsec_data.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");
@ -115,7 +113,7 @@ int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto
}
cJSON_AddItemToArray(j_acls, j_acl);
if(cJSON_AddStringToObject(j_acl, "acltype", ACL_TYPE_PUB_C_SEND) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", default_access.publish_c_send) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", g_dynsec_data.default_access.publish_c_send) == NULL
){
goto internal_error;
@ -128,7 +126,7 @@ int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto
}
cJSON_AddItemToArray(j_acls, j_acl);
if(cJSON_AddStringToObject(j_acl, "acltype", ACL_TYPE_PUB_C_RECV) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", default_access.publish_c_recv) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", g_dynsec_data.default_access.publish_c_recv) == NULL
){
goto internal_error;
@ -141,7 +139,7 @@ int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto
}
cJSON_AddItemToArray(j_acls, j_acl);
if(cJSON_AddStringToObject(j_acl, "acltype", ACL_TYPE_SUB_GENERIC) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", default_access.subscribe) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", g_dynsec_data.default_access.subscribe) == NULL
){
goto internal_error;
@ -154,7 +152,7 @@ int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto
}
cJSON_AddItemToArray(j_acls, j_acl);
if(cJSON_AddStringToObject(j_acl, "acltype", ACL_TYPE_UNSUB_GENERIC) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", default_access.unsubscribe) == NULL
|| cJSON_AddBoolToObject(j_acl, "allow", g_dynsec_data.default_access.unsubscribe) == NULL
){
goto internal_error;

@ -130,8 +130,15 @@ struct dynsec__acl_default_access{
bool unsubscribe;
};
extern struct dynsec__group *dynsec_anonymous_group;
extern struct dynsec__acl_default_access default_access;
struct dynsec__data{
struct dynsec__client *clients;
struct dynsec__group *groups;
struct dynsec__role *roles;
struct dynsec__group *anonymous_group;
struct dynsec__acl_default_access default_access;
};
extern struct dynsec__data g_dynsec_data;
extern char *g_config_file;
/* ################################################################

@ -34,9 +34,6 @@ Contributors:
* #
* ################################################################ */
struct dynsec__group *dynsec_anonymous_group = NULL;
/* ################################################################
* #
* # Function declarations
@ -54,9 +51,6 @@ static cJSON *add_group_to_json(struct dynsec__group *group);
* #
* ################################################################ */
static struct dynsec__group *local_groups = NULL;
/* ################################################################
* #
* # Utility functions
@ -65,7 +59,7 @@ static struct dynsec__group *local_groups = NULL;
static void group__kick_all(struct dynsec__group *group)
{
if(group == dynsec_anonymous_group){
if(group == g_dynsec_data.anonymous_group){
mosquitto_kick_client_by_username(NULL, false);
}
dynsec_clientlist__kick_all(group->clientlist);
@ -86,7 +80,7 @@ struct dynsec__group *dynsec_groups__find(const char *groupname)
struct dynsec__group *group = NULL;
if(groupname){
HASH_FIND(hh, local_groups, groupname, strlen(groupname), group);
HASH_FIND(hh, g_dynsec_data.groups, groupname, strlen(groupname), group);
}
return group;
}
@ -99,7 +93,7 @@ static void group__free_item(struct dynsec__group *group)
found_group = dynsec_groups__find(group->groupname);
if(found_group){
HASH_DEL(local_groups, found_group);
HASH_DEL(g_dynsec_data.groups, found_group);
}
dynsec__remove_all_clients_from_group(group);
mosquitto_free(group->text_name);
@ -180,7 +174,7 @@ void dynsec_groups__cleanup(void)
{
struct dynsec__group *group, *group_tmp = NULL;
HASH_ITER(hh, local_groups, group, group_tmp){
HASH_ITER(hh, g_dynsec_data.groups, group, group_tmp){
group__free_item(group);
}
}
@ -271,7 +265,7 @@ int dynsec_groups__config_load(cJSON *tree)
}
/* This must go before clients are loaded, otherwise the group won't be found */
HASH_ADD_KEYPTR(hh, local_groups, group->groupname, strlen(group->groupname), group);
HASH_ADD_KEYPTR(hh, g_dynsec_data.groups, group->groupname, strlen(group->groupname), group);
/* Clients */
j_clientlist = cJSON_GetObjectItem(j_group, "clients");
@ -288,11 +282,11 @@ int dynsec_groups__config_load(cJSON *tree)
}
}
}
HASH_SORT(local_groups, group_cmp);
HASH_SORT(g_dynsec_data.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);
g_dynsec_data.anonymous_group = dynsec_groups__find(j_group->valuestring);
}
return 0;
@ -311,7 +305,7 @@ static int dynsec__config_add_groups(cJSON *j_groups)
struct dynsec__group *group, *group_tmp = NULL;
cJSON *j_group, *j_clients, *j_roles;
HASH_ITER(hh, local_groups, group, group_tmp){
HASH_ITER(hh, g_dynsec_data.groups, group, group_tmp){
j_group = cJSON_CreateObject();
if(j_group == NULL) return 1;
cJSON_AddItemToArray(j_groups, j_group);
@ -354,8 +348,8 @@ int dynsec_groups__config_save(cJSON *tree)
return 1;
}
if(dynsec_anonymous_group
&& cJSON_AddStringToObject(tree, "anonymousGroup", dynsec_anonymous_group->groupname) == NULL){
if(g_dynsec_data.anonymous_group
&& cJSON_AddStringToObject(tree, "anonymousGroup", g_dynsec_data.anonymous_group->groupname) == NULL){
return 1;
}
@ -436,7 +430,7 @@ int dynsec_groups__process_create(cJSON *j_responses, struct mosquitto *context,
return MOSQ_ERR_INVAL;
}
HASH_ADD_KEYPTR_INORDER(hh, local_groups, group->groupname, strlen(group->groupname), group, group_cmp);
HASH_ADD_KEYPTR_INORDER(hh, g_dynsec_data.groups, group->groupname, strlen(group->groupname), group, group_cmp);
admin_clientid = mosquitto_client_id(context);
admin_username = mosquitto_client_username(context);
@ -744,7 +738,7 @@ int dynsec_groups__process_list(cJSON *j_responses, struct mosquitto *context, c
if(cJSON_AddStringToObject(tree, "command", "listGroups") == NULL
|| (j_data = cJSON_AddObjectToObject(tree, "data")) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, local_groups)) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, g_dynsec_data.groups)) == NULL
|| (j_groups = cJSON_AddArrayToObject(j_data, "groups")) == NULL
|| (correlation_data && cJSON_AddStringToObject(tree, "correlationData", correlation_data) == NULL)
){
@ -755,7 +749,7 @@ int dynsec_groups__process_list(cJSON *j_responses, struct mosquitto *context, c
}
i = 0;
HASH_ITER(hh, local_groups, group, group_tmp){
HASH_ITER(hh, g_dynsec_data.groups, group, group_tmp){
if(i>=offset){
if(verbose){
j_group = add_group_to_json(group);
@ -1030,7 +1024,7 @@ int dynsec_groups__process_set_anonymous_group(cJSON *j_responses, struct mosqui
return MOSQ_ERR_SUCCESS;
}
dynsec_anonymous_group = group;
g_dynsec_data.anonymous_group = group;
dynsec__config_save();
dynsec__command_reply(j_responses, context, "setAnonymousGroup", NULL, correlation_data);
@ -1060,8 +1054,8 @@ int dynsec_groups__process_get_anonymous_group(cJSON *j_responses, struct mosqui
return MOSQ_ERR_NOMEM;
}
if(dynsec_anonymous_group){
groupname = dynsec_anonymous_group->groupname;
if(g_dynsec_data.anonymous_group){
groupname = g_dynsec_data.anonymous_group->groupname;
}else{
groupname = "";
}

@ -33,6 +33,7 @@ Contributors:
MOSQUITTO_PLUGIN_DECLARE_VERSION(5);
struct dynsec__data g_dynsec_data;
static mosquitto_plugin_id_t *plg_id = NULL;
char *g_config_file = NULL;
@ -42,6 +43,8 @@ int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, s
UNUSED(user_data);
memset(&g_dynsec_data, 0, sizeof(struct dynsec__data));
for(i=0; i<option_count; i++){
if(!strcasecmp(options[i].key, "config_file")){
g_config_file = mosquitto_strdup(options[i].value);

@ -33,15 +33,6 @@ Contributors:
static cJSON *add_role_to_json(struct dynsec__role *role, bool verbose);
static void role__remove_all_clients(struct dynsec__role *role);
/* ################################################################
* #
* # Local variables
* #
* ################################################################ */
static struct dynsec__role *local_roles = NULL;
/* ################################################################
* #
* # Utility functions
@ -76,7 +67,7 @@ static void role__free_all_acls(struct dynsec__acl **acl)
static void role__free_item(struct dynsec__role *role, bool remove_from_hash)
{
if(remove_from_hash){
HASH_DEL(local_roles, role);
HASH_DEL(g_dynsec_data.roles, role);
}
dynsec_clientlist__cleanup(&role->clientlist);
dynsec_grouplist__cleanup(&role->grouplist);
@ -97,7 +88,7 @@ struct dynsec__role *dynsec_roles__find(const char *rolename)
struct dynsec__role *role = NULL;
if(rolename){
HASH_FIND(hh, local_roles, rolename, strlen(rolename), role);
HASH_FIND(hh, g_dynsec_data.roles, rolename, strlen(rolename), role);
}
return role;
}
@ -107,7 +98,7 @@ void dynsec_roles__cleanup(void)
{
struct dynsec__role *role, *role_tmp = NULL;
HASH_ITER(hh, local_roles, role, role_tmp){
HASH_ITER(hh, g_dynsec_data.roles, role, role_tmp){
role__free_item(role, true);
}
}
@ -120,7 +111,7 @@ static void role__kick_all(struct dynsec__role *role)
dynsec_clientlist__kick_all(role->clientlist);
HASH_ITER(hh, role->grouplist, grouplist, grouplist_tmp){
if(grouplist->group == dynsec_anonymous_group){
if(grouplist->group == g_dynsec_data.anonymous_group){
mosquitto_kick_client_by_username(NULL, false);
}
dynsec_clientlist__kick_all(grouplist->group->clientlist);
@ -191,7 +182,7 @@ int dynsec_roles__config_save(cJSON *tree)
return 1;
}
HASH_ITER(hh, local_roles, role, role_tmp){
HASH_ITER(hh, g_dynsec_data.roles, role, role_tmp){
j_role = add_role_to_json(role, true);
if(j_role == NULL){
return 1;
@ -330,10 +321,10 @@ int dynsec_roles__config_load(cJSON *tree)
}
}
HASH_ADD_KEYPTR(hh, local_roles, role->rolename, strlen(role->rolename), role);
HASH_ADD_KEYPTR(hh, g_dynsec_data.roles, role->rolename, strlen(role->rolename), role);
}
}
HASH_SORT(local_roles, role_cmp);
HASH_SORT(g_dynsec_data.roles, role_cmp);
return 0;
}
@ -426,7 +417,7 @@ int dynsec_roles__process_create(cJSON *j_responses, struct mosquitto *context,
}
HASH_ADD_KEYPTR_INORDER(hh, local_roles, role->rolename, strlen(role->rolename), role, role_cmp);
HASH_ADD_KEYPTR_INORDER(hh, g_dynsec_data.roles, role->rolename, strlen(role->rolename), role, role_cmp);
dynsec__config_save();
@ -462,7 +453,7 @@ static void role__remove_all_groups(struct dynsec__role *role)
struct dynsec__grouplist *grouplist, *grouplist_tmp = NULL;
HASH_ITER(hh, role->grouplist, grouplist, grouplist_tmp){
if(grouplist->group == dynsec_anonymous_group){
if(grouplist->group == g_dynsec_data.anonymous_group){
mosquitto_kick_client_by_username(NULL, false);
}
dynsec_clientlist__kick_all(grouplist->group->clientlist);
@ -559,7 +550,7 @@ int dynsec_roles__process_list(cJSON *j_responses, struct mosquitto *context, cJ
if(cJSON_AddStringToObject(tree, "command", "listRoles") == NULL
|| (j_data = cJSON_AddObjectToObject(tree, "data")) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, local_roles)) == NULL
|| cJSON_AddIntToObject(j_data, "totalCount", (int)HASH_CNT(hh, g_dynsec_data.roles)) == NULL
|| (j_roles = cJSON_AddArrayToObject(j_data, "roles")) == NULL
|| (correlation_data && cJSON_AddStringToObject(tree, "correlationData", correlation_data) == NULL)
){
@ -570,7 +561,7 @@ int dynsec_roles__process_list(cJSON *j_responses, struct mosquitto *context, cJ
}
i = 0;
HASH_ITER(hh, local_roles, role, role_tmp){
HASH_ITER(hh, g_dynsec_data.roles, role, role_tmp){
if(i>=offset){
j_role = add_role_to_json(role, verbose);
if(j_role == NULL){

Loading…
Cancel
Save