X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/58d030a0db2b320459ce55d5a7b7b440d873d1d1..21ba4dfad49d2d489a9399d36d078eab8c44e0d6:/projects/stargazer/plugins/other/radius/radius.cpp diff --git a/projects/stargazer/plugins/other/radius/radius.cpp b/projects/stargazer/plugins/other/radius/radius.cpp index e517c959..68291dcf 100644 --- a/projects/stargazer/plugins/other/radius/radius.cpp +++ b/projects/stargazer/plugins/other/radius/radius.cpp @@ -1,16 +1,18 @@ #include "radius.h" -#include "server.h" #include "radproto/error.h" - #include "stg/common.h" +#include -#include -#include +#include +#include #include +#include #include using STG::RADIUS; using STG::RAD_SETTINGS; +using AttrValue = RAD_SETTINGS::AttrValue; +using ASection = RAD_SETTINGS::ASection; extern "C" STG::Plugin* GetPlugin() { @@ -18,9 +20,86 @@ extern "C" STG::Plugin* GetPlugin() return &plugin; } +namespace +{ + std::string ShowRules(const std::vector>& attributes) + { + std::string result; + for (const auto& at : attributes) + { + if (!result.empty()) + result += ", "; + + if (at.second.type == AttrValue::Type::PARAM_NAME) + result.append(at.first + " = " + at.second.value); + else + result.append(at.first + " = '" + at.second.value + "'"); + } + return result; + } +} + +std::vector> RAD_SETTINGS::ParseRules(const std::string& value, const std::string& paramName) +{ + using tokenizer = boost::tokenizer>; + const boost::char_separator sep(","); + + const tokenizer tokens(value, sep); + + std::vector> res; + for (const auto& token : tokens) + { + const boost::char_separator sp(" ="); + const tokenizer tok(token, sp); + + std::vector keyValue; + for (const auto& t : tok) + keyValue.push_back(t); + + if (keyValue.size() != 2) + { + m_logger("The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(), token.c_str()); + printfd(__FILE__, "The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(), token.c_str()); + return {}; + } + + auto type = AttrValue::Type::PARAM_NAME; + std::string valueName = keyValue[1]; + if (valueName.front() == '\'' && valueName.back() == '\'') + { + type = AttrValue::Type::VALUE; + valueName.erase(0, 1); + valueName.erase(valueName.length() - 1, 1); + } + else if ((valueName.front() == '\'' && valueName.back() != '\'') || (valueName.front() != '\'' && valueName.back() == '\'')) + { + m_logger("Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str()); + printfd(__FILE__, "Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str()); + return {}; + } + res.emplace_back(keyValue[0], AttrValue{valueName, type}); + } + return res; +} + +ASection RAD_SETTINGS::parseASection(const std::vector& conf) +{ + ASection res; + const auto mit = std::find(conf.begin(), conf.end(), ParamValue("match", {})); + if (mit != conf.end()) + res.match = ParseRules(mit->value[0], mit->param); + + const auto sit = std::find(conf.begin(), conf.end(), ParamValue("send", {})); + if (sit != conf.end()) + res.send = ParseRules(sit->value[0], sit->param); + + return res; +} + RAD_SETTINGS::RAD_SETTINGS() : m_port(1812), - m_dictionaries("/usr/share/freeradius/dictionary") + m_dictionaries("/usr/share/freeradius/dictionary"), + m_logger(PluginLogger::get("radius")) {} int RAD_SETTINGS::ParseSettings(const ModuleSettings & s) @@ -50,44 +129,36 @@ int RAD_SETTINGS::ParseSettings(const ModuleSettings & s) m_secret = ""; } else - { m_secret = pvi->value[0]; - } pv.param = "Dictionaries"; pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv); if (pvi != s.moduleParams.end() && !pvi->value.empty()) m_dictionaries = pvi->value[0]; + + const auto authIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("auth", {})); + if (authIt != s.moduleParams.end()) + m_auth = parseASection(authIt->sections); + + const auto autzIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("autz", {})); + if (autzIt != s.moduleParams.end()) + m_autz = parseASection(autzIt->sections); + + printfd(__FILE__, " auth.match = \"%s\"\n", ShowRules(m_auth.match).c_str()); + printfd(__FILE__, " auth.send = \"%s\"\n", ShowRules(m_auth.send).c_str()); + printfd(__FILE__, " autz.match = \"%s\"\n", ShowRules(m_autz.match).c_str()); + printfd(__FILE__, " autz.send = \"%s\"\n", ShowRules(m_autz.send).c_str()); + return 0; } RADIUS::RADIUS() : m_running(false), + m_users(NULL), m_logger(PluginLogger::get("radius")) { } -int RADIUS::Run(std::stop_token token) -{ - SetRunning(true); - - try - { - boost::asio::io_service ioService; - Server server(ioService, m_radSettings.GetSecret(), m_radSettings.GetPort(), m_radSettings.GetDictionaries()); - ioService.run(); - } - catch (const std::exception& e) - { - m_errorStr = "Exception in RADIUS::Run(): " + std::string(e.what()); - m_logger("Exception in RADIUS:: Run(): %s", e.what()); - printfd(__FILE__, "Exception in RADIUS:: Run(). Message: '%s'\n", e.what()); - } - - SetRunning(false); - return 0; -} - int RADIUS::ParseSettings() { auto ret = m_radSettings.ParseSettings(m_settings); @@ -115,6 +186,9 @@ int RADIUS::Stop() m_thread.request_stop(); + if (m_server) + m_server->stop(); + m_thread.join(); return 0; } @@ -130,3 +204,24 @@ void RADIUS::SetRunning(bool val) const std::lock_guard lock(m_mutex); m_running = val; } + +int RADIUS::Run(std::stop_token token) +{ + SetRunning(true); + + try + { + if (!m_server) + m_server = std::make_unique(m_ioContext, m_radSettings.GetSecret(), m_radSettings.GetPort(), m_radSettings.GetDictionaries(), std::move(token), m_logger, m_users); + m_ioContext.run(); + } + catch (const std::exception& e) + { + m_errorStr = "Exception in RADIUS::Run(): " + std::string(e.what()); + m_logger("Exception in RADIUS:: Run(): %s", e.what()); + printfd(__FILE__, "Exception in RADIUS:: Run(). Message: '%s'\n", e.what()); + } + + SetRunning(false); + return 0; +}