diff --git a/ChangeLog.txt b/ChangeLog.txt
index c51f4ad8..ef182544 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -41,6 +41,8 @@ Broker:
across the broker, so only a single plugin can register for a given $CONTROL
topic.
- Password salts are now 64 bytes long.
+- Add the `global_plugin` option, which gives global plugin loaded regardless
+ of `per_listener_settings`.
Client library:
- Add MOSQ_OPT_DISABLE_SOCKETPAIR to allow the disabling of the socketpair
diff --git a/man/mosquitto.conf.5.xml b/man/mosquitto.conf.5.xml
index 2fc95356..9d36300c 100644
--- a/man/mosquitto.conf.5.xml
+++ b/man/mosquitto.conf.5.xml
@@ -205,9 +205,9 @@
[ true | false ]
- This option is deprecated and will be removed in a
- future version. The behaviour will default to true.
-
+ This option is deprecated and will be removed in a
+ future version. The behaviour will default to true.
+ If a client is subscribed to multiple subscriptions
that overlap, e.g. foo/# and foo/+/baz , then MQTT
expects that when the broker receives a message on a
@@ -252,35 +252,6 @@
Reloaded on reload signal.
-
- value
-
- Options to be passed to the auth plugin. See the
- specific plugin instructions.
-
- Applies to the current authentication plugin being configured.
-
-
-
- file path
-
- Specify an external module to use for authentication
- and access control. This allows custom
- username/password and access control functions to be
- created.
- Can be specified multiple times to load multiple
- plugins. The plugins will be processed in the order
- that they are specified.
- If , or
- are used in the config file
- alongsize , the plugin
- checks will run after the built in checks.
- Not currently reloaded on reload signal.
- See also
-
-
-
- [ true | false ]
@@ -382,8 +353,8 @@
prefix
- This option is deprecated and will be removed in a
- future version.
+ This option is deprecated and will be removed in a
+ future version.If defined, only clients that have a clientid with a
prefix that matches clientid_prefixes will be allowed
to connect to the broker. For example, setting
@@ -411,6 +382,30 @@
Reloaded on reload signal.
+
+ file path
+
+
+ Load an external module to extend broker features. This loads plugins
+ for use across all listeners, regardless of the value of the
+ option. This option functions
+ the same as the option in all other ways.
+
+
+
+ If you set , then define both a
+ and a (which will be
+ attached to a specific listener), then the global plugin will always be
+ processed first.
+
+
+
+ If you set , then
+ behaves identically to
+ .
+
+
+ dir
@@ -781,7 +776,7 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
, ,
,
,
- ,
+ ,
,
.
Note that if set to true, then a durable client (i.e.
@@ -886,6 +881,43 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
Not reloaded on reload signal.
+
+ value
+ value
+
+ Options to be passed to a plugin. See the
+ specific plugin instructions.
+
+ Applies to the current plugin/global_plugin being configured.
+
+
+
+ file path
+ file path
+
+ Specify an external module to use for authentication,
+ access control, and other features. This allows custom
+ username/password and access control functions to be
+ created and other behaviour to be modified.
+ Can be specified multiple times to load multiple
+ plugins. The plugins will be processed in the order
+ that they are specified.
+ If , or
+ are used in the config file
+ alongsize , the plugin
+ checks will run after the built in checks.
+ Not currently reloaded on reload signal.
+
+ If is set to
+ true, this plugin will be
+ loaded for the current listener only.
+
+ See also
+
+ and the option.
+
+
+ file path
@@ -1022,9 +1054,9 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
address
- This option is deprecated and will be removed in a
+ This option is deprecated and will be removed in a
future version. Use the instead.
-
+ Listen for incoming network connections on the
specified IP address/hostname only. This is useful
to restrict access to certain network interfaces.
@@ -1185,9 +1217,9 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
port number
- This option is deprecated and will be removed in a
+ This option is deprecated and will be removed in a
future version. Use the instead.
-
+ Set the network port for the default listener to
listen on. Defaults to 1883.Not reloaded on reload signal.
@@ -1331,21 +1363,21 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
cipher:list
-
- The list of allowed ciphers for this listener, for
- TLS v1.2 and earlier only, each separated with
- a colon. Available ciphers can be obtained using
- the "openssl ciphers" command.
-
+
+ The list of allowed ciphers for this listener, for
+ TLS v1.2 and earlier only, each separated with
+ a colon. Available ciphers can be obtained using
+ the "openssl ciphers" command.
+ cipher:list
-
- The list of allowed ciphersuites for this listener,
- for TLS v1.3, each separated with a colon.
-
+
+ The list of allowed ciphersuites for this listener,
+ for TLS v1.3, each separated with a colon.
+
@@ -1649,15 +1681,15 @@ openssl dhparam -out dhparam.pem 2048
idleintervalcounter
-
- Set TCP keepalive parameters for this bridge connection.
- Use this option to allow you to set a long MQTT
- keepalive value, whilst still being able to detect the
- connection dropping in a reasonable time.
+
+ Set TCP keepalive parameters for this bridge connection.
+ Use this option to allow you to set a long MQTT
+ keepalive value, whilst still being able to detect the
+ connection dropping in a reasonable time.
- This may be useful when bridging to services that bill
- for PINGREQ messages.
+ This may be useful when bridging to services that bill
+ for PINGREQ messages.
Disabled by default.
diff --git a/mosquitto.conf b/mosquitto.conf
index 51c72fd3..36bcb1c4 100644
--- a/mosquitto.conf
+++ b/mosquitto.conf
@@ -19,7 +19,7 @@
# options are controlled on a per listener basis. The following options are
# affected:
#
-# password_file acl_file psk_file auth_plugin auth_opt_* allow_anonymous
+# password_file acl_file psk_file plugin plugin_opt_* allow_anonymous
# auto_id_prefix allow_zero_length_clientid
#
# Note that if set to true, then a durable client (i.e. with clean session set
@@ -529,8 +529,8 @@
# offers very little in the way of security.
#
# See the TLS client require_certificate and use_identity_as_username options
-# for alternative authentication options. If an auth_plugin is used as well as
-# password_file, the auth_plugin check will be made first.
+# for alternative authentication options. If a plugin is used as well as
+# password_file, the plugin check will be made after the password_file check.
#password_file
# Access may also be controlled using a pre-shared-key file. This requires
@@ -538,7 +538,7 @@
# lines in the format:
# identity:key
# The key should be in hexadecimal format without a leading "0x".
-# If an auth_plugin is used as well, the auth_plugin check will be made first.
+# If an plugin is used as well, the plugin check will be made second.
#psk_file
# Control access to topics on the broker using an access control list
@@ -592,8 +592,8 @@
#
# pattern write sensor/%u/data
#
-# If an auth_plugin is used as well as acl_file, the auth_plugin check will be
-# made first.
+# If an plugin is used as well as acl_file, the plugin check will be
+# made after the acl_file check.
#acl_file
# -----------------------------------------------------------------
@@ -601,25 +601,39 @@
# -----------------------------------------------------------------
# External authentication and access control can be supported with the
-# auth_plugin option. This is a path to a loadable plugin. See also the
-# auth_opt_* options described below.
+# plugin option. This is a path to a loadable plugin. See also the
+# plugin_opt_* options described below.
#
-# The auth_plugin option can be specified multiple times to load multiple
+# The plugin option can be specified multiple times to load multiple
# plugins. The plugins will be processed in the order that they are specified
-# here. If the auth_plugin option is specified alongside either of
-# password_file or acl_file then the plugin checks will be made first.
+# here. If the plugin option is specified alongside either of
+# password_file or acl_file then the plugin checks will be made after the built
+# in checks.
#
-#auth_plugin
+#plugin
-# If the auth_plugin option above is used, define options to pass to the
+# If the plugin option above is used, define options to pass to the
# plugin here as described by the plugin instructions. All options named
-# using the format auth_opt_* will be passed to the plugin, for example:
+# using the format plugin_opt_* will be passed to the plugin, for example:
#
-# auth_opt_db_host
-# auth_opt_db_port
-# auth_opt_db_username
-# auth_opt_db_password
+# plugin_opt_db_host
+# plugin_opt_db_port
+# plugin_opt_db_username
+# plugin_opt_db_password
+# The `plugin` option is affected by the `per_listener_settings` option. If you
+# want to set `per_listener_settings true` but still want to use a plugin work
+# across all listeners, then use the `global_plugin` option. This option
+# functions the same as the `plugin` option in all other ways.
+#
+# If you set `per_listener_settings true`, then define both a `global_plugin`
+# and a `plugin` (which will be attached to a specific listener), then the
+# global plugin will always be processed first.
+#
+# If you set `per_listener_settings false`, then `global_plugin` behaves
+# identically to `plugin`.
+#
+#global_plugin
# =================================================================
# Bridges
diff --git a/src/conf.c b/src/conf.c
index 94a4d29b..f7c08100 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -928,9 +928,14 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
mosquitto__free(key);
return MOSQ_ERR_INVAL;
}
- }else if(!strcmp(token, "auth_plugin") || !strcmp(token, "plugin")){
- if(reload) continue; /* Auth plugin not currently valid for reloading. */
- conf__set_cur_security_options(config, cur_listener, &cur_security_options);
+ }else if(!strcmp(token, "auth_plugin") || !strcmp(token, "plugin") || !strcmp(token, "global_plugin")){
+ if(reload) continue; /* plugin not currently valid for reloading. */
+ if(!strcmp(token, "global_plugin")){
+ cur_security_options = &db.config->security_options;
+ }else{
+ conf__set_cur_security_options(config, cur_listener, &cur_security_options);
+ }
+
cur_security_options->auth_plugin_configs = mosquitto__realloc(cur_security_options->auth_plugin_configs, (size_t)(cur_security_options->auth_plugin_config_count+1)*sizeof(struct mosquitto__auth_plugin_config));
if(!cur_security_options->auth_plugin_configs){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
diff --git a/src/plugin.c b/src/plugin.c
index b44c235a..07f4214a 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -104,22 +104,12 @@ int plugin__load_v5(struct mosquitto__listener *listener, struct mosquitto__auth
}
-void plugin__handle_connect(struct mosquitto *context)
+static void plugin__handle_connect_single(struct mosquitto__security_options *opts, struct mosquitto *context)
{
struct mosquitto_evt_connect event_data;
struct mosquitto__callback *cb_base;
- struct mosquitto__security_options *opts;
- if(db.config->per_listener_settings){
- if(context->listener == NULL){
- return;
- }
- opts = &context->listener->security_options;
- }else{
- opts = &db.config->security_options;
- }
memset(&event_data, 0, sizeof(event_data));
-
event_data.client = context;
DL_FOREACH(opts->plugin_callbacks.connect, cb_base){
cb_base->cb(MOSQ_EVT_CONNECT, &event_data, cb_base->userdata);
@@ -127,22 +117,24 @@ void plugin__handle_connect(struct mosquitto *context)
}
-void plugin__handle_disconnect(struct mosquitto *context, int reason)
+void plugin__handle_connect(struct mosquitto *context)
+{
+ /* Global plugins */
+ plugin__handle_connect_single(&db.config->security_options, context);
+
+ /* Per listener plugins */
+ if(db.config->per_listener_settings && context->listener){
+ plugin__handle_connect_single(&context->listener->security_options, context);
+ }
+}
+
+
+static void plugin__handle_disconnect_single(struct mosquitto__security_options *opts, struct mosquitto *context, int reason)
{
struct mosquitto_evt_disconnect event_data;
struct mosquitto__callback *cb_base;
- struct mosquitto__security_options *opts;
- if(db.config->per_listener_settings){
- if(context->listener == NULL){
- return;
- }
- opts = &context->listener->security_options;
- }else{
- opts = &db.config->security_options;
- }
memset(&event_data, 0, sizeof(event_data));
-
event_data.client = context;
event_data.reason = reason;
DL_FOREACH(opts->plugin_callbacks.disconnect, cb_base){
@@ -151,26 +143,25 @@ void plugin__handle_disconnect(struct mosquitto *context, int reason)
}
-int plugin__handle_message(struct mosquitto *context, struct mosquitto_msg_store *stored)
+void plugin__handle_disconnect(struct mosquitto *context, int reason)
+{
+ /* Global plugins */
+ plugin__handle_disconnect_single(&db.config->security_options, context, reason);
+
+ /* Per listener plugins */
+ if(db.config->per_listener_settings && context->listener){
+ plugin__handle_disconnect_single(&context->listener->security_options, context, reason);
+ }
+}
+
+
+static int plugin__handle_message_single(struct mosquitto__security_options *opts, struct mosquitto *context, struct mosquitto_msg_store *stored)
{
struct mosquitto_evt_message event_data;
struct mosquitto__callback *cb_base;
- struct mosquitto__security_options *opts;
int rc = MOSQ_ERR_SUCCESS;
- if(db.config->per_listener_settings){
- if(context->listener == NULL){
- return MOSQ_ERR_SUCCESS;
- }
- opts = &context->listener->security_options;
- }else{
- opts = &db.config->security_options;
- }
- if(opts->plugin_callbacks.message == NULL){
- return MOSQ_ERR_SUCCESS;
- }
memset(&event_data, 0, sizeof(event_data));
-
event_data.client = context;
event_data.topic = stored->topic;
event_data.payloadlen = stored->payloadlen;
@@ -198,11 +189,40 @@ int plugin__handle_message(struct mosquitto *context, struct mosquitto_msg_store
return rc;
}
+int plugin__handle_message(struct mosquitto *context, struct mosquitto_msg_store *stored)
+{
+ int rc = MOSQ_ERR_SUCCESS;
-void plugin__handle_tick(void)
+ /* Global plugins */
+ rc = plugin__handle_message_single(&db.config->security_options,
+ context, stored);
+ if(rc) return rc;
+
+ if(db.config->per_listener_settings && context->listener){
+ rc = plugin__handle_message_single(&context->listener->security_options,
+ context, stored);
+ }
+
+ return rc;
+}
+
+
+static void plugin__handle_tick_single(struct mosquitto__security_options *opts)
{
struct mosquitto_evt_tick event_data;
struct mosquitto__callback *cb_base;
+
+ /* FIXME - set now_s and now_ns to avoid need for multiple time lookups */
+ memset(&event_data, 0, sizeof(event_data));
+
+ DL_FOREACH(opts->plugin_callbacks.tick, cb_base){
+ cb_base->cb(MOSQ_EVT_TICK, &event_data, cb_base->userdata);
+ }
+}
+
+
+void plugin__handle_tick(void)
+{
struct mosquitto__security_options *opts;
int i;
@@ -211,20 +231,11 @@ void plugin__handle_tick(void)
for(i=0; ilistener_count; i++){
opts = &db.config->listeners[i].security_options;
if(opts && opts->plugin_callbacks.tick){
- memset(&event_data, 0, sizeof(event_data));
-
- DL_FOREACH(opts->plugin_callbacks.tick, cb_base){
- cb_base->cb(MOSQ_EVT_TICK, &event_data, cb_base->userdata);
- }
+ plugin__handle_tick_single(opts);
}
}
}else{
- opts = &db.config->security_options;
- memset(&event_data, 0, sizeof(event_data));
-
- DL_FOREACH(opts->plugin_callbacks.tick, cb_base){
- cb_base->cb(MOSQ_EVT_TICK, &event_data, cb_base->userdata);
- }
+ plugin__handle_tick_single(&db.config->security_options);
}
}
diff --git a/src/security.c b/src/security.c
index 1f51d72b..239c9974 100644
--- a/src/security.c
+++ b/src/security.c
@@ -676,14 +676,47 @@ static int acl__check_dollar(const char *topic, int access)
}
+static int plugin__acl_check(struct mosquitto__security_options *opts, struct mosquitto *context, const char *topic, uint32_t payloadlen, void* payload, uint8_t qos, bool retain, int access)
+{
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
+ struct mosquitto_acl_msg msg;
+ struct mosquitto__callback *cb_base;
+ struct mosquitto_evt_acl_check event_data;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.topic = topic;
+ msg.payloadlen = payloadlen;
+ msg.payload = payload;
+ msg.qos = qos;
+ msg.retain = retain;
+
+ DL_FOREACH(opts->plugin_callbacks.acl_check, cb_base){
+ /* FIXME - username deny special chars */
+
+ memset(&event_data, 0, sizeof(event_data));
+ event_data.client = context;
+ event_data.access = access;
+ event_data.topic = topic;
+ event_data.payloadlen = payloadlen;
+ event_data.payload = payload;
+ event_data.qos = qos;
+ event_data.retain = retain;
+ event_data.properties = NULL;
+ rc = cb_base->cb(MOSQ_EVT_ACL_CHECK, &event_data, cb_base->userdata);
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
int mosquitto_acl_check(struct mosquitto *context, const char *topic, uint32_t payloadlen, void* payload, uint8_t qos, bool retain, int access)
{
int rc;
int i;
struct mosquitto__security_options *opts;
struct mosquitto_acl_msg msg;
- struct mosquitto__callback *cb_base;
- struct mosquitto_evt_acl_check event_data;
if(!context->id){
return MOSQ_ERR_ACL_DENIED;
@@ -700,16 +733,34 @@ int mosquitto_acl_check(struct mosquitto *context, const char *topic, uint32_t p
*/
rc = MOSQ_ERR_SUCCESS;
+ if(db.config->security_options.plugin_callbacks.acl_check){
+ rc = plugin__acl_check(&db.config->security_options, context, topic, payloadlen,
+ payload, qos, retain, access);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+
if(db.config->per_listener_settings){
if(context->listener){
- opts = &context->listener->security_options;
+ if(context->listener->security_options.plugin_callbacks.acl_check){
+ rc = plugin__acl_check(&context->listener->security_options, context, topic, payloadlen,
+ payload, qos, retain, access);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
}else{
return MOSQ_ERR_ACL_DENIED;
}
+ opts = &context->listener->security_options;
}else{
opts = &db.config->security_options;
}
+ /* Old plugin version checks */
memset(&msg, 0, sizeof(msg));
msg.topic = topic;
msg.payloadlen = payloadlen;
@@ -717,24 +768,6 @@ int mosquitto_acl_check(struct mosquitto *context, const char *topic, uint32_t p
msg.qos = qos;
msg.retain = retain;
- DL_FOREACH(opts->plugin_callbacks.acl_check, cb_base){
- /* FIXME - username deny special chars */
-
- memset(&event_data, 0, sizeof(event_data));
- event_data.client = context;
- event_data.access = access;
- event_data.topic = topic;
- event_data.payloadlen = payloadlen;
- event_data.payload = payload;
- event_data.qos = qos;
- event_data.retain = retain;
- event_data.properties = NULL;
- rc = cb_base->cb(MOSQ_EVT_ACL_CHECK, &event_data, cb_base->userdata);
- if(rc != MOSQ_ERR_PLUGIN_DEFER){
- return rc;
- }
- }
-
for(i=0; iauth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.version < 5){
rc = acl__check_single(&opts->auth_plugin_configs[i], context, &msg, access);
@@ -752,13 +785,32 @@ int mosquitto_acl_check(struct mosquitto *context, const char *topic, uint32_t p
return rc;
}
+
+static int plugin__unpwd_check(struct mosquitto__security_options *opts, struct mosquitto *context)
+{
+ struct mosquitto_evt_basic_auth event_data;
+ struct mosquitto__callback *cb_base;
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
+
+ DL_FOREACH(opts->plugin_callbacks.basic_auth, cb_base){
+ memset(&event_data, 0, sizeof(event_data));
+ event_data.client = context;
+ event_data.username = context->username;
+ event_data.password = context->password;
+ rc = cb_base->cb(MOSQ_EVT_BASIC_AUTH, &event_data, cb_base->userdata);
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+ return rc;
+}
+
+
int mosquitto_unpwd_check(struct mosquitto *context)
{
int rc;
int i;
struct mosquitto__security_options *opts;
- struct mosquitto_evt_basic_auth event_data;
- struct mosquitto__callback *cb_base;
bool plugin_used = false;
rc = MOSQ_ERR_PLUGIN_DEFER;
@@ -772,18 +824,33 @@ int mosquitto_unpwd_check(struct mosquitto *context)
opts = &db.config->security_options;
}
- DL_FOREACH(opts->plugin_callbacks.basic_auth, cb_base){
- memset(&event_data, 0, sizeof(event_data));
- event_data.client = context;
- event_data.username = context->username;
- event_data.password = context->password;
- rc = cb_base->cb(MOSQ_EVT_BASIC_AUTH, &event_data, cb_base->userdata);
+ /* Global plugins */
+ if(db.config->security_options.plugin_callbacks.basic_auth){
+ rc = plugin__unpwd_check(&db.config->security_options, context);
+
if(rc != MOSQ_ERR_PLUGIN_DEFER){
return rc;
}
plugin_used = true;
}
+ /* Per listener plugins */
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ if(context->listener->security_options.plugin_callbacks.basic_auth){
+ rc = plugin__unpwd_check(&context->listener->security_options, context);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ plugin_used = true;
+ }
+ }
+
+
+ /* Old plugin checks */
for(i=0; iauth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.version == 4
&& opts->auth_plugin_configs[i].plugin.unpwd_check_v4){
@@ -838,13 +905,34 @@ int mosquitto_unpwd_check(struct mosquitto *context)
return rc;
}
+
+static int plugin__psk_key_get(struct mosquitto__security_options *opts, struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len)
+{
+ struct mosquitto_evt_psk_key event_data;
+ struct mosquitto__callback *cb_base;
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
+
+ DL_FOREACH(opts->plugin_callbacks.psk_key, cb_base){
+ memset(&event_data, 0, sizeof(event_data));
+ event_data.client = context;
+ event_data.hint = hint;
+ event_data.identity = identity;
+ event_data.key = key;
+ event_data.max_key_len = max_key_len;
+ rc = cb_base->cb(MOSQ_EVT_PSK_KEY, &event_data, cb_base->userdata);
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+ return rc;
+}
+
+
int mosquitto_psk_key_get(struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len)
{
int rc;
int i;
struct mosquitto__security_options *opts;
- struct mosquitto_evt_psk_key event_data;
- struct mosquitto__callback *cb_base;
rc = mosquitto_psk_key_get_default(context, hint, identity, key, max_key_len);
if(rc != MOSQ_ERR_PLUGIN_DEFER){
@@ -856,24 +944,40 @@ int mosquitto_psk_key_get(struct mosquitto *context, const char *hint, const cha
*/
if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
opts = &context->listener->security_options;
}else{
opts = &db.config->security_options;
}
- DL_FOREACH(opts->plugin_callbacks.psk_key, cb_base){
- memset(&event_data, 0, sizeof(event_data));
- event_data.client = context;
- event_data.hint = hint;
- event_data.identity = identity;
- event_data.key = key;
- event_data.max_key_len = max_key_len;
- rc = cb_base->cb(MOSQ_EVT_PSK_KEY, &event_data, cb_base->userdata);
+ /* Global plugins */
+ if(db.config->security_options.plugin_callbacks.psk_key){
+ rc = plugin__psk_key_get(&db.config->security_options, context,
+ hint, identity, key, max_key_len);
+
if(rc != MOSQ_ERR_PLUGIN_DEFER){
return rc;
}
}
+ /* Per listener plugins */
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ if(context->listener->security_options.plugin_callbacks.psk_key){
+ rc = plugin__psk_key_get(&context->listener->security_options, context,
+ hint, identity, key, max_key_len);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+ }
+
+ /* Old plugins */
for(i=0; iauth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.version == 4
&& opts->auth_plugin_configs[i].plugin.psk_key_get_v4){
@@ -919,22 +1023,13 @@ int mosquitto_psk_key_get(struct mosquitto *context, const char *hint, const cha
}
-int mosquitto_security_auth_start(struct mosquitto *context, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
+static int plugin__ext_auth_start(struct mosquitto__security_options *opts, struct mosquitto *context, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
{
- int rc = MOSQ_ERR_PLUGIN_DEFER;
- int i;
- struct mosquitto__security_options *opts;
struct mosquitto_evt_extended_auth event_data;
struct mosquitto__callback *cb_base;
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
- if(!context || !context->listener || !context->auth_method) return MOSQ_ERR_INVAL;
- if(!data_out || !data_out_len) return MOSQ_ERR_INVAL;
-
- if(db.config->per_listener_settings){
- opts = &context->listener->security_options;
- }else{
- opts = &db.config->security_options;
- }
+ UNUSED(reauth);
DL_FOREACH(opts->plugin_callbacks.ext_auth_start, cb_base){
memset(&event_data, 0, sizeof(event_data));
@@ -951,7 +1046,54 @@ int mosquitto_security_auth_start(struct mosquitto *context, bool reauth, const
return rc;
}
}
+ return rc;
+}
+
+
+int mosquitto_security_auth_start(struct mosquitto *context, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
+{
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
+ int i;
+ struct mosquitto__security_options *opts;
+
+ if(!context || !context->listener || !context->auth_method) return MOSQ_ERR_INVAL;
+ if(!data_out || !data_out_len) return MOSQ_ERR_INVAL;
+
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ opts = &context->listener->security_options;
+ }else{
+ opts = &db.config->security_options;
+ }
+ /* Global plugins */
+ if(db.config->security_options.plugin_callbacks.ext_auth_start){
+ rc = plugin__ext_auth_start(&db.config->security_options, context,
+ reauth, data_in, data_in_len, data_out, data_out_len);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+
+ /* Per listener plugins */
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ if(context->listener->security_options.plugin_callbacks.ext_auth_start){
+ rc = plugin__ext_auth_start(&context->listener->security_options, context,
+ reauth, data_in, data_in_len, data_out, data_out_len);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+ }
+
+ /* Old plugins */
for(i=0; iauth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.auth_start_v4){
*data_out = NULL;
@@ -979,23 +1121,12 @@ int mosquitto_security_auth_start(struct mosquitto *context, bool reauth, const
}
-int mosquitto_security_auth_continue(struct mosquitto *context, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
+static int plugin__ext_auth_continue(struct mosquitto__security_options *opts, struct mosquitto *context, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
{
int rc = MOSQ_ERR_PLUGIN_DEFER;
- int i;
- struct mosquitto__security_options *opts;
struct mosquitto_evt_extended_auth event_data;
struct mosquitto__callback *cb_base;
- if(!context || !context->listener || !context->auth_method) return MOSQ_ERR_INVAL;
- if(!data_out || !data_out_len) return MOSQ_ERR_INVAL;
-
- if(db.config->per_listener_settings){
- opts = &context->listener->security_options;
- }else{
- opts = &db.config->security_options;
- }
-
DL_FOREACH(opts->plugin_callbacks.ext_auth_continue, cb_base){
memset(&event_data, 0, sizeof(event_data));
event_data.client = context;
@@ -1010,7 +1141,54 @@ int mosquitto_security_auth_continue(struct mosquitto *context, const void *data
return rc;
}
}
+ return rc;
+}
+
+
+int mosquitto_security_auth_continue(struct mosquitto *context, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
+{
+ int rc = MOSQ_ERR_PLUGIN_DEFER;
+ int i;
+ struct mosquitto__security_options *opts;
+
+ if(!context || !context->listener || !context->auth_method) return MOSQ_ERR_INVAL;
+ if(!data_out || !data_out_len) return MOSQ_ERR_INVAL;
+
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ opts = &context->listener->security_options;
+ }else{
+ opts = &db.config->security_options;
+ }
+
+ /* Global plugins */
+ if(db.config->security_options.plugin_callbacks.ext_auth_continue){
+ rc = plugin__ext_auth_continue(&db.config->security_options, context,
+ data_in, data_in_len, data_out, data_out_len);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+
+ /* Per listener plugins */
+ if(db.config->per_listener_settings){
+ if(context->listener == NULL){
+ return MOSQ_ERR_AUTH;
+ }
+ if(context->listener->security_options.plugin_callbacks.ext_auth_continue){
+ rc = plugin__ext_auth_continue(&context->listener->security_options, context,
+ data_in, data_in_len, data_out, data_out_len);
+
+ if(rc != MOSQ_ERR_PLUGIN_DEFER){
+ return rc;
+ }
+ }
+ }
+ /* Old plugins */
for(i=0; iauth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.auth_continue_v4){
*data_out = NULL;