1331722Seadler/*
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
591553Srgrimesint
60201387Sedmain(int argc, char *argv[])
611553Srgrimes{
62115952Smtm	struct group	*gp;
63115952Smtm	struct passwd	*pw;
64227223Sed	char		*endp, *p, *user, *group, *grouplist;
65115952Smtm	const char	*shell;
66194494Sbrooks	gid_t		gid, *gidlist;
67115952Smtm	uid_t		uid;
68115952Smtm	int		ch, gids;
69194494Sbrooks	long		ngroups_max;
701553Srgrimes
71115952Smtm	gid = 0;
72115952Smtm	uid = 0;
73227223Sed	user = group = grouplist = NULL;
74115952Smtm	while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
751553Srgrimes		switch(ch) {
76115952Smtm		case 'u':
77115952Smtm			user = optarg;
78115952Smtm			if (*user == '\0')
79115952Smtm				usage();
80115952Smtm			break;
81115952Smtm		case 'g':
82115952Smtm			group = optarg;
83115952Smtm			if (*group == '\0')
84115952Smtm				usage();
85115952Smtm			break;
86115952Smtm		case 'G':
87115952Smtm			grouplist = optarg;
88115952Smtm			if (*grouplist == '\0')
89115952Smtm				usage();
90115952Smtm			break;
911553Srgrimes		case '?':
921553Srgrimes		default:
931553Srgrimes			usage();
941553Srgrimes		}
95115952Smtm	}
961553Srgrimes	argc -= optind;
971553Srgrimes	argv += optind;
981553Srgrimes
991553Srgrimes	if (argc < 1)
1001553Srgrimes		usage();
1011553Srgrimes
102115952Smtm	if (group != NULL) {
103115952Smtm		if (isdigit((unsigned char)*group)) {
104115952Smtm			gid = (gid_t)strtoul(group, &endp, 0);
105115952Smtm			if (*endp != '\0')
106115952Smtm				goto getgroup;
107115952Smtm		} else {
108115952Smtm getgroup:
109115952Smtm			if ((gp = getgrnam(group)) != NULL)
110115952Smtm				gid = gp->gr_gid;
111115952Smtm			else
112115952Smtm				errx(1, "no such group `%s'", group);
113115952Smtm		}
114115952Smtm	}
115115952Smtm
116194494Sbrooks	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
117194494Sbrooks	if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
118194494Sbrooks		err(1, "malloc");
119115952Smtm	for (gids = 0;
120194494Sbrooks	    (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) {
121115952Smtm		if (*p == '\0')
122115952Smtm			continue;
123115952Smtm
124115952Smtm		if (isdigit((unsigned char)*p)) {
125115952Smtm			gidlist[gids] = (gid_t)strtoul(p, &endp, 0);
126115952Smtm			if (*endp != '\0')
127115952Smtm				goto getglist;
128115952Smtm		} else {
129115952Smtm getglist:
130115952Smtm			if ((gp = getgrnam(p)) != NULL)
131115952Smtm				gidlist[gids] = gp->gr_gid;
132115952Smtm			else
133115952Smtm				errx(1, "no such group `%s'", p);
134115952Smtm		}
135115952Smtm		gids++;
136115952Smtm	}
137194494Sbrooks	if (p != NULL && gids == ngroups_max)
138115952Smtm		errx(1, "too many supplementary groups provided");
139115952Smtm
140115952Smtm	if (user != NULL) {
141115952Smtm		if (isdigit((unsigned char)*user)) {
142115952Smtm			uid = (uid_t)strtoul(user, &endp, 0);
143115952Smtm			if (*endp != '\0')
144115952Smtm				goto getuser;
145115952Smtm		} else {
146115952Smtm getuser:
147115952Smtm			if ((pw = getpwnam(user)) != NULL)
148115952Smtm				uid = pw->pw_uid;
149115952Smtm			else
150115952Smtm				errx(1, "no such user `%s'", user);
151115952Smtm		}
152115952Smtm	}
153115952Smtm
154115677Smtm	if (chdir(argv[0]) == -1 || chroot(".") == -1)
1551553Srgrimes		err(1, "%s", argv[0]);
1561553Srgrimes
157115952Smtm	if (gids && setgroups(gids, gidlist) == -1)
158115952Smtm		err(1, "setgroups");
159115952Smtm	if (group && setgid(gid) == -1)
160115952Smtm		err(1, "setgid");
161115952Smtm	if (user && setuid(uid) == -1)
162115952Smtm		err(1, "setuid");
163115952Smtm
1641553Srgrimes	if (argv[1]) {
1651553Srgrimes		execvp(argv[1], &argv[1]);
1661553Srgrimes		err(1, "%s", argv[1]);
1671553Srgrimes	}
1681553Srgrimes
1691553Srgrimes	if (!(shell = getenv("SHELL")))
1701553Srgrimes		shell = _PATH_BSHELL;
17179452Sbrian	execlp(shell, shell, "-i", (char *)NULL);
1721553Srgrimes	err(1, "%s", shell);
1731553Srgrimes	/* NOTREACHED */
1741553Srgrimes}
1751553Srgrimes
17629448Scharnierstatic void
177201387Sedusage(void)
1781553Srgrimes{
179115952Smtm	(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
180115952Smtm	    "[-u user] newroot [command]\n");
1811553Srgrimes	exit(1);
1821553Srgrimes}
183