id: fix "id <user>" case. Requires getgrouplist().
function old new delta getgrouplist_internal - 200 +200 id_main 462 539 +77 bb_internal_getgrouplist - 67 +67 bb__parsespent 119 117 -2 bb_internal_initgroups 213 58 -155 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 1/2 up/down: 344/-157) Total: 187 bytes
This commit is contained in:
parent
28f5619e84
commit
2228426512
@ -38,14 +38,25 @@ static int printf_full(unsigned id, const char *arg, const char *prefix)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (defined(__GLIBC__) && !defined(__UCLIBC__))
|
||||||
|
#define HAVE_getgrouplist 1
|
||||||
|
#elif ENABLE_USE_BB_PWD_GRP
|
||||||
|
#define HAVE_getgrouplist 1
|
||||||
|
#else
|
||||||
|
#define HAVE_getgrouplist 0
|
||||||
|
#endif
|
||||||
|
|
||||||
int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||||
int id_main(int argc UNUSED_PARAM, char **argv)
|
int id_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
|
const char *username;
|
||||||
struct passwd *p;
|
struct passwd *p;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
#if HAVE_getgrouplist
|
||||||
gid_t *groups;
|
gid_t *groups;
|
||||||
int n;
|
int n;
|
||||||
|
#endif
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
short status;
|
short status;
|
||||||
#if ENABLE_SELINUX
|
#if ENABLE_SELINUX
|
||||||
@ -55,6 +66,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* Don't allow more than one username */
|
/* Don't allow more than one username */
|
||||||
opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
|
opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
|
||||||
flags = getopt32(argv, "rnugG" USE_SELINUX("Z"));
|
flags = getopt32(argv, "rnugG" USE_SELINUX("Z"));
|
||||||
|
username = argv[optind];
|
||||||
|
|
||||||
/* This values could be overwritten later */
|
/* This values could be overwritten later */
|
||||||
uid = geteuid();
|
uid = geteuid();
|
||||||
@ -64,19 +76,34 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
gid = getgid();
|
gid = getgid();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[optind]) {
|
if (username) {
|
||||||
p = getpwnam(argv[optind]);
|
#if HAVE_getgrouplist
|
||||||
|
int m;
|
||||||
|
#endif
|
||||||
|
p = getpwnam(username);
|
||||||
/* xuname2uid is needed because it exits on failure */
|
/* xuname2uid is needed because it exits on failure */
|
||||||
uid = xuname2uid(argv[optind]);
|
uid = xuname2uid(username);
|
||||||
gid = p->pw_gid;
|
gid = p->pw_gid; /* in this case PRINT_REAL is the same */
|
||||||
/* in this case PRINT_REAL is the same */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if HAVE_getgrouplist
|
||||||
|
n = 16;
|
||||||
|
groups = NULL;
|
||||||
|
do {
|
||||||
|
m = n;
|
||||||
|
groups = xrealloc(groups, sizeof(groups[0]) * m);
|
||||||
|
getgrouplist(username, gid, groups, &n); /* GNUism? */
|
||||||
|
} while (n > m);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
#if HAVE_getgrouplist
|
||||||
n = getgroups(0, NULL);
|
n = getgroups(0, NULL);
|
||||||
groups = xmalloc(sizeof(groups[0]) * n);
|
groups = xmalloc(sizeof(groups[0]) * n);
|
||||||
getgroups(n, groups);
|
getgroups(n, groups);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & JUST_ALL_GROUPS) {
|
if (flags & JUST_ALL_GROUPS) {
|
||||||
|
#if HAVE_getgrouplist
|
||||||
while (n--) {
|
while (n--) {
|
||||||
if (flags & NAME_NOT_NUMBER)
|
if (flags & NAME_NOT_NUMBER)
|
||||||
printf("%s", bb_getgrgid(NULL, 0, *groups++));
|
printf("%s", bb_getgrgid(NULL, 0, *groups++));
|
||||||
@ -84,6 +111,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
printf("%u", (unsigned) *groups++);
|
printf("%u", (unsigned) *groups++);
|
||||||
bb_putchar((n > 0) ? ' ' : '\n');
|
bb_putchar((n > 0) ? ' ' : '\n');
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* exit */
|
/* exit */
|
||||||
fflush_stdout_and_exit(EXIT_SUCCESS);
|
fflush_stdout_and_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -105,7 +133,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
#if ENABLE_SELINUX
|
#if ENABLE_SELINUX
|
||||||
if (flags & JUST_CONTEXT) {
|
if (flags & JUST_CONTEXT) {
|
||||||
selinux_or_die();
|
selinux_or_die();
|
||||||
if (argv[optind]) {
|
if (username) {
|
||||||
bb_error_msg_and_die("user name can't be passed with -Z");
|
bb_error_msg_and_die("user name can't be passed with -Z");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +151,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
|
/* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
|
||||||
status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid=");
|
status = printf_full(uid, bb_getpwuid(NULL, 0, uid), "uid=");
|
||||||
status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid=");
|
status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), " gid=");
|
||||||
|
#if HAVE_getgrouplist
|
||||||
{
|
{
|
||||||
const char *msg = " groups=";
|
const char *msg = " groups=";
|
||||||
while (n--) {
|
while (n--) {
|
||||||
@ -132,6 +161,7 @@ int id_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* we leak groups vector... */
|
/* we leak groups vector... */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_SELINUX
|
#if ENABLE_SELINUX
|
||||||
if (is_selinux_enabled()) {
|
if (is_selinux_enabled()) {
|
||||||
|
@ -620,43 +620,67 @@ struct spwd *sgetspent(const char *string)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int initgroups(const char *user, gid_t gid)
|
static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
|
||||||
{
|
{
|
||||||
FILE *grfile;
|
FILE *grfile;
|
||||||
gid_t *group_list;
|
gid_t *group_list;
|
||||||
int num_groups, rv;
|
int ngroups;
|
||||||
char **m;
|
|
||||||
struct group group;
|
struct group group;
|
||||||
char buff[PWD_BUFFER_SIZE];
|
char buff[PWD_BUFFER_SIZE];
|
||||||
|
|
||||||
rv = -1;
|
|
||||||
grfile = fopen_for_read(_PATH_GROUP);
|
|
||||||
if (grfile != NULL) {
|
|
||||||
|
|
||||||
/* We alloc space for 8 gids at a time. */
|
/* We alloc space for 8 gids at a time. */
|
||||||
group_list = xmalloc(8 * sizeof(gid_t *));
|
group_list = xmalloc(8 * sizeof(group_list[0]));
|
||||||
*group_list = gid;
|
group_list[0] = gid;
|
||||||
num_groups = 1;
|
ngroups = 1;
|
||||||
|
|
||||||
|
grfile = fopen_for_read(_PATH_GROUP);
|
||||||
|
if (grfile) {
|
||||||
while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
|
while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
|
||||||
|
char **m;
|
||||||
assert(group.gr_mem); /* Must have at least a NULL terminator. */
|
assert(group.gr_mem); /* Must have at least a NULL terminator. */
|
||||||
if (group.gr_gid != gid) {
|
if (group.gr_gid == gid)
|
||||||
|
continue;
|
||||||
for (m = group.gr_mem; *m; m++) {
|
for (m = group.gr_mem; *m; m++) {
|
||||||
if (!strcmp(*m, user)) {
|
if (strcmp(*m, user) != 0)
|
||||||
group_list = xrealloc_vector(group_list, 3, num_groups);
|
continue;
|
||||||
group_list[num_groups++] = group.gr_gid;
|
group_list = xrealloc_vector(group_list, 3, ngroups);
|
||||||
|
group_list[ngroups++] = group.gr_gid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = setgroups(num_groups, group_list);
|
|
||||||
free(group_list);
|
|
||||||
fclose(grfile);
|
fclose(grfile);
|
||||||
}
|
}
|
||||||
|
*ngroups_ptr = ngroups;
|
||||||
|
return group_list;
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
int initgroups(const char *user, gid_t gid)
|
||||||
|
{
|
||||||
|
int ngroups;
|
||||||
|
gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
|
||||||
|
|
||||||
|
if (!group_list)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ngroups = setgroups(ngroups, group_list);
|
||||||
|
free(group_list);
|
||||||
|
return ngroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: uclibc needs this ported to it! */
|
||||||
|
int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
|
||||||
|
{
|
||||||
|
int ngroups_old = *ngroups;
|
||||||
|
gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
|
||||||
|
|
||||||
|
if (*ngroups <= ngroups_old) {
|
||||||
|
ngroups_old = *ngroups;
|
||||||
|
memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
|
||||||
|
} else {
|
||||||
|
ngroups_old = -1;
|
||||||
|
}
|
||||||
|
free(group_list);
|
||||||
|
return ngroups_old;
|
||||||
}
|
}
|
||||||
|
|
||||||
int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
|
int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
|
||||||
|
Loading…
Reference in New Issue
Block a user