#include <string.h>
#include <errno.h>
#include <sys/types.h>
+#include <grp.h>
#include <sys/wait.h>
#define DEBUG 0
-void Usage_and_abort(void)
+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";
+
+void Usage_and_abort(const char *name)
{
- fprintf(stderr, "Usage: runas -u user_id [ -g grp_id ]"
- " command_to_be_run \n");
- exit(-1);
+ fprintf(stderr, usage, name);
+ exit(-1);
}
-// Usage: runas -u user_id [ -g grp_id ] [--] command_to_be_run
-// return: the return value of "command_to_be_run"
-// NOTE: returning -1 might be the return code of this program itself or
-// the "command_to_be_run"
-
-// ROOT runs "runas" for free
-// Other users run "runas" requires chmod 6755 "command_to_be_run"
-
int main(int argc, char **argv)
{
- char **my_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;
if (argc == 1)
- Usage_and_abort();
+ Usage_and_abort(name);
// get UID and GID
- while ((c = getopt (argc, argv, "+u:g:h")) != -1) {
+ while ((c = getopt (argc, argv, "+u:g:hG")) != -1) {
switch (c) {
case 'u':
user_id = (uid_t)atoi(optarg);
gid_is_set = 1;
break;
- case 'h':
- Usage_and_abort();
+ case 'G':
+ clear_supp_groups = 1;
break;
default:
- //fprintf(stderr, "Bad parameters.\n");
- //Usage_and_abort ();
+ case 'h':
+ Usage_and_abort(name);
break;
}
}
if (!uid_is_set)
- Usage_and_abort();
+ Usage_and_abort(name);
if (optind == argc) {
- fprintf(stderr, "Bad parameters.\n");
- Usage_and_abort();
+ fputs("Must specify command to run.\n", stderr);
+ Usage_and_abort(name);
}
// assemble the command
exit(-1);
}
+ if (clear_supp_groups) {
+ status = setgroups(0, NULL);
+ if (status == -1) {
+ perror("clearing supplementary groups");
+ exit(-1);
+ }
+ }
+
// set UID
status = setreuid(user_id, user_id );
if(status == -1) {
exit(-1);
}
-
- fprintf(stderr, "running as USER(%d), Grp (%d): ", user_id, grp_id );
+ fprintf(stderr, "running as UID %d, GID %d%s:", user_id, grp_id,
+ clear_supp_groups ? ", cleared groups" : "");
for (i = 0; i < argc - optind; i++)
fprintf(stderr, " [%s]", my_argv[i]);