mirror of
https://github.com/sheumann/hush.git
synced 2024-12-23 05:29:58 +00:00
Use alternative code (also from BusyBox) for checking if the user is in a group, avoiding a call to getgroups(), which isn't supported.
This could actually be further simplified, since GNO doesn't really have group-based file permissions, but I'll leave that until later.
This commit is contained in:
parent
a60c64d6c7
commit
7e5a584f0c
@ -390,8 +390,6 @@ struct test_statics {
|
||||
/* set only by check_operator(), either to bogus struct
|
||||
* or points to matching operator_t struct. Never NULL. */
|
||||
const struct operator_t *last_operator;
|
||||
gid_t *group_array;
|
||||
int ngroups;
|
||||
jmp_buf leaving;
|
||||
};
|
||||
|
||||
@ -401,8 +399,6 @@ extern struct test_statics *const test_ptr_to_statics;
|
||||
#define S (*test_ptr_to_statics)
|
||||
#define args (S.args )
|
||||
#define last_operator (S.last_operator)
|
||||
#define group_array (S.group_array )
|
||||
#define ngroups (S.ngroups )
|
||||
#define leaving (S.leaving )
|
||||
|
||||
#define INIT_S() do { \
|
||||
@ -561,46 +557,14 @@ static int binop(void)
|
||||
}
|
||||
|
||||
|
||||
static void initialize_group_array(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* getgroups may be expensive, try to use it only once */
|
||||
ngroups = 32;
|
||||
do {
|
||||
/* FIXME: ash tries so hard to not die on OOM,
|
||||
* and we spoil it with just one xrealloc here */
|
||||
/* We realloc, because test_main can be entered repeatedly by shell.
|
||||
* Testcase (ash): 'while true; do test -x some_file; done'
|
||||
* and watch top. (some_file must have owner != you) */
|
||||
n = ngroups;
|
||||
group_array = xrealloc(group_array, n * sizeof(gid_t));
|
||||
ngroups = getgroups(n, group_array);
|
||||
} while (ngroups > n);
|
||||
}
|
||||
|
||||
|
||||
/* Return non-zero if GID is one that we have in our groups list. */
|
||||
//XXX: FIXME: duplicate of existing libbb function?
|
||||
// see toplevel TODO file:
|
||||
// possible code duplication ingroup() and is_a_group_member()
|
||||
static int is_a_group_member(gid_t gid)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Short-circuit if possible, maybe saving a call to getgroups(). */
|
||||
/* Short-circuit if possible */
|
||||
if (gid == getgid() || gid == getegid())
|
||||
return 1;
|
||||
|
||||
if (ngroups == 0)
|
||||
initialize_group_array();
|
||||
|
||||
/* Search through the list looking for GID. */
|
||||
for (i = 0; i < ngroups; i++)
|
||||
if (gid == group_array[i])
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
return ingroup(getuid(), gid) || ingroup(geteuid(), gid);
|
||||
}
|
||||
|
||||
|
||||
@ -863,16 +827,6 @@ int test_main(int argc, char **argv)
|
||||
if (res)
|
||||
goto ret;
|
||||
|
||||
/* resetting ngroups is probably unnecessary. it will
|
||||
* force a new call to getgroups(), which prevents using
|
||||
* group data fetched during a previous call. but the
|
||||
* only way the group data could be stale is if there's
|
||||
* been an intervening call to setgroups(), and this
|
||||
* isn't likely in the case of a shell. paranoia
|
||||
* prevails...
|
||||
*/
|
||||
/*ngroups = 0; - done by INIT_S() */
|
||||
|
||||
argv++;
|
||||
args = argv;
|
||||
|
||||
|
@ -841,6 +841,8 @@ void die_if_bad_username(const char* name) FAST_FUNC;
|
||||
#define die_if_bad_username(name) ((void)(name))
|
||||
#endif
|
||||
|
||||
int ingroup(uid_t u, gid_t g);
|
||||
|
||||
#if ENABLE_FEATURE_UTMP
|
||||
void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
|
||||
void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
|
||||
|
@ -18,3 +18,18 @@ void FAST_FUNC bb_show_usage(void)
|
||||
{
|
||||
xfunc_die();
|
||||
}
|
||||
|
||||
/* check if u is member of group g */
|
||||
int ingroup(uid_t u, gid_t g)
|
||||
{
|
||||
struct group *grp = getgrgid(g);
|
||||
if (grp) {
|
||||
char **mem;
|
||||
for (mem = grp->gr_mem; *mem; mem++) {
|
||||
struct passwd *pwd = getpwnam(*mem);
|
||||
if (pwd && (pwd->pw_uid == u))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user