/src/mosquitto/plugins/dynamic-security/plugin.c
Line | Count | Source |
1 | | /* |
2 | | Copyright (c) 2020-2021 Roger Light <roger@atchoo.org> |
3 | | |
4 | | All rights reserved. This program and the accompanying materials |
5 | | are made available under the terms of the Eclipse Public License 2.0 |
6 | | and Eclipse Distribution License v1.0 which accompany this distribution. |
7 | | |
8 | | The Eclipse Public License is available at |
9 | | https://www.eclipse.org/legal/epl-2.0/ |
10 | | and the Eclipse Distribution License is available at |
11 | | http://www.eclipse.org/org/documents/edl-v10.php. |
12 | | |
13 | | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
14 | | |
15 | | Contributors: |
16 | | Roger Light - initial implementation and documentation. |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <errno.h> |
22 | | #include <stdio.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #include <sys/stat.h> |
26 | | |
27 | | #ifndef WIN32 |
28 | | # include <strings.h> |
29 | | #endif |
30 | | |
31 | | #include "mosquitto.h" |
32 | | |
33 | | #include "dynamic_security.h" |
34 | | #include "json_help.h" |
35 | | |
36 | | MOSQUITTO_PLUGIN_DECLARE_VERSION(5); |
37 | | |
38 | | static struct dynsec__data dynsec_data; |
39 | | static mosquitto_plugin_id_t *plg_id = NULL; |
40 | | |
41 | | #ifdef WIN32 |
42 | | # include <winsock2.h> |
43 | | # include <aclapi.h> |
44 | | # include <io.h> |
45 | | # include <lmcons.h> |
46 | | # include <fcntl.h> |
47 | | # define PATH_MAX MAX_PATH |
48 | | #else |
49 | | # include <sys/stat.h> |
50 | | # include <pwd.h> |
51 | | # include <grp.h> |
52 | | # include <unistd.h> |
53 | | #endif |
54 | | |
55 | | |
56 | | int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **user_data, struct mosquitto_opt *options, int option_count) |
57 | 5.78k | { |
58 | 5.78k | int i; |
59 | 5.78k | int rc; |
60 | | |
61 | 5.78k | UNUSED(user_data); |
62 | | |
63 | 5.78k | memset(&dynsec_data, 0, sizeof(struct dynsec__data)); |
64 | | |
65 | 11.5k | for(i=0; i<option_count; i++){ |
66 | 5.78k | if(!strcasecmp(options[i].key, "config_file")){ |
67 | 5.78k | dynsec_data.config_file = mosquitto_strdup(options[i].value); |
68 | 5.78k | if(dynsec_data.config_file == NULL){ |
69 | 0 | return MOSQ_ERR_NOMEM; |
70 | 0 | } |
71 | 5.78k | }else if(!strcasecmp(options[i].key, "password_init_file")){ |
72 | 0 | dynsec_data.password_init_file = mosquitto_strdup(options[i].value); |
73 | 0 | if(dynsec_data.password_init_file == NULL){ |
74 | 0 | return MOSQ_ERR_NOMEM; |
75 | 0 | } |
76 | 0 | } |
77 | 5.78k | } |
78 | 5.78k | if(dynsec_data.config_file == NULL){ |
79 | 0 | mosquitto_log_printf(MOSQ_LOG_WARNING, "Warning: Dynamic security plugin has no plugin_opt_config_file defined. The plugin will not be activated."); |
80 | 0 | return MOSQ_ERR_SUCCESS; |
81 | 0 | } |
82 | | |
83 | 5.78k | plg_id = identifier; |
84 | 5.78k | mosquitto_plugin_set_info(identifier, "dynamic-security", NULL); |
85 | | |
86 | 5.78k | dynsec__config_load(&dynsec_data); |
87 | | |
88 | 5.78k | rc = mosquitto_callback_register(plg_id, MOSQ_EVT_CONTROL, dynsec_control_callback, "$CONTROL/dynamic-security/v1", &dynsec_data); |
89 | 5.78k | if(rc == MOSQ_ERR_ALREADY_EXISTS){ |
90 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can currently only be loaded once."); |
91 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Note that this was previously incorrectly allowed but could cause problems with duplicate entries in the config."); |
92 | 0 | goto error; |
93 | 5.78k | }else if(rc == MOSQ_ERR_NOMEM){ |
94 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); |
95 | 0 | goto error; |
96 | 5.78k | }else if(rc != MOSQ_ERR_SUCCESS){ |
97 | 0 | goto error; |
98 | 0 | } |
99 | | |
100 | 5.78k | rc = mosquitto_callback_register(plg_id, MOSQ_EVT_BASIC_AUTH, dynsec_auth__basic_auth_callback, NULL, &dynsec_data); |
101 | 5.78k | if(rc == MOSQ_ERR_ALREADY_EXISTS){ |
102 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can only be loaded once."); |
103 | 0 | goto error; |
104 | 5.78k | }else if(rc == MOSQ_ERR_NOMEM){ |
105 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); |
106 | 0 | goto error; |
107 | 5.78k | }else if(rc != MOSQ_ERR_SUCCESS){ |
108 | 5.78k | goto error; |
109 | 5.78k | } |
110 | | |
111 | 0 | rc = mosquitto_callback_register(plg_id, MOSQ_EVT_ACL_CHECK, dynsec__acl_check_callback, NULL, &dynsec_data); |
112 | 0 | if(rc == MOSQ_ERR_ALREADY_EXISTS){ |
113 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Dynamic security plugin can only be loaded once."); |
114 | 0 | goto error; |
115 | 0 | }else if(rc == MOSQ_ERR_NOMEM){ |
116 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); |
117 | 0 | goto error; |
118 | 0 | }else if(rc != MOSQ_ERR_SUCCESS){ |
119 | 0 | goto error; |
120 | 0 | } |
121 | | |
122 | 0 | rc = mosquitto_callback_register(plg_id, MOSQ_EVT_TICK, dynsec__tick_callback, NULL, &dynsec_data); |
123 | 0 | if(rc == MOSQ_ERR_NOMEM){ |
124 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); |
125 | 0 | goto error; |
126 | 0 | }else if(rc != MOSQ_ERR_SUCCESS){ |
127 | 0 | goto error; |
128 | 0 | } |
129 | | |
130 | 0 | return MOSQ_ERR_SUCCESS; |
131 | 5.78k | error: |
132 | 5.78k | mosquitto_free(dynsec_data.config_file); |
133 | 5.78k | dynsec_data.config_file = NULL; |
134 | 5.78k | return rc; |
135 | 0 | } |
136 | | |
137 | | |
138 | | int mosquitto_plugin_cleanup(void *user_data, struct mosquitto_opt *options, int option_count) |
139 | 5.78k | { |
140 | 5.78k | UNUSED(user_data); |
141 | 5.78k | UNUSED(options); |
142 | 5.78k | UNUSED(option_count); |
143 | | |
144 | 5.78k | dynsec_groups__cleanup(&dynsec_data); |
145 | 5.78k | dynsec_clients__cleanup(&dynsec_data); |
146 | 5.78k | dynsec_roles__cleanup(&dynsec_data); |
147 | 5.78k | dynsec_kicklist__cleanup(&dynsec_data); |
148 | | |
149 | 5.78k | mosquitto_free(dynsec_data.config_file); |
150 | 5.78k | dynsec_data.config_file = NULL; |
151 | | |
152 | 5.78k | mosquitto_free(dynsec_data.password_init_file); |
153 | 5.78k | dynsec_data.password_init_file = NULL; |
154 | | |
155 | 5.78k | mosquitto_callback_unregister(plg_id, MOSQ_EVT_CONTROL, dynsec_control_callback, "$CONTROL/dynamic-security/v1"); |
156 | 5.78k | mosquitto_callback_unregister(plg_id, MOSQ_EVT_BASIC_AUTH, dynsec_auth__basic_auth_callback, NULL); |
157 | 5.78k | mosquitto_callback_unregister(plg_id, MOSQ_EVT_ACL_CHECK, dynsec__acl_check_callback, NULL); |
158 | 5.78k | mosquitto_callback_unregister(plg_id, MOSQ_EVT_TICK, dynsec__tick_callback, NULL); |
159 | | |
160 | 5.78k | return MOSQ_ERR_SUCCESS; |
161 | 5.78k | } |