/* * Perform chroot, set uid and gid, and then run prog * * Usage: chroot+setuidgid [--chroot chrootdir] [--setuidgid uid gid] prog [prog_args...] * * Alternatively, chrootdir, uid, gid, and prog can be compiled in * by defining macros for CHROOTDIR, UID, GID, PROG * * R. Perry, Jan. 2003 * * 29 Aug. 2003, added --stdout option to redirect stdout to a file after setting chroot and uidgid */ #include #include #include #include #include #include #include int putenv(char *string); int main( int argc, char *argv[]) { char *progname = argv[0]; char *chrootdir; uid_t uid; gid_t gid; gid_t grouplist[1]; char *prog; char **args; /*** Must be the first command-line option: --chroot chrootdir ***/ #ifdef CHROOTDIR chrootdir = CHROOTDIR; #else if( argc >= 3 && strcmp( argv[1], "--chroot") == 0) { chrootdir = argv[2]; #endif if( chroot( chrootdir)) { fprintf( stderr, "%s: chroot(\"%s\") failed: %s\n", progname, chrootdir, strerror(errno)); exit(1); } if( chdir( "/")) { fprintf( stderr, "%s: chdir(\"/\") failed: %s\n", progname, strerror(errno)); exit(1); } #ifndef CHROOTDIR argc -= 2; argv += 2; } #endif /*** Must be the first command-line option: --setuidgid uid gid ***/ #ifdef UID uid = UID; gid = GID; #else if( argc >= 4 && strcmp( argv[1], "--setuidgid") == 0) { uid = atoi( argv[2]); gid = atoi( argv[3]); #endif grouplist[0] = gid; if( setgroups( 1, grouplist)) { fprintf( stderr, "%s: setgroups() failed: %s\n", progname, strerror(errno)); exit(1); } if( setgid( gid)) { fprintf( stderr, "%s: setgid() failed: %s\n", progname, strerror(errno)); exit(1); } if( setuid( uid)) { fprintf( stderr, "%s: setuid() failed: %s\n", progname, strerror(errno)); exit(1); } #ifndef UID argc -= 3; argv += 3; } #endif #ifdef STDOUT /*** Must be the first command-line option: --stdout file ***/ if( argc >= 3 && strcmp( argv[1], "--stdout") == 0) { char *outfile = argv[2]; if( freopen( outfile, "w", stdout) == NULL) { fprintf( stderr, "%s: freopen(\"%s\") failed: %s\n", progname, outfile, strerror(errno)); exit(1); } argc -= 2; argv += 2; } #endif /* STDOUT */ /*** exec prog ***/ #ifdef PROG prog = PROG; args = argv; #else if( argc < 2) { fprintf( stderr, "Usage: %s [--chroot chrootdir] [--setuidgid uid gid]" #ifdef STDOUT " [--stdout outfile]" #endif " prog [prog_args...]\n", progname); exit(1); } prog = argv[1]; args = argv+1; #endif #ifdef PUTENV_COURSE { char *val, course[1024]; val = strrchr( progname, '/'); val = val ? val+1 : progname; strcpy( course, "COURSE="); strncat( course, val, 1024-10); if( putenv( course) ) fprintf( stderr, "%s: putenv(\"%s\") failed: %s\n", progname, course, strerror(errno)); } #endif execv( prog, args); /* if execv() returns, it failed */ fprintf( stderr, "%s: execv(\"%s\") failed: %s\n", progname, prog, strerror(errno)); exit(1); }