11553Srgrimes/*
21553Srgrimes * Copyright (c) 1988, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 4. Neither the name of the University nor the names of its contributors
141553Srgrimes *    may be used to endorse or promote products derived from this software
151553Srgrimes *    without specific prior written permission.
161553Srgrimes *
171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271553Srgrimes * SUCH DAMAGE.
281553Srgrimes */
291553Srgrimes
30114601Sobrien#if 0
311553Srgrimes#ifndef lint
3229448Scharnierstatic const char copyright[] =
331553Srgrimes"@(#) Copyright (c) 1988, 1993\n\
341553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
351553Srgrimes#endif /* not lint */
361553Srgrimes
371553Srgrimes#ifndef lint
381553Srgrimesstatic char sccsid[] = "@(#)chroot.c	8.1 (Berkeley) 6/9/93";
39114601Sobrien#endif /* not lint */
4029448Scharnier#endif
41114601Sobrien#include <sys/cdefs.h>
42114601Sobrien__FBSDID("$FreeBSD$");
431553Srgrimes
441553Srgrimes#include <sys/types.h>
451553Srgrimes
46115952Smtm#include <ctype.h>
471553Srgrimes#include <err.h>
48115952Smtm#include <grp.h>
49115952Smtm#include <limits.h>
501553Srgrimes#include <paths.h>
51115952Smtm#include <pwd.h>
521553Srgrimes#include <stdio.h>
531553Srgrimes#include <stdlib.h>
541553Srgrimes#include <string.h>
551553Srgrimes#include <unistd.h>
561553Srgrimes
5799800Salfredstatic void usage(void);
581553Srgrimes
59115952Smtmchar	*user;		/* user to switch to before running program */
60115952Smtmchar	*group;		/* group to switch to ... */
61115952Smtmchar	*grouplist;	/* group list to switch to ... */
62115952Smtm
631553Srgrimesint
64201387Sedmain(int argc, char *argv[])
651553Srgrimes{
66115952Smtm	struct group	*gp;
67115952Smtm	struct passwd	*pw;
68115952Smtm	char		*endp, *p;
69115952Smtm	const char	*shell;
70194494Sbrooks	gid_t		gid, *gidlist;
71115952Smtm	uid_t		uid;
72115952Smtm	int		ch, gids;
73194494Sbrooks	long		ngroups_max;
741553Srgrimes
75115952Smtm	gid = 0;
76115952Smtm	uid = 0;
77115952Smtm	while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
781553Srgrimes		switch(ch) {
79115952Smtm		case 'u':
80115952Smtm			user = optarg;
81115952Smtm			if (*user == '\0')
82115952Smtm				usage();
83115952Smtm			break;
84115952Smtm		case 'g':
85115952Smtm			group = optarg;
86115952Smtm			if (*group == '\0')
87115952Smtm				usage();
88115952Smtm			break;
89115952Smtm		case 'G':
90115952Smtm			grouplist = optarg;
91115952Smtm			if (*grouplist == '\0')
92115952Smtm				usage();
93115952Smtm			break;
941553Srgrimes		case '?':
951553Srgrimes		default:
961553Srgrimes			usage();
971553Srgrimes		}
98115952Smtm	}
991553Srgrimes	argc -= optind;
1001553Srgrimes	argv += optind;
1011553Srgrimes
1021553Srgrimes	if (argc < 1)
1031553Srgrimes		usage();
1041553Srgrimes
105115952Smtm	if (group != NULL) {
106115952Smtm		if (isdigit((unsigned char)*group)) {
107115952Smtm			gid = (gid_t)strtoul(group, &endp, 0);
108115952Smtm			if (*endp != '\0')
109115952Smtm				goto getgroup;
110115952Smtm		} else {
111115952Smtm getgroup:
112115952Smtm			if ((gp = getgrnam(group)) != NULL)
113115952Smtm				gid = gp->gr_gid;
114115952Smtm			else
115115952Smtm				errx(1, "no such group `%s'", group);
116115952Smtm		}
117115952Smtm	}
118115952Smtm
119194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
120194494Sbrooks	if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
121194494Sbrooks		err(1, "malloc");
122115952Smtm	for (gids = 0;
123194494Sbrooks	    (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) {
124115952Smtm		if (*p == '\0')
125115952Smtm			continue;
126115952Smtm
127115952Smtm		if (isdigit((unsigned char)*p)) {
128115952Smtm			gidlist[gids] = (gid_t)strtoul(p, &endp, 0);
129115952Smtm			if (*endp != '\0')
130115952Smtm				goto getglist;
131115952Smtm		} else {
132115952Smtm getglist:
133115952Smtm			if ((gp = getgrnam(p)) != NULL)
134115952Smtm				gidlist[gids] = gp->gr_gid;
135115952Smtm			else
136115952Smtm				errx(1, "no such group `%s'", p);
137115952Smtm		}
138115952Smtm		gids++;
139115952Smtm	}
140194494Sbrooks	if (p != NULL && gids == ngroups_max)
141115952Smtm		errx(1, "too many supplementary groups provided");
142115952Smtm
143115952Smtm	if (user != NULL) {
144115952Smtm		if (isdigit((unsigned char)*user)) {
145115952Smtm			uid = (uid_t)strtoul(user, &endp, 0);
146115952Smtm			if (*endp != '\0')
147115952Smtm				goto getuser;
148115952Smtm		} else {
149115952Smtm getuser:
150115952Smtm			if ((pw = getpwnam(user)) != NULL)
151115952Smtm				uid = pw->pw_uid;
152115952Smtm			else
153115952Smtm				errx(1, "no such user `%s'", user);
154115952Smtm		}
155115952Smtm	}
156115952Smtm
157115677Smtm	if (chdir(argv[0]) == -1 || chroot(".") == -1)
1581553Srgrimes		err(1, "%s", argv[0]);
1591553Srgrimes
160115952Smtm	if (gids && setgroups(gids, gidlist) == -1)
161115952Smtm		err(1, "setgroups");
162115952Smtm	if (group && setgid(gid) == -1)
163115952Smtm		err(1, "setgid");
164115952Smtm	if (user && setuid(uid) == -1)
165115952Smtm		err(1, "setuid");
166115952Smtm
1671553Srgrimes	if (argv[1]) {
1681553Srgrimes		execvp(argv[1], &argv[1]);
1691553Srgrimes		err(1, "%s", argv[1]);
1701553Srgrimes	}
1711553Srgrimes
1721553Srgrimes	if (!(shell = getenv("SHELL")))
1731553Srgrimes		shell = _PATH_BSHELL;
17479452Sbrian	execlp(shell, shell, "-i", (char *)NULL);
1751553Srgrimes	err(1, "%s", shell);
1761553Srgrimes	/* NOTREACHED */
1771553Srgrimes}
1781553Srgrimes
17929448Scharnierstatic void
180201387Sedusage(void)
1811553Srgrimes{
182115952Smtm	(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
183115952Smtm	    "[-u user] newroot [command]\n");
1841553Srgrimes	exit(1);
1851553Srgrimes}
186