1 /*++
2 /* NAME
3 /* chrootuid 1
4 /* SUMMARY
5 /* run command in restricted environment
6 /* SYNOPSIS
7 /* \fBchrootuid\fR \fInewroot newuser command\fR...
8 /* DESCRIPTION
9 /* The \fBchrootuid\fR command sets up a restricted environment for
10 /* executing \fIcommand\fR. Access to the file system is restricted to
11 /* the \fInewroot\fR subtree; privileges are restricted to those of
12 /* the \fInewuser\fR account (which must be a known account in the
13 /* unrestricted environment).
14 /* The initial working directory is changed to \fInewroot\fR.
15 /*
16 /* \fBchrootuid\fR combines chroot(8) and su(1) into one program, so
17 /* that there is no need to have commands such as /usr/bin/su
18 /* in the restricted environment.
19 /*
20 /* Only the superuser can use the \fBchrootuid\fR command.
21 /* DIAGNOSTICS
22 /* The exit status is 1 when \fBchrootuid\fR has a problem, otherwise
23 /* the exit status is the exit status of \fIcommand\fR.
24 /* SEE ALSO
25 /* chroot(8), su(1)
26 /* DIAGNOSTICS
27 /* Problems are reported to the syslog daemon.
28 /* AUTHOR(S)
29 /* Wietse Venema
30 /* Eindhoven University of Technology
31 /* Department of Mathematics and Computer Science
32 /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
33 /*
34 /* IBM T.J. Watson Research
35 /* P.O. Box 704
36 /* Yorktown Heights, NY 10598, USA
37 /* CREATION DATE
38 /* Tue Oct 13 11:37:29 MET 1992
39 /* LAST MODIFICATION
40 /* Wed Jul 25 11:25:08 EDT 2001
41 /* VERSION/RELEASE
42 /* 1.3
43 /*--*/
44
45 #ifndef lint
46 static char sccsid[] = "@(#) chrootuid.c 1.3 2001/07/25 11:25:08";
47 #endif
48
49 /* System libraries. */
50
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <pwd.h>
54 #include <grp.h>
55 #include <syslog.h>
56
main(argc,argv)57 int main(argc, argv)
58 int argc;
59 char **argv;
60 {
61 struct passwd *pwd;
62
63 /*
64 * Open a channel to the syslog daemon. Older versions of openlog()
65 * require only two arguments.
66 */
67
68 #ifdef LOG_DAEMON
69 (void) openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_DAEMON);
70 #else
71 (void) openlog(argv[0], LOG_PID);
72 #endif
73
74 /*
75 * Require proper amount of arguments. In all cases of error, exit with
76 * zero status because we have already reported the problem via syslogd.
77 * No need to make inetd complain, too.
78 */
79
80 if (argc < 4) {
81 syslog(LOG_ERR, "usage: %s path user command", argv[0]);
82 return (0);
83 }
84
85 syslog(LOG_NOTICE, "chrootuid: dir(%s) user(%s) command(%s)",
86 argv[1], argv[2], argv[3]);
87
88 /* Must step into the new subtree. */
89
90 if (chdir(argv[1])) {
91 syslog(LOG_ERR, "chdir(%s): %m", argv[1]);
92 return (0);
93 }
94 /* The user must be known in the *unrestricted* universe... */
95
96 if ((pwd = getpwnam(argv[2])) == 0) {
97 syslog(LOG_ERR, "%s: user unknown", argv[2]);
98 return (0);
99 }
100 /* initgroups() accesses the group file in the unrestricted universe... */
101
102 if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
103 syslog(LOG_ERR, "initgroups: %m");
104 return (0);
105 }
106 endgrent();
107
108 /* Do the chroot() before giving away root privileges. */
109
110 if (chroot(argv[1])) {
111 syslog(LOG_ERR, "chroot(%s): %m", argv[1]);
112 return (0);
113 }
114 /* Switch group id then user id. */
115
116 if (setgid(pwd->pw_gid)) {
117 syslog(LOG_ERR, "setgid(%d): %m", pwd->pw_gid);
118 return (0);
119 }
120 if (setuid(pwd->pw_uid)) {
121 syslog(LOG_ERR, "setuid(%d): %m", pwd->pw_uid);
122 return (0);
123 }
124 /* In case we still have the /etc/passwd file still open. */
125
126 endpwent();
127
128 /* Run the command and hope for the best. */
129
130 (void) execv(argv[3], argv + 3);
131 syslog(LOG_ERR, "%s: %m", argv[3]);
132 return (0);
133 }
134