diff --git a/apps/mosquitto_ctrl/dynsec.c b/apps/mosquitto_ctrl/dynsec.c index 8ecb761f..f00e0f1d 100644 --- a/apps/mosquitto_ctrl/dynsec.c +++ b/apps/mosquitto_ctrl/dynsec.c @@ -41,6 +41,7 @@ void dynsec__print_usage(void) printf("Create a new client: createClient [-c clientid] [-p password]\n"); printf("Delete a client: deleteClient \n"); printf("Set a client password: setClientPassword [password]\n"); + printf("Set a client id: setClientId [clientid]\n"); printf("Add a role to a client: addClientRole [priority]\n"); printf(" Higher priority (larger numerical value) roles are evaluated first.\n"); printf("Remove role from a client: removeClientRole \n"); @@ -803,6 +804,8 @@ int dynsec__main(int argc, char *argv[], struct mosq_ctrl *ctrl) rc = dynsec_client__get(argc-1, &argv[1], j_command); }else if(!strcasecmp(argv[0], "listClients")){ rc = dynsec_client__list_all(argc-1, &argv[1], j_command); + }else if(!strcasecmp(argv[0], "setClientId")){ + rc = dynsec_client__set_id(argc-1, &argv[1], j_command); }else if(!strcasecmp(argv[0], "setClientPassword")){ rc = dynsec_client__set_password(argc-1, &argv[1], j_command); }else if(!strcasecmp(argv[0], "addClientRole")){ diff --git a/apps/mosquitto_ctrl/dynsec_client.c b/apps/mosquitto_ctrl/dynsec_client.c index d6bc3a11..f007b3da 100644 --- a/apps/mosquitto_ctrl/dynsec_client.c +++ b/apps/mosquitto_ctrl/dynsec_client.c @@ -117,6 +117,30 @@ int dynsec_client__enable_disable(int argc, char *argv[], cJSON *j_command, cons } } +int dynsec_client__set_id(int argc, char *argv[], cJSON *j_command) +{ + char *username = NULL, *clientid = NULL; + + if(argc == 2){ + username = argv[0]; + clientid = argv[1]; + }else if(argc == 1){ + username = argv[0]; + }else{ + return MOSQ_ERR_INVAL; + } + + if(cJSON_AddStringToObject(j_command, "command", "setClientId") == NULL + || cJSON_AddStringToObject(j_command, "username", username) == NULL + || (clientid && cJSON_AddStringToObject(j_command, "clientid", clientid) == NULL) + ){ + + return MOSQ_ERR_NOMEM; + }else{ + return MOSQ_ERR_SUCCESS; + } +} + int dynsec_client__set_password(int argc, char *argv[], cJSON *j_command) { char *username = NULL, *password = NULL; diff --git a/apps/mosquitto_ctrl/mosquitto_ctrl.h b/apps/mosquitto_ctrl/mosquitto_ctrl.h index 248b8401..a51af2c3 100644 --- a/apps/mosquitto_ctrl/mosquitto_ctrl.h +++ b/apps/mosquitto_ctrl/mosquitto_ctrl.h @@ -95,6 +95,7 @@ int dynsec_client__delete(int argc, char *argv[], cJSON *j_command); int dynsec_client__enable_disable(int argc, char *argv[], cJSON *j_command, const char *command); int dynsec_client__get(int argc, char *argv[], cJSON *j_command); int dynsec_client__list_all(int argc, char *argv[], cJSON *j_command); +int dynsec_client__set_id(int argc, char *argv[], cJSON *j_command); int dynsec_client__set_password(int argc, char *argv[], cJSON *j_command); int dynsec_group__add_remove_client(int argc, char *argv[], cJSON *j_command, const char *command); diff --git a/plugins/dynamic-security/clients.c b/plugins/dynamic-security/clients.c index 9c04b1bf..d4841231 100644 --- a/plugins/dynamic-security/clients.c +++ b/plugins/dynamic-security/clients.c @@ -546,6 +546,52 @@ int dynsec_clients__process_enable(cJSON *j_responses, struct mosquitto *context } +int dynsec_clients__process_set_id(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data) +{ + char *username, *clientid, *clientid_heap; + struct dynsec__client *client; + + if(json_get_string(command, "username", &username, false) != MOSQ_ERR_SUCCESS){ + dynsec__command_reply(j_responses, context, "setClientId", "Invalid/missing username", correlation_data); + return MOSQ_ERR_INVAL; + } + if(mosquitto_validate_utf8(username, (int)strlen(username)) != MOSQ_ERR_SUCCESS){ + dynsec__command_reply(j_responses, context, "setClientId", "Username not valid UTF-8", correlation_data); + return MOSQ_ERR_INVAL; + } + + if(json_get_string(command, "clientid", &clientid, false) != MOSQ_ERR_SUCCESS){ + dynsec__command_reply(j_responses, context, "setClientId", "Invalid/missing client ID", correlation_data); + return MOSQ_ERR_INVAL; + } + if(mosquitto_validate_utf8(clientid, (int)strlen(clientid)) != MOSQ_ERR_SUCCESS){ + dynsec__command_reply(j_responses, context, "setClientId", "Client ID not valid UTF-8", correlation_data); + return MOSQ_ERR_INVAL; + } + + client = dynsec_clients__find(username); + if(client == NULL){ + dynsec__command_reply(j_responses, context, "setClientId", "Client not found", correlation_data); + return MOSQ_ERR_SUCCESS; + } + + clientid_heap = mosquitto_strdup(clientid); + if(clientid_heap == NULL){ + dynsec__command_reply(j_responses, context, "setClientId", "Internal error", correlation_data); + return MOSQ_ERR_NOMEM; + } + if(client->clientid){ + mosquitto_free(client->clientid); + } + client->clientid = clientid_heap; + + /* Enforce any changes */ + mosquitto_kick_client_by_username(username, false); + + return MOSQ_ERR_SUCCESS; +} + + int dynsec_clients__process_set_password(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data) { char *username, *password; diff --git a/plugins/dynamic-security/dynamic_security.h b/plugins/dynamic-security/dynamic_security.h index 8ddcc893..f46e437d 100644 --- a/plugins/dynamic-security/dynamic_security.h +++ b/plugins/dynamic-security/dynamic_security.h @@ -182,6 +182,7 @@ int dynsec_clients__process_get(cJSON *j_responses, struct mosquitto *context, c int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); int dynsec_clients__process_remove_role(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); +int dynsec_clients__process_set_id(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); int dynsec_clients__process_set_password(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); struct dynsec__client *dynsec_clients__find(const char *username); diff --git a/plugins/dynamic-security/plugin.c b/plugins/dynamic-security/plugin.c index 837f15d2..264fef35 100644 --- a/plugins/dynamic-security/plugin.c +++ b/plugins/dynamic-security/plugin.c @@ -539,6 +539,8 @@ int dynsec__handle_control(cJSON *j_responses, struct mosquitto *context, cJSON rc = dynsec_clients__process_modify(j_responses, context, aiter, correlation_data); }else if(!strcasecmp(command, "setClientPassword")){ rc = dynsec_clients__process_set_password(j_responses, context, aiter, correlation_data); + }else if(!strcasecmp(command, "setClientId")){ + rc = dynsec_clients__process_set_id(j_responses, context, aiter, correlation_data); }else if(!strcasecmp(command, "addClientRole")){ rc = dynsec_clients__process_add_role(j_responses, context, aiter, correlation_data); }else if(!strcasecmp(command, "removeClientRole")){