1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/*++
/* 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
extern char *optarg;
extern int optind, opterr, optopt;
int main(argc, argv)
int argc;
char **argv;
{
struct passwd *pwd;
int interactive = 1;
int optstart = 0;
/*
* 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 we use -i, skip it over and increment optstart */
/* we cannot use the getopt library using:
* if (getopt(argc, argv, "i") != -1) {
* in order to preserve the arguments provided to the command
* This means that -i must be the *first* (and only) argument */
if ( argv[1] != NULL && strncmp(argv[1], "-i", 2) == 0 ) {
interactive = 0;
optstart++;
}
if (argc-optstart < 4) {
if (interactive) {
syslog(LOG_ERR, "usage: %s [-i] path user command", argv[0]);
} else {
fprintf(stderr,"usage: %s [-i] path user command\n", argv[0]);
return (1);
}
return (0);
}
/* Must step into the new subtree. */
if (chdir(argv[1+optstart])) {
if (interactive) {
syslog(LOG_ERR, "chdir(%s): %m", argv[1+optstart]);
return (0);
} else {
fprintf(stderr, "chdir(%s): %s\n", argv[1+optstart], strerror(errno));
return (1);
}
}
/* The user must be known in the *unrestricted* universe... */
if ((pwd = getpwnam(argv[2+optstart])) == 0) {
if (interactive) {
syslog(LOG_ERR, "%s: user unknown", argv[2+optstart]);
return (0);
} else {
fprintf(stderr, "%s: user unknown\n", argv[2+optstart]);
return (1);
}
}
/* initgroups() accesses the group file in the unrestricted universe... */
if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
if (interactive) {
syslog(LOG_ERR, "initgroups: %m");
return (0);
} else {
fprintf(stderr, "initgroups: %s\n", strerror(errno));
return (1);
}
}
endgrent();
/* Do the chroot() before giving away root privileges. */
if (chroot(argv[1+optstart])) {
if (interactive) {
syslog(LOG_ERR, "chroot(%s): %m", argv[1+optstart]);
return (0);
} else {
fprintf(stderr, "chroot(%s): %s\n", argv[1+optstart], strerror(errno));
return (1);
}
}
/* Switch group id then user id. */
if (setgid(pwd->pw_gid)) {
if (interactive) {
syslog(LOG_ERR, "setgid(%d): %m", pwd->pw_gid);
return (0);
} else {
fprintf(stderr, "setgid(%d): %s\n", pwd->pw_gid, strerror(errno));
return (1);
}
}
if (setuid(pwd->pw_uid)) {
if (interactive) {
syslog(LOG_ERR, "setuid(%d): %m", pwd->pw_uid);
return (0);
} else {
fprintf(stderr, "setuid(%d): %s\n", pwd->pw_uid, strerror(errno));
return (1);
}
}
/* In case we still have the /etc/passwd file still open. */
endpwent();
/* Run the command and hope for the best. */
(void) execv(argv[3+optstart], argv + 3+optstart);
if (interactive) {
syslog(LOG_ERR, "%s: %m", argv[3+optstart]);
return (0);
}
fprintf(stderr, "%s: %s", argv[3+optstart], strerror(errno));
return (1);
}
|