Commit 543d4451d2a619415d0cdd962ddb161a8a84baf9

Authored by Wiebe Cazemier
1 parent 1b9f0978

Auth plugin init works

It can be defined in the config file, along with options.
CMakeLists.txt
@@ -23,6 +23,7 @@ add_executable(FlashMQ @@ -23,6 +23,7 @@ add_executable(FlashMQ
23 cirbuf.cpp 23 cirbuf.cpp
24 logger.cpp 24 logger.cpp
25 authplugin.cpp 25 authplugin.cpp
  26 + configfileparser.cpp
26 ) 27 )
27 28
28 target_link_libraries(FlashMQ pthread dl) 29 target_link_libraries(FlashMQ pthread dl)
authplugin.cpp
@@ -7,10 +7,6 @@ @@ -7,10 +7,6 @@
7 7
8 #include "exceptions.h" 8 #include "exceptions.h"
9 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, ...) 10 void mosquitto_log_printf(int level, const char *fmt, ...)
15 { 11 {
16 Logger *logger = Logger::getInstance(); 12 Logger *logger = Logger::getInstance();
@@ -21,12 +17,18 @@ void mosquitto_log_printf(int level, const char *fmt, ...) @@ -21,12 +17,18 @@ void mosquitto_log_printf(int level, const char *fmt, ...)
21 } 17 }
22 18
23 19
24 -AuthPlugin::AuthPlugin() // our configuration object as param 20 +AuthPlugin::AuthPlugin(ConfigFileParser &confFileParser) :
  21 + confFileParser(confFileParser)
25 { 22 {
26 logger = Logger::getInstance(); 23 logger = Logger::getInstance();
27 } 24 }
28 25
29 -void *AuthPlugin::loadSymbol(void *handle, const char *symbol) 26 +AuthPlugin::~AuthPlugin()
  27 +{
  28 + cleanup();
  29 +}
  30 +
  31 +void *AuthPlugin::loadSymbol(void *handle, const char *symbol) const
30 { 32 {
31 void *r = dlsym(handle, symbol); 33 void *r = dlsym(handle, symbol);
32 34
@@ -41,8 +43,14 @@ void *AuthPlugin::loadSymbol(void *handle, const char *symbol) @@ -41,8 +43,14 @@ void *AuthPlugin::loadSymbol(void *handle, const char *symbol)
41 43
42 void AuthPlugin::loadPlugin(const std::string &pathToSoFile) 44 void AuthPlugin::loadPlugin(const std::string &pathToSoFile)
43 { 45 {
  46 + if (pathToSoFile.empty())
  47 + return;
  48 +
44 logger->logf(LOG_INFO, "Loading auth plugin %s", pathToSoFile.c_str()); 49 logger->logf(LOG_INFO, "Loading auth plugin %s", pathToSoFile.c_str());
45 50
  51 + initialized = false;
  52 + wanted = true;
  53 +
46 if (access(pathToSoFile.c_str(), R_OK) != 0) 54 if (access(pathToSoFile.c_str(), R_OK) != 0)
47 { 55 {
48 std::ostringstream oss; 56 std::ostringstream oss;
@@ -72,47 +80,105 @@ void AuthPlugin::loadPlugin(const std::string &pathToSoFile) @@ -72,47 +80,105 @@ void AuthPlugin::loadPlugin(const std::string &pathToSoFile)
72 acl_check_v2 = (F_auth_plugin_acl_check_v2)loadSymbol(r, "mosquitto_auth_acl_check"); 80 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"); 81 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"); 82 psk_key_get_v2 = (F_auth_plugin_psk_key_get_v2)loadSymbol(r, "mosquitto_auth_psk_key_get");
  83 +
  84 + initialized = true;
75 } 85 }
76 86
77 -int AuthPlugin::init() 87 +void AuthPlugin::init()
78 { 88 {
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; 89 + if (!wanted)
  90 + return;
  91 +
  92 + AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
  93 + int result = init_v2(&pluginData, authOpts.head(), authOpts.size());
  94 + if (result != 0)
  95 + throw FatalError("Error initialising auth plugin.");
83 } 96 }
84 97
85 -int AuthPlugin::cleanup() 98 +void AuthPlugin::cleanup()
86 { 99 {
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); 100 + if (!cleanup_v2)
  101 + return;
  102 +
  103 + securityCleanup(false);
  104 +
  105 + AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
  106 + int result = cleanup_v2(pluginData, authOpts.head(), authOpts.size());
  107 + if (result != 0)
  108 + logger->logf(LOG_ERR, "Error cleaning up auth plugin"); // Not doing exception, because we're shutting down anyway.
90 } 109 }
91 110
92 -int AuthPlugin::securityInit(bool reloading) 111 +void AuthPlugin::securityInit(bool reloading)
93 { 112 {
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); 113 + if (!wanted)
  114 + return;
  115 +
  116 + AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
  117 + int result = security_init_v2(pluginData, authOpts.head(), authOpts.size(), reloading);
  118 + if (result != 0)
  119 + {
  120 + throw AuthPluginException("Plugin function mosquitto_auth_security_init returned an error. If it didn't log anything, we don't know what it was.");
  121 + }
  122 + initialized = true;
97 } 123 }
98 124
99 -int AuthPlugin::securityCleanup(bool reloading) 125 +void AuthPlugin::securityCleanup(bool reloading)
100 { 126 {
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); 127 + if (!wanted)
  128 + return;
  129 +
  130 + initialized = false;
  131 + AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
  132 + int result = security_cleanup_v2(pluginData, authOpts.head(), authOpts.size(), reloading);
  133 +
  134 + if (result != 0)
  135 + {
  136 + throw AuthPluginException("Plugin function mosquitto_auth_security_cleanup returned an error. If it didn't log anything, we don't know what it was.");
  137 + }
104 } 138 }
105 139
106 AuthResult AuthPlugin::aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access) 140 AuthResult AuthPlugin::aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access)
107 { 141 {
  142 + if (!wanted)
  143 + return AuthResult::success;
  144 +
  145 + if (!initialized)
  146 + {
  147 + logger->logf(LOG_ERR, "ACL check wanted, but initialization failed. Can't perform check.");
  148 + return AuthResult::error;
  149 + }
  150 +
108 int result = acl_check_v2(pluginData, clientid.c_str(), username.c_str(), topic.c_str(), static_cast<int>(access)); 151 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); 152 + AuthResult result_ = static_cast<AuthResult>(result);
  153 +
  154 + if (result_ == AuthResult::error)
  155 + {
  156 + logger->logf(LOG_ERR, "ACL check by plugin returned error for topic '%s'. If it didn't log anything, we don't know what it was.", topic.c_str());
  157 + }
  158 +
  159 + return result_;
110 } 160 }
111 161
112 AuthResult AuthPlugin::unPwdCheck(const std::string &username, const std::string &password) 162 AuthResult AuthPlugin::unPwdCheck(const std::string &username, const std::string &password)
113 { 163 {
  164 + if (!wanted)
  165 + return AuthResult::success;
  166 +
  167 + if (!initialized)
  168 + {
  169 + logger->logf(LOG_ERR, "Username+password check wanted, but initialization failed. Can't perform check.");
  170 + return AuthResult::error;
  171 + }
  172 +
114 int result = unpwd_check_v2(pluginData, username.c_str(), password.c_str()); 173 int result = unpwd_check_v2(pluginData, username.c_str(), password.c_str());
115 - return static_cast<AuthResult>(result); 174 + AuthResult r = static_cast<AuthResult>(result);
  175 +
  176 + if (r == AuthResult::error)
  177 + {
  178 + logger->logf(LOG_ERR, "Username+password check by plugin returned error for user '%s'. If it didn't log anything, we don't know what it was.", username.c_str());
  179 + }
  180 +
  181 + return r;
116 } 182 }
117 183
118 184
authplugin.h
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 #include <cstring> 5 #include <cstring>
6 6
7 #include "logger.h" 7 #include "logger.h"
  8 +#include "configfileparser.h"
8 9
9 // Compatible with Mosquitto 10 // Compatible with Mosquitto
10 enum class AclAccess 11 enum class AclAccess
@@ -23,11 +24,6 @@ enum class AuthResult @@ -23,11 +24,6 @@ enum class AuthResult
23 error = 13 24 error = 13
24 }; 25 };
25 26
26 -struct mosquitto_auth_opt {  
27 - char *key;  
28 - char *value;  
29 -};  
30 -  
31 typedef int (*F_auth_plugin_version)(void); 27 typedef int (*F_auth_plugin_version)(void);
32 28
33 typedef int (*F_auth_plugin_init_v2)(void **, struct mosquitto_auth_opt *, int); 29 typedef int (*F_auth_plugin_init_v2)(void **, struct mosquitto_auth_opt *, int);
@@ -55,18 +51,25 @@ class AuthPlugin @@ -55,18 +51,25 @@ class AuthPlugin
55 F_auth_plugin_unpwd_check_v2 unpwd_check_v2 = nullptr; 51 F_auth_plugin_unpwd_check_v2 unpwd_check_v2 = nullptr;
56 F_auth_plugin_psk_key_get_v2 psk_key_get_v2 = nullptr; 52 F_auth_plugin_psk_key_get_v2 psk_key_get_v2 = nullptr;
57 53
  54 + ConfigFileParser &confFileParser;
  55 +
58 void *pluginData = nullptr; 56 void *pluginData = nullptr;
59 Logger *logger = nullptr; 57 Logger *logger = nullptr;
  58 + bool initialized = false;
  59 + bool wanted = false;
60 60
61 - void *loadSymbol(void *handle, const char *symbol); 61 + void *loadSymbol(void *handle, const char *symbol) const;
62 public: 62 public:
63 - AuthPlugin(); 63 + AuthPlugin(ConfigFileParser &confFileParser);
  64 + AuthPlugin(const AuthPlugin &other) = delete;
  65 + AuthPlugin(AuthPlugin &&other) = delete;
  66 + ~AuthPlugin();
64 67
65 void loadPlugin(const std::string &pathToSoFile); 68 void loadPlugin(const std::string &pathToSoFile);
66 - int init();  
67 - int cleanup();  
68 - int securityInit(bool reloading);  
69 - int securityCleanup(bool reloading); 69 + void init();
  70 + void cleanup();
  71 + void securityInit(bool reloading);
  72 + void securityCleanup(bool reloading);
70 AuthResult aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access); 73 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); 74 AuthResult unPwdCheck(const std::string &username, const std::string &password);
72 75
configfileparser.cpp 0 โ†’ 100644
  1 +#include "configfileparser.h"
  2 +
  3 +#include <fcntl.h>
  4 +#include <unistd.h>
  5 +#include <sstream>
  6 +#include "fstream"
  7 +
  8 +#include "exceptions.h"
  9 +#include "utils.h"
  10 +#include <regex>
  11 +
  12 +
  13 +mosquitto_auth_opt::mosquitto_auth_opt(const std::string &key, const std::string &value)
  14 +{
  15 + this->key = strdup(key.c_str());
  16 + this->value = strdup(value.c_str());
  17 +}
  18 +
  19 +mosquitto_auth_opt::mosquitto_auth_opt(mosquitto_auth_opt &&other)
  20 +{
  21 + this->key = other.key;
  22 + this->value = other.value;
  23 + other.key = nullptr;
  24 + other.value = nullptr;
  25 +}
  26 +
  27 +mosquitto_auth_opt::~mosquitto_auth_opt()
  28 +{
  29 + if (key)
  30 + delete key;
  31 + if (value)
  32 + delete value;
  33 +}
  34 +
  35 +AuthOptCompatWrap::AuthOptCompatWrap(const std::unordered_map<std::string, std::string> &authOpts)
  36 +{
  37 + for(auto &pair : authOpts)
  38 + {
  39 + mosquitto_auth_opt opt(pair.first, pair.second);
  40 + optArray.push_back(std::move(opt));
  41 + }
  42 +}
  43 +
  44 +ConfigFileParser::ConfigFileParser(const std::string &path) :
  45 + path(path)
  46 +{
  47 + validKeys.insert("auth_plugin");
  48 +}
  49 +
  50 +void ConfigFileParser::loadFile()
  51 +{
  52 + if (access(path.c_str(), R_OK) != 0)
  53 + {
  54 + std::ostringstream oss;
  55 + oss << "Error: " << path << " is not there or not readable";
  56 + throw ConfigFileException(oss.str());
  57 + }
  58 +
  59 + std::ifstream infile(path, std::ios::in);
  60 +
  61 + if (!infile.is_open())
  62 + {
  63 + std::ostringstream oss;
  64 + oss << "Error loading " << path;
  65 + throw ConfigFileException(oss.str());
  66 + }
  67 +
  68 + std::list<std::string> lines;
  69 +
  70 + const std::regex r("^([a-zA-Z0-9_\\-]+) +([a-zA-Z0-9_\\-/\\.]+)$");
  71 +
  72 + // First parse the file and keep the valid lines.
  73 + for(std::string line; getline(infile, line ); )
  74 + {
  75 + trim(line);
  76 +
  77 + if (startsWith(line, "#"))
  78 + continue;
  79 +
  80 + if (line.empty())
  81 + continue;
  82 +
  83 + std::smatch matches;
  84 +
  85 + if (!std::regex_search(line, matches, r) || matches.size() != 3)
  86 + {
  87 + std::ostringstream oss;
  88 + oss << "Line '" << line << "' not in 'key value' format";
  89 + throw ConfigFileException(oss.str());
  90 + }
  91 +
  92 + lines.push_back(line);
  93 + }
  94 +
  95 + authOpts.clear();
  96 + authOptCompatWrap.reset();
  97 +
  98 + // Then once we know the config file is valid, process it.
  99 + for (std::string &line : lines)
  100 + {
  101 + std::smatch matches;
  102 +
  103 + if (!std::regex_search(line, matches, r) || matches.size() != 3)
  104 + {
  105 + throw ConfigFileException("Config parse error at a point that should not be possible.");
  106 + }
  107 +
  108 + std::string key = matches[1].str();
  109 + const std::string value = matches[2].str();
  110 +
  111 + const std::string auth_opt_ = "auth_opt_";
  112 + if (startsWith(key, auth_opt_))
  113 + {
  114 + key.replace(0, auth_opt_.length(), "");
  115 + authOpts[key] = value;
  116 + }
  117 + else
  118 + {
  119 + auto valid_key_it = validKeys.find(key);
  120 + if (valid_key_it == validKeys.end())
  121 + {
  122 + std::ostringstream oss;
  123 + oss << "Config key '" << key << "' is not valid";
  124 + throw ConfigFileException(oss.str());
  125 + }
  126 +
  127 + if (key == "auth_plugin")
  128 + {
  129 + this->authPluginPath = value;
  130 + }
  131 + }
  132 + }
  133 +
  134 + authOptCompatWrap.reset(new AuthOptCompatWrap(authOpts));
  135 +}
  136 +
  137 +AuthOptCompatWrap &ConfigFileParser::getAuthOptsCompat()
  138 +{
  139 + return *authOptCompatWrap.get();
  140 +}
  141 +
  142 +
  143 +
configfileparser.h 0 โ†’ 100644
  1 +#ifndef CONFIGFILEPARSER_H
  2 +#define CONFIGFILEPARSER_H
  3 +
  4 +#include <string>
  5 +#include <set>
  6 +#include <unordered_map>
  7 +#include <vector>
  8 +#include <memory>
  9 +
  10 +struct mosquitto_auth_opt
  11 +{
  12 + char *key = nullptr;
  13 + char *value = nullptr;
  14 +
  15 + mosquitto_auth_opt(const std::string &key, const std::string &value);
  16 + mosquitto_auth_opt(mosquitto_auth_opt &&other);
  17 + mosquitto_auth_opt(const mosquitto_auth_opt &other) = delete;
  18 + ~mosquitto_auth_opt();
  19 +};
  20 +
  21 +struct AuthOptCompatWrap
  22 +{
  23 + std::vector<struct mosquitto_auth_opt> optArray;
  24 +
  25 + AuthOptCompatWrap(const std::unordered_map<std::string, std::string> &authOpts);
  26 + AuthOptCompatWrap(const AuthOptCompatWrap &other) = delete;
  27 + AuthOptCompatWrap(AuthOptCompatWrap &&other) = delete;
  28 +
  29 + struct mosquitto_auth_opt *head() { return &optArray[0]; }
  30 + int size() { return optArray.size(); }
  31 +};
  32 +
  33 +class ConfigFileParser
  34 +{
  35 + const std::string path;
  36 + std::set<std::string> validKeys;
  37 + std::unordered_map<std::string, std::string> authOpts;
  38 + std::unique_ptr<AuthOptCompatWrap> authOptCompatWrap;
  39 + std::string authPluginPath;
  40 +
  41 +public:
  42 + ConfigFileParser(const std::string &path);
  43 + void loadFile();
  44 + AuthOptCompatWrap &getAuthOptsCompat();
  45 +
  46 + std::string getAuthPluginPath() { return authPluginPath; }
  47 +};
  48 +
  49 +#endif // CONFIGFILEPARSER_H
exceptions.h
@@ -22,4 +22,16 @@ public: @@ -22,4 +22,16 @@ public:
22 FatalError(const std::string &msg) : std::runtime_error(msg) {} 22 FatalError(const std::string &msg) : std::runtime_error(msg) {}
23 }; 23 };
24 24
  25 +class ConfigFileException : public std::runtime_error
  26 +{
  27 +public:
  28 + ConfigFileException(const std::string &msg) : std::runtime_error(msg) {}
  29 +};
  30 +
  31 +class AuthPluginException : public std::runtime_error
  32 +{
  33 +public:
  34 + AuthPluginException(const std::string &msg) : std::runtime_error(msg) {}
  35 +};
  36 +
25 #endif // EXCEPTIONS_H 37 #endif // EXCEPTIONS_H
main.cpp
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 #include "mainapp.h" 7 #include "mainapp.h"
8 8
9 -MainApp *mainApp = MainApp::getMainApp(); 9 +MainApp *mainApp = nullptr;
10 10
11 static void signal_handler(int signal) 11 static void signal_handler(int signal)
12 { 12 {
@@ -65,6 +65,7 @@ int main() @@ -65,6 +65,7 @@ int main()
65 { 65 {
66 try 66 try
67 { 67 {
  68 + mainApp = MainApp::getMainApp();
68 check<std::runtime_error>(register_signal_handers()); 69 check<std::runtime_error>(register_signal_handers());
69 mainApp->start(); 70 mainApp->start();
70 } 71 }
mainapp.cpp
@@ -111,7 +111,8 @@ void do_thread_work(ThreadData *threadData) @@ -111,7 +111,8 @@ void do_thread_work(ThreadData *threadData)
111 MainApp::MainApp() : 111 MainApp::MainApp() :
112 subscriptionStore(new SubscriptionStore()) 112 subscriptionStore(new SubscriptionStore())
113 { 113 {
114 - 114 + confFileParser.reset(new ConfigFileParser("/home/halfgaar/Projects/FlashMQThings/config.txt")); // TODO: from argv
  115 + confFileParser->loadFile();
115 } 116 }
116 117
117 MainApp *MainApp::getMainApp() 118 MainApp *MainApp::getMainApp()
@@ -154,7 +155,7 @@ void MainApp::start() @@ -154,7 +155,7 @@ void MainApp::start()
154 155
155 for (int i = 0; i < NR_OF_THREADS; i++) 156 for (int i = 0; i < NR_OF_THREADS; i++)
156 { 157 {
157 - std::shared_ptr<ThreadData> t(new ThreadData(i, subscriptionStore)); 158 + std::shared_ptr<ThreadData> t(new ThreadData(i, subscriptionStore, *confFileParser.get()));
158 std::thread thread(do_thread_work, t.get()); 159 std::thread thread(do_thread_work, t.get());
159 t->moveThreadHere(std::move(thread)); 160 t->moveThreadHere(std::move(thread));
160 threads.push_back(t); 161 threads.push_back(t);
mainapp.h
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 #include "client.h" 16 #include "client.h"
17 #include "mqttpacket.h" 17 #include "mqttpacket.h"
18 #include "subscriptionstore.h" 18 #include "subscriptionstore.h"
  19 +#include "configfileparser.h"
19 20
20 class MainApp 21 class MainApp
21 { 22 {
@@ -25,6 +26,7 @@ class MainApp @@ -25,6 +26,7 @@ class MainApp
25 bool running = true; 26 bool running = true;
26 std::vector<std::shared_ptr<ThreadData>> threads; 27 std::vector<std::shared_ptr<ThreadData>> threads;
27 std::shared_ptr<SubscriptionStore> subscriptionStore; 28 std::shared_ptr<SubscriptionStore> subscriptionStore;
  29 + std::unique_ptr<ConfigFileParser> confFileParser;
28 30
29 MainApp(); 31 MainApp();
30 public: 32 public:
threaddata.cpp
@@ -2,11 +2,19 @@ @@ -2,11 +2,19 @@
2 #include <string> 2 #include <string>
3 #include <sstream> 3 #include <sstream>
4 4
5 -ThreadData::ThreadData(int threadnr, std::shared_ptr<SubscriptionStore> &subscriptionStore) : 5 +ThreadData::ThreadData(int threadnr, std::shared_ptr<SubscriptionStore> &subscriptionStore, ConfigFileParser &confFileParser) :
6 subscriptionStore(subscriptionStore), 6 subscriptionStore(subscriptionStore),
  7 + confFileParser(confFileParser),
  8 + authPlugin(confFileParser),
7 threadnr(threadnr) 9 threadnr(threadnr)
8 { 10 {
  11 + logger = Logger::getInstance();
  12 +
9 epollfd = check<std::runtime_error>(epoll_create(999)); 13 epollfd = check<std::runtime_error>(epoll_create(999));
  14 +
  15 + authPlugin.loadPlugin(confFileParser.getAuthPluginPath());
  16 + authPlugin.init();
  17 + authPlugin.securityInit(false);
10 } 18 }
11 19
12 void ThreadData::moveThreadHere(std::thread &&thread) 20 void ThreadData::moveThreadHere(std::thread &&thread)
@@ -92,5 +100,18 @@ bool ThreadData::doKeepAliveCheck() @@ -92,5 +100,18 @@ bool ThreadData::doKeepAliveCheck()
92 return true; 100 return true;
93 } 101 }
94 102
  103 +void ThreadData::reload()
  104 +{
  105 + try
  106 + {
  107 + authPlugin.securityCleanup(true);
  108 + authPlugin.securityInit(true);
  109 + }
  110 + catch (AuthPluginException &ex)
  111 + {
  112 + logger->logf(LOG_ERR, "Error reloading auth plugin: %s. Security checks will now fail, because we don't know the status of the plugin anymore.", ex.what());
  113 + }
  114 +}
  115 +
95 116
96 117
threaddata.h
@@ -16,14 +16,18 @@ @@ -16,14 +16,18 @@
16 #include "client.h" 16 #include "client.h"
17 #include "subscriptionstore.h" 17 #include "subscriptionstore.h"
18 #include "utils.h" 18 #include "utils.h"
19 -  
20 - 19 +#include "configfileparser.h"
  20 +#include "authplugin.h"
  21 +#include "logger.h"
21 22
22 class ThreadData 23 class ThreadData
23 { 24 {
24 std::unordered_map<int, Client_p> clients_by_fd; 25 std::unordered_map<int, Client_p> clients_by_fd;
25 std::mutex clients_by_fd_mutex; 26 std::mutex clients_by_fd_mutex;
26 std::shared_ptr<SubscriptionStore> subscriptionStore; 27 std::shared_ptr<SubscriptionStore> subscriptionStore;
  28 + ConfigFileParser &confFileParser;
  29 + AuthPlugin authPlugin;
  30 + Logger *logger;
27 31
28 public: 32 public:
29 bool running = true; 33 bool running = true;
@@ -31,7 +35,9 @@ public: @@ -31,7 +35,9 @@ public:
31 int threadnr = 0; 35 int threadnr = 0;
32 int epollfd = 0; 36 int epollfd = 0;
33 37
34 - ThreadData(int threadnr, std::shared_ptr<SubscriptionStore> &subscriptionStore); 38 + ThreadData(int threadnr, std::shared_ptr<SubscriptionStore> &subscriptionStore, ConfigFileParser &confFileParser);
  39 + ThreadData(const ThreadData &other) = delete;
  40 + ThreadData(ThreadData &&other) = delete;
35 41
36 void moveThreadHere(std::thread &&thread); 42 void moveThreadHere(std::thread &&thread);
37 void quit(); 43 void quit();
@@ -42,6 +48,7 @@ public: @@ -42,6 +48,7 @@ public:
42 std::shared_ptr<SubscriptionStore> &getSubscriptionStore(); 48 std::shared_ptr<SubscriptionStore> &getSubscriptionStore();
43 49
44 bool doKeepAliveCheck(); 50 bool doKeepAliveCheck();
  51 + void reload();
45 }; 52 };
46 53
47 #endif // THREADDATA_H 54 #endif // THREADDATA_H
utils.cpp
1 #include "utils.h" 1 #include "utils.h"
2 2
3 - 3 +#include <algorithm>
4 4
5 std::list<std::__cxx11::string> split(const std::string &input, const char sep, size_t max, bool keep_empty_parts) 5 std::list<std::__cxx11::string> split(const std::string &input, const char sep, size_t max, bool keep_empty_parts)
6 { 6 {
@@ -143,3 +143,28 @@ std::vector&lt;std::string&gt; splitToVector(const std::string &amp;input, const char sep, @@ -143,3 +143,28 @@ std::vector&lt;std::string&gt; splitToVector(const std::string &amp;input, const char sep,
143 list.push_back(input.substr(start, std::string::npos)); 143 list.push_back(input.substr(start, std::string::npos));
144 return list; 144 return list;
145 } 145 }
  146 +
  147 +void ltrim(std::string &s)
  148 +{
  149 + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
  150 + return !std::isspace(ch);
  151 + }));
  152 +}
  153 +
  154 +void rtrim(std::string &s)
  155 +{
  156 + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
  157 + return !std::isspace(ch);
  158 + }).base(), s.end());
  159 +}
  160 +
  161 +void trim(std::string &s)
  162 +{
  163 + ltrim(s);
  164 + rtrim(s);
  165 +}
  166 +
  167 +bool startsWith(const std::string &s, const std::string &needle)
  168 +{
  169 + return s.find(needle) == 0;
  170 +}
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <list> 7 #include <list>
8 #include <limits> 8 #include <limits>
9 #include <vector> 9 #include <vector>
  10 +#include <algorithm>
10 11
11 template<typename T> int check(int rc) 12 template<typename T> int check(int rc)
12 { 13 {
@@ -31,4 +32,10 @@ bool strContains(const std::string &amp;s, const std::string &amp;needle); @@ -31,4 +32,10 @@ bool strContains(const std::string &amp;s, const std::string &amp;needle);
31 32
32 bool isValidPublishPath(const std::string &s); 33 bool isValidPublishPath(const std::string &s);
33 34
  35 +void ltrim(std::string &s);
  36 +void rtrim(std::string &s);
  37 +void trim(std::string &s);
  38 +bool startsWith(const std::string &s, const std::string &needle);
  39 +
  40 +
34 #endif // UTILS_H 41 #endif // UTILS_H