From 33f1f69e9c92076bfb81bd6bb29c3127eebdfdb1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 14 Aug 2017 11:38:46 +0200 Subject: [PATCH] newgrp: avoid unnecessary group lookups In case a system uses remote identity server (LDAP) the group lookup can be very slow. We avoid it when we already know the user has the group membership. --- src/newgrp.c | 58 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/newgrp.c b/src/newgrp.c index b0fa8d5a..221b0baa 100644 --- a/src/newgrp.c +++ b/src/newgrp.c @@ -83,16 +83,30 @@ static void usage (void) } } -/* - * find_matching_group - search all groups of a given group id for - * membership of a given username - */ -static /*@null@*/struct group *find_matching_group (const char *name, gid_t gid) +static bool ingroup(const char *name, struct group *gr) { - struct group *gr; char **look; bool notfound = true; + look = gr->gr_mem; + while (*look && notfound) + notfound = strcmp (*look++, name); + + return !notfound; +} + +/* + * find_matching_group - search all groups of a gr's group id for + * membership of a given username + * but check gr itself first + */ +static /*@null@*/struct group *find_matching_group (const char *name, struct group *gr) +{ + gid_t gid = gr->gr_gid; + + if (ingroup(name, gr)) + return gr; + setgrent (); while ((gr = getgrent ()) != NULL) { if (gr->gr_gid != gid) { @@ -103,14 +117,8 @@ static /*@null@*/struct group *find_matching_group (const char *name, gid_t gid) * A group with matching GID was found. * Test for membership of 'name'. */ - look = gr->gr_mem; - while ((NULL != *look) && notfound) { - notfound = (strcmp (*look, name) != 0); - look++; - } - if (!notfound) { + if (ingroup(name, gr)) break; - } } endgrent (); return gr; @@ -643,17 +651,19 @@ int main (int argc, char **argv) * groups of the same GID like the requested group for * membership of the current user. */ - grp = find_matching_group (name, grp->gr_gid); - if (NULL == grp) { - /* - * No matching group found. As we already know that - * the group exists, this happens only in the case - * of a requested group where the user is not member. - * - * Re-read the group entry for further processing. - */ - grp = xgetgrnam (group); - assert (NULL != grp); + if (!is_member) { + grp = find_matching_group (name, grp); + if (NULL == grp) { + /* + * No matching group found. As we already know that + * the group exists, this happens only in the case + * of a requested group where the user is not member. + * + * Re-read the group entry for further processing. + */ + grp = xgetgrnam (group); + assert (NULL != grp); + } } #ifdef SHADOWGRP sgrp = getsgnam (group);