From: Selva Nair <selva.n...@gmail.com>

- When management-client-group is in use, allow access if any of
  the supplementary groups of the user matches the specified group.

  Currently only the effective gid of the peer socket is checked
  which is normally the primary group of user. As unprivileged users
  have no easy way of changing the effective gid of a process,
  group based access control is of very limited use without this change.

- Also accept if uid = 0 irrespective of the group.

Github: OpenVPN/openvpn#264

Signed-off-by: Selva Nair <selva.n...@gmail.com>
---
 configure.ac         |  2 +-
 src/openvpn/manage.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 67f680b2..979903a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -659,7 +659,7 @@ AC_CHECK_FUNCS([ \
        daemon chroot getpwnam setuid nice system dup dup2 \
        syslog openlog mlockall getrlimit getgrnam setgid \
        setgroups flock readv writev time gettimeofday \
-       setsid chdir \
+       setsid chdir getpwuid getgrent \
        chsize ftruncate execve getpeereid basename dirname access \
        epoll_create strsep \
 ])
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index db88e347..73dc7d57 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -1771,6 +1771,42 @@ man_new_connection_post(struct management *man, const 
char *description)
 }
 
 #if UNIX_SOCK_SUPPORT
+/**
+ * Return true if user uid is a member of group gid.
+ * On error or lack of platform support, we return false.
+ */
+
+static bool
+is_user_in_group(uid_t uid, gid_t gid)
+{
+    bool ret = false;
+#if defined(HAVE_GETPWUID) && defined(HAVE_GETGRENT)
+    struct passwd *pw = getpwuid(uid);
+    if (!pw)
+    {
+        return ret;
+    }
+
+    struct group *gr = getgrent();
+    char **members = NULL;
+    while (gr)
+    {
+        if (gr->gr_gid == gid)
+        {
+            /* found the group -- check user is a member */
+            members = gr->gr_mem;
+            for (char *s = *members; s && !ret; s++)
+            {
+                ret = !strcmp(s, pw->pw_name);
+            }
+            break; /* out of the while loop */
+        }
+        gr = getgrent();
+    }
+#endif /* if defined(HAVE_GETPWUID) && defined(HAVE_GETGRENT) */
+    return ret;
+}
+
 static bool
 man_verify_unix_peer_uid_gid(struct management *man, const socket_descriptor_t 
sd)
 {
@@ -1780,13 +1816,18 @@ man_verify_unix_peer_uid_gid(struct management *man, 
const socket_descriptor_t s
         int uid, gid;
         if (unix_socket_get_peer_uid_gid(man->connection.sd_cli, &uid, &gid))
         {
+            if (uid == 0) /* accept if root */
+            {
+                return true;
+            }
             if (man->settings.client_uid != -1 && man->settings.client_uid != 
uid)
             {
                 msg(D_MANAGEMENT, "%s UID of socket peer (%d) doesn't match 
required value (%d) as given by --management-client-user",
                     err_prefix, uid, man->settings.client_uid);
                 return false;
             }
-            if (man->settings.client_gid != -1 && man->settings.client_gid != 
gid)
+            if (man->settings.client_gid != -1 && man->settings.client_gid != 
gid
+                && !is_user_in_group(uid, man->settings.client_gid))
             {
                 msg(D_MANAGEMENT, "%s GID of socket peer (%d) doesn't match 
required value (%d) as given by --management-client-group",
                     err_prefix, gid, man->settings.client_gid);
-- 
2.34.1



_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to