/*++ /* NAME /* chrootuid 1 /* SUMMARY /* run command in restricted environment /* SYNOPSIS /* \fBchrootuid\fR \fInewroot newuser command\fR... /* DESCRIPTION /* The \fBchrootuid\fR command sets up a restricted environment for /* executing \fIcommand\fR. Access to the file system is restricted to /* the \fInewroot\fR subtree; privileges are restricted to those of /* the \fInewuser\fR account (which must be a known account in the /* unrestricted environment). /* The initial working directory is changed to \fInewroot\fR. /* /* \fBchrootuid\fR combines chroot(8) and su(1) into one program, so /* that there is no need to have commands such as /usr/bin/su /* in the restricted environment. /* /* Only the superuser can use the \fBchrootuid\fR command. /* DIAGNOSTICS /* The exit status is 1 when \fBchrootuid\fR has a problem, otherwise /* the exit status is the exit status of \fIcommand\fR. /* SEE ALSO /* chroot(8), su(1) /* DIAGNOSTICS /* Problems are reported to the syslog daemon. /* AUTHOR(S) /* Wietse Venema /* Eindhoven University of Technology /* Department of Mathematics and Computer Science /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands /* /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* CREATION DATE /* Tue Oct 13 11:37:29 MET 1992 /* LAST MODIFICATION /* Wed Jul 25 11:25:08 EDT 2001 /* VERSION/RELEASE /* 1.3 /*--*/ #ifndef lint static char sccsid[] = "@(#) chrootuid.c 1.3 2001/07/25 11:25:08"; #endif /* System libraries. */ #include #include #include #include #include int main(argc, argv) int argc; char **argv; { struct passwd *pwd; /* * Open a channel to the syslog daemon. Older versions of openlog() * require only two arguments. */ #ifdef LOG_DAEMON (void) openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON); #else (void) openlog(argv[0], LOG_PID); #endif /* * Require proper amount of arguments. In all cases of error, exit with * zero status because we have already reported the problem via syslogd. * No need to make inetd complain, too. */ if (argc < 4) { syslog(LOG_ERR, "usage: %s path user command", argv[0]); return (0); } syslog(LOG_NOTICE, "chrootuid: dir(%s) user(%s) command(%s)", argv[1], argv[2], argv[3]); /* Must step into the new subtree. */ if (chdir(argv[1])) { syslog(LOG_ERR, "chdir(%s): %m", argv[1]); return (0); } /* The user must be known in the *unrestricted* universe... */ if ((pwd = getpwnam(argv[2])) == 0) { syslog(LOG_ERR, "%s: user unknown", argv[2]); return (0); } /* initgroups() accesses the group file in the unrestricted universe... */ if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) { syslog(LOG_ERR, "initgroups: %m"); return (0); } endgrent(); /* Do the chroot() before giving away root privileges. */ if (chroot(argv[1])) { syslog(LOG_ERR, "chroot(%s): %m", argv[1]); return (0); } /* Switch group id then user id. */ if (setgid(pwd->pw_gid)) { syslog(LOG_ERR, "setgid(%d): %m", pwd->pw_gid); return (0); } if (setuid(pwd->pw_uid)) { syslog(LOG_ERR, "setuid(%d): %m", pwd->pw_uid); return (0); } /* In case we still have the /etc/passwd file still open. */ endpwent(); /* Run the command and hope for the best. */ (void) execv(argv[3], argv + 3); syslog(LOG_ERR, "%s: %m", argv[3]); return (0); }