Commit 1b9f09780e1ae659ef0e9b8086b173da2365a5a1

Authored by Wiebe Cazemier
1 parent 4315fb5b

Start of auth plugin.

I kind of need a config file parser first, so I'm going to make that.
CMakeLists.txt
... ... @@ -5,6 +5,7 @@ project(FlashMQ LANGUAGES CXX)
5 5 set(CMAKE_CXX_STANDARD 11)
6 6 set(CMAKE_CXX_STANDARD_REQUIRED ON)
7 7  
  8 +SET(CMAKE_CXX_FLAGS "-rdynamic")
8 9  
9 10 add_executable(FlashMQ
10 11 mainapp.cpp
... ... @@ -21,6 +22,7 @@ add_executable(FlashMQ
21 22 retainedmessage.cpp
22 23 cirbuf.cpp
23 24 logger.cpp
  25 + authplugin.cpp
24 26 )
25 27  
26   -target_link_libraries(FlashMQ pthread)
  28 +target_link_libraries(FlashMQ pthread dl)
... ...
FlashMQTests/FlashMQTests.pro
... ... @@ -26,6 +26,7 @@ SOURCES += tst_maintests.cpp \
26 26 ../types.cpp \
27 27 ../utils.cpp \
28 28 ../logger.cpp \
  29 + ../authplugin.cpp \
29 30 mainappthread.cpp \
30 31 twoclienttestcontext.cpp
31 32  
... ... @@ -44,5 +45,10 @@ HEADERS += \
44 45 ../types.h \
45 46 ../utils.h \
46 47 ../logger.h \
  48 + ../authplugin.h \
47 49 mainappthread.h \
48 50 twoclienttestcontext.h
  51 +
  52 +LIBS += -ldl
  53 +
  54 +QMAKE_LFLAGS += -rdynamic
... ...
authplugin.cpp 0 → 100644
  1 +#include "authplugin.h"
  2 +
  3 +#include <unistd.h>
  4 +#include <fcntl.h>
  5 +#include <sstream>
  6 +#include <dlfcn.h>
  7 +
  8 +#include "exceptions.h"
  9 +
  10 +// TODO: error handling on all the calls to the plugin. Exceptions? Passing to the caller?
  11 +// TODO: where to do the conditionals about whether the plugin is loaded, what to do on error, etc?
  12 +// -> Perhaps merely log the error (and return 'denied'?)?
  13 +
  14 +void mosquitto_log_printf(int level, const char *fmt, ...)
  15 +{
  16 + Logger *logger = Logger::getInstance();
  17 + va_list valist;
  18 + va_start(valist, fmt);
  19 + logger->logf(level, fmt);
  20 + va_end(valist);
  21 +}
  22 +
  23 +
  24 +AuthPlugin::AuthPlugin() // our configuration object as param
  25 +{
  26 + logger = Logger::getInstance();
  27 +}
  28 +
  29 +void *AuthPlugin::loadSymbol(void *handle, const char *symbol)
  30 +{
  31 + void *r = dlsym(handle, symbol);
  32 +
  33 + if (r == NULL)
  34 + {
  35 + std::string errmsg(dlerror());
  36 + throw FatalError(errmsg);
  37 + }
  38 +
  39 + return r;
  40 +}
  41 +
  42 +void AuthPlugin::loadPlugin(const std::string &pathToSoFile)
  43 +{
  44 + logger->logf(LOG_INFO, "Loading auth plugin %s", pathToSoFile.c_str());
  45 +
  46 + if (access(pathToSoFile.c_str(), R_OK) != 0)
  47 + {
  48 + std::ostringstream oss;
  49 + oss << "Error loading auth plugin: The file " << pathToSoFile << " is not there or not readable";
  50 + throw FatalError(oss.str());
  51 + }
  52 +
  53 + void *r = dlopen(pathToSoFile.c_str(), RTLD_NOW|RTLD_GLOBAL);
  54 +
  55 + if (r == NULL)
  56 + {
  57 + std::string errmsg(dlerror());
  58 + throw FatalError(errmsg);
  59 + }
  60 +
  61 + version = (F_auth_plugin_version)loadSymbol(r, "mosquitto_auth_plugin_version");
  62 +
  63 + if (version() != 2)
  64 + {
  65 + throw FatalError("Only Mosquitto plugin version 2 is supported at this time.");
  66 + }
  67 +
  68 + init_v2 = (F_auth_plugin_init_v2)loadSymbol(r, "mosquitto_auth_plugin_init");
  69 + cleanup_v2 = (F_auth_plugin_cleanup_v2)loadSymbol(r, "mosquitto_auth_plugin_cleanup");
  70 + security_init_v2 = (F_auth_plugin_security_init_v2)loadSymbol(r, "mosquitto_auth_security_init");
  71 + security_cleanup_v2 = (F_auth_plugin_security_cleanup_v2)loadSymbol(r, "mosquitto_auth_security_cleanup");
  72 + acl_check_v2 = (F_auth_plugin_acl_check_v2)loadSymbol(r, "mosquitto_auth_acl_check");
  73 + unpwd_check_v2 = (F_auth_plugin_unpwd_check_v2)loadSymbol(r, "mosquitto_auth_unpwd_check");
  74 + psk_key_get_v2 = (F_auth_plugin_psk_key_get_v2)loadSymbol(r, "mosquitto_auth_psk_key_get");
  75 +}
  76 +
  77 +int AuthPlugin::init()
  78 +{
  79 + struct mosquitto_auth_opt auth_opts[2]; // TODO: get auth opts from central config object
  80 + std::memset(&auth_opts, 0, sizeof(struct mosquitto_auth_opt) * 2);
  81 + int result = init_v2(&pluginData, auth_opts, 2);
  82 + return result;
  83 +}
  84 +
  85 +int AuthPlugin::cleanup()
  86 +{
  87 + struct mosquitto_auth_opt auth_opts[2]; // TODO: get auth opts from central config object
  88 + std::memset(&auth_opts, 0, sizeof(struct mosquitto_auth_opt) * 2);
  89 + return cleanup_v2(pluginData, auth_opts, 2);
  90 +}
  91 +
  92 +int AuthPlugin::securityInit(bool reloading)
  93 +{
  94 + struct mosquitto_auth_opt auth_opts[2]; // TODO: get auth opts from central config object
  95 + std::memset(&auth_opts, 0, sizeof(struct mosquitto_auth_opt) * 2);
  96 + return security_init_v2(pluginData, auth_opts, 2, reloading);
  97 +}
  98 +
  99 +int AuthPlugin::securityCleanup(bool reloading)
  100 +{
  101 + struct mosquitto_auth_opt auth_opts[2]; // TODO: get auth opts from central config object
  102 + std::memset(&auth_opts, 0, sizeof(struct mosquitto_auth_opt) * 2);
  103 + return security_cleanup_v2(pluginData, auth_opts, 2, reloading);
  104 +}
  105 +
  106 +AuthResult AuthPlugin::aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access)
  107 +{
  108 + int result = acl_check_v2(pluginData, clientid.c_str(), username.c_str(), topic.c_str(), static_cast<int>(access));
  109 + return static_cast<AuthResult>(result);
  110 +}
  111 +
  112 +AuthResult AuthPlugin::unPwdCheck(const std::string &username, const std::string &password)
  113 +{
  114 + int result = unpwd_check_v2(pluginData, username.c_str(), password.c_str());
  115 + return static_cast<AuthResult>(result);
  116 +}
  117 +
  118 +
... ...
authplugin.h 0 → 100644
  1 +#ifndef AUTHPLUGIN_H
  2 +#define AUTHPLUGIN_H
  3 +
  4 +#include <string>
  5 +#include <cstring>
  6 +
  7 +#include "logger.h"
  8 +
  9 +// Compatible with Mosquitto
  10 +enum class AclAccess
  11 +{
  12 + none = 0,
  13 + read = 1,
  14 + write = 2
  15 +};
  16 +
  17 +// Compatible with Mosquitto
  18 +enum class AuthResult
  19 +{
  20 + success = 0,
  21 + acl_denied = 12,
  22 + login_denied = 11,
  23 + error = 13
  24 +};
  25 +
  26 +struct mosquitto_auth_opt {
  27 + char *key;
  28 + char *value;
  29 +};
  30 +
  31 +typedef int (*F_auth_plugin_version)(void);
  32 +
  33 +typedef int (*F_auth_plugin_init_v2)(void **, struct mosquitto_auth_opt *, int);
  34 +typedef int (*F_auth_plugin_cleanup_v2)(void *, struct mosquitto_auth_opt *, int);
  35 +typedef int (*F_auth_plugin_security_init_v2)(void *, struct mosquitto_auth_opt *, int, bool);
  36 +typedef int (*F_auth_plugin_security_cleanup_v2)(void *, struct mosquitto_auth_opt *, int, bool);
  37 +typedef int (*F_auth_plugin_acl_check_v2)(void *, const char *, const char *, const char *, int);
  38 +typedef int (*F_auth_plugin_unpwd_check_v2)(void *, const char *, const char *);
  39 +typedef int (*F_auth_plugin_psk_key_get_v2)(void *, const char *, const char *, char *, int);
  40 +
  41 +extern "C"
  42 +{
  43 + // Gets called by the plugin, so it needs to exist, globally
  44 + void mosquitto_log_printf(int level, const char *fmt, ...);
  45 +}
  46 +
  47 +class AuthPlugin
  48 +{
  49 + F_auth_plugin_version version = nullptr;
  50 + F_auth_plugin_init_v2 init_v2 = nullptr;
  51 + F_auth_plugin_cleanup_v2 cleanup_v2 = nullptr;
  52 + F_auth_plugin_security_init_v2 security_init_v2 = nullptr;
  53 + F_auth_plugin_security_cleanup_v2 security_cleanup_v2 = nullptr;
  54 + F_auth_plugin_acl_check_v2 acl_check_v2 = nullptr;
  55 + F_auth_plugin_unpwd_check_v2 unpwd_check_v2 = nullptr;
  56 + F_auth_plugin_psk_key_get_v2 psk_key_get_v2 = nullptr;
  57 +
  58 + void *pluginData = nullptr;
  59 + Logger *logger = nullptr;
  60 +
  61 + void *loadSymbol(void *handle, const char *symbol);
  62 +public:
  63 + AuthPlugin();
  64 +
  65 + void loadPlugin(const std::string &pathToSoFile);
  66 + int init();
  67 + int cleanup();
  68 + int securityInit(bool reloading);
  69 + int securityCleanup(bool reloading);
  70 + AuthResult aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access);
  71 + AuthResult unPwdCheck(const std::string &username, const std::string &password);
  72 +
  73 +};
  74 +
  75 +#endif // AUTHPLUGIN_H
... ...
exceptions.h
... ... @@ -16,5 +16,10 @@ public:
16 16 NotImplementedException(const std::string &msg) : std::runtime_error(msg) {}
17 17 };
18 18  
  19 +class FatalError : public std::runtime_error
  20 +{
  21 +public:
  22 + FatalError(const std::string &msg) : std::runtime_error(msg) {}
  23 +};
19 24  
20 25 #endif // EXCEPTIONS_H
... ...