authplugin.cpp
5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "authplugin.h"
#include <unistd.h>
#include <fcntl.h>
#include <sstream>
#include <dlfcn.h>
#include "exceptions.h"
void mosquitto_log_printf(int level, const char *fmt, ...)
{
Logger *logger = Logger::getInstance();
va_list valist;
va_start(valist, fmt);
logger->logf(level, fmt);
va_end(valist);
}
AuthPlugin::AuthPlugin(ConfigFileParser &confFileParser) :
confFileParser(confFileParser)
{
logger = Logger::getInstance();
}
AuthPlugin::~AuthPlugin()
{
cleanup();
}
void *AuthPlugin::loadSymbol(void *handle, const char *symbol) const
{
void *r = dlsym(handle, symbol);
if (r == NULL)
{
std::string errmsg(dlerror());
throw FatalError(errmsg);
}
return r;
}
void AuthPlugin::loadPlugin(const std::string &pathToSoFile)
{
if (pathToSoFile.empty())
return;
logger->logf(LOG_INFO, "Loading auth plugin %s", pathToSoFile.c_str());
initialized = false;
wanted = true;
if (access(pathToSoFile.c_str(), R_OK) != 0)
{
std::ostringstream oss;
oss << "Error loading auth plugin: The file " << pathToSoFile << " is not there or not readable";
throw FatalError(oss.str());
}
void *r = dlopen(pathToSoFile.c_str(), RTLD_NOW|RTLD_GLOBAL);
if (r == NULL)
{
std::string errmsg(dlerror());
throw FatalError(errmsg);
}
version = (F_auth_plugin_version)loadSymbol(r, "mosquitto_auth_plugin_version");
if (version() != 2)
{
throw FatalError("Only Mosquitto plugin version 2 is supported at this time.");
}
init_v2 = (F_auth_plugin_init_v2)loadSymbol(r, "mosquitto_auth_plugin_init");
cleanup_v2 = (F_auth_plugin_cleanup_v2)loadSymbol(r, "mosquitto_auth_plugin_cleanup");
security_init_v2 = (F_auth_plugin_security_init_v2)loadSymbol(r, "mosquitto_auth_security_init");
security_cleanup_v2 = (F_auth_plugin_security_cleanup_v2)loadSymbol(r, "mosquitto_auth_security_cleanup");
acl_check_v2 = (F_auth_plugin_acl_check_v2)loadSymbol(r, "mosquitto_auth_acl_check");
unpwd_check_v2 = (F_auth_plugin_unpwd_check_v2)loadSymbol(r, "mosquitto_auth_unpwd_check");
psk_key_get_v2 = (F_auth_plugin_psk_key_get_v2)loadSymbol(r, "mosquitto_auth_psk_key_get");
initialized = true;
}
void AuthPlugin::init()
{
if (!wanted)
return;
AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
int result = init_v2(&pluginData, authOpts.head(), authOpts.size());
if (result != 0)
throw FatalError("Error initialising auth plugin.");
}
void AuthPlugin::cleanup()
{
if (!cleanup_v2)
return;
securityCleanup(false);
AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
int result = cleanup_v2(pluginData, authOpts.head(), authOpts.size());
if (result != 0)
logger->logf(LOG_ERR, "Error cleaning up auth plugin"); // Not doing exception, because we're shutting down anyway.
}
void AuthPlugin::securityInit(bool reloading)
{
if (!wanted)
return;
AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
int result = security_init_v2(pluginData, authOpts.head(), authOpts.size(), reloading);
if (result != 0)
{
throw AuthPluginException("Plugin function mosquitto_auth_security_init returned an error. If it didn't log anything, we don't know what it was.");
}
initialized = true;
}
void AuthPlugin::securityCleanup(bool reloading)
{
if (!wanted)
return;
initialized = false;
AuthOptCompatWrap &authOpts = confFileParser.getAuthOptsCompat();
int result = security_cleanup_v2(pluginData, authOpts.head(), authOpts.size(), reloading);
if (result != 0)
{
throw AuthPluginException("Plugin function mosquitto_auth_security_cleanup returned an error. If it didn't log anything, we don't know what it was.");
}
}
AuthResult AuthPlugin::aclCheck(const std::string &clientid, const std::string &username, const std::string &topic, AclAccess access)
{
if (!wanted)
return AuthResult::success;
if (!initialized)
{
logger->logf(LOG_ERR, "ACL check wanted, but initialization failed. Can't perform check.");
return AuthResult::error;
}
int result = acl_check_v2(pluginData, clientid.c_str(), username.c_str(), topic.c_str(), static_cast<int>(access));
AuthResult result_ = static_cast<AuthResult>(result);
if (result_ == AuthResult::error)
{
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());
}
return result_;
}
AuthResult AuthPlugin::unPwdCheck(const std::string &username, const std::string &password)
{
if (!wanted)
return AuthResult::success;
if (!initialized)
{
logger->logf(LOG_ERR, "Username+password check wanted, but initialization failed. Can't perform check.");
return AuthResult::error;
}
int result = unpwd_check_v2(pluginData, username.c_str(), password.c_str());
AuthResult r = static_cast<AuthResult>(result);
if (r == AuthResult::error)
{
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());
}
return r;
}