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