diff options
Diffstat (limited to 'lib/nss_wrapper/nss_wrapper.c')
-rw-r--r-- | lib/nss_wrapper/nss_wrapper.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c index 1875dc3e4f..d7f7b0ba56 100644 --- a/lib/nss_wrapper/nss_wrapper.c +++ b/lib/nss_wrapper/nss_wrapper.c @@ -68,6 +68,11 @@ #define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS #endif +/* not all systems have getgrouplist */ +#ifndef HAVE_GETGROUPLIST +#define getgrouplist(user, group, groups, ngroups) 0 +#endif + /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support * for now */ #define REWRITE_CALLS @@ -90,6 +95,7 @@ #define real_initgroups_dyn initgroups_dyn */ #define real_initgroups initgroups +#define real_getgrouplist getgrouplist #define real_getgrnam getgrnam #define real_getgrnam_r getgrnam_r @@ -1222,3 +1228,81 @@ _PUBLIC_ void nwrap_endgrent(void) nwrap_files_endgrent(); } + +static int nwrap_files_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + struct group *grp; + gid_t *groups_tmp; + int count = 1; + const char *name_of_group = NULL; + + NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user)); + + groups_tmp = (gid_t *)malloc(count * sizeof(gid_t)); + if (!groups_tmp) { + NWRAP_ERROR(("%s:calloc failed\n",__location__)); + errno = ENOMEM; + return -1; + } + + memcpy(groups_tmp, &group, sizeof(gid_t)); + + grp = nwrap_getgrgid(group); + if (grp) { + name_of_group = grp->gr_name; + } + + nwrap_files_setgrent(); + while ((grp = nwrap_files_getgrent()) != NULL) { + int i = 0; + + NWRAP_VERBOSE(("%s: inspecting %s for group membership\n", + __location__, grp->gr_name)); + + for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { + + if ((strcmp(user, grp->gr_mem[i]) == 0) && + (strcmp(name_of_group, grp->gr_name) != 0)) { + + NWRAP_DEBUG(("%s: %s is member of %s\n", + __location__, user, grp->gr_name)); + + groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t)); + if (!groups_tmp) { + NWRAP_ERROR(("%s:calloc failed\n",__location__)); + errno = ENOMEM; + return -1; + } + + memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t)); + count++; + } + } + } + nwrap_files_endgrent(); + + NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n", + __location__, user, *ngroups)); + + if (*ngroups < count) { + *ngroups = count; + free(groups_tmp); + return -1; + } + + *ngroups = count; + memcpy(groups, groups_tmp, count * sizeof(gid_t)); + free(groups_tmp); + + return count; +} + +_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) +{ + if (!nwrap_enabled()) { + return real_getgrouplist(user, group, groups, ngroups); + } + + return nwrap_files_getgrouplist(user, group, groups, ngroups); +} + |