From 0605fd402a627e5dca07d54954407fd465db5159 Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Mon, 30 Nov 2020 10:10:12 +0000 Subject: [PATCH] dynsec: Command logging. --- plugins/dynamic-security/clients.c | 77 ++++++++++++++++++++++++---- plugins/dynamic-security/groups.c | 72 ++++++++++++++++++++++++-- plugins/dynamic-security/plugin.c | 12 +++++ plugins/dynamic-security/roles.c | 82 +++++++++++++++++++++--------- 4 files changed, 205 insertions(+), 38 deletions(-) diff --git a/plugins/dynamic-security/clients.c b/plugins/dynamic-security/clients.c index b81be383..d74aea44 100644 --- a/plugins/dynamic-security/clients.c +++ b/plugins/dynamic-security/clients.c @@ -125,20 +125,17 @@ int dynsec_clients__config_load(cJSON *tree) if(cJSON_IsObject(j_client) == true){ client = mosquitto_calloc(1, sizeof(struct dynsec__client)); if(client == NULL){ - // FIXME log return MOSQ_ERR_NOMEM; } /* Username */ jtmp = cJSON_GetObjectItem(j_client, "username"); if(jtmp == NULL || !cJSON_IsString(jtmp)){ - // FIXME log mosquitto_free(client); continue; } client->username = mosquitto_strdup(jtmp->valuestring); if(client->username == NULL){ - // FIXME log mosquitto_free(client); continue; } @@ -159,7 +156,6 @@ int dynsec_clients__config_load(cJSON *tree) iterations = (int)j_iterations->valuedouble; if(iterations < 1){ - // FIXME log mosquitto_free(client->username); mosquitto_free(client); continue; @@ -170,7 +166,6 @@ int dynsec_clients__config_load(cJSON *tree) if(dynsec_auth__base64_decode(j_salt->valuestring, &buf, &buf_len) != MOSQ_ERR_SUCCESS || buf_len != sizeof(client->pw.salt)){ - // FIXME log mosquitto_free(client->username); mosquitto_free(client); continue; @@ -181,7 +176,6 @@ int dynsec_clients__config_load(cJSON *tree) if(dynsec_auth__base64_decode(j_password->valuestring, &buf, &buf_len) != MOSQ_ERR_SUCCESS || buf_len != sizeof(client->pw.password_hash)){ - // FIXME log mosquitto_free(client->username); mosquitto_free(client); continue; @@ -198,7 +192,6 @@ int dynsec_clients__config_load(cJSON *tree) if(jtmp != NULL && cJSON_IsString(jtmp)){ client->clientid = mosquitto_strdup(jtmp->valuestring); if(client->clientid == NULL){ - // FIXME log mosquitto_free(client->username); mosquitto_free(client); continue; @@ -210,7 +203,6 @@ int dynsec_clients__config_load(cJSON *tree) if(jtmp != NULL && cJSON_IsString(jtmp)){ client->text_name = mosquitto_strdup(jtmp->valuestring); if(client->text_name == NULL){ - // FIXME log mosquitto_free(client->clientid); mosquitto_free(client->username); mosquitto_free(client); @@ -223,7 +215,6 @@ int dynsec_clients__config_load(cJSON *tree) if(jtmp != NULL && cJSON_IsString(jtmp)){ client->text_description = mosquitto_strdup(jtmp->valuestring); if(client->text_description == NULL){ - // FIXME log mosquitto_free(client->text_name); mosquitto_free(client->clientid); mosquitto_free(client->username); @@ -334,6 +325,7 @@ int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context int rc; cJSON *j_groups, *j_group, *jtmp; int priority; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "createClient", "Invalid/missing username", correlation_data); @@ -464,6 +456,12 @@ int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context dynsec__config_save(); dynsec__command_reply(j_responses, context, "createClient", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | createClient | username=%s | password=%s", + admin_clientid, admin_username, username, password?"*****":"no password"); + return MOSQ_ERR_SUCCESS; } @@ -472,6 +470,7 @@ int dynsec_clients__process_delete(cJSON *j_responses, struct mosquitto *context { char *username; struct dynsec__client *client; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "deleteClient", "Invalid/missing username", correlation_data); @@ -488,6 +487,11 @@ int dynsec_clients__process_delete(cJSON *j_responses, struct mosquitto *context /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | deleteClient | username=%s", + admin_clientid, admin_username, username); + return MOSQ_ERR_SUCCESS; }else{ dynsec__command_reply(j_responses, context, "deleteClient", "Client not found", correlation_data); @@ -499,6 +503,7 @@ int dynsec_clients__process_disable(cJSON *j_responses, struct mosquitto *contex { char *username; struct dynsec__client *client; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "disableClient", "Invalid/missing username", correlation_data); @@ -521,6 +526,12 @@ int dynsec_clients__process_disable(cJSON *j_responses, struct mosquitto *contex dynsec__config_save(); dynsec__command_reply(j_responses, context, "disableClient", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | disableClient | username=%s", + admin_clientid, admin_username, username); + return MOSQ_ERR_SUCCESS; } @@ -529,6 +540,7 @@ int dynsec_clients__process_enable(cJSON *j_responses, struct mosquitto *context { char *username; struct dynsec__client *client; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "enableClient", "Invalid/missing username", correlation_data); @@ -549,6 +561,12 @@ int dynsec_clients__process_enable(cJSON *j_responses, struct mosquitto *context dynsec__config_save(); dynsec__command_reply(j_responses, context, "enableClient", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | enableClient | username=%s", + admin_clientid, admin_username, username); + return MOSQ_ERR_SUCCESS; } @@ -558,6 +576,7 @@ int dynsec_clients__process_set_id(cJSON *j_responses, struct mosquitto *context char *username, *clientid, *clientid_heap = NULL; struct dynsec__client *client; size_t slen; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "setClientId", "Invalid/missing username", correlation_data); @@ -605,6 +624,11 @@ int dynsec_clients__process_set_id(cJSON *j_responses, struct mosquitto *context /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | setClientId | username=%s | clientid=%s", + admin_clientid, admin_username, username, client->clientid); + return MOSQ_ERR_SUCCESS; } @@ -627,6 +651,7 @@ int dynsec_clients__process_set_password(cJSON *j_responses, struct mosquitto *c char *username, *password; struct dynsec__client *client; int rc; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "setClientPassword", "Invalid/missing username", correlation_data); @@ -658,6 +683,11 @@ int dynsec_clients__process_set_password(cJSON *j_responses, struct mosquitto *c /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | setClientPassword | username=%s | password=******", + admin_clientid, admin_username, username); }else{ dynsec__command_reply(j_responses, context, "setClientPassword", "Internal error", correlation_data); } @@ -695,6 +725,7 @@ int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context int rc; int priority; cJSON *j_group, *j_groups, *jtmp; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "modifyClient", "Invalid/missing username", correlation_data); @@ -803,6 +834,10 @@ int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | modifyClient | username=%s", + admin_clientid, admin_username, username); return MOSQ_ERR_SUCCESS; } @@ -872,6 +907,7 @@ int dynsec_clients__process_get(cJSON *j_responses, struct mosquitto *context, c char *username; struct dynsec__client *client; cJSON *tree, *j_client, *j_data; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "getClient", "Invalid/missing username", correlation_data); @@ -913,6 +949,11 @@ int dynsec_clients__process_get(cJSON *j_responses, struct mosquitto *context, c cJSON_AddItemToObject(j_data, "client", j_client); cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | getClient | username=%s", + admin_clientid, admin_username, username); + return MOSQ_ERR_SUCCESS; } @@ -923,6 +964,7 @@ int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context, struct dynsec__client *client, *client_tmp; cJSON *tree, *j_clients, *j_client, *j_data; int i, count, offset; + const char *admin_clientid, *admin_username; json_get_bool(command, "verbose", &verbose, true, false); json_get_int(command, "count", &count, true, -1); @@ -968,6 +1010,11 @@ int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context, } cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | listClients | verbose=%s | count=%d | offset=%d", + admin_clientid, admin_username, verbose?"true":"false", count, offset); + return MOSQ_ERR_SUCCESS; } @@ -978,6 +1025,7 @@ int dynsec_clients__process_add_role(cJSON *j_responses, struct mosquitto *conte struct dynsec__client *client; struct dynsec__role *role; int priority; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "addClientRole", "Invalid/missing username", correlation_data); @@ -1017,6 +1065,11 @@ int dynsec_clients__process_add_role(cJSON *j_responses, struct mosquitto *conte /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | addClientRole | username=%s | rolename=%s | priority=%d", + admin_clientid, admin_username, username, rolename, priority); + return MOSQ_ERR_SUCCESS; } @@ -1026,6 +1079,7 @@ int dynsec_clients__process_remove_role(cJSON *j_responses, struct mosquitto *co char *username, *rolename; struct dynsec__client *client; struct dynsec__role *role; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "removeClientRole", "Invalid/missing username", correlation_data); @@ -1065,5 +1119,10 @@ int dynsec_clients__process_remove_role(cJSON *j_responses, struct mosquitto *co /* Enforce any changes */ mosquitto_kick_client_by_username(username, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | removeClientRole | username=%s | rolename=%s", + admin_clientid, admin_username, username, rolename); + return MOSQ_ERR_SUCCESS; } diff --git a/plugins/dynamic-security/groups.c b/plugins/dynamic-security/groups.c index ee8d0bfc..c6d6a129 100644 --- a/plugins/dynamic-security/groups.c +++ b/plugins/dynamic-security/groups.c @@ -112,6 +112,7 @@ int dynsec_groups__process_add_role(cJSON *j_responses, struct mosquitto *contex struct dynsec__group *group; struct dynsec__role *role; int priority; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "addGroupRole", "Invalid/missing groupname", correlation_data); @@ -144,6 +145,12 @@ int dynsec_groups__process_add_role(cJSON *j_responses, struct mosquitto *contex return MOSQ_ERR_SUCCESS; } + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | addGroupRole | groupname=%s | rolename=%s | priority=%d", + admin_clientid, admin_username, groupname, rolename, priority); + dynsec_rolelist__group_add(group, role, priority); dynsec__config_save(); dynsec__command_reply(j_responses, context, "addGroupRole", NULL, correlation_data); @@ -195,19 +202,16 @@ int dynsec_groups__config_load(cJSON *tree) if(cJSON_IsObject(j_group) == true){ group = mosquitto_calloc(1, sizeof(struct dynsec__group)); if(group == NULL){ - // FIXME log return MOSQ_ERR_NOMEM; } /* Group name */ if(json_get_string(j_group, "groupname", &str, false) != MOSQ_ERR_SUCCESS){ - // FIXME log mosquitto_free(group); continue; } group->groupname = strdup(str); if(group->groupname == NULL){ - // FIXME log mosquitto_free(group); continue; } @@ -217,7 +221,6 @@ int dynsec_groups__config_load(cJSON *tree) if(str){ group->text_name = strdup(str); if(group->text_name == NULL){ - // FIXME log mosquitto_free(group->groupname); mosquitto_free(group); continue; @@ -230,7 +233,6 @@ int dynsec_groups__config_load(cJSON *tree) if(str){ group->text_description = strdup(str); if(group->text_description == NULL){ - // FIXME log mosquitto_free(group->text_name); mosquitto_free(group->groupname); mosquitto_free(group); @@ -353,6 +355,7 @@ int dynsec_groups__process_create(cJSON *j_responses, struct mosquitto *context, char *groupname, *text_name, *text_description; struct dynsec__group *group = NULL; int rc = MOSQ_ERR_SUCCESS; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "createGroup", "Invalid/missing groupname", correlation_data); @@ -421,6 +424,11 @@ int dynsec_groups__process_create(cJSON *j_responses, struct mosquitto *context, HASH_ADD_KEYPTR_INORDER(hh, local_groups, group->groupname, strlen(group->groupname), group, group_cmp); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | createGroup | groupname=%s", + admin_clientid, admin_username, groupname); + dynsec__config_save(); dynsec__command_reply(j_responses, context, "createGroup", NULL, correlation_data); return MOSQ_ERR_SUCCESS; @@ -431,6 +439,7 @@ int dynsec_groups__process_delete(cJSON *j_responses, struct mosquitto *context, { char *groupname; struct dynsec__group *group; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "deleteGroup", "Invalid/missing groupname", correlation_data); @@ -450,6 +459,11 @@ int dynsec_groups__process_delete(cJSON *j_responses, struct mosquitto *context, dynsec__config_save(); dynsec__command_reply(j_responses, context, "deleteGroup", NULL, correlation_data); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | deleteGroup | groupname=%s", + admin_clientid, admin_username, groupname); + return MOSQ_ERR_SUCCESS; }else{ dynsec__command_reply(j_responses, context, "deleteGroup", "Group not found", correlation_data); @@ -504,6 +518,7 @@ int dynsec_groups__process_add_client(cJSON *j_responses, struct mosquitto *cont char *username, *groupname; int rc; int priority; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "addGroupClient", "Invalid/missing username", correlation_data); @@ -527,6 +542,11 @@ int dynsec_groups__process_add_client(cJSON *j_responses, struct mosquitto *cont rc = dynsec_groups__add_client(username, groupname, priority, true); if(rc == MOSQ_ERR_SUCCESS){ + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | addGroupClient | groupname=%s | username=%s | priority=%d", + admin_clientid, admin_username, groupname, username, priority); + dynsec__command_reply(j_responses, context, "addGroupClient", NULL, correlation_data); }else if(rc == ERR_USER_NOT_FOUND){ dynsec__command_reply(j_responses, context, "addGroupClient", "Client not found", correlation_data); @@ -586,6 +606,7 @@ int dynsec_groups__process_remove_client(cJSON *j_responses, struct mosquitto *c { char *username, *groupname; int rc; + const char *admin_clientid, *admin_username; if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "removeGroupClient", "Invalid/missing username", correlation_data); @@ -607,6 +628,11 @@ int dynsec_groups__process_remove_client(cJSON *j_responses, struct mosquitto *c rc = dynsec_groups__remove_client(username, groupname, true); if(rc == MOSQ_ERR_SUCCESS){ + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | removeGroupClient | groupname=%s | username=%s", + admin_clientid, admin_username, groupname, username); + dynsec__command_reply(j_responses, context, "removeGroupClient", NULL, correlation_data); }else if(rc == ERR_USER_NOT_FOUND){ dynsec__command_reply(j_responses, context, "removeGroupClient", "Client not found", correlation_data); @@ -676,6 +702,7 @@ int dynsec_groups__process_list(cJSON *j_responses, struct mosquitto *context, c cJSON *tree, *j_groups, *j_group, *j_data; struct dynsec__group *group, *group_tmp; int i, count, offset; + const char *admin_clientid, *admin_username; json_get_bool(command, "verbose", &verbose, true, false); json_get_int(command, "count", &count, true, -1); @@ -734,6 +761,11 @@ int dynsec_groups__process_list(cJSON *j_responses, struct mosquitto *context, c cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | listGroups | verbose=%s | count=%d | offset=%d", + admin_clientid, admin_username, verbose?"true":"false", count, offset); + return MOSQ_ERR_SUCCESS; } @@ -743,6 +775,7 @@ int dynsec_groups__process_get(cJSON *j_responses, struct mosquitto *context, cJ char *groupname; cJSON *tree, *j_group, *j_data; struct dynsec__group *group; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "getGroup", "Invalid/missing groupname", correlation_data); @@ -786,6 +819,11 @@ int dynsec_groups__process_get(cJSON *j_responses, struct mosquitto *context, cJ cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | getGroup | groupname=%s", + admin_clientid, admin_username, groupname); + return MOSQ_ERR_SUCCESS; } @@ -795,6 +833,7 @@ int dynsec_groups__process_remove_role(cJSON *j_responses, struct mosquitto *con char *groupname, *rolename; struct dynsec__group *group; struct dynsec__role *role; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "removeGroupRole", "Invalid/missing groupname", correlation_data); @@ -833,6 +872,11 @@ int dynsec_groups__process_remove_role(cJSON *j_responses, struct mosquitto *con /* Enforce any changes */ group__kick_all(group); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | removeGroupRole | groupname=%s | rolename=%s", + admin_clientid, admin_username, groupname, rolename); + return MOSQ_ERR_SUCCESS; } @@ -847,6 +891,7 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context, int rc; int priority; cJSON *j_client, *j_clients, *jtmp; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "modifyGroup", "Invalid/missing groupname", correlation_data); @@ -927,6 +972,11 @@ int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context, /* Enforce any changes */ group__kick_all(group); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | modifyGroup | groupname=%s", + admin_clientid, admin_username, groupname); + return MOSQ_ERR_SUCCESS; } @@ -935,6 +985,7 @@ int dynsec_groups__process_set_anonymous_group(cJSON *j_responses, struct mosqui { char *groupname; struct dynsec__group *group = NULL; + const char *admin_clientid, *admin_username; if(json_get_string(command, "groupname", &groupname, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "setAnonymousGroup", "Invalid/missing groupname", correlation_data); @@ -959,6 +1010,11 @@ int dynsec_groups__process_set_anonymous_group(cJSON *j_responses, struct mosqui /* Enforce any changes */ mosquitto_kick_client_by_username(NULL, false); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | setAnonymousGroup | groupname=%s", + admin_clientid, admin_username, groupname); + return MOSQ_ERR_SUCCESS; } @@ -966,6 +1022,7 @@ int dynsec_groups__process_get_anonymous_group(cJSON *j_responses, struct mosqui { cJSON *tree, *j_data, *j_group; const char *groupname; + const char *admin_clientid, *admin_username; tree = cJSON_CreateObject(); if(tree == NULL){ @@ -993,5 +1050,10 @@ int dynsec_groups__process_get_anonymous_group(cJSON *j_responses, struct mosqui cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | getAnonymousGroup", + admin_clientid, admin_username); + return MOSQ_ERR_SUCCESS; } diff --git a/plugins/dynamic-security/plugin.c b/plugins/dynamic-security/plugin.c index f5dce083..27da43a0 100644 --- a/plugins/dynamic-security/plugin.c +++ b/plugins/dynamic-security/plugin.c @@ -128,6 +128,7 @@ int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto { cJSON *j_actions, *j_action, *j_acltype, *j_allow; bool allow; + const char *admin_clientid, *admin_username; j_actions = cJSON_GetObjectItem(command, "acls"); if(j_actions == NULL || !cJSON_IsArray(j_actions)){ @@ -135,6 +136,9 @@ int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto return MOSQ_ERR_INVAL; } + admin_clientid = mosquitto_client_id(context); + 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"); @@ -152,6 +156,8 @@ int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto }else if(!strcasecmp(j_acltype->valuestring, 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"); } } @@ -164,6 +170,7 @@ int dynsec__process_set_default_acl_access(cJSON *j_responses, struct mosquitto int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data) { cJSON *tree, *jtmp, *j_data, *j_acls, *j_acl; + const char *admin_clientid, *admin_username; tree = cJSON_CreateObject(); if(tree == NULL){ @@ -171,6 +178,11 @@ int dynsec__process_get_default_acl_access(cJSON *j_responses, struct mosquitto return MOSQ_ERR_NOMEM; } + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | getDefaultACLAccess", + admin_clientid, admin_username); + if(cJSON_AddStringToObject(tree, "command", "getDefaultACLAccess") == NULL || ((j_data = cJSON_AddObjectToObject(tree, "data")) == NULL) diff --git a/plugins/dynamic-security/roles.c b/plugins/dynamic-security/roles.c index 579a1c92..e78895ab 100644 --- a/plugins/dynamic-security/roles.c +++ b/plugins/dynamic-security/roles.c @@ -265,20 +265,17 @@ int dynsec_roles__config_load(cJSON *tree) if(cJSON_IsObject(j_role) == true){ role = mosquitto_calloc(1, sizeof(struct dynsec__role)); if(role == NULL){ - // FIXME log return MOSQ_ERR_NOMEM; } /* Role name */ jtmp = cJSON_GetObjectItem(j_role, "rolename"); if(jtmp == NULL){ - // FIXME log mosquitto_free(role); continue; } role->rolename = mosquitto_strdup(jtmp->valuestring); if(role->rolename == NULL){ - // FIXME log mosquitto_free(role); continue; } @@ -288,7 +285,6 @@ int dynsec_roles__config_load(cJSON *tree) if(jtmp != NULL){ role->text_name = mosquitto_strdup(jtmp->valuestring); if(role->text_name == NULL){ - // FIXME log mosquitto_free(role->rolename); mosquitto_free(role); continue; @@ -300,7 +296,6 @@ int dynsec_roles__config_load(cJSON *tree) if(jtmp != NULL){ role->text_description = mosquitto_strdup(jtmp->valuestring); if(role->text_description == NULL){ - // FIXME log mosquitto_free(role->text_name); mosquitto_free(role->rolename); mosquitto_free(role); @@ -319,7 +314,6 @@ int dynsec_roles__config_load(cJSON *tree) || dynsec_roles__acl_load(j_acls, ACL_TYPE_UNSUB_PATTERN, &role->acls.unsubscribe_pattern) != 0 ){ - // FIXME log mosquitto_free(role->rolename); mosquitto_free(role); continue; @@ -342,6 +336,7 @@ int dynsec_roles__process_create(cJSON *j_responses, struct mosquitto *context, struct dynsec__role *role; int rc = MOSQ_ERR_SUCCESS; cJSON *j_acls; + const char *admin_clientid, *admin_username; if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "createRole", "Invalid/missing rolename", correlation_data); @@ -419,6 +414,12 @@ int dynsec_roles__process_create(cJSON *j_responses, struct mosquitto *context, dynsec__config_save(); dynsec__command_reply(j_responses, context, "createRole", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | createRole | rolename=%s", + admin_clientid, admin_username, rolename); + return MOSQ_ERR_SUCCESS; error: if(role){ @@ -457,6 +458,7 @@ int dynsec_roles__process_delete(cJSON *j_responses, struct mosquitto *context, { char *rolename; struct dynsec__role *role; + const char *admin_clientid, *admin_username; if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "deleteRole", "Invalid/missing rolename", correlation_data); @@ -474,6 +476,12 @@ int dynsec_roles__process_delete(cJSON *j_responses, struct mosquitto *context, role__free_item(role, true); dynsec__config_save(); dynsec__command_reply(j_responses, context, "deleteRole", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | deleteRole | rolename=%s", + admin_clientid, admin_username, rolename); + return MOSQ_ERR_SUCCESS; }else{ dynsec__command_reply(j_responses, context, "deleteRole", "Role not found", correlation_data); @@ -519,6 +527,7 @@ int dynsec_roles__process_list(cJSON *j_responses, struct mosquitto *context, cJ struct dynsec__role *role, *role_tmp; cJSON *tree, *j_roles, *j_role, *j_data; int i, count, offset; + const char *admin_clientid, *admin_username; json_get_bool(command, "verbose", &verbose, true, false); json_get_int(command, "count", &count, true, -1); @@ -565,6 +574,11 @@ int dynsec_roles__process_list(cJSON *j_responses, struct mosquitto *context, cJ cJSON_AddItemToArray(j_responses, tree); + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | listRoles | rolename=%s | verbose=%s | count=%d | offset=%d", + admin_clientid, admin_username, verbose?"true":"false", count, offset); + return MOSQ_ERR_SUCCESS; } @@ -574,9 +588,10 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context, char *rolename; char *topic; struct dynsec__role *role; - cJSON *jtmp; + cJSON *jtmp, *j_acltype; struct dynsec__acl **acllist, *acl; int rc; + const char *admin_clientid, *admin_username; if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "addRoleACL", "Invalid/missing rolename", correlation_data); @@ -593,22 +608,22 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context, return MOSQ_ERR_SUCCESS; } - jtmp = cJSON_GetObjectItem(command, "acltype"); - if(jtmp == NULL || !cJSON_IsString(jtmp)){ + j_acltype = cJSON_GetObjectItem(command, "acltype"); + if(j_acltype == NULL || !cJSON_IsString(j_acltype)){ dynsec__command_reply(j_responses, context, "addRoleACL", "Invalid/missing acltype", correlation_data); return MOSQ_ERR_SUCCESS; } - if(!strcasecmp(jtmp->valuestring, ACL_TYPE_PUB_C_SEND)){ + if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){ acllist = &role->acls.publish_c_send; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_PUB_C_RECV)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){ acllist = &role->acls.publish_c_recv; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_SUB_LITERAL)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_LITERAL)){ acllist = &role->acls.subscribe_literal; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_SUB_PATTERN)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_PATTERN)){ acllist = &role->acls.subscribe_pattern; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_UNSUB_LITERAL)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_LITERAL)){ acllist = &role->acls.unsubscribe_literal; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_UNSUB_PATTERN)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_PATTERN)){ acllist = &role->acls.unsubscribe_pattern; }else{ dynsec__command_reply(j_responses, context, "addRoleACL", "Unknown acltype", correlation_data); @@ -660,6 +675,11 @@ int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context, role__kick_all(role); + 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"); + return MOSQ_ERR_SUCCESS; } @@ -670,8 +690,9 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte struct dynsec__role *role; struct dynsec__acl **acllist, *acl; char *topic; - cJSON *jtmp; + cJSON *j_acltype; int rc; + const char *admin_clientid, *admin_username; if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "removeRoleACL", "Invalid/missing rolename", correlation_data); @@ -688,22 +709,22 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte return MOSQ_ERR_SUCCESS; } - jtmp = cJSON_GetObjectItem(command, "acltype"); - if(jtmp == NULL || !cJSON_IsString(jtmp)){ + j_acltype = cJSON_GetObjectItem(command, "acltype"); + if(j_acltype == NULL || !cJSON_IsString(j_acltype)){ dynsec__command_reply(j_responses, context, "removeRoleACL", "Invalid/missing acltype", correlation_data); return MOSQ_ERR_SUCCESS; } - if(!strcasecmp(jtmp->valuestring, ACL_TYPE_PUB_C_SEND)){ + if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_SEND)){ acllist = &role->acls.publish_c_send; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_PUB_C_RECV)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_PUB_C_RECV)){ acllist = &role->acls.publish_c_recv; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_SUB_LITERAL)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_LITERAL)){ acllist = &role->acls.subscribe_literal; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_SUB_PATTERN)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_SUB_PATTERN)){ acllist = &role->acls.subscribe_pattern; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_UNSUB_LITERAL)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_LITERAL)){ acllist = &role->acls.unsubscribe_literal; - }else if(!strcasecmp(jtmp->valuestring, ACL_TYPE_UNSUB_PATTERN)){ + }else if(!strcasecmp(j_acltype->valuestring, ACL_TYPE_UNSUB_PATTERN)){ acllist = &role->acls.unsubscribe_pattern; }else{ dynsec__command_reply(j_responses, context, "removeRoleACL", "Unknown acltype", correlation_data); @@ -731,6 +752,12 @@ int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *conte dynsec__command_reply(j_responses, context, "removeRoleACL", NULL, correlation_data); role__kick_all(role); + + 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); + }else{ dynsec__command_reply(j_responses, context, "removeRoleACL", "ACL not found", correlation_data); } @@ -799,6 +826,7 @@ int dynsec_roles__process_modify(cJSON *j_responses, struct mosquitto *context, struct dynsec__acl *tmp_publish_c_send = NULL, *tmp_publish_c_recv = NULL; struct dynsec__acl *tmp_subscribe_literal = NULL, *tmp_subscribe_pattern = NULL; struct dynsec__acl *tmp_unsubscribe_literal = NULL, *tmp_unsubscribe_pattern = NULL; + const char *admin_clientid, *admin_username; if(json_get_string(command, "rolename", &rolename, false) != MOSQ_ERR_SUCCESS){ dynsec__command_reply(j_responses, context, "modifyRole", "Invalid/missing rolename", correlation_data); @@ -875,5 +903,11 @@ int dynsec_roles__process_modify(cJSON *j_responses, struct mosquitto *context, dynsec__config_save(); dynsec__command_reply(j_responses, context, "modifyRole", NULL, correlation_data); + + admin_clientid = mosquitto_client_id(context); + admin_username = mosquitto_client_username(context); + mosquitto_log_printf(MOSQ_LOG_INFO, "dynsec: %s/%s | modifyRole | rolename=%s", + admin_clientid, admin_username, rolename); + return MOSQ_ERR_SUCCESS; }