1ebf5d9bcSMike Barcroft /*- 2*1de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*1de7b4b8SPedro F. Giffuni * 4ebf5d9bcSMike Barcroft * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> 5413628a7SBjoern A. Zeeb * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org> 6ebf5d9bcSMike Barcroft * All rights reserved. 7ebf5d9bcSMike Barcroft * 8ebf5d9bcSMike Barcroft * Redistribution and use in source and binary forms, with or without 9ebf5d9bcSMike Barcroft * modification, are permitted provided that the following conditions 10ebf5d9bcSMike Barcroft * are met: 11ebf5d9bcSMike Barcroft * 1. Redistributions of source code must retain the above copyright 12ebf5d9bcSMike Barcroft * notice, this list of conditions and the following disclaimer. 13ebf5d9bcSMike Barcroft * 2. Redistributions in binary form must reproduce the above copyright 14ebf5d9bcSMike Barcroft * notice, this list of conditions and the following disclaimer in the 15ebf5d9bcSMike Barcroft * documentation and/or other materials provided with the distribution. 16ebf5d9bcSMike Barcroft * 17ebf5d9bcSMike Barcroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18ebf5d9bcSMike Barcroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19ebf5d9bcSMike Barcroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20ebf5d9bcSMike Barcroft * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21ebf5d9bcSMike Barcroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22ebf5d9bcSMike Barcroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23ebf5d9bcSMike Barcroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24ebf5d9bcSMike Barcroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25ebf5d9bcSMike Barcroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26ebf5d9bcSMike Barcroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27ebf5d9bcSMike Barcroft * SUCH DAMAGE. 28ebf5d9bcSMike Barcroft * 29ebf5d9bcSMike Barcroft * $FreeBSD$ 30ebf5d9bcSMike Barcroft */ 31ebf5d9bcSMike Barcroft 32ebf5d9bcSMike Barcroft #include <sys/param.h> 33ebf5d9bcSMike Barcroft #include <sys/jail.h> 3473d0971bSJamie Gritton #include <sys/socket.h> 351f406de7SMichael Reifenberger #include <sys/sysctl.h> 361f406de7SMichael Reifenberger 3773d0971bSJamie Gritton #include <arpa/inet.h> 38413628a7SBjoern A. Zeeb #include <netinet/in.h> 39ebf5d9bcSMike Barcroft 40ebf5d9bcSMike Barcroft #include <err.h> 4170b75adfSXin LI #include <errno.h> 42de6f3704SJamie Gritton #include <jail.h> 4373d0971bSJamie Gritton #include <limits.h> 4470b75adfSXin LI #include <login_cap.h> 453bbdb8a7SJamie Gritton #include <paths.h> 463bbdb8a7SJamie Gritton #include <pwd.h> 47ebf5d9bcSMike Barcroft #include <stdio.h> 48ebf5d9bcSMike Barcroft #include <stdlib.h> 49413628a7SBjoern A. Zeeb #include <string.h> 50ebf5d9bcSMike Barcroft #include <unistd.h> 51ebf5d9bcSMike Barcroft 523bbdb8a7SJamie Gritton extern char **environ; 53413628a7SBjoern A. Zeeb 543bbdb8a7SJamie Gritton static void get_user_info(const char *username, const struct passwd **pwdp, 553bbdb8a7SJamie Gritton login_cap_t **lcapp); 563bbdb8a7SJamie Gritton static void usage(void); 5770b75adfSXin LI 58ebf5d9bcSMike Barcroft int 59ebf5d9bcSMike Barcroft main(int argc, char *argv[]) 60ebf5d9bcSMike Barcroft { 61ebf5d9bcSMike Barcroft int jid; 6270b75adfSXin LI login_cap_t *lcap = NULL; 633bbdb8a7SJamie Gritton int ch, clean, uflag, Uflag; 643bbdb8a7SJamie Gritton char *cleanenv; 653bbdb8a7SJamie Gritton const struct passwd *pwd = NULL; 663bbdb8a7SJamie Gritton const char *username, *shell, *term; 675b4a0a4fSJamie Gritton 683bbdb8a7SJamie Gritton ch = clean = uflag = Uflag = 0; 6973d0971bSJamie Gritton username = NULL; 7054404cfbSBrooks Davis 713bbdb8a7SJamie Gritton while ((ch = getopt(argc, argv, "lnu:U:")) != -1) { 7270b75adfSXin LI switch (ch) { 733bbdb8a7SJamie Gritton case 'l': 743bbdb8a7SJamie Gritton clean = 1; 753bbdb8a7SJamie Gritton break; 76413628a7SBjoern A. Zeeb case 'n': 7773d0971bSJamie Gritton /* Specified name, now unused */ 78413628a7SBjoern A. Zeeb break; 7970b75adfSXin LI case 'u': 8070b75adfSXin LI username = optarg; 8170b75adfSXin LI uflag = 1; 8270b75adfSXin LI break; 8370b75adfSXin LI case 'U': 8470b75adfSXin LI username = optarg; 8570b75adfSXin LI Uflag = 1; 8670b75adfSXin LI break; 8770b75adfSXin LI default: 88ebf5d9bcSMike Barcroft usage(); 8970b75adfSXin LI } 9070b75adfSXin LI } 9170b75adfSXin LI argc -= optind; 9270b75adfSXin LI argv += optind; 933bbdb8a7SJamie Gritton if (argc < 1) 9470b75adfSXin LI usage(); 9570b75adfSXin LI if (uflag && Uflag) 9670b75adfSXin LI usage(); 973bbdb8a7SJamie Gritton if (uflag || (clean && !Uflag)) 983bbdb8a7SJamie Gritton /* User info from the home environment */ 993bbdb8a7SJamie Gritton get_user_info(username, &pwd, &lcap); 1003bbdb8a7SJamie Gritton 1013bbdb8a7SJamie Gritton /* Attach to the jail */ 102de6f3704SJamie Gritton jid = jail_getid(argv[0]); 10373d0971bSJamie Gritton if (jid < 0) 104de6f3704SJamie Gritton errx(1, "%s", jail_errmsg); 105ebf5d9bcSMike Barcroft if (jail_attach(jid) == -1) 106de6f3704SJamie Gritton err(1, "jail_attach(%d)", jid); 107ebf5d9bcSMike Barcroft if (chdir("/") == -1) 108ebf5d9bcSMike Barcroft err(1, "chdir(): /"); 1093bbdb8a7SJamie Gritton 1103bbdb8a7SJamie Gritton /* Set up user environment */ 1113bbdb8a7SJamie Gritton if (clean || username != NULL) { 11270b75adfSXin LI if (Uflag) 1133bbdb8a7SJamie Gritton /* User info from the jail environment */ 1143bbdb8a7SJamie Gritton get_user_info(username, &pwd, &lcap); 1153bbdb8a7SJamie Gritton if (clean) { 1163bbdb8a7SJamie Gritton term = getenv("TERM"); 1173bbdb8a7SJamie Gritton cleanenv = NULL; 1183bbdb8a7SJamie Gritton environ = &cleanenv; 1193bbdb8a7SJamie Gritton setenv("PATH", "/bin:/usr/bin", 1); 1203bbdb8a7SJamie Gritton if (term != NULL) 1213bbdb8a7SJamie Gritton setenv("TERM", term, 1); 1223bbdb8a7SJamie Gritton } 12370b75adfSXin LI if (setgid(pwd->pw_gid) != 0) 12470b75adfSXin LI err(1, "setgid"); 1253bbdb8a7SJamie Gritton if (setusercontext(lcap, pwd, pwd->pw_uid, username 1263bbdb8a7SJamie Gritton ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN 1273bbdb8a7SJamie Gritton : LOGIN_SETPATH | LOGIN_SETENV) != 0) 12870b75adfSXin LI err(1, "setusercontext"); 12970b75adfSXin LI login_close(lcap); 1303bbdb8a7SJamie Gritton setenv("USER", pwd->pw_name, 1); 1313bbdb8a7SJamie Gritton setenv("HOME", pwd->pw_dir, 1); 1323bbdb8a7SJamie Gritton setenv("SHELL", 1333bbdb8a7SJamie Gritton *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1); 1343bbdb8a7SJamie Gritton if (clean && chdir(pwd->pw_dir) < 0) 1353bbdb8a7SJamie Gritton err(1, "chdir: %s", pwd->pw_dir); 1363bbdb8a7SJamie Gritton endpwent(); 13770b75adfSXin LI } 1383bbdb8a7SJamie Gritton 1393bbdb8a7SJamie Gritton /* Run the specified command, or the shell */ 1403bbdb8a7SJamie Gritton if (argc > 1) { 1413bbdb8a7SJamie Gritton if (execvp(argv[1], argv + 1) < 0) 1423bbdb8a7SJamie Gritton err(1, "execvp: %s", argv[1]); 1433bbdb8a7SJamie Gritton } else { 1443bbdb8a7SJamie Gritton if (!(shell = getenv("SHELL"))) 1453bbdb8a7SJamie Gritton shell = _PATH_BSHELL; 1463bbdb8a7SJamie Gritton if (execlp(shell, shell, "-i", NULL) < 0) 1473bbdb8a7SJamie Gritton err(1, "execlp: %s", shell); 1483bbdb8a7SJamie Gritton } 149ebf5d9bcSMike Barcroft exit(0); 150ebf5d9bcSMike Barcroft } 151ebf5d9bcSMike Barcroft 152ebf5d9bcSMike Barcroft static void 1533bbdb8a7SJamie Gritton get_user_info(const char *username, const struct passwd **pwdp, 1543bbdb8a7SJamie Gritton login_cap_t **lcapp) 1553bbdb8a7SJamie Gritton { 1563bbdb8a7SJamie Gritton uid_t uid; 1573bbdb8a7SJamie Gritton const struct passwd *pwd; 1583bbdb8a7SJamie Gritton 1593bbdb8a7SJamie Gritton errno = 0; 1603bbdb8a7SJamie Gritton if (username) { 1613bbdb8a7SJamie Gritton pwd = getpwnam(username); 1623bbdb8a7SJamie Gritton if (pwd == NULL) { 1633bbdb8a7SJamie Gritton if (errno) 1643bbdb8a7SJamie Gritton err(1, "getpwnam: %s", username); 1653bbdb8a7SJamie Gritton else 1663bbdb8a7SJamie Gritton errx(1, "%s: no such user", username); 1673bbdb8a7SJamie Gritton } 1683bbdb8a7SJamie Gritton } else { 1693bbdb8a7SJamie Gritton uid = getuid(); 1703bbdb8a7SJamie Gritton pwd = getpwuid(uid); 1713bbdb8a7SJamie Gritton if (pwd == NULL) { 1723bbdb8a7SJamie Gritton if (errno) 1733bbdb8a7SJamie Gritton err(1, "getpwuid: %d", uid); 1743bbdb8a7SJamie Gritton else 1753bbdb8a7SJamie Gritton errx(1, "unknown uid: %d", uid); 1763bbdb8a7SJamie Gritton } 1773bbdb8a7SJamie Gritton } 1783bbdb8a7SJamie Gritton *pwdp = pwd; 1793bbdb8a7SJamie Gritton *lcapp = login_getpwclass(pwd); 1803bbdb8a7SJamie Gritton if (*lcapp == NULL) 1813bbdb8a7SJamie Gritton err(1, "getpwclass: %s", pwd->pw_name); 1823bbdb8a7SJamie Gritton if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) 1833bbdb8a7SJamie Gritton err(1, "initgroups: %s", pwd->pw_name); 1843bbdb8a7SJamie Gritton } 1853bbdb8a7SJamie Gritton 1863bbdb8a7SJamie Gritton static void 187ebf5d9bcSMike Barcroft usage(void) 188ebf5d9bcSMike Barcroft { 189ebf5d9bcSMike Barcroft 19073d0971bSJamie Gritton fprintf(stderr, "%s\n", 1913bbdb8a7SJamie Gritton "usage: jexec [-l] [-u username | -U username] jail [command ...]"); 192ebf5d9bcSMike Barcroft exit(1); 193ebf5d9bcSMike Barcroft } 194