add alternate backend support for getgrouplist
This completes the alternate backend support that was previously added to the getpw* and getgr* functions. Unlike those, though, it unconditionally queries nscd. Any groups from nscd that aren't in the /etc/groups file are added to the returned list, and any that are present in the file are ignored. The purpose of this behavior is to provide a view of the group database consistent with what is observed by the getgr* functions. If group memberships reported by nscd were honored when the corresponding group already has a definition in the /etc/groups file, the user's getgrouplist-based membership in the group would conflict with their non-membership in the reported gr_mem[] for the group. The changes made also make getgrouplist thread-safe and eliminate its clobbering of the global getgrent state.
This commit is contained in:
committed by
Rich Felker
parent
962cbfbf86
commit
2894a44b40
@@ -1,24 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <grp.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
|
||||
{
|
||||
size_t n, i;
|
||||
struct group *gr;
|
||||
if (*ngroups<1) return -1;
|
||||
n = *ngroups;
|
||||
*groups++ = gid;
|
||||
*ngroups = 1;
|
||||
|
||||
setgrent();
|
||||
while ((gr = getgrent()) && *ngroups < INT_MAX) {
|
||||
for (i=0; gr->gr_mem[i] && strcmp(user, gr->gr_mem[i]); i++);
|
||||
if (!gr->gr_mem[i]) continue;
|
||||
if (++*ngroups <= n) *groups++ = gr->gr_gid;
|
||||
}
|
||||
endgrent();
|
||||
|
||||
return *ngroups > n ? -1 : *ngroups;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "pwf.h"
|
||||
#include <grp.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <byteswap.h>
|
||||
#include <errno.h>
|
||||
#include "nscd.h"
|
||||
|
||||
int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
|
||||
{
|
||||
int rv, nlim, ret = -1;
|
||||
ssize_t i, n = 1;
|
||||
struct group gr;
|
||||
struct group *res;
|
||||
FILE *f;
|
||||
int swap = 0;
|
||||
int32_t resp[INITGR_LEN];
|
||||
uint32_t *nscdbuf = 0;
|
||||
char *buf = 0;
|
||||
char **mem = 0;
|
||||
size_t nmem = 0;
|
||||
size_t size;
|
||||
nlim = *ngroups;
|
||||
if (nlim >= 1) *groups++ = gid;
|
||||
|
||||
f = __nscd_query(GETINITGR, user, resp, sizeof resp, &swap);
|
||||
if (!f) goto cleanup;
|
||||
if (f != (FILE*)-1 && resp[INITGRFOUND]) {
|
||||
nscdbuf = calloc(resp[INITGRNGRPS], sizeof(uint32_t));
|
||||
if (!nscdbuf) goto cleanup;
|
||||
if (!fread(nscdbuf, sizeof(*nscdbuf)*resp[INITGRNGRPS], 1, f)) {
|
||||
if (!ferror(f)) errno = EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
if (swap) {
|
||||
for (i = 0; i < resp[INITGRNGRPS]; i++)
|
||||
nscdbuf[i] = bswap_32(nscdbuf[i]);
|
||||
}
|
||||
}
|
||||
if (f != (FILE*)-1) fclose(f);
|
||||
|
||||
f = fopen("/etc/group", "rbe");
|
||||
if (!f && errno != ENOENT && errno != ENOTDIR)
|
||||
goto cleanup;
|
||||
|
||||
if (f) {
|
||||
while (!(rv = __getgrent_a(f, &gr, &buf, &size, &mem, &nmem, &res)) && res) {
|
||||
if (nscdbuf)
|
||||
for (i=0; i < resp[INITGRNGRPS]; i++) {
|
||||
if (nscdbuf[i] == gr.gr_gid) nscdbuf[i] = gid;
|
||||
}
|
||||
for (i=0; gr.gr_mem[i] && strcmp(user, gr.gr_mem[i]); i++);
|
||||
if (!gr.gr_mem[i]) continue;
|
||||
if (++n <= nlim) *groups++ = gr.gr_gid;
|
||||
}
|
||||
if (rv) {
|
||||
errno = rv;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (nscdbuf) {
|
||||
for(i=0; i < resp[INITGRNGRPS]; i++) {
|
||||
if (nscdbuf[i] != gid)
|
||||
if(++n <= nlim) *groups++ = nscdbuf[i];
|
||||
}
|
||||
}
|
||||
|
||||
ret = n > nlim ? -1 : n;
|
||||
*ngroups = n;
|
||||
|
||||
cleanup:
|
||||
if (f) fclose(f);
|
||||
free(nscdbuf);
|
||||
free(buf);
|
||||
free(mem);
|
||||
return ret;
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#define GETPWBYUID 1
|
||||
#define GETGRBYNAME 2
|
||||
#define GETGRBYGID 3
|
||||
#define GETINITGR 15
|
||||
|
||||
#define REQVERSION 0
|
||||
#define REQTYPE 1
|
||||
@@ -33,6 +34,11 @@
|
||||
#define GRMEMCNT 5
|
||||
#define GR_LEN 6
|
||||
|
||||
#define INITGRVERSION 0
|
||||
#define INITGRFOUND 1
|
||||
#define INITGRNGRPS 2
|
||||
#define INITGR_LEN 3
|
||||
|
||||
FILE *__nscd_query(int32_t req, const char *key, int32_t *buf, size_t len, int *swap);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user