Allow the optional setting of a user, primary group, or grouplist

when chrooting.

Obtained from:	NetBSD
MFC after:	4 weeks
This commit is contained in:
mtm 2003-06-07 10:56:12 +00:00
parent dd1aaed417
commit 5ba88e8391
2 changed files with 114 additions and 6 deletions

View File

@ -32,7 +32,7 @@
.\" @(#)chroot.8 8.1 (Berkeley) 6/9/93 .\" @(#)chroot.8 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd January 24, 2002 .Dd June 7, 2003
.Dt CHROOT 8 .Dt CHROOT 8
.Os .Os
.Sh NAME .Sh NAME
@ -40,6 +40,9 @@
.Nd change root directory .Nd change root directory
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl G Ar group,group,...
.Ar newroot .Ar newroot
.Op Ar command .Op Ar command
.Sh DESCRIPTION .Sh DESCRIPTION
@ -49,7 +52,20 @@ utility changes its current and root directories to the supplied directory
.Ar newroot .Ar newroot
and then exec's and then exec's
.Ar command , .Ar command ,
if supplied, or an interactive copy of the user's login shell. if supplied,
or an interactive copy of the user's login shell.
.Pp
If the
.Fl u ,
.Fl g
or
.Fl G
options are given,
the user,
group and group list of the process are set to
these values after the
.Xr chroot 8
has taken place.
.Sh ENVIRONMENT .Sh ENVIRONMENT
The following environment variable is referenced by The following environment variable is referenced by
.Nm : .Nm :
@ -69,6 +85,10 @@ is used.
.Sh SEE ALSO .Sh SEE ALSO
.Xr chdir 2 , .Xr chdir 2 ,
.Xr chroot 2 , .Xr chroot 2 ,
.Xr setgid 2 ,
.Xr setgroups 2 ,
.Xr setuid 2 ,
.Xr getgrnam 3 ,
.Xr environ 7 , .Xr environ 7 ,
.Xr jail 8 .Xr jail 8
.Sh HISTORY .Sh HISTORY

View File

@ -47,8 +47,12 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include <err.h> #include <err.h>
#include <grp.h>
#include <limits.h>
#include <paths.h> #include <paths.h>
#include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -56,29 +60,112 @@ __FBSDID("$FreeBSD$");
static void usage(void); static void usage(void);
char *user; /* user to switch to before running program */
char *group; /* group to switch to ... */
char *grouplist; /* group list to switch to ... */
int int
main(argc, argv) main(argc, argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
int ch; struct group *gp;
const char *shell; struct passwd *pw;
char *endp, *p;
const char *shell;
gid_t gid, gidlist[NGROUPS_MAX];
uid_t uid;
int ch, gids;
while ((ch = getopt(argc, argv, "")) != -1) gid = 0;
uid = 0;
while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
switch(ch) { switch(ch) {
case 'u':
user = optarg;
if (*user == '\0')
usage();
break;
case 'g':
group = optarg;
if (*group == '\0')
usage();
break;
case 'G':
grouplist = optarg;
if (*grouplist == '\0')
usage();
break;
case '?': case '?':
default: default:
usage(); usage();
} }
}
argc -= optind; argc -= optind;
argv += optind; argv += optind;
if (argc < 1) if (argc < 1)
usage(); usage();
if (group != NULL) {
if (isdigit((unsigned char)*group)) {
gid = (gid_t)strtoul(group, &endp, 0);
if (*endp != '\0')
goto getgroup;
} else {
getgroup:
if ((gp = getgrnam(group)) != NULL)
gid = gp->gr_gid;
else
errx(1, "no such group `%s'", group);
}
}
for (gids = 0;
(p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX; ) {
if (*p == '\0')
continue;
if (isdigit((unsigned char)*p)) {
gidlist[gids] = (gid_t)strtoul(p, &endp, 0);
if (*endp != '\0')
goto getglist;
} else {
getglist:
if ((gp = getgrnam(p)) != NULL)
gidlist[gids] = gp->gr_gid;
else
errx(1, "no such group `%s'", p);
}
gids++;
}
if (p != NULL && gids == NGROUPS_MAX)
errx(1, "too many supplementary groups provided");
if (user != NULL) {
if (isdigit((unsigned char)*user)) {
uid = (uid_t)strtoul(user, &endp, 0);
if (*endp != '\0')
goto getuser;
} else {
getuser:
if ((pw = getpwnam(user)) != NULL)
uid = pw->pw_uid;
else
errx(1, "no such user `%s'", user);
}
}
if (chdir(argv[0]) == -1 || chroot(".") == -1) if (chdir(argv[0]) == -1 || chroot(".") == -1)
err(1, "%s", argv[0]); err(1, "%s", argv[0]);
if (gids && setgroups(gids, gidlist) == -1)
err(1, "setgroups");
if (group && setgid(gid) == -1)
err(1, "setgid");
if (user && setuid(uid) == -1)
err(1, "setuid");
if (argv[1]) { if (argv[1]) {
execvp(argv[1], &argv[1]); execvp(argv[1], &argv[1]);
err(1, "%s", argv[1]); err(1, "%s", argv[1]);
@ -94,6 +181,7 @@ main(argc, argv)
static void static void
usage() usage()
{ {
(void)fprintf(stderr, "usage: chroot newroot [command]\n"); (void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
"[-u user] newroot [command]\n");
exit(1); exit(1);
} }