提交 2894a44b 编写于 作者: J Josiah Worcester 提交者: Rich Felker

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.
上级 962cbfbf
#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;
}
#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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册