#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#include <sys/types.h>
#include <grp.h>
#include <sys/wait.h>
#define DEBUG 0
+#ifndef NGROUPS_MAX
+#define NGROUPS_MAX 32
+#endif
+
static const char usage[] =
-"Usage: %s -u user_id [-g grp_id ] [ -G ] command\n"
-" -u user_id switch to UID user_id\n"
-" -g grp_id switch to GID grp_id\n"
-" -G clear supplementary groups\n";
+"Usage: %s -u user_id [-g grp_id] [-G[gid0,gid1,...]] command\n"
+" -u user_id switch to UID user_id\n"
+" -g grp_id switch to GID grp_id\n"
+" -G[gid0,gid1,...] set supplementary groups\n";
void Usage_and_abort(const char *name)
{
int main(int argc, char **argv)
{
- char **my_argv, *name = argv[0];
- int status;
- int c,i;
- int gid_is_set = 0;
- int uid_is_set = 0;
- int clear_supp_groups = 0;
- uid_t user_id;
- gid_t grp_id;
+ char **my_argv, *name = argv[0], *grp;
+ int status, c, i;
+ int gid_is_set = 0, uid_is_set = 0, num_supp = -1;
+ uid_t user_id = 0;
+ gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 };
if (argc == 1)
Usage_and_abort(name);
// get UID and GID
- while ((c = getopt (argc, argv, "+u:g:hG")) != -1) {
+ while ((c = getopt(argc, argv, "+u:g:hG::")) != -1) {
switch (c) {
case 'u':
user_id = (uid_t)atoi(optarg);
break;
case 'G':
- clear_supp_groups = 1;
+ num_supp = 0;
+ if (optarg == NULL || !isdigit(optarg[0]))
+ break;
+ while ((grp = strsep(&optarg, ",")) != NULL) {
+ printf("adding supp group %d\n", atoi(grp));
+ supp_groups[num_supp++] = atoi(grp);
+ if (num_supp >= NGROUPS_MAX)
+ break;
+ }
break;
default:
exit(-1);
}
- if (clear_supp_groups) {
- status = setgroups(0, NULL);
+ if (num_supp >= 0) {
+ status = setgroups(num_supp, supp_groups);
if (status == -1) {
- perror("clearing supplementary groups");
+ perror("setting supplementary groups");
exit(-1);
}
}
-
+
// set UID
status = setreuid(user_id, user_id );
if(status == -1) {
exit(-1);
}
- fprintf(stderr, "running as UID %d, GID %d%s:", user_id, grp_id,
- clear_supp_groups ? ", cleared groups" : "");
+ fprintf(stderr, "running as UID %d, GID %d", user_id, grp_id);
+ for (i = 0; i < num_supp; i++)
+ fprintf(stderr, ":%d", supp_groups[i]);
+ fprintf(stderr, "\n");
for (i = 0; i < argc - optind; i++)
fprintf(stderr, " [%s]", my_argv[i]);