]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
Add UnixGroupIDs to connection credentials
authorMatthijs van Duin <matthijsvanduin@gmail.com>
Mon, 25 Mar 2019 22:01:26 +0000 (23:01 +0100)
committerMatthijs van Duin <matthijsvanduin@gmail.com>
Mon, 25 Mar 2019 22:01:26 +0000 (23:01 +0100)
Signed-off-by: Matthijs van Duin <matthijsvanduin@gmail.com>
bus/driver.c
doc/dbus-specification.xml
test/dbus-daemon.c

index 267c881dc229cfd3a8d45f0e01a1ae55c9ad7f82..6714fe0625d47da59df2022fcf131c7de18a40b0 100644 (file)
@@ -1904,6 +1904,56 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne
   return FALSE;
 }
 
+/*
+ * Write the unix group ids of credentials @credentials, if available, into
+ * the a{sv} @asv_iter. Return #FALSE on OOM.
+ */
+static dbus_bool_t
+bus_driver_credentials_fill_unix_gids (DBusCredentials *credentials,
+                                       DBusMessageIter *asv_iter)
+{
+  const dbus_gid_t *gids = NULL;
+  size_t n_gids = 0;
+
+  if (!_dbus_credentials_get_unix_gids (credentials, &gids, &n_gids))
+    return TRUE;
+
+  if (sizeof (dbus_gid_t) == sizeof (dbus_uint32_t))
+    {
+      return _dbus_asv_add_fixed_array (asv_iter, "UnixGroupIDs",
+                                        DBUS_TYPE_UINT32, gids, n_gids);
+    }
+  else
+    {
+      /* we can't represent > 32-bit uids; if your system needs them, please
+       * add UnixGroupIDs64 to the spec or something */
+      dbus_uint32_t *gids_u32;
+      size_t i;
+      dbus_bool_t result;
+
+      gids_u32 = dbus_new (dbus_uint32_t, n_gids);
+      if (gids_u32 == NULL)
+        return FALSE;
+
+      for (i = 0; i < n_gids; i++)
+        {
+          if (gids[i] > _DBUS_UINT32_MAX)
+            {
+              dbus_free (gids_u32);
+              return TRUE;
+            }
+          gids_u32[i] = gids[i];
+        }
+
+      result = _dbus_asv_add_fixed_array (asv_iter, "UnixGroupIDs",
+                                          DBUS_TYPE_UINT32, gids_u32, n_gids);
+
+      dbus_free (gids_u32);
+
+      return result;
+    }
+}
+
 /*
  * Write the credentials of connection @conn (or the bus daemon itself,
  * if @conn is #NULL) into the a{sv} @asv_iter. Return #FALSE on OOM.
@@ -1943,6 +1993,10 @@ bus_driver_fill_connection_credentials (DBusCredentials *credentials,
       !_dbus_asv_add_uint32 (asv_iter, "UnixUserID", uid))
     return FALSE;
 
+  if (credentials != NULL &&
+      !bus_driver_credentials_fill_unix_gids (credentials, asv_iter))
+    return FALSE;
+
   if (windows_sid != NULL)
     {
       DBusString str;
index 461404c85c83ceaac5f56f638128d3970de982a0..0b9226b3563a6a319d5f7674623f3cee58b5eabb 100644 (file)
                 <entry>UINT32</entry>
                 <entry>The numeric Unix user ID, as defined by POSIX</entry>
               </row>
+              <row>
+                <entry>UnixGroupIDs</entry>
+                <entry>ARRAY of UINT32</entry>
+                <entry>The numeric Unix group IDs (including both the primary
+                  group and the supplementary groups), as defined by POSIX, in
+                  numerically sorted order. This array is either complete or
+                  absent: if the message bus is able to determine some but not
+                  all of the caller's groups, it must not add this credential
+                  to the dictionary.
+                </entry>
+              </row>
               <row>
                 <entry>ProcessID</entry>
                 <entry>UINT32</entry>
index e4e11f16fdc43162424c038557dfbe5c3c5d3a34..fdc75dc8be2e715f4728dbb1760e0427abd99982 100644 (file)
@@ -45,6 +45,8 @@
 #ifdef DBUS_UNIX
 # include <pwd.h>
 # include <unistd.h>
+# include <stdlib.h>
+# include <search.h>
 # include <sys/types.h>
 
 # ifdef HAVE_GIO_UNIX
@@ -392,6 +394,20 @@ test_no_reply (Fixture *f,
   dbus_clear_message (&reply);
 }
 
+#ifdef G_OS_UNIX
+static int
+gid_cmp (const void *ap, const void *bp)
+{
+  gid_t a = *(const gid_t *)ap;
+  gid_t b = *(const gid_t *)bp;
+  if (a < b)
+    return -1;
+  if (a > b)
+    return 1;
+  return 0;
+}
+#endif
+
 static void
 test_creds (Fixture *f,
     gconstpointer context)
@@ -408,7 +424,8 @@ test_creds (Fixture *f,
       SEEN_UNIX_USER = 1,
       SEEN_PID = 2,
       SEEN_WINDOWS_SID = 4,
-      SEEN_LINUX_SECURITY_LABEL = 8
+      SEEN_LINUX_SECURITY_LABEL = 8,
+      SEEN_UNIX_GROUPS = 16,
   } seen = 0;
 
   if (m == NULL)
@@ -458,6 +475,44 @@ test_creds (Fixture *f,
           seen |= SEEN_UNIX_USER;
 #else
           g_assert_not_reached ();
+#endif
+        }
+      else if (g_strcmp0 (name, "UnixGroupIDs") == 0)
+        {
+#ifdef G_OS_UNIX
+          guint32 *groups;
+          gid_t egid = getegid();
+          gid_t *actual_groups;
+          int len, ret, i;
+          size_t nmemb;
+          DBusMessageIter ay_iter;
+
+          g_assert (!(seen & SEEN_UNIX_GROUPS));
+          g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
+              DBUS_TYPE_ARRAY);
+          dbus_message_iter_recurse (&var_iter, &ay_iter);
+          g_assert_cmpuint (dbus_message_iter_get_arg_type (&ay_iter), ==,
+              DBUS_TYPE_UINT32);
+          dbus_message_iter_get_fixed_array (&ay_iter, &groups, &len);
+          g_test_message ("%s of this process present (%d groups)", name, len);
+          g_assert_cmpint (len, >=, 1);
+
+          actual_groups = g_new0 (gid_t, len+1);
+          ret = getgroups (len, actual_groups);
+          if (ret < 0)
+            g_error ("getgroups: %s", g_strerror (errno));
+          nmemb = ret;
+          if (!lfind (&egid, actual_groups, &nmemb, sizeof (gid_t), gid_cmp))
+            actual_groups[ret++] = egid;
+          g_assert_cmpint (ret, ==, len);
+          qsort (actual_groups, len, sizeof (gid_t), gid_cmp);
+          for (i = 0; i < len; i++)
+            g_assert_true (groups[i] == actual_groups[i]);
+          g_free (actual_groups);
+
+          seen |= SEEN_UNIX_GROUPS;
+#else
+          g_assert_not_reached ();
 #endif
         }
       else if (g_strcmp0 (name, "WindowsSID") == 0)