commit 3ccb929687c9b477892ef00d29ef0dcbf2029ac3 Author: James Pace Date: Mon Nov 8 00:47:39 2021 +0000 Initial iteration of plugin. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..60dcfde --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.5) +project(jwp-mosquitto-plugin) + +add_library(jwp-plugin SHARED src/jwp-plugin.cpp) diff --git a/README.md b/README.md new file mode 100644 index 0000000..baf0544 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +sudo apt install mosquitto-dev g++ cmake libmosquitto-dev mosquitto-clients diff --git a/src/jwp-plugin.cpp b/src/jwp-plugin.cpp new file mode 100644 index 0000000..62265b6 --- /dev/null +++ b/src/jwp-plugin.cpp @@ -0,0 +1,100 @@ +extern "C" { + #include "mosquitto.h" + #include "mosquitto_broker.h" + #include "mosquitto_plugin.h" +} +#include + +// Stuff we're "exporting" for the dynamic loading. +extern "C" { + int mosquitto_plugin_version(int supported_version_count, const int *supported_versions); + int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **userdata, struct mosquitto_opt *options, int option_count); + int mosquitto_plugin_cleanup(void *userdata, struct mosquitto_opt *options, int option_count); +} +// My functions +int jwp_auth_basic_auth_callback(int event, void *event_data, void *userdata); +int jwp_acl_check_callback(int event, void *event_data, void *userdata); + + +// Mosquitto Globals +static mosquitto_plugin_id_t *plugin_id = nullptr; + + +int mosquitto_plugin_version(int supported_version_count, const int *supported_versions) +{ + for(int index = 0; index < supported_version_count; index++) + { + if(supported_versions[index] == 5) + { + return 5; + } + } + return -1; +} + +int mosquitto_plugin_init(mosquitto_plugin_id_t *identifier, void **userdata, struct mosquitto_opt *options, int option_count) +{ + plugin_id = identifier; + + mosquitto_callback_register(plugin_id, MOSQ_EVT_BASIC_AUTH, jwp_auth_basic_auth_callback, NULL, NULL); + mosquitto_callback_register(plugin_id, MOSQ_EVT_ACL_CHECK, jwp_acl_check_callback, NULL, NULL); + // May want MOSQ_EVT_RELOAD as well. + + return MOSQ_ERR_SUCCESS; +} + +int mosquitto_plugin_cleanup(void *userdata, struct mosquitto_opt *options, int option_count) +{ + if(plugin_id) + { + mosquitto_callback_unregister(plugin_id, MOSQ_EVT_BASIC_AUTH, jwp_auth_basic_auth_callback, NULL); + mosquitto_callback_unregister(plugin_id, MOSQ_EVT_ACL_CHECK, jwp_acl_check_callback, NULL); + } + + return MOSQ_ERR_SUCCESS; +} + +int jwp_auth_basic_auth_callback(int event, void *event_data, void *userdata) +{ + struct mosquitto_evt_basic_auth *auth_data = static_cast(event_data); + + if(!auth_data->username or !auth_data->password) + { + mosquitto_log_printf(MOSQ_LOG_ERR, "No username or password."); + return MOSQ_ERR_PLUGIN_DEFER; + } + mosquitto_log_printf(MOSQ_LOG_ERR, "Username: %s Password: %s", + auth_data->username, auth_data->password); + + return MOSQ_ERR_SUCCESS; // MOSQ_ERR_AUTH; +} + +int jwp_acl_check_callback(int event, void *event_data, void *userdata) +{ + struct mosquitto_evt_acl_check *acl_data = static_cast(event_data); + + std::string event_name = "none"; + switch(acl_data->access) + { + case MOSQ_ACL_SUBSCRIBE: + event_name = "subscribe"; + break; + case MOSQ_ACL_UNSUBSCRIBE: + event_name = "unsubscribe"; + break; + case MOSQ_ACL_WRITE: + event_name = "write"; + break; + case MOSQ_ACL_READ: + event_name = "read"; + break; + } + + mosquitto_log_printf(MOSQ_LOG_ERR, "Topic: %s Event: %s", + acl_data->topic, event_name.c_str()); + + return MOSQ_ERR_SUCCESS; // MOSQ_ERR_ACL_DENIED; + +} + + diff --git a/test/mosquitto.conf b/test/mosquitto.conf new file mode 100644 index 0000000..3ae57db --- /dev/null +++ b/test/mosquitto.conf @@ -0,0 +1,54 @@ +listener 8082 +protocol websockets + +listener 8081 +protocol mqtt + + +log_type all +allow_anonymous true + +auth_plugin /home/jimmy/Develop/mosquitto-plugin/build/libjwp-plugin.so + +# ----------------------------------------------------------------- +# External authentication and topic access plugin options +# ----------------------------------------------------------------- + +# 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. +# +# 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. 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 + +# If the auth_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: +# +# auth_opt_db_host +# auth_opt_db_port +# auth_opt_db_username +# auth_opt_db_password + +# ----------------------------------------------------------------- +# Default authentication and topic access control +# ----------------------------------------------------------------- + +# Control access to the broker using a password file. This file can be +# generated using the mosquitto_passwd utility. If TLS support is not compiled +# into mosquitto (it is recommended that TLS support should be included) then +# plain text passwords are used, in which case the file should be a text file +# with lines in the format: +# username:password +# The password (and colon) may be omitted if desired, although this +# 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. +#password_file + diff --git a/test/pub.sh b/test/pub.sh new file mode 100755 index 0000000..a75f3c9 --- /dev/null +++ b/test/pub.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +mosquitto_pub -u james -P test -h localhost -p 8081 -t test -m "test" diff --git a/test/run.sh b/test/run.sh new file mode 100755 index 0000000..2399d4d --- /dev/null +++ b/test/run.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +/usr/sbin/mosquitto -c $PWD/mosquitto.conf