1 #ifndef DYNAMIC_SECURITY_H 2 #define DYNAMIC_SECURITY_H 3 /* 4 Copyright (c) 2020 Roger Light <roger@atchoo.org> 5 6 All rights reserved. This program and the accompanying materials 7 are made available under the terms of the Eclipse Public License 2.0 8 and Eclipse Distribution License v1.0 which accompany this distribution. 9 10 The Eclipse Public License is available at 11 https://www.eclipse.org/legal/epl-2.0/ 12 and the Eclipse Distribution License is available at 13 http://www.eclipse.org/org/documents/edl-v10.php. 14 15 SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause 16 17 Contributors: 18 Roger Light - initial implementation and documentation. 19 */ 20 21 #include <cjson/cJSON.h> 22 #include <uthash.h> 23 #include "mosquitto.h" 24 #include "password_mosq.h" 25 26 /* ################################################################ 27 * # 28 * # ACL types 29 * # 30 * ################################################################ */ 31 32 #define ACL_TYPE_PUB_C_RECV "publishClientReceive" 33 #define ACL_TYPE_PUB_C_SEND "publishClientSend" 34 #define ACL_TYPE_SUB_GENERIC "subscribe" 35 #define ACL_TYPE_SUB_LITERAL "subscribeLiteral" 36 #define ACL_TYPE_SUB_PATTERN "subscribePattern" 37 #define ACL_TYPE_UNSUB_GENERIC "unsubscribe" 38 #define ACL_TYPE_UNSUB_LITERAL "unsubscribeLiteral" 39 #define ACL_TYPE_UNSUB_PATTERN "unsubscribePattern" 40 41 /* ################################################################ 42 * # 43 * # Error codes 44 * # 45 * ################################################################ */ 46 47 #define ERR_USER_NOT_FOUND 10000 48 #define ERR_GROUP_NOT_FOUND 10001 49 #define ERR_LIST_NOT_FOUND 10002 50 51 /* ################################################################ 52 * # 53 * # Datatypes 54 * # 55 * ################################################################ */ 56 57 struct dynsec__clientlist{ 58 UT_hash_handle hh; 59 struct dynsec__client *client; 60 int priority; 61 }; 62 63 struct dynsec__grouplist{ 64 UT_hash_handle hh; 65 struct dynsec__group *group; 66 int priority; 67 }; 68 69 struct dynsec__rolelist{ 70 UT_hash_handle hh; 71 char *rolename; 72 struct dynsec__role *role; 73 int priority; 74 }; 75 76 struct dynsec__client{ 77 UT_hash_handle hh; 78 struct mosquitto_pw pw; 79 struct dynsec__rolelist *rolelist; 80 struct dynsec__grouplist *grouplist; 81 char *username; 82 char *clientid; 83 char *text_name; 84 char *text_description; 85 bool disabled; 86 }; 87 88 struct dynsec__group{ 89 UT_hash_handle hh; 90 struct dynsec__rolelist *rolelist; 91 struct dynsec__clientlist *clientlist; 92 char *groupname; 93 char *text_name; 94 char *text_description; 95 }; 96 97 98 struct dynsec__acl{ 99 UT_hash_handle hh; 100 char *topic; 101 int priority; 102 bool allow; 103 }; 104 105 struct dynsec__acls{ 106 struct dynsec__acl *publish_c_send; 107 struct dynsec__acl *publish_c_recv; 108 struct dynsec__acl *subscribe_literal; 109 struct dynsec__acl *subscribe_pattern; 110 struct dynsec__acl *unsubscribe_literal; 111 struct dynsec__acl *unsubscribe_pattern; 112 }; 113 114 struct dynsec__role{ 115 UT_hash_handle hh; 116 struct dynsec__acls acls; 117 struct dynsec__clientlist *clientlist; 118 struct dynsec__grouplist *grouplist; 119 char *rolename; 120 char *text_name; 121 char *text_description; 122 }; 123 124 struct dynsec__acl_default_access{ 125 bool publish_c_send; 126 bool publish_c_recv; 127 bool subscribe; 128 bool unsubscribe; 129 }; 130 131 extern struct dynsec__group *dynsec_anonymous_group; 132 extern struct dynsec__acl_default_access default_access; 133 134 /* ################################################################ 135 * # 136 * # Plugin Functions 137 * # 138 * ################################################################ */ 139 140 void dynsec__config_save(void); 141 int dynsec__handle_control(cJSON *j_responses, struct mosquitto *context, cJSON *commands); 142 void dynsec__command_reply(cJSON *j_responses, struct mosquitto *context, const char *command, const char *error, const char *correlation_data); 143 144 145 /* ################################################################ 146 * # 147 * # ACL Functions 148 * # 149 * ################################################################ */ 150 151 int dynsec__acl_check_callback(int event, void *event_data, void *userdata); 152 bool sub_acl_check(const char *acl, const char *sub); 153 154 155 /* ################################################################ 156 * # 157 * # Auth Functions 158 * # 159 * ################################################################ */ 160 161 int dynsec_auth__base64_encode(unsigned char *in, int in_len, char **encoded); 162 int dynsec_auth__base64_decode(char *in, unsigned char **decoded, int *decoded_len); 163 int dynsec_auth__pw_hash(struct dynsec__client *client, const char *password, unsigned char *password_hash, int password_hash_len, bool new_password); 164 int dynsec_auth__basic_auth_callback(int event, void *event_data, void *userdata); 165 166 167 /* ################################################################ 168 * # 169 * # Client Functions 170 * # 171 * ################################################################ */ 172 173 void dynsec_clients__cleanup(void); 174 int dynsec_clients__config_load(cJSON *tree); 175 int dynsec_clients__config_save(cJSON *tree); 176 int dynsec_clients__process_add_role(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 177 int dynsec_clients__process_create(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 178 int dynsec_clients__process_delete(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 179 int dynsec_clients__process_disable(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 180 int dynsec_clients__process_enable(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 181 int dynsec_clients__process_get(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 182 int dynsec_clients__process_list(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 183 int dynsec_clients__process_modify(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 184 int dynsec_clients__process_remove_role(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 185 int dynsec_clients__process_set_id(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 186 int dynsec_clients__process_set_password(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 187 struct dynsec__client *dynsec_clients__find(const char *username); 188 189 190 /* ################################################################ 191 * # 192 * # Client List Functions 193 * # 194 * ################################################################ */ 195 196 cJSON *dynsec_clientlist__all_to_json(struct dynsec__clientlist *base_clientlist); 197 int dynsec_clientlist__add(struct dynsec__clientlist **base_clientlist, struct dynsec__client *client, int priority); 198 void dynsec_clientlist__cleanup(struct dynsec__clientlist **base_clientlist); 199 void dynsec_clientlist__remove(struct dynsec__clientlist **base_clientlist, struct dynsec__client *client); 200 void dynsec_clientlist__kick_all(struct dynsec__clientlist *base_clientlist); 201 202 203 /* ################################################################ 204 * # 205 * # Group Functions 206 * # 207 * ################################################################ */ 208 209 void dynsec_groups__cleanup(void); 210 int dynsec_groups__config_load(cJSON *tree); 211 int dynsec_groups__add_client(const char *username, const char *groupname, int priority, bool update_config); 212 int dynsec_groups__config_save(cJSON *tree); 213 int dynsec_groups__process_add_client(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 214 int dynsec_groups__process_add_role(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 215 int dynsec_groups__process_create(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 216 int dynsec_groups__process_delete(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 217 int dynsec_groups__process_get(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 218 int dynsec_groups__process_list(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 219 int dynsec_groups__process_modify(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 220 int dynsec_groups__process_remove_client(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 221 int dynsec_groups__process_remove_role(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 222 int dynsec_groups__process_get_anonymous_group(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 223 int dynsec_groups__process_set_anonymous_group(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 224 int dynsec_groups__remove_client(const char *username, const char *groupname, bool update_config); 225 struct dynsec__group *dynsec_groups__find(const char *groupname); 226 227 228 /* ################################################################ 229 * # 230 * # Group List Functions 231 * # 232 * ################################################################ */ 233 234 cJSON *dynsec_grouplist__all_to_json(struct dynsec__grouplist *base_grouplist); 235 int dynsec_grouplist__add(struct dynsec__grouplist **base_grouplist, struct dynsec__group *group, int priority); 236 void dynsec_grouplist__cleanup(struct dynsec__grouplist **base_grouplist); 237 void dynsec_grouplist__remove(struct dynsec__grouplist **base_grouplist, struct dynsec__group *group); 238 239 240 /* ################################################################ 241 * # 242 * # Role Functions 243 * # 244 * ################################################################ */ 245 246 void dynsec_roles__cleanup(void); 247 int dynsec_roles__config_load(cJSON *tree); 248 int dynsec_roles__config_save(cJSON *tree); 249 int dynsec_roles__process_add_acl(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 250 int dynsec_roles__process_create(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 251 int dynsec_roles__process_delete(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 252 int dynsec_roles__process_get(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 253 int dynsec_roles__process_list(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 254 int dynsec_roles__process_modify(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 255 int dynsec_roles__process_remove_acl(cJSON *j_responses, struct mosquitto *context, cJSON *command, char *correlation_data); 256 struct dynsec__role *dynsec_roles__find(const char *rolename); 257 258 259 /* ################################################################ 260 * # 261 * # Role List Functions 262 * # 263 * ################################################################ */ 264 265 int dynsec_rolelist__client_add(struct dynsec__client *client, struct dynsec__role *role, int priority); 266 int dynsec_rolelist__client_remove(struct dynsec__client *client, struct dynsec__role *role); 267 int dynsec_rolelist__group_add(struct dynsec__group *group, struct dynsec__role *role, int priority); 268 void dynsec_rolelist__group_remove(struct dynsec__group *group, struct dynsec__role *role); 269 int dynsec_rolelist__load_from_json(cJSON *command, struct dynsec__rolelist **rolelist); 270 void dynsec_rolelist__cleanup(struct dynsec__rolelist **base_rolelist); 271 cJSON *dynsec_rolelist__all_to_json(struct dynsec__rolelist *base_rolelist); 272 273 #endif 274