]> git.stg.codes - stg.git/blobdiff - projects/stargazer/plugins/other/radius/radius.cpp
Merge branch 'stg-2.409-radius'
[stg.git] / projects / stargazer / plugins / other / radius / radius.cpp
index daa8634caa58ba8f3af9f6b85a8a724ee0c65b8c..45a9d0e19446f80054df4c9bdf972b0ba79ef73f 100644 (file)
@@ -23,6 +23,7 @@
 #include "stg/store.h"
 #include "stg/users.h"
 #include "stg/plugin_creator.h"
+#include "stg/common.h"
 
 #include <algorithm>
 #include <stdexcept>
@@ -53,7 +54,7 @@ extern "C" PLUGIN * GetPlugin()
 }
 
 RADIUS::RADIUS()
-    : m_config(m_settings),
+    : m_config(),
       m_running(false),
       m_stopped(true),
       m_users(NULL),
@@ -90,6 +91,11 @@ int RADIUS::Start()
 
 int RADIUS::Stop()
 {
+    std::set<std::string>::const_iterator it = m_logins.begin();
+    for (; it != m_logins.end(); ++it)
+        m_users->Unauthorize(*it, this, "Stopping RADIUS plugin.");
+    m_logins.clear();
+
     if (m_stopped)
         return 0;
 
@@ -105,6 +111,9 @@ int RADIUS::Stop()
         return 0;
     }
 
+    if (m_config.connectionType == Config::UNIX)
+        unlink(m_config.bindAddress.c_str());
+
     m_error = "Failed to stop thread.";
     m_logger(m_error);
     return -1;
@@ -134,8 +143,6 @@ bool RADIUS::reconnect()
     {
         shutdown(m_listenSocket, SHUT_RDWR);
         close(m_listenSocket);
-        if (m_config.connectionType == Config::UNIX)
-            unlink(m_config.bindAddress.c_str());
     }
     if (m_config.connectionType == Config::UNIX)
         m_listenSocket = createUNIX();
@@ -165,6 +172,7 @@ int RADIUS::createUNIX() const
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
     strncpy(addr.sun_path, m_config.bindAddress.c_str(), m_config.bindAddress.length());
+    unlink(m_config.bindAddress.c_str());
     if (bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1)
     {
         shutdown(fd, SHUT_RDWR);
@@ -173,6 +181,9 @@ int RADIUS::createUNIX() const
         m_logger(m_error);
         return 0;
     }
+    chown(m_config.bindAddress.c_str(), m_config.sockUID, m_config.sockGID);
+    if (m_config.sockMode != static_cast<mode_t>(-1))
+        chmod(m_config.bindAddress.c_str(), m_config.sockMode);
     return fd;
 }
 
@@ -193,7 +204,7 @@ int RADIUS::createTCP() const
     int res = getaddrinfo(m_config.bindAddress.c_str(), m_config.portStr.c_str(), &hints, &ais);
     if (res != 0)
     {
-        m_error = "Error resolvin address '" + m_config.bindAddress + "': " + gai_strerror(res);
+        m_error = "Error resolving address '" + m_config.bindAddress + "': " + gai_strerror(res);
         m_logger(m_error);
         return 0;
     }
@@ -230,6 +241,7 @@ int RADIUS::createTCP() const
 void RADIUS::runImpl()
 {
     m_running = true;
+    m_stopped = false;
 
     while (m_running) {
         fd_set fds;
@@ -243,6 +255,8 @@ void RADIUS::runImpl()
         int res = select(maxFD() + 1, &fds, NULL, NULL, &tv);
         if (res < 0)
         {
+            if (errno == EINTR)
+                continue;
             m_error = std::string("'select' is failed: '") + strerror(errno) + "'.";
             m_logger(m_error);
             break;
@@ -332,7 +346,8 @@ void RADIUS::acceptUNIX()
         m_logger(m_error);
         return;
     }
-    m_conns.push_back(new Conn(*m_users, m_logger, m_config, res, addr.sun_path));
+    printfd(__FILE__, "New UNIX connection: '%s'\n", addr.sun_path);
+    m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, addr.sun_path));
 }
 
 void RADIUS::acceptTCP()
@@ -348,5 +363,28 @@ void RADIUS::acceptTCP()
         return;
     }
     std::string remote = inet_ntostring(addr.sin_addr.s_addr) + ":" + x2str(ntohs(addr.sin_port));
-    m_conns.push_back(new Conn(*m_users, m_logger, m_config, res, remote));
+    printfd(__FILE__, "New TCP connection: '%s'\n", remote.c_str());
+    m_conns.push_back(new Conn(*m_users, m_logger, *this, m_config, res, remote));
+}
+
+void RADIUS::authorize(const USER& user)
+{
+    uint32_t ip = 0;
+    const std::string& login(user.GetLogin());
+    if (!m_users->Authorize(login, ip, 0xffFFffFF, this))
+    {
+        m_error = "Unable to authorize user '" + login + "' with ip " + inet_ntostring(ip) + ".";
+        m_logger(m_error);
+    }
+    else
+        m_logins.insert(login);
+}
+
+void RADIUS::unauthorize(const std::string& login, const std::string& reason)
+{
+    const std::set<std::string>::const_iterator it = m_logins.find(login);
+    if (it == m_logins.end())
+        return;
+    m_logins.erase(it);
+    m_users->Unauthorize(login, this, reason);
 }