2014-05-07 22:27:00 +00:00
|
|
|
/*
|
2018-04-11 14:24:29 +00:00
|
|
|
Copyright (c) 2011-2018 Roger Light <roger@atchoo.org>
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "config.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-07-08 09:10:04 +00:00
|
|
|
#include "mosquitto_broker_internal.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
#include "mosquitto_plugin.h"
|
2015-04-29 20:37:47 +00:00
|
|
|
#include "memory_mosq.h"
|
2014-05-07 22:27:00 +00:00
|
|
|
#include "lib_load.h"
|
|
|
|
|
|
|
|
typedef int (*FUNC_auth_plugin_version)(void);
|
2016-07-10 22:17:30 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
static int security__cleanup_single(struct mosquitto__security_options *opts, bool reload);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2014-11-20 22:33:40 +00:00
|
|
|
void LIB_ERROR(void)
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
char *buf;
|
|
|
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
|
|
|
NULL, GetLastError(), LANG_NEUTRAL, &buf, 0, NULL);
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Load error: %s", buf);
|
2014-11-20 22:33:40 +00:00
|
|
|
LocalFree(buf);
|
|
|
|
#else
|
2015-05-18 07:53:21 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR, "Load error: %s", dlerror());
|
2014-11-20 22:33:40 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-07-10 22:17:30 +00:00
|
|
|
|
|
|
|
int security__load_v2(struct mosquitto_db *db, struct mosquitto__auth_plugin *plugin, struct mosquitto_auth_opt *auth_options, int auth_option_count, void *lib)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if(!(plugin->plugin_init_v2 = (FUNC_auth_plugin_init_v2)LIB_SYM(lib, "mosquitto_auth_plugin_init"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_plugin_init().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(!(plugin->plugin_cleanup_v2 = (FUNC_auth_plugin_cleanup_v2)LIB_SYM(lib, "mosquitto_auth_plugin_cleanup"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_plugin_cleanup().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->security_init_v2 = (FUNC_auth_plugin_security_init_v2)LIB_SYM(lib, "mosquitto_auth_security_init"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_security_init().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->security_cleanup_v2 = (FUNC_auth_plugin_security_cleanup_v2)LIB_SYM(lib, "mosquitto_auth_security_cleanup"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_security_cleanup().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->acl_check_v2 = (FUNC_auth_plugin_acl_check_v2)LIB_SYM(lib, "mosquitto_auth_acl_check"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_acl_check().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->unpwd_check_v2 = (FUNC_auth_plugin_unpwd_check_v2)LIB_SYM(lib, "mosquitto_auth_unpwd_check"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_unpwd_check().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->psk_key_get_v2 = (FUNC_auth_plugin_psk_key_get_v2)LIB_SYM(lib, "mosquitto_auth_psk_key_get"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_psk_key_get().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
plugin->lib = lib;
|
|
|
|
plugin->user_data = NULL;
|
|
|
|
|
|
|
|
if(plugin->plugin_init_v2){
|
|
|
|
rc = plugin->plugin_init_v2(&plugin->user_data, auth_options, auth_option_count);
|
|
|
|
if(rc){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Authentication plugin returned %d when initialising.", rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int security__load_v3(struct mosquitto_db *db, struct mosquitto__auth_plugin *plugin, struct mosquitto_opt *auth_options, int auth_option_count, void *lib)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if(!(plugin->plugin_init_v3 = (FUNC_auth_plugin_init_v3)LIB_SYM(lib, "mosquitto_auth_plugin_init"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_plugin_init().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(!(plugin->plugin_cleanup_v3 = (FUNC_auth_plugin_cleanup_v3)LIB_SYM(lib, "mosquitto_auth_plugin_cleanup"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_plugin_cleanup().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->security_init_v3 = (FUNC_auth_plugin_security_init_v3)LIB_SYM(lib, "mosquitto_auth_security_init"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_security_init().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->security_cleanup_v3 = (FUNC_auth_plugin_security_cleanup_v3)LIB_SYM(lib, "mosquitto_auth_security_cleanup"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_security_cleanup().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->acl_check_v3 = (FUNC_auth_plugin_acl_check_v3)LIB_SYM(lib, "mosquitto_auth_acl_check"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_acl_check().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->unpwd_check_v3 = (FUNC_auth_plugin_unpwd_check_v3)LIB_SYM(lib, "mosquitto_auth_unpwd_check"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_unpwd_check().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(plugin->psk_key_get_v3 = (FUNC_auth_plugin_psk_key_get_v3)LIB_SYM(lib, "mosquitto_auth_psk_key_get"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_psk_key_get().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
plugin->lib = lib;
|
|
|
|
plugin->user_data = NULL;
|
|
|
|
if(plugin->plugin_init_v3){
|
|
|
|
rc = plugin->plugin_init_v3(&plugin->user_data, auth_options, auth_option_count);
|
|
|
|
if(rc){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Authentication plugin returned %d when initialising.", rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
static int security__module_init_single(struct mosquitto_db *db, struct mosquitto__security_options *opts)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
|
|
|
void *lib;
|
|
|
|
int (*plugin_version)(void) = NULL;
|
|
|
|
int version;
|
2015-06-29 21:22:28 +00:00
|
|
|
int i;
|
2018-03-26 14:23:00 +00:00
|
|
|
int rc;
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
if(opts->auth_plugin_config_count == 0){
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
|
|
|
if(opts->auth_plugin_configs[i].path){
|
|
|
|
memset(&opts->auth_plugin_configs[i].plugin, 0, sizeof(struct mosquitto__auth_plugin));
|
|
|
|
|
|
|
|
lib = LIB_LOAD(opts->auth_plugin_configs[i].path);
|
2015-06-29 21:22:28 +00:00
|
|
|
if(!lib){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
2018-03-26 14:23:00 +00:00
|
|
|
"Error: Unable to load auth plugin \"%s\".", opts->auth_plugin_configs[i].path);
|
2015-06-29 21:22:28 +00:00
|
|
|
LIB_ERROR();
|
|
|
|
return 1;
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
opts->auth_plugin_configs[i].plugin.lib = NULL;
|
2015-06-29 21:22:28 +00:00
|
|
|
if(!(plugin_version = (FUNC_auth_plugin_version)LIB_SYM(lib, "mosquitto_auth_plugin_version"))){
|
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Unable to load auth plugin function mosquitto_auth_plugin_version().");
|
|
|
|
LIB_ERROR();
|
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
version = plugin_version();
|
2018-03-26 14:23:00 +00:00
|
|
|
opts->auth_plugin_configs[i].plugin.version = version;
|
2016-07-10 22:17:30 +00:00
|
|
|
if(version == 3){
|
2018-03-26 14:23:00 +00:00
|
|
|
rc = security__load_v3(
|
|
|
|
db,
|
|
|
|
&opts->auth_plugin_configs[i].plugin,
|
|
|
|
opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
lib);
|
|
|
|
|
2016-07-10 22:17:30 +00:00
|
|
|
if(rc){
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}else if(version == 2){
|
2018-03-26 14:23:00 +00:00
|
|
|
rc = security__load_v2(
|
|
|
|
db,
|
|
|
|
&opts->auth_plugin_configs[i].plugin,
|
|
|
|
(struct mosquitto_auth_opt *)opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
lib);
|
|
|
|
|
2016-07-10 22:17:30 +00:00
|
|
|
if(rc){
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}else{
|
2015-06-29 21:22:28 +00:00
|
|
|
log__printf(NULL, MOSQ_LOG_ERR,
|
|
|
|
"Error: Incorrect auth plugin version (got %d, expected %d).",
|
|
|
|
version, MOSQ_AUTH_PLUGIN_VERSION);
|
|
|
|
LIB_ERROR();
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2015-06-29 21:22:28 +00:00
|
|
|
LIB_CLOSE(lib);
|
|
|
|
return 1;
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
int mosquitto_security_module_init(struct mosquitto_db *db)
|
|
|
|
{
|
2018-03-26 21:50:41 +00:00
|
|
|
int rc = MOSQ_ERR_SUCCESS;
|
2018-03-26 14:23:00 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if(db->config->per_listener_settings){
|
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
rc = security__module_init_single(db, &db->config->listeners[i].security_options);
|
|
|
|
if(rc) return rc;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
rc = security__module_init_single(db, &db->config->security_options);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void security__module_cleanup_single(struct mosquitto__security_options *opts)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
2018-08-01 14:52:42 +00:00
|
|
|
/* Run plugin cleanup function */
|
|
|
|
if(opts->auth_plugin_configs[i].plugin.version == 3){
|
|
|
|
opts->auth_plugin_configs[i].plugin.plugin_cleanup_v3(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count);
|
|
|
|
|
|
|
|
}else if(opts->auth_plugin_configs[i].plugin.version == 2){
|
|
|
|
opts->auth_plugin_configs[i].plugin.plugin_cleanup_v2(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
(struct mosquitto_auth_opt *)opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count);
|
|
|
|
}
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
if(opts->auth_plugin_configs[i].plugin.lib){
|
|
|
|
LIB_CLOSE(opts->auth_plugin_configs[i].plugin.lib);
|
|
|
|
}
|
|
|
|
memset(&opts->auth_plugin_configs[i].plugin, 0, sizeof(struct mosquitto__auth_plugin));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
int mosquitto_security_module_cleanup(struct mosquitto_db *db)
|
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int i;
|
|
|
|
|
2014-05-07 22:27:00 +00:00
|
|
|
mosquitto_security_cleanup(db, false);
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
security__module_cleanup_single(&db->config->security_options);
|
2014-05-07 22:27:00 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
security__module_cleanup_single(&db->config->listeners[i].security_options);
|
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
static int security__init_single(struct mosquitto__security_options *opts, bool reload)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
|
|
|
if(opts->auth_plugin_configs[i].plugin.version == 3){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.security_init_v3(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
reload);
|
|
|
|
|
|
|
|
}else if(opts->auth_plugin_configs[i].plugin.version == 2){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.security_init_v2(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
(struct mosquitto_auth_opt *)opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
reload);
|
2016-07-10 22:17:30 +00:00
|
|
|
}else{
|
|
|
|
rc = MOSQ_ERR_INVAL;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
if(rc != MOSQ_ERR_SUCCESS){
|
|
|
|
return rc;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2018-03-26 14:23:00 +00:00
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mosquitto_security_init(struct mosquitto_db *db, bool reload)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if(db->config->per_listener_settings){
|
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
rc = security__init_single(&db->config->listeners[i].security_options, reload);
|
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
rc = security__init_single(&db->config->security_options, reload);
|
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
return mosquitto_security_init_default(db, reload);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Apply security settings after a reload.
|
|
|
|
* Includes:
|
|
|
|
* - Disconnecting anonymous users if appropriate
|
|
|
|
* - Disconnecting users with invalid passwords
|
|
|
|
* - Reapplying ACLs
|
|
|
|
*/
|
|
|
|
int mosquitto_security_apply(struct mosquitto_db *db)
|
|
|
|
{
|
2015-06-29 22:31:39 +00:00
|
|
|
return mosquitto_security_apply_default(db);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
static int security__cleanup_single(struct mosquitto__security_options *opts, bool reload)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
|
|
|
if(opts->auth_plugin_configs[i].plugin.version == 3){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.security_cleanup_v3(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
reload);
|
|
|
|
|
|
|
|
}else if(opts->auth_plugin_configs[i].plugin.version == 2){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.security_cleanup_v2(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
(struct mosquitto_auth_opt *)opts->auth_plugin_configs[i].options,
|
|
|
|
opts->auth_plugin_configs[i].option_count,
|
|
|
|
reload);
|
2016-07-10 22:17:30 +00:00
|
|
|
}else{
|
|
|
|
rc = MOSQ_ERR_INVAL;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
if(rc != MOSQ_ERR_SUCCESS){
|
|
|
|
return rc;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mosquitto_security_cleanup(struct mosquitto_db *db, bool reload)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = security__cleanup_single(&db->config->security_options, reload);
|
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
|
|
|
|
for(i=0; i<db->config->listener_count; i++){
|
|
|
|
rc = security__cleanup_single(&db->config->listeners[i].security_options, reload);
|
|
|
|
if(rc != MOSQ_ERR_SUCCESS) return rc;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
return mosquitto_security_cleanup_default(db, reload);
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
//int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, int access)
|
2018-05-22 14:51:26 +00:00
|
|
|
static int acl__check_single(struct mosquitto__auth_plugin_config *auth_plugin, struct mosquitto *context, struct mosquitto_acl_msg *msg, int access)
|
2018-03-26 14:23:00 +00:00
|
|
|
{
|
|
|
|
const char *username;
|
2018-05-22 14:51:26 +00:00
|
|
|
const char *topic = msg->topic;
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
username = mosquitto_client_username(context);
|
|
|
|
if(auth_plugin->deny_special_chars == true){
|
|
|
|
/* Check whether the client id or username contains a +, # or / and if
|
|
|
|
* so deny access.
|
|
|
|
*
|
|
|
|
* Do this check for every message regardless, we have to protect the
|
|
|
|
* plugins against possible pattern based attacks.
|
|
|
|
*/
|
|
|
|
if(username && strpbrk(username, "+#")){
|
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous username \"%s\"", username);
|
|
|
|
return MOSQ_ERR_ACL_DENIED;
|
|
|
|
}
|
|
|
|
if(context->id && strpbrk(context->id, "+#")){
|
|
|
|
log__printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous client id \"%s\"", context->id);
|
|
|
|
return MOSQ_ERR_ACL_DENIED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(auth_plugin->plugin.version == 3){
|
2018-05-22 14:51:26 +00:00
|
|
|
return auth_plugin->plugin.acl_check_v3(auth_plugin->plugin.user_data, access, context, msg);
|
2018-03-26 14:23:00 +00:00
|
|
|
}else if(auth_plugin->plugin.version == 2){
|
|
|
|
if(access == MOSQ_ACL_SUBSCRIBE){
|
|
|
|
return MOSQ_ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
return auth_plugin->plugin.acl_check_v2(auth_plugin->plugin.user_data, context->id, username, topic, access);
|
|
|
|
}else{
|
|
|
|
return MOSQ_ERR_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-22 14:51:26 +00:00
|
|
|
int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, long payloadlen, void* payload, int qos, bool retain, int access)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int rc;
|
|
|
|
int i;
|
2018-03-26 14:23:00 +00:00
|
|
|
struct mosquitto__security_options *opts;
|
2018-05-22 14:51:26 +00:00
|
|
|
struct mosquitto_acl_msg msg;
|
2014-10-29 22:11:18 +00:00
|
|
|
|
2014-07-08 22:07:19 +00:00
|
|
|
if(!context->id){
|
|
|
|
return MOSQ_ERR_ACL_DENIED;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
|
2015-10-02 20:44:39 +00:00
|
|
|
rc = mosquitto_acl_check_default(db, context, topic, access);
|
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
|
|
|
}
|
2016-07-08 08:36:25 +00:00
|
|
|
/* Default check has accepted or deferred at this point.
|
2015-10-02 20:44:39 +00:00
|
|
|
* If no plugins exist we should accept at this point so set rc to success.
|
|
|
|
*/
|
|
|
|
rc = MOSQ_ERR_SUCCESS;
|
2017-05-31 20:05:26 +00:00
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
if(db->config->per_listener_settings){
|
|
|
|
opts = &context->listener->security_options;
|
|
|
|
}else{
|
|
|
|
opts = &db->config->security_options;
|
|
|
|
}
|
|
|
|
|
2018-05-22 14:51:26 +00:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.topic = topic;
|
|
|
|
msg.payloadlen = payloadlen;
|
|
|
|
msg.payload = payload;
|
|
|
|
msg.qos = qos;
|
|
|
|
msg.retain = retain;
|
|
|
|
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
2018-05-22 14:51:26 +00:00
|
|
|
rc = acl__check_single(&opts->auth_plugin_configs[i], context, &msg, access);
|
2015-06-29 22:31:39 +00:00
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2018-03-26 14:23:00 +00:00
|
|
|
|
2015-10-02 20:44:39 +00:00
|
|
|
/* If all plugins deferred, this is a denial. If rc == MOSQ_ERR_SUCCESS
|
|
|
|
* here, then no plugins were configured. */
|
|
|
|
if(rc == MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
rc = MOSQ_ERR_ACL_DENIED;
|
|
|
|
}
|
|
|
|
return rc;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
2016-07-08 12:27:14 +00:00
|
|
|
int mosquitto_unpwd_check(struct mosquitto_db *db, struct mosquitto *context, const char *username, const char *password)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int rc;
|
|
|
|
int i;
|
2018-03-26 14:23:00 +00:00
|
|
|
struct mosquitto__security_options *opts;
|
2015-06-29 21:22:28 +00:00
|
|
|
|
2018-03-13 17:44:33 +00:00
|
|
|
rc = mosquitto_unpwd_check_default(db, context, username, password);
|
2015-10-02 20:44:39 +00:00
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
|
|
|
}
|
2016-07-08 08:36:25 +00:00
|
|
|
/* Default check has accepted or deferred at this point.
|
2015-10-02 20:44:39 +00:00
|
|
|
* If no plugins exist we should accept at this point so set rc to success.
|
|
|
|
*/
|
2018-03-26 14:23:00 +00:00
|
|
|
if(db->config->per_listener_settings){
|
|
|
|
opts = &context->listener->security_options;
|
|
|
|
}else{
|
|
|
|
opts = &db->config->security_options;
|
|
|
|
}
|
|
|
|
|
2015-10-02 20:44:39 +00:00
|
|
|
rc = MOSQ_ERR_SUCCESS;
|
2018-03-26 14:23:00 +00:00
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
|
|
|
if(opts->auth_plugin_configs[i].plugin.version == 3){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.unpwd_check_v3(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
context,
|
|
|
|
username,
|
|
|
|
password);
|
|
|
|
|
|
|
|
}else if(opts->auth_plugin_configs[i].plugin.version == 2){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.unpwd_check_v2(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
username,
|
|
|
|
password);
|
2016-07-10 22:17:30 +00:00
|
|
|
}else{
|
|
|
|
rc = MOSQ_ERR_INVAL;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2015-10-02 20:44:39 +00:00
|
|
|
/* If all plugins deferred, this is a denial. If rc == MOSQ_ERR_SUCCESS
|
|
|
|
* here, then no plugins were configured. */
|
|
|
|
if(rc == MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
rc = MOSQ_ERR_AUTH;
|
|
|
|
}
|
|
|
|
return rc;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|
2016-07-08 12:52:02 +00:00
|
|
|
int mosquitto_psk_key_get(struct mosquitto_db *db, struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len)
|
2014-05-07 22:27:00 +00:00
|
|
|
{
|
2015-06-29 21:22:28 +00:00
|
|
|
int rc;
|
|
|
|
int i;
|
2018-03-26 14:23:00 +00:00
|
|
|
struct mosquitto__security_options *opts;
|
2015-06-29 21:22:28 +00:00
|
|
|
|
2018-03-15 21:39:42 +00:00
|
|
|
rc = mosquitto_psk_key_get_default(db, context, hint, identity, key, max_key_len);
|
2016-07-08 08:36:25 +00:00
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Default check has accepted or deferred at this point.
|
|
|
|
* If no plugins exist we should accept at this point so set rc to success.
|
|
|
|
*/
|
2018-03-26 14:23:00 +00:00
|
|
|
|
|
|
|
if(db->config->per_listener_settings){
|
|
|
|
opts = &context->listener->security_options;
|
|
|
|
}else{
|
|
|
|
opts = &db->config->security_options;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<opts->auth_plugin_config_count; i++){
|
|
|
|
if(opts->auth_plugin_configs[i].plugin.version == 3){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.psk_key_get_v3(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
context,
|
|
|
|
hint,
|
|
|
|
identity,
|
|
|
|
key,
|
|
|
|
max_key_len);
|
|
|
|
|
|
|
|
}else if(opts->auth_plugin_configs[i].plugin.version == 2){
|
|
|
|
rc = opts->auth_plugin_configs[i].plugin.psk_key_get_v2(
|
|
|
|
opts->auth_plugin_configs[i].plugin.user_data,
|
|
|
|
hint,
|
|
|
|
identity,
|
|
|
|
key,
|
|
|
|
max_key_len);
|
2016-07-10 22:17:30 +00:00
|
|
|
}else{
|
|
|
|
rc = MOSQ_ERR_INVAL;
|
|
|
|
}
|
2015-06-29 22:31:39 +00:00
|
|
|
if(rc != MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
return rc;
|
2015-06-29 21:22:28 +00:00
|
|
|
}
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
2018-03-26 14:23:00 +00:00
|
|
|
|
2016-07-08 08:36:25 +00:00
|
|
|
/* If all plugins deferred, this is a denial. If rc == MOSQ_ERR_SUCCESS
|
|
|
|
* here, then no plugins were configured. */
|
|
|
|
if(rc == MOSQ_ERR_PLUGIN_DEFER){
|
|
|
|
rc = MOSQ_ERR_AUTH;
|
|
|
|
}
|
|
|
|
return rc;
|
2014-05-07 22:27:00 +00:00
|
|
|
}
|
|
|
|
|