summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2020-05-01 14:28:36 +0100
committerRay Strode <halfline@gmail.com>2020-05-01 14:38:09 +0000
commit229a772888b24184b4f3024efd9d40e8ff46d27c (patch)
treed7dc557c02530aef79461851104dfcf963444eda
parentdfecf170fd66e736908ece055ee5aa9aa1c61170 (diff)
util: Split out helper method for getting admin group IDs
This introduces one small functional change: if any of the groups in `EXTRA_ADMIN_GROUPS` can’t be resolved using `getgrnam()`, an error will now be thrown. Previously, it would be ignored. Other than that, this introduces no functional changes and is just intended as a code cleanup. Signed-off-by: Philip Withnall <withnall@endlessm.com>
-rw-r--r--src/user.c18
-rw-r--r--src/util.c71
-rw-r--r--src/util.h4
3 files changed, 76 insertions, 17 deletions
diff --git a/src/user.c b/src/user.c
index 0fbda7a..590d76f 100644
--- a/src/user.c
+++ b/src/user.c
@@ -1687,7 +1687,6 @@ user_change_account_type_authorized_cb (Daemon *daemon,
g_autofree gid_t *extra_admin_groups_gids = NULL;
gsize n_extra_admin_groups_gids = 0;
gid_t admin_gid;
- struct group *grp;
gint i;
const gchar *argv[6];
@@ -1698,25 +1697,10 @@ user_change_account_type_authorized_cb (Daemon *daemon,
accounts_user_get_uid (ACCOUNTS_USER (user)),
account_type);
- grp = getgrnam (ADMIN_GROUP);
- if (grp == NULL) {
+ if (!get_admin_groups (&admin_gid, &extra_admin_groups_gids, &n_extra_admin_groups_gids)) {
throw_error (context, ERROR_FAILED, "failed to set account type: " ADMIN_GROUP " group not found");
return;
}
- admin_gid = grp->gr_gid;
-
- extra_admin_groups = g_strsplit (EXTRA_ADMIN_GROUPS, ",", 0);
- n_extra_admin_groups_gids = 0;
- extra_admin_groups_gids = g_new0 (gid_t, g_strv_length (extra_admin_groups));
-
- for (i = 0; extra_admin_groups[i] != NULL; i++) {
- struct group *extra_group;
- extra_group = getgrnam (extra_admin_groups[i]);
- if (extra_group == NULL || extra_group->gr_gid == admin_gid)
- continue;
-
- extra_admin_groups_gids[n_extra_admin_groups_gids++] = extra_group->gr_gid;
- }
ngroups = get_user_groups (accounts_user_get_user_name (ACCOUNTS_USER (user)), user->gid, &groups);
diff --git a/src/util.c b/src/util.c
index 0372b4b..a235403 100644
--- a/src/util.c
+++ b/src/util.c
@@ -257,6 +257,77 @@ get_user_groups (const gchar *user,
return res;
}
+/**
+ * get_admin_groups:
+ * @admin_gid_out: (out caller-allocates) (optional): return location for the ID
+ * of the main admin group
+ * @groups_out: (out callee-allocates) (transfer container) (optional) (length=n_groups_out):
+ * return location for an array of the extra admin group IDs
+ * @n_groups_out: (out caller-allocates) (optional): return location for the
+ * number of elements in @group_out
+ *
+ * Get the GIDs of the admin groups on the system, as set at configure time for
+ * accountsservice. The main admin group ID (typically for the `sudo` or `wheel`
+ * group) will be returned in @admin_gid_out. Any group IDs for other admin
+ * groups (such as `lpadmin` or `systemd-journal`) will be returned in
+ * @groups_out, which should be freed by the caller using g_free().
+ *
+ * Returns: %TRUE on success, %FALSE if one or more of the groups could not be
+ * looked up
+ */
+gboolean
+get_admin_groups (gid_t *admin_gid_out,
+ gid_t **groups_out,
+ gsize *n_groups_out)
+{
+ g_auto(GStrv) extra_admin_groups = NULL;
+ g_autofree gid_t *extra_admin_groups_gids = NULL;
+ gsize n_extra_admin_groups_gids = 0;
+ gsize i;
+ gboolean retval = FALSE;
+ struct group *grp;
+ gid_t admin_gid = 0;
+
+ /* Get the main admin group ID. */
+ grp = getgrnam (ADMIN_GROUP);
+ if (grp == NULL)
+ goto out;
+ admin_gid = grp->gr_gid;
+
+ /* Get the extra admin group IDs. */
+ extra_admin_groups = g_strsplit (EXTRA_ADMIN_GROUPS, ",", 0);
+ n_extra_admin_groups_gids = 0;
+ extra_admin_groups_gids = g_new0 (gid_t, g_strv_length (extra_admin_groups));
+
+ for (i = 0; extra_admin_groups[i] != NULL; i++) {
+ struct group *extra_group;
+ extra_group = getgrnam (extra_admin_groups[i]);
+ if (extra_group == NULL)
+ goto out;
+ if (extra_group->gr_gid == admin_gid)
+ continue;
+
+ extra_admin_groups_gids[n_extra_admin_groups_gids++] = extra_group->gr_gid;
+ }
+
+ retval = TRUE;
+
+out:
+ if (!retval) {
+ admin_gid = 0;
+ g_clear_pointer (&extra_admin_groups_gids, g_free);
+ n_extra_admin_groups_gids = 0;
+ }
+
+ if (admin_gid_out != NULL)
+ *admin_gid_out = admin_gid;
+ if (groups_out != NULL)
+ *groups_out = g_steal_pointer (&extra_admin_groups_gids);
+ if (n_groups_out != NULL)
+ *n_groups_out = n_extra_admin_groups_gids;
+
+ return retval;
+}
gboolean
get_caller_uid (GDBusMethodInvocation *context,
diff --git a/src/util.h b/src/util.h
index 41ba545..1af46dd 100644
--- a/src/util.h
+++ b/src/util.h
@@ -36,6 +36,10 @@ gboolean spawn_with_login_uid (GDBusMethodInvocation *context,
const gchar *argv[],
GError **error);
+gboolean get_admin_groups (gid_t *admin_gid_out,
+ gid_t **groups_out,
+ gsize *n_groups_out);
+
gint get_user_groups (const gchar *username,
gid_t group,
gid_t **groups);