implemented user access control in NamedPipeListener
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 12 Sep 2017 12:33:16 +0000 (15:33 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 12 Sep 2017 12:33:16 +0000 (15:33 +0300)
configure.ac
include/nxproc.h
src/agent/core/extagent.cpp
src/agent/core/push.cpp
src/libnetxms/nxproc.cpp
src/libnetxms/nxproc_unix.cpp
src/libnetxms/nxproc_win32.cpp

index 0d7a6f0..20896d0 100644 (file)
@@ -2129,7 +2129,8 @@ AC_CHECK_FUNCS([strrchr strlwr strtok_r strtol strtoul strtoll strtoull setlocal
 AC_CHECK_FUNCS([tolower if_nametoindex daemon mmap strerror_r scandir uname poll])
 AC_CHECK_FUNCS([usleep nanosleep gmtime_r localtime_r stat64 fstat64 lstat64])
 AC_CHECK_FUNCS([fopen64 strptime timegm gethostbyname2_r getaddrinfo rand_r])
-AC_CHECK_FUNCS([itoa _itoa isatty getgrnam getpwnam malloc_info malloc_trim utime])
+AC_CHECK_FUNCS([itoa _itoa isatty malloc_info malloc_trim utime])
+AC_CHECK_FUNCS([getgrnam getpwnam getpwuid getpwuid_r])
 
 AC_CHECK_DECLS([nanosleep, daemon, strerror])
 
index e2252f9..c3c12ca 100644 (file)
@@ -19,14 +19,16 @@ private:
    TCHAR m_name[MAX_PIPE_NAME_LEN];
    HPIPE m_handle;
    MUTEX m_writeLock;
+   TCHAR m_user[64];
 
-   NamedPipe(const TCHAR *name, HPIPE handle);
+   NamedPipe(const TCHAR *name, HPIPE handle, const TCHAR *user);
 
 public:
    ~NamedPipe();
 
    const TCHAR *name() const { return m_name; }
    HPIPE handle() { return m_handle; }
+   const TCHAR *user() const { return m_user; }
 
    bool write(const void *data, size_t size);
 
@@ -50,11 +52,12 @@ private:
    void *m_userArg;
    THREAD m_serverThread;
    bool m_stop;
+   TCHAR m_user[64];
 
    void serverThread();
    static THREAD_RESULT THREAD_CALL serverThreadStarter(void *arg);
 
-   NamedPipeListener(const TCHAR *name, HPIPE handle, NamedPipeRequestHandler reqHandler, void *userArg);
+   NamedPipeListener(const TCHAR *name, HPIPE handle, NamedPipeRequestHandler reqHandler, void *userArg, const TCHAR *user);
 
 public:
    ~NamedPipeListener();
@@ -64,7 +67,7 @@ public:
    void start();
    void stop();
 
-   static NamedPipeListener *create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg);
+   static NamedPipeListener *create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg, const TCHAR *user = NULL);
 };
 
 #endif   /* _nxproc_h_ */
index 598d669..02f418d 100644 (file)
@@ -65,7 +65,8 @@ void ExternalSubagent::startListener()
 {
    TCHAR name[MAX_PIPE_NAME_LEN];
    _sntprintf(name, MAX_PIPE_NAME_LEN, _T("nxagentd.subagent.%s"), m_name);
-   m_listener = NamedPipeListener::create(name, RequestHandler, this);
+   m_listener = NamedPipeListener::create(name, RequestHandler, this,
+            (m_user[0] != 0) && _tcscmp(m_user, _T("*")) ? m_user : NULL);
    if (m_listener != NULL)
       m_listener->start();
 }
index ff3affb..27779d9 100644 (file)
@@ -109,7 +109,9 @@ static NamedPipeListener *s_listener;
  */
 void StartPushConnector()
 {
-   s_listener = NamedPipeListener::create(_T("nxagentd.push"), ProcessPushRequest, NULL);
+   const TCHAR *user = g_config->getValue(_T("/%agent/PushUser"), _T("*"));
+   s_listener = NamedPipeListener::create(_T("nxagentd.push"), ProcessPushRequest, NULL,
+            (user != NULL) && (user[0] != 0) && _tcscmp(user, _T("*")) ? user : NULL);
    if (s_listener != NULL)
       s_listener->start();
 }
index 655eefd..374e844 100644 (file)
@@ -27,7 +27,7 @@
 /**
  * Named pipe listener constructor
  */
-NamedPipeListener::NamedPipeListener(const TCHAR *name, HPIPE handle, NamedPipeRequestHandler reqHandler, void *userArg)
+NamedPipeListener::NamedPipeListener(const TCHAR *name, HPIPE handle, NamedPipeRequestHandler reqHandler, void *userArg, const TCHAR *user)
 {
    nx_strncpy(m_name, name, MAX_PIPE_NAME_LEN);
    m_handle = handle;
@@ -35,6 +35,7 @@ NamedPipeListener::NamedPipeListener(const TCHAR *name, HPIPE handle, NamedPipeR
    m_userArg = userArg;
    m_serverThread = INVALID_THREAD_HANDLE;
    m_stop = false;
+   nx_strncpy(m_user, CHECK_NULL_EX(user), 64);
 }
 
 /**
@@ -71,9 +72,10 @@ THREAD_RESULT THREAD_CALL NamedPipeListener::serverThreadStarter(void *arg)
 /**
  * Named pipe constructor
  */
-NamedPipe::NamedPipe(const TCHAR *name, HPIPE handle)
+NamedPipe::NamedPipe(const TCHAR *name, HPIPE handle, const TCHAR *user)
 {
    nx_strncpy(m_name, name, MAX_PIPE_NAME_LEN);
    m_handle = handle;
    m_writeLock = MutexCreate();
+   nx_strncpy(m_user, CHECK_NULL_EX(user), 64);
 }
index 34102b5..0cd3600 100644 (file)
 
 #include "libnetxms.h"
 #include <nxproc.h>
+#include <pwd.h>
 
 /**
  * Create listener end for named pipe
  */
-NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg)
+NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg, const TCHAR *user)
 {
    mode_t prevMask = 0;
 
@@ -61,7 +62,7 @@ NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequest
       goto failure;
    }
 
-   return new NamedPipeListener(name, s, reqHandler, userArg);
+   return new NamedPipeListener(name, s, reqHandler, userArg, user);
 
 failure:
    close(s);
@@ -98,9 +99,48 @@ void NamedPipeListener::serverThread()
       SOCKET cs = accept(m_handle, (struct sockaddr *)&addrRemote, &size);
       if (cs > 0)
       {
-         NamedPipe *cp = new NamedPipe(m_name, cs);
-         m_reqHandler(cp, m_userArg);
-         delete cp;
+         TCHAR user[64];
+
+         struct ucred peer;
+         unsigned int len = sizeof(peer);
+         if (getsockopt(cs, SOL_SOCKET, SO_PEERCRED, &peer, &len) == 0)
+         {
+#if HAVE_GETPWUID_R
+            struct passwd pwbuf, *pw;
+            char sbuf[4096];
+            getpwuid_r(peer.uid, &pwbuf, sbuf, 4096, &pw);
+#else
+            struct passwd *pw = getpwuid(peer.uid);
+#endif
+            if (pw != NULL)
+            {
+#ifdef UNICODE
+               MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pw->pw_name, -1, user, 64);
+#else
+               nx_strncpy(user, pw->pw_name, 64);
+#endif
+            }
+            else
+            {
+               _sntprintf(user, 64, _T("[%d]"), (int)peer.uid);
+            }
+         }
+         else
+         {
+            _tcscpy(user, _T("[unknown]"));
+         }
+
+         if ((m_user[0] == 0) || !_tcscmp(m_user, user))
+         {
+            nxlog_debug(5, _T("NamedPipeListener(%s): accepted connection by user %s"), m_name, user);
+            NamedPipe *cp = new NamedPipe(m_name, cs, user);
+            m_reqHandler(cp, m_userArg);
+            delete cp;
+         }
+         else
+         {
+            nxlog_debug(5, _T("NamedPipeListener(%s): rejected connection by user %s"), m_name, user);
+         }
       }
       else
       {
@@ -143,7 +183,7 @@ NamedPipe *NamedPipe::connect(const TCHAR *name, UINT32 timeout)
       return NULL;
    }
 
-   return new NamedPipe(name, s);
+   return new NamedPipe(name, s, NULL);
 }
 
 /**
index ac0d12e..4f0fd22 100644 (file)
@@ -27,7 +27,7 @@
 /**
  * Create listener end for named pipe
  */
-NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg)
+NamedPipeListener *NamedPipeListener::create(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg, const TCHAR *user)
 {
    mode_t prevMask = 0;