[464543] Run default checks after plugins.
This commit is contained in:
parent
5c642c9cfd
commit
e773ea1bee
@ -80,9 +80,9 @@
|
||||
authenticate using the MQTT username/password if using the
|
||||
password_file option.</para>
|
||||
<para>Both certificate and PSK based encryption are configured on a per-listener basis.</para>
|
||||
<para>Authentication plugins can be created to replace the
|
||||
password_file and psk_file options (as well as the ACL options)
|
||||
with e.g. SQL based lookups.</para>
|
||||
<para>Authentication plugins can be created to augment the
|
||||
password_file, acl_file and psk_file options with e.g. SQL based
|
||||
lookups.</para>
|
||||
<para>It is possible to support multiple authentication schemes at
|
||||
once. A config could be created that had a listener for all of the
|
||||
different encryption options described above and hence a large
|
||||
@ -205,6 +205,12 @@
|
||||
<para>Can be specified multiple times to load multiple
|
||||
plugins. The plugins will be processed in the order
|
||||
that they are specified.</para>
|
||||
<para>If <option>password_file</option>, or
|
||||
<option>acl_file</option> are used in the config file
|
||||
alongsize <option>auth_plugin</option>, the plugin
|
||||
checks will run first. If a plugin is used but neither
|
||||
of the default password or acl options are used, access
|
||||
will be denied.</para>
|
||||
<para>Not currently reloaded on reload signal.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -528,7 +528,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.
|
||||
# for alternative authentication options. If an auth_plugin is used as well as
|
||||
# password_file, the auth_plugin check will be made first.
|
||||
#password_file
|
||||
|
||||
# Access may also be controlled using a pre-shared-key file. This requires
|
||||
@ -536,6 +537,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.
|
||||
#psk_file
|
||||
|
||||
# Control access to topics on the broker using an access control list
|
||||
@ -585,6 +587,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.
|
||||
#acl_file
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
@ -597,7 +601,8 @@
|
||||
#
|
||||
# The auth_plugin option can be specified multiple times to load multiple
|
||||
# plugins. The plugins will be processed in the order that they are specified
|
||||
# here.
|
||||
# here. If the auth_plugin option is specified alongside either of
|
||||
# password_file or acl_file then the plugin checks will be made first.
|
||||
#
|
||||
#auth_plugin
|
||||
|
||||
|
@ -38,7 +38,20 @@ struct mosquitto_auth_opt {
|
||||
*
|
||||
* Authentication plugins can implement one or both of authentication and
|
||||
* access control. If your plugin does not wish to handle either of
|
||||
* authentication or access control it should return MOSQ_ERR_DEFER.
|
||||
* authentication or access control it should return MOSQ_ERR_DEFER. In this
|
||||
* case, the next plugin will handle it. If all plugins return MOSQ_ERR_DEFER,
|
||||
* the request will be denied.
|
||||
*
|
||||
* For each check, the following flow happens:
|
||||
*
|
||||
* * First plugin does the check, if it returns anything other than
|
||||
* MOSQ_ERR_DEFER, then the check returns immediately. If the plugin returns
|
||||
* MOSQ_ERR_DEFER then the next plugin runs its check.
|
||||
* * If the final plugin returns MOSQ_ERR_DEFER, then the default password file
|
||||
* and/or acl file check will be made if they are specified in the config
|
||||
* file.
|
||||
* * If plugins are defined and the password file and/or acl file are not
|
||||
* specified, then the request will be denied.
|
||||
*/
|
||||
|
||||
/* =========================================================================
|
||||
@ -228,7 +241,7 @@ int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char
|
||||
* Return value:
|
||||
* Return 0 on success.
|
||||
* Return >0 on failure.
|
||||
* Return >0 if this function is not required.
|
||||
* Return MOSQ_ERR_DEFER if your plugin does not wish to handle this check.
|
||||
*/
|
||||
int mosquitto_auth_psk_key_get(void *user_data, const char *hint, const char *identity, char *key, int max_key_len);
|
||||
|
||||
|
61
src/plugin_defer.c
Normal file
61
src/plugin_defer.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (c) 2015 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
/* This is a skeleton authentication and access control plugin that simply defers all checks. */
|
||||
|
||||
#include "mosquitto_plugin.h"
|
||||
#include "mosquitto.h"
|
||||
|
||||
int mosquitto_auth_plugin_version(void)
|
||||
{
|
||||
return MOSQ_AUTH_PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_security_init(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_acl_check(void *user_data, const char *clientid, const char *username, const char *topic, int access)
|
||||
{
|
||||
return MOSQ_ERR_DEFER;
|
||||
}
|
||||
|
||||
int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char *password)
|
||||
{
|
||||
return MOSQ_ERR_DEFER;
|
||||
}
|
||||
|
||||
int mosquitto_auth_psk_key_get(void *user_data, const char *hint, const char *identity, char *key, int max_key_len)
|
||||
{
|
||||
return MOSQ_ERR_DEFER;
|
||||
}
|
||||
|
@ -197,18 +197,13 @@ int mosquitto_security_init(struct mosquitto_db *db, bool reload)
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_security_init_default(db, reload);
|
||||
}else{
|
||||
for(i=0; i<db->config->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].security_init(db->auth_plugins[i].user_data, db->config->auth_plugins[i].options, db->config->auth_plugins[i].option_count, reload);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
return rc;
|
||||
}
|
||||
for(i=0; i<db->config->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].security_init(db->auth_plugins[i].user_data, db->config->auth_plugins[i].options, db->config->auth_plugins[i].option_count, reload);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
return mosquitto_security_init_default(db, reload);
|
||||
}
|
||||
|
||||
/* Apply security settings after a reload.
|
||||
@ -219,10 +214,7 @@ int mosquitto_security_init(struct mosquitto_db *db, bool reload)
|
||||
*/
|
||||
int mosquitto_security_apply(struct mosquitto_db *db)
|
||||
{
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_security_apply_default(db);
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
return mosquitto_security_apply_default(db);
|
||||
}
|
||||
|
||||
int mosquitto_security_cleanup(struct mosquitto_db *db, bool reload)
|
||||
@ -230,17 +222,13 @@ int mosquitto_security_cleanup(struct mosquitto_db *db, bool reload)
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_security_cleanup_default(db, reload);
|
||||
}else{
|
||||
for(i=0; i<db->config->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].security_cleanup(db->auth_plugins[i].user_data, db->config->auth_plugins[i].options, db->config->auth_plugins[i].option_count, reload);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
return rc;
|
||||
}
|
||||
for(i=0; i<db->config->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].security_cleanup(db->auth_plugins[i].user_data, db->config->auth_plugins[i].options, db->config->auth_plugins[i].option_count, reload);
|
||||
if(rc != MOSQ_ERR_SUCCESS){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
return mosquitto_security_cleanup_default(db, reload);
|
||||
}
|
||||
|
||||
int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, int access)
|
||||
@ -252,25 +240,22 @@ int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, cons
|
||||
if(!context->id){
|
||||
return MOSQ_ERR_ACL_DENIED;
|
||||
}
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_acl_check_default(db, context, topic, access);
|
||||
}else{
|
||||
|
||||
#ifdef WITH_BRIDGE
|
||||
if(context->bridge){
|
||||
username = context->bridge->local_username;
|
||||
}else
|
||||
if(context->bridge){
|
||||
username = context->bridge->local_username;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
username = context->username;
|
||||
}
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].acl_check(db->auth_plugins[i].user_data, context->id, username, topic, access);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
{
|
||||
username = context->username;
|
||||
}
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].acl_check(db->auth_plugins[i].user_data, context->id, username, topic, access);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_ACL_DENIED;
|
||||
return mosquitto_acl_check_default(db, context, topic, access);
|
||||
}
|
||||
|
||||
int mosquitto_unpwd_check(struct mosquitto_db *db, const char *username, const char *password)
|
||||
@ -278,17 +263,13 @@ int mosquitto_unpwd_check(struct mosquitto_db *db, const char *username, const c
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_unpwd_check_default(db, username, password);
|
||||
}else{
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].unpwd_check(db->auth_plugins[i].user_data, username, password);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].unpwd_check(db->auth_plugins[i].user_data, username, password);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_AUTH;
|
||||
return mosquitto_unpwd_check_default(db, username, password);
|
||||
}
|
||||
|
||||
int mosquitto_psk_key_get(struct mosquitto_db *db, const char *hint, const char *identity, char *key, int max_key_len)
|
||||
@ -296,16 +277,12 @@ int mosquitto_psk_key_get(struct mosquitto_db *db, const char *hint, const char
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
if(!db->auth_plugins){
|
||||
return mosquitto_psk_key_get_default(db, hint, identity, key, max_key_len);
|
||||
}else{
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].psk_key_get(db->auth_plugins[i].user_data, hint, identity, key, max_key_len);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
for(i=0; i<db->auth_plugin_count; i++){
|
||||
rc = db->auth_plugins[i].psk_key_get(db->auth_plugins[i].user_data, hint, identity, key, max_key_len);
|
||||
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return MOSQ_ERR_AUTH;
|
||||
return mosquitto_psk_key_get_default(db, hint, identity, key, max_key_len);
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
|
||||
char *s;
|
||||
|
||||
if(!db || !context || !topic) return MOSQ_ERR_INVAL;
|
||||
if(!db->acl_list && !db->acl_patterns) return MOSQ_ERR_SUCCESS;
|
||||
if(!db->acl_list && !db->acl_patterns && !db->auth_plugins) return MOSQ_ERR_SUCCESS;
|
||||
if(context->bridge) return MOSQ_ERR_SUCCESS;
|
||||
if(!context->acl_list && !db->acl_patterns) return MOSQ_ERR_ACL_DENIED;
|
||||
|
||||
@ -639,7 +639,7 @@ int mosquitto_unpwd_check_default(struct mosquitto_db *db, const char *username,
|
||||
#endif
|
||||
|
||||
if(!db) return MOSQ_ERR_INVAL;
|
||||
if(!db->unpwd) return MOSQ_ERR_SUCCESS;
|
||||
if(!db->unpwd && !db->auth_plugins) return MOSQ_ERR_SUCCESS;
|
||||
if(!username) return MOSQ_ERR_INVAL; /* Check must be made only after checking db->unpwd. */
|
||||
|
||||
HASH_ITER(hh, db->unpwd, u, tmp){
|
||||
|
Loading…
Reference in New Issue
Block a user