X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/1538d6276533140505fddb71c99a0bafe6ca9182..refs/heads/master:/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 fe989b28..8e5b37a8 100644 --- a/projects/stargazer/plugins/other/radius/radius.cpp +++ b/projects/stargazer/plugins/other/radius/radius.cpp @@ -1,186 +1,131 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - #include "radius.h" +#include "radproto/error.h" +#include "stg/common.h" -#include "stg/store.h" -#include "stg/users.h" -#include "stg/plugin_creator.h" +#include +#include -#include -#include -#include +using STG::RADIUS; +using STG::RAD_SETTINGS; -namespace +extern "C" STG::Plugin* GetPlugin() { - -PLUGIN_CREATOR creator; - + static RADIUS plugin; + return &plugin; } -extern "C" PLUGIN * GetPlugin() +RAD_SETTINGS::RAD_SETTINGS() + : m_port(1812), + m_dictionaries("/usr/share/freeradius/dictionary") +{} + +int RAD_SETTINGS::ParseSettings(const ModuleSettings & s) { - return creator.GetPlugin(); + ParamValue pv; + int p; + + pv.param = "Port"; + auto pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv); + if (pvi != s.moduleParams.end() && !pvi->value.empty()) + { + if (ParseIntInRange(pvi->value[0], 2, 65535, &p) != 0) + { + m_errorStr = "Cannot parse parameter \'Port\': " + m_errorStr; + printfd(__FILE__, "Cannot parse parameter 'Port'\n"); + return -1; + } + m_port = static_cast(p); + } + + pv.param = "Secret"; + pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv); + if (pvi == s.moduleParams.end() || pvi->value.empty()) + { + m_errorStr = "Parameter \'Secret\' not found."; + printfd(__FILE__, "Parameter 'Secret' not found\n"); + 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]; + return 0; } RADIUS::RADIUS() : m_running(false), - m_stopped(true), - m_users(NULL), - m_store(NULL), - m_logger(GetPluginLogger(GetStgLogger(), "radius")) + m_logger(PluginLogger::get("radius")) { } int RADIUS::ParseSettings() { - try { - m_config = STG::Config(m_settings); - return 0; - } catch (const std::runtime_error& ex) { - m_logger("Failed to parse settings. %s", ex.what()); - return -1; - } -} - -int RADIUS::Start() -{ - if (m_running) - return 0; - - int res = pthread_create(&m_thread, NULL, run, this); - if (res == 0) - return 0; + auto ret = m_radSettings.ParseSettings(m_settings); + if (ret != 0) + m_errorStr = m_radSettings.GetStrError(); - m_error = strerror(res); - m_logger("Failed to create thread: '" + m_error + "'."); - return -1; + return ret; } -int RADIUS::Stop() +std::string RADIUS::GetVersion() const { - if (m_stopped) - return 0; - - m_running = false; - - for (size_t i = 0; i < 25 && !m_stopped; i++) { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - - if (m_stopped) { - pthread_join(m_thread, NULL); - return 0; - } - - m_error = "Failed to stop thread."; - m_logger(m_error); - return -1; + return "Radius v.1.0"; } -//----------------------------------------------------------------------------- -void* RADIUS::run(void* d) -{ - sigset_t signalSet; - sigfillset(&signalSet); - pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - static_cast(d)->runImpl(); - - return NULL; +int RADIUS::Start() +{ + m_thread = std::jthread([this](auto token){ Run(std::move(token)); }); + return 0; } -void RADIUS::runImpl() +int RADIUS::Stop() { - m_running = true; - - while (m_running) { - fd_set fds; - - buildFDSet(fds); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 500000; - - int res = select(maxFD() + 1, &fds, NULL, NULL, &tv); - if (res < 0) - { - m_error = std::string("'select' is failed: '") + strerror(errno) + "'."; - m_logger(m_error); - break; - } - - if (!m_running) - break; + if (!m_thread.joinable()) + return 0; - if (res > 0) - handleEvents(fds); + m_thread.request_stop(); - cleanupConns(); - } + if (m_server) + m_server->stop(); - m_stopped = true; + m_thread.join(); + return 0; } -int RADIUS::maxFD() const +bool RADIUS::IsRunning() { - int maxFD = m_listenSocket; - std::deque::const_iterator it; - for (it = m_conns.begin(); it != m_conns.end(); ++it) - if (maxFD < (*it)->sock()) - maxFD = (*it)->sock(); - return maxFD; + const std::lock_guard lock(m_mutex); + return m_running; } -void RADIUS::buildFDSet(fd_set & fds) const +void RADIUS::SetRunning(bool val) { - FD_ZERO(&fds); - FD_SET(m_listenSocket, &fds); - std::deque::const_iterator it; - for (it = m_conns.begin(); it != m_conns.end(); ++it) - FD_SET((*it)->sock(), &fds); + const std::lock_guard lock(m_mutex); + m_running = val; } -void RADIUS::cleanupConns() +int RADIUS::Run(std::stop_token token) { - std::deque::iterator pos; - for (pos = m_conns.begin(); pos != m_conns.end(); ++pos) - if (((*pos)->isDone() && !(*pos)->isKeepAlive()) || !(*pos)->isOk()) { - delete *pos; - *pos = NULL; - } + SetRunning(true); - pos = std::remove(m_conns.begin(), m_conns.end(), static_cast(NULL)); - m_conns.erase(pos, m_conns.end()); -} - -void RADIUS::handleEvents(const fd_set & fds) -{ - if (FD_ISSET(m_listenSocket, &fds)) - acceptConnection(); - else + try { - std::deque::iterator it; - for (it = m_conns.begin(); it != m_conns.end(); ++it) - if (FD_ISSET((*it)->sock(), &fds)) - (*it)->read(); + if (!m_server) + m_server = std::make_unique(m_ioService, m_radSettings.GetSecret(), m_radSettings.GetPort(), m_radSettings.GetDictionaries(), std::move(token), m_logger); + m_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; }