1ebf5d9bcSMike Barcroft /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro 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
30ebf5d9bcSMike Barcroft #include <sys/param.h>
31ebf5d9bcSMike Barcroft #include <sys/jail.h>
3273d0971bSJamie Gritton #include <sys/socket.h>
331f406de7SMichael Reifenberger #include <sys/sysctl.h>
341f406de7SMichael Reifenberger
3573d0971bSJamie Gritton #include <arpa/inet.h>
36413628a7SBjoern A. Zeeb #include <netinet/in.h>
37ebf5d9bcSMike Barcroft
38ebf5d9bcSMike Barcroft #include <err.h>
3970b75adfSXin LI #include <errno.h>
40de6f3704SJamie Gritton #include <jail.h>
4173d0971bSJamie Gritton #include <limits.h>
4270b75adfSXin LI #include <login_cap.h>
433bbdb8a7SJamie Gritton #include <paths.h>
443bbdb8a7SJamie Gritton #include <pwd.h>
45ebf5d9bcSMike Barcroft #include <stdio.h>
46ebf5d9bcSMike Barcroft #include <stdlib.h>
47413628a7SBjoern A. Zeeb #include <string.h>
48ebf5d9bcSMike Barcroft #include <unistd.h>
49ebf5d9bcSMike Barcroft
503bbdb8a7SJamie Gritton extern char **environ;
51413628a7SBjoern A. Zeeb
523bbdb8a7SJamie Gritton static void get_user_info(const char *username, const struct passwd **pwdp,
533bbdb8a7SJamie Gritton login_cap_t **lcapp);
543bbdb8a7SJamie Gritton static void usage(void);
5570b75adfSXin LI
56ebf5d9bcSMike Barcroft int
main(int argc,char * argv[])57ebf5d9bcSMike Barcroft main(int argc, char *argv[])
58ebf5d9bcSMike Barcroft {
59ebf5d9bcSMike Barcroft int jid;
6070b75adfSXin LI login_cap_t *lcap = NULL;
613bbdb8a7SJamie Gritton int ch, clean, uflag, Uflag;
623bbdb8a7SJamie Gritton char *cleanenv;
633bbdb8a7SJamie Gritton const struct passwd *pwd = NULL;
643bbdb8a7SJamie Gritton const char *username, *shell, *term;
655b4a0a4fSJamie Gritton
663bbdb8a7SJamie Gritton ch = clean = uflag = Uflag = 0;
6773d0971bSJamie Gritton username = NULL;
6854404cfbSBrooks Davis
693bbdb8a7SJamie Gritton while ((ch = getopt(argc, argv, "lnu:U:")) != -1) {
7070b75adfSXin LI switch (ch) {
713bbdb8a7SJamie Gritton case 'l':
723bbdb8a7SJamie Gritton clean = 1;
733bbdb8a7SJamie Gritton break;
74413628a7SBjoern A. Zeeb case 'n':
7573d0971bSJamie Gritton /* Specified name, now unused */
76413628a7SBjoern A. Zeeb break;
7770b75adfSXin LI case 'u':
7870b75adfSXin LI username = optarg;
7970b75adfSXin LI uflag = 1;
8070b75adfSXin LI break;
8170b75adfSXin LI case 'U':
8270b75adfSXin LI username = optarg;
8370b75adfSXin LI Uflag = 1;
8470b75adfSXin LI break;
8570b75adfSXin LI default:
86ebf5d9bcSMike Barcroft usage();
8770b75adfSXin LI }
8870b75adfSXin LI }
8970b75adfSXin LI argc -= optind;
9070b75adfSXin LI argv += optind;
913bbdb8a7SJamie Gritton if (argc < 1)
9270b75adfSXin LI usage();
9370b75adfSXin LI if (uflag && Uflag)
9470b75adfSXin LI usage();
953bbdb8a7SJamie Gritton if (uflag || (clean && !Uflag))
963bbdb8a7SJamie Gritton /* User info from the home environment */
973bbdb8a7SJamie Gritton get_user_info(username, &pwd, &lcap);
983bbdb8a7SJamie Gritton
993bbdb8a7SJamie Gritton /* Attach to the jail */
100de6f3704SJamie Gritton jid = jail_getid(argv[0]);
10173d0971bSJamie Gritton if (jid < 0)
102de6f3704SJamie Gritton errx(1, "%s", jail_errmsg);
103ebf5d9bcSMike Barcroft if (jail_attach(jid) == -1)
104de6f3704SJamie Gritton err(1, "jail_attach(%d)", jid);
105ebf5d9bcSMike Barcroft if (chdir("/") == -1)
106ebf5d9bcSMike Barcroft err(1, "chdir(): /");
1073bbdb8a7SJamie Gritton
1083bbdb8a7SJamie Gritton /* Set up user environment */
1093bbdb8a7SJamie Gritton if (clean || username != NULL) {
11070b75adfSXin LI if (Uflag)
1113bbdb8a7SJamie Gritton /* User info from the jail environment */
1123bbdb8a7SJamie Gritton get_user_info(username, &pwd, &lcap);
1133bbdb8a7SJamie Gritton if (clean) {
1143bbdb8a7SJamie Gritton term = getenv("TERM");
1153bbdb8a7SJamie Gritton cleanenv = NULL;
1163bbdb8a7SJamie Gritton environ = &cleanenv;
1173bbdb8a7SJamie Gritton setenv("PATH", "/bin:/usr/bin", 1);
1183bbdb8a7SJamie Gritton if (term != NULL)
1193bbdb8a7SJamie Gritton setenv("TERM", term, 1);
1203bbdb8a7SJamie Gritton }
12170b75adfSXin LI if (setgid(pwd->pw_gid) != 0)
12270b75adfSXin LI err(1, "setgid");
1233bbdb8a7SJamie Gritton if (setusercontext(lcap, pwd, pwd->pw_uid, username
1243bbdb8a7SJamie Gritton ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN
1253bbdb8a7SJamie Gritton : LOGIN_SETPATH | LOGIN_SETENV) != 0)
12670b75adfSXin LI err(1, "setusercontext");
12770b75adfSXin LI login_close(lcap);
1283bbdb8a7SJamie Gritton setenv("USER", pwd->pw_name, 1);
1293bbdb8a7SJamie Gritton setenv("HOME", pwd->pw_dir, 1);
1303bbdb8a7SJamie Gritton setenv("SHELL",
1313bbdb8a7SJamie Gritton *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);
1323bbdb8a7SJamie Gritton if (clean && chdir(pwd->pw_dir) < 0)
1333bbdb8a7SJamie Gritton err(1, "chdir: %s", pwd->pw_dir);
1343bbdb8a7SJamie Gritton endpwent();
13570b75adfSXin LI }
1363bbdb8a7SJamie Gritton
1373bbdb8a7SJamie Gritton /* Run the specified command, or the shell */
1383bbdb8a7SJamie Gritton if (argc > 1) {
1393bbdb8a7SJamie Gritton if (execvp(argv[1], argv + 1) < 0)
1403bbdb8a7SJamie Gritton err(1, "execvp: %s", argv[1]);
1413bbdb8a7SJamie Gritton } else {
1423bbdb8a7SJamie Gritton if (!(shell = getenv("SHELL")))
1433bbdb8a7SJamie Gritton shell = _PATH_BSHELL;
1443bbdb8a7SJamie Gritton if (execlp(shell, shell, "-i", NULL) < 0)
1453bbdb8a7SJamie Gritton err(1, "execlp: %s", shell);
1463bbdb8a7SJamie Gritton }
147ebf5d9bcSMike Barcroft exit(0);
148ebf5d9bcSMike Barcroft }
149ebf5d9bcSMike Barcroft
150ebf5d9bcSMike Barcroft static void
get_user_info(const char * username,const struct passwd ** pwdp,login_cap_t ** lcapp)1513bbdb8a7SJamie Gritton get_user_info(const char *username, const struct passwd **pwdp,
1523bbdb8a7SJamie Gritton login_cap_t **lcapp)
1533bbdb8a7SJamie Gritton {
1543bbdb8a7SJamie Gritton uid_t uid;
1553bbdb8a7SJamie Gritton const struct passwd *pwd;
1563bbdb8a7SJamie Gritton
1573bbdb8a7SJamie Gritton errno = 0;
1583bbdb8a7SJamie Gritton if (username) {
1593bbdb8a7SJamie Gritton pwd = getpwnam(username);
1603bbdb8a7SJamie Gritton if (pwd == NULL) {
1613bbdb8a7SJamie Gritton if (errno)
1623bbdb8a7SJamie Gritton err(1, "getpwnam: %s", username);
1633bbdb8a7SJamie Gritton else
1643bbdb8a7SJamie Gritton errx(1, "%s: no such user", username);
1653bbdb8a7SJamie Gritton }
1663bbdb8a7SJamie Gritton } else {
1673bbdb8a7SJamie Gritton uid = getuid();
1683bbdb8a7SJamie Gritton pwd = getpwuid(uid);
1693bbdb8a7SJamie Gritton if (pwd == NULL) {
1703bbdb8a7SJamie Gritton if (errno)
1713bbdb8a7SJamie Gritton err(1, "getpwuid: %d", uid);
1723bbdb8a7SJamie Gritton else
1733bbdb8a7SJamie Gritton errx(1, "unknown uid: %d", uid);
1743bbdb8a7SJamie Gritton }
1753bbdb8a7SJamie Gritton }
1763bbdb8a7SJamie Gritton *pwdp = pwd;
1773bbdb8a7SJamie Gritton *lcapp = login_getpwclass(pwd);
1783bbdb8a7SJamie Gritton if (*lcapp == NULL)
1793bbdb8a7SJamie Gritton err(1, "getpwclass: %s", pwd->pw_name);
1803bbdb8a7SJamie Gritton if (initgroups(pwd->pw_name, pwd->pw_gid) < 0)
1813bbdb8a7SJamie Gritton err(1, "initgroups: %s", pwd->pw_name);
1823bbdb8a7SJamie Gritton }
1833bbdb8a7SJamie Gritton
1843bbdb8a7SJamie Gritton static void
usage(void)185ebf5d9bcSMike Barcroft usage(void)
186ebf5d9bcSMike Barcroft {
187ebf5d9bcSMike Barcroft
18873d0971bSJamie Gritton fprintf(stderr, "%s\n",
1893bbdb8a7SJamie Gritton "usage: jexec [-l] [-u username | -U username] jail [command ...]");
190ebf5d9bcSMike Barcroft exit(1);
191ebf5d9bcSMike Barcroft }
192