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.
!_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;
<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>
#ifdef DBUS_UNIX
# include <pwd.h>
# include <unistd.h>
+# include <stdlib.h>
+# include <search.h>
# include <sys/types.h>
# ifdef HAVE_GIO_UNIX
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)
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)
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)