xref: /freebsd/usr.sbin/jexec/jexec.c (revision 73d0971bf21829235964a8e3a09ecd7fea6344b4)
1ebf5d9bcSMike Barcroft /*-
2ebf5d9bcSMike Barcroft  * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3413628a7SBjoern A. Zeeb  * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
4ebf5d9bcSMike Barcroft  * All rights reserved.
5ebf5d9bcSMike Barcroft  *
6ebf5d9bcSMike Barcroft  * Redistribution and use in source and binary forms, with or without
7ebf5d9bcSMike Barcroft  * modification, are permitted provided that the following conditions
8ebf5d9bcSMike Barcroft  * are met:
9ebf5d9bcSMike Barcroft  * 1. Redistributions of source code must retain the above copyright
10ebf5d9bcSMike Barcroft  *    notice, this list of conditions and the following disclaimer.
11ebf5d9bcSMike Barcroft  * 2. Redistributions in binary form must reproduce the above copyright
12ebf5d9bcSMike Barcroft  *    notice, this list of conditions and the following disclaimer in the
13ebf5d9bcSMike Barcroft  *    documentation and/or other materials provided with the distribution.
14ebf5d9bcSMike Barcroft  *
15ebf5d9bcSMike Barcroft  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16ebf5d9bcSMike Barcroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17ebf5d9bcSMike Barcroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ebf5d9bcSMike Barcroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ebf5d9bcSMike Barcroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20ebf5d9bcSMike Barcroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21ebf5d9bcSMike Barcroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ebf5d9bcSMike Barcroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ebf5d9bcSMike Barcroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ebf5d9bcSMike Barcroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ebf5d9bcSMike Barcroft  * SUCH DAMAGE.
26ebf5d9bcSMike Barcroft  *
27ebf5d9bcSMike Barcroft  * $FreeBSD$
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>
3473d0971bSJamie Gritton #include <sys/uio.h>
351f406de7SMichael Reifenberger 
3673d0971bSJamie Gritton #include <arpa/inet.h>
37413628a7SBjoern A. Zeeb #include <netinet/in.h>
38ebf5d9bcSMike Barcroft 
39ebf5d9bcSMike Barcroft #include <err.h>
4070b75adfSXin LI #include <errno.h>
4173d0971bSJamie Gritton #include <limits.h>
4270b75adfSXin LI #include <login_cap.h>
43ebf5d9bcSMike Barcroft #include <stdio.h>
44ebf5d9bcSMike Barcroft #include <stdlib.h>
45413628a7SBjoern A. Zeeb #include <string.h>
4670b75adfSXin LI #include <pwd.h>
47ebf5d9bcSMike Barcroft #include <unistd.h>
48ebf5d9bcSMike Barcroft 
49ebf5d9bcSMike Barcroft static void	usage(void);
50413628a7SBjoern A. Zeeb 
5170b75adfSXin LI #define GET_USER_INFO do {						\
5270b75adfSXin LI 	pwd = getpwnam(username);					\
5370b75adfSXin LI 	if (pwd == NULL) {						\
5470b75adfSXin LI 		if (errno)						\
5570b75adfSXin LI 			err(1, "getpwnam: %s", username);		\
5670b75adfSXin LI 		else							\
5770b75adfSXin LI 			errx(1, "%s: no such user", username);		\
5870b75adfSXin LI 	}								\
5970b75adfSXin LI 	lcap = login_getpwclass(pwd);					\
6070b75adfSXin LI 	if (lcap == NULL)						\
6170b75adfSXin LI 		err(1, "getpwclass: %s", username);			\
6270b75adfSXin LI 	ngroups = NGROUPS;						\
6370b75adfSXin LI 	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
6470b75adfSXin LI 		err(1, "getgrouplist: %s", username);			\
6570b75adfSXin LI } while (0)
6670b75adfSXin LI 
67ebf5d9bcSMike Barcroft int
68ebf5d9bcSMike Barcroft main(int argc, char *argv[])
69ebf5d9bcSMike Barcroft {
7073d0971bSJamie Gritton 	struct iovec params[2];
71ebf5d9bcSMike Barcroft 	int jid;
7270b75adfSXin LI 	login_cap_t *lcap = NULL;
7370b75adfSXin LI 	struct passwd *pwd = NULL;
7470b75adfSXin LI 	gid_t groups[NGROUPS];
75413628a7SBjoern A. Zeeb 	int ch, ngroups, uflag, Uflag;
7673d0971bSJamie Gritton 	char *ep, *username;
77413628a7SBjoern A. Zeeb 	ch = uflag = Uflag = 0;
7873d0971bSJamie Gritton 	username = NULL;
79413628a7SBjoern A. Zeeb 
8073d0971bSJamie Gritton 	while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
8170b75adfSXin LI 		switch (ch) {
82413628a7SBjoern A. Zeeb 		case 'n':
8373d0971bSJamie Gritton 			/* Specified name, now unused */
84413628a7SBjoern A. Zeeb 			break;
8570b75adfSXin LI 		case 'u':
8670b75adfSXin LI 			username = optarg;
8770b75adfSXin LI 			uflag = 1;
8870b75adfSXin LI 			break;
8970b75adfSXin LI 		case 'U':
9070b75adfSXin LI 			username = optarg;
9170b75adfSXin LI 			Uflag = 1;
9270b75adfSXin LI 			break;
9370b75adfSXin LI 		default:
94ebf5d9bcSMike Barcroft 			usage();
9570b75adfSXin LI 		}
9670b75adfSXin LI 	}
9770b75adfSXin LI 	argc -= optind;
9870b75adfSXin LI 	argv += optind;
9970b75adfSXin LI 	if (argc < 2)
10070b75adfSXin LI 		usage();
10170b75adfSXin LI 	if (uflag && Uflag)
10270b75adfSXin LI 		usage();
10370b75adfSXin LI 	if (uflag)
10470b75adfSXin LI 		GET_USER_INFO;
10573d0971bSJamie Gritton 	jid = strtoul(argv[0], &ep, 10);
10673d0971bSJamie Gritton 	if (!*argv[0] || *ep) {
10773d0971bSJamie Gritton 		*(const void **)&params[0].iov_base = "name";
10873d0971bSJamie Gritton 		params[0].iov_len = sizeof("name");
10973d0971bSJamie Gritton 		params[1].iov_base = argv[0];
11073d0971bSJamie Gritton 		params[1].iov_len = strlen(argv[0]) + 1;
11173d0971bSJamie Gritton 		jid = jail_get(params, 2, 0);
11273d0971bSJamie Gritton 		if (jid < 0)
11373d0971bSJamie Gritton 			errx(1, "Unknown jail: %s", argv[0]);
11473d0971bSJamie Gritton 	}
115ebf5d9bcSMike Barcroft 	if (jail_attach(jid) == -1)
116ea119c82SMichael Reifenberger 		err(1, "jail_attach(): %d", jid);
117ebf5d9bcSMike Barcroft 	if (chdir("/") == -1)
118ebf5d9bcSMike Barcroft 		err(1, "chdir(): /");
11970b75adfSXin LI 	if (username != NULL) {
12070b75adfSXin LI 		if (Uflag)
12170b75adfSXin LI 			GET_USER_INFO;
12270b75adfSXin LI 		if (setgroups(ngroups, groups) != 0)
12370b75adfSXin LI 			err(1, "setgroups");
12470b75adfSXin LI 		if (setgid(pwd->pw_gid) != 0)
12570b75adfSXin LI 			err(1, "setgid");
12670b75adfSXin LI 		if (setusercontext(lcap, pwd, pwd->pw_uid,
12770b75adfSXin LI 		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
12870b75adfSXin LI 			err(1, "setusercontext");
12970b75adfSXin LI 		login_close(lcap);
13070b75adfSXin LI 	}
13170b75adfSXin LI 	if (execvp(argv[1], argv + 1) == -1)
13270b75adfSXin LI 		err(1, "execvp(): %s", argv[1]);
133ebf5d9bcSMike Barcroft 	exit(0);
134ebf5d9bcSMike Barcroft }
135ebf5d9bcSMike Barcroft 
136ebf5d9bcSMike Barcroft static void
137ebf5d9bcSMike Barcroft usage(void)
138ebf5d9bcSMike Barcroft {
139ebf5d9bcSMike Barcroft 
14073d0971bSJamie Gritton 	fprintf(stderr, "%s\n",
14173d0971bSJamie Gritton 		"usage: jexec [-u username | -U username] jail command ...");
142ebf5d9bcSMike Barcroft 	exit(1);
143ebf5d9bcSMike Barcroft }
144