From: Matthijs van Duin Date: Mon, 25 Mar 2019 22:01:26 +0000 (+0100) Subject: Add UnixGroupIDs to connection credentials X-Git-Tag: dbus-1.13.10~2^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=afafd2fad0f53dc3f03d67047d4be5c58eead56a;p=thirdparty%2Fdbus.git Add UnixGroupIDs to connection credentials Signed-off-by: Matthijs van Duin --- diff --git a/bus/driver.c b/bus/driver.c index 267c881dc..6714fe062 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -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; diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index 461404c85..0b9226b35 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -6725,6 +6725,17 @@ UINT32 The numeric Unix user ID, as defined by POSIX + + UnixGroupIDs + ARRAY of UINT32 + 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. + + ProcessID UINT32 diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index e4e11f16f..fdc75dc8b 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -45,6 +45,8 @@ #ifdef DBUS_UNIX # include # include +# include +# include # include # 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)