2 #include "radproto/error.h"
3 #include "stg/common.h"
4 #include <boost/tokenizer.hpp>
13 using STG::RAD_SETTINGS;
14 using AttrValue = RAD_SETTINGS::AttrValue;
15 using ASection = RAD_SETTINGS::ASection;
17 extern "C" STG::Plugin* GetPlugin()
25 std::string ShowRules(const std::vector<std::pair<std::string, AttrValue>>& attributes)
28 for (const auto& at : attributes)
33 if (at.second.type == AttrValue::Type::PARAM_NAME)
34 result.append(at.first + " = " + at.second.value);
36 result.append(at.first + " = '" + at.second.value + "'");
42 std::vector<std::pair<std::string, AttrValue>> RAD_SETTINGS::ParseRules(const std::string& value, const std::string& paramName)
44 using tokenizer = boost::tokenizer<boost::char_separator<char>>;
45 const boost::char_separator<char> sep(",");
47 const tokenizer tokens(value, sep);
49 std::vector<std::pair<std::string, AttrValue>> res;
50 for (const auto& token : tokens)
52 const boost::char_separator<char> sp(" =");
53 const tokenizer tok(token, sp);
55 std::vector<std::string> keyValue;
56 for (const auto& t : tok)
57 keyValue.push_back(t);
59 if (keyValue.size() != 2)
61 m_logger("The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(), token.c_str());
62 printfd(__FILE__, "The '%s' attribute specification has an incorrect format: '%s'.", paramName.c_str(), token.c_str());
66 auto type = AttrValue::Type::PARAM_NAME;
67 std::string valueName = keyValue[1];
68 if (valueName.front() == '\'' && valueName.back() == '\'')
70 type = AttrValue::Type::VALUE;
71 valueName.erase(0, 1);
72 valueName.erase(valueName.length() - 1, 1);
74 else if ((valueName.front() == '\'' && valueName.back() != '\'') || (valueName.front() != '\'' && valueName.back() == '\''))
76 m_logger("Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str());
77 printfd(__FILE__, "Error ParseRules: '%s' attribute parameter value is invalid.\n", paramName.c_str());
80 res.emplace_back(keyValue[0], AttrValue{valueName, type});
85 ASection RAD_SETTINGS::parseASection(const std::vector<ParamValue>& conf)
88 const auto mit = std::find(conf.begin(), conf.end(), ParamValue("match", {}));
89 if (mit != conf.end())
90 res.match = ParseRules(mit->value[0], mit->param);
92 const auto sit = std::find(conf.begin(), conf.end(), ParamValue("send", {}));
93 if (sit != conf.end())
94 res.send = ParseRules(sit->value[0], sit->param);
99 RAD_SETTINGS::RAD_SETTINGS()
101 m_dictionaries("/usr/share/freeradius/dictionary"),
102 m_logger(PluginLogger::get("radius"))
105 int RAD_SETTINGS::ParseSettings(const ModuleSettings & s)
111 auto pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
112 if (pvi != s.moduleParams.end() && !pvi->value.empty())
114 if (ParseIntInRange(pvi->value[0], 2, 65535, &p) != 0)
116 m_errorStr = "Cannot parse parameter \'Port\': " + m_errorStr;
117 printfd(__FILE__, "Cannot parse parameter 'Port'\n");
120 m_port = static_cast<uint16_t>(p);
124 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
125 if (pvi == s.moduleParams.end() || pvi->value.empty())
127 m_errorStr = "Parameter \'Secret\' not found.";
128 printfd(__FILE__, "Parameter 'Secret' not found\n");
132 m_secret = pvi->value[0];
134 pv.param = "Dictionaries";
135 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
136 if (pvi != s.moduleParams.end() && !pvi->value.empty())
137 m_dictionaries = pvi->value[0];
139 const auto authIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("auth", {}));
140 if (authIt != s.moduleParams.end())
141 m_auth = parseASection(authIt->sections);
143 const auto autzIt = std::find(s.moduleParams.begin(), s.moduleParams.end(), ParamValue("autz", {}));
144 if (autzIt != s.moduleParams.end())
145 m_autz = parseASection(autzIt->sections);
147 printfd(__FILE__, " auth.match = \"%s\"\n", ShowRules(m_auth.match).c_str());
148 printfd(__FILE__, " auth.send = \"%s\"\n", ShowRules(m_auth.send).c_str());
149 printfd(__FILE__, " autz.match = \"%s\"\n", ShowRules(m_autz.match).c_str());
150 printfd(__FILE__, " autz.send = \"%s\"\n", ShowRules(m_autz.send).c_str());
158 m_logger(PluginLogger::get("radius"))
162 int RADIUS::ParseSettings()
164 auto ret = m_radSettings.ParseSettings(m_settings);
166 m_errorStr = m_radSettings.GetStrError();
171 std::string RADIUS::GetVersion() const
173 return "Radius v.1.0";
178 m_thread = std::jthread([this](auto token){ Run(std::move(token)); });
184 if (!m_thread.joinable())
187 m_thread.request_stop();
196 bool RADIUS::IsRunning()
198 const std::lock_guard lock(m_mutex);
202 void RADIUS::SetRunning(bool val)
204 const std::lock_guard lock(m_mutex);
208 int RADIUS::Run(std::stop_token token)
215 m_server = std::make_unique<Server>(m_ioContext, m_radSettings.GetSecret(), m_radSettings.GetPort(), m_radSettings.GetDictionaries(), std::move(token), m_logger, m_users);
218 catch (const std::exception& e)
220 m_errorStr = "Exception in RADIUS::Run(): " + std::string(e.what());
221 m_logger("Exception in RADIUS:: Run(): %s", e.what());
222 printfd(__FILE__, "Exception in RADIUS:: Run(). Message: '%s'\n", e.what());