xref: /freebsd/usr.sbin/jexec/jexec.c (revision de6f37045c093865da6d233be60dbc3db241f383)
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>
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>
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);			\
6254404cfbSBrooks Davis 	ngroups = ngroups_max;						\
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 {
70ebf5d9bcSMike Barcroft 	int jid;
7170b75adfSXin LI 	login_cap_t *lcap = NULL;
7270b75adfSXin LI 	struct passwd *pwd = NULL;
7354404cfbSBrooks Davis 	gid_t *groups = NULL;
74413628a7SBjoern A. Zeeb 	int ch, ngroups, uflag, Uflag;
7554404cfbSBrooks Davis 	long ngroups_max;
76de6f3704SJamie Gritton 	char *username;
775b4a0a4fSJamie Gritton 
78413628a7SBjoern A. Zeeb 	ch = uflag = Uflag = 0;
7973d0971bSJamie Gritton 	username = NULL;
8054404cfbSBrooks Davis 	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
8154404cfbSBrooks Davis 	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
8254404cfbSBrooks Davis 		err(1, "malloc");
8354404cfbSBrooks Davis 
8473d0971bSJamie Gritton 	while ((ch = getopt(argc, argv, "nu:U:")) != -1) {
8570b75adfSXin LI 		switch (ch) {
86413628a7SBjoern A. Zeeb 		case 'n':
8773d0971bSJamie Gritton 			/* Specified name, now unused */
88413628a7SBjoern A. Zeeb 			break;
8970b75adfSXin LI 		case 'u':
9070b75adfSXin LI 			username = optarg;
9170b75adfSXin LI 			uflag = 1;
9270b75adfSXin LI 			break;
9370b75adfSXin LI 		case 'U':
9470b75adfSXin LI 			username = optarg;
9570b75adfSXin LI 			Uflag = 1;
9670b75adfSXin LI 			break;
9770b75adfSXin LI 		default:
98ebf5d9bcSMike Barcroft 			usage();
9970b75adfSXin LI 		}
10070b75adfSXin LI 	}
10170b75adfSXin LI 	argc -= optind;
10270b75adfSXin LI 	argv += optind;
10370b75adfSXin LI 	if (argc < 2)
10470b75adfSXin LI 		usage();
10570b75adfSXin LI 	if (uflag && Uflag)
10670b75adfSXin LI 		usage();
10770b75adfSXin LI 	if (uflag)
10870b75adfSXin LI 		GET_USER_INFO;
109de6f3704SJamie Gritton 	jid = jail_getid(argv[0]);
11073d0971bSJamie Gritton 	if (jid < 0)
111de6f3704SJamie Gritton 		errx(1, "%s", jail_errmsg);
112ebf5d9bcSMike Barcroft 	if (jail_attach(jid) == -1)
113de6f3704SJamie Gritton 		err(1, "jail_attach(%d)", jid);
114ebf5d9bcSMike Barcroft 	if (chdir("/") == -1)
115ebf5d9bcSMike Barcroft 		err(1, "chdir(): /");
11670b75adfSXin LI 	if (username != NULL) {
11770b75adfSXin LI 		if (Uflag)
11870b75adfSXin LI 			GET_USER_INFO;
11970b75adfSXin LI 		if (setgroups(ngroups, groups) != 0)
12070b75adfSXin LI 			err(1, "setgroups");
12170b75adfSXin LI 		if (setgid(pwd->pw_gid) != 0)
12270b75adfSXin LI 			err(1, "setgid");
12370b75adfSXin LI 		if (setusercontext(lcap, pwd, pwd->pw_uid,
12470b75adfSXin LI 		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
12570b75adfSXin LI 			err(1, "setusercontext");
12670b75adfSXin LI 		login_close(lcap);
12770b75adfSXin LI 	}
12870b75adfSXin LI 	if (execvp(argv[1], argv + 1) == -1)
12970b75adfSXin LI 		err(1, "execvp(): %s", argv[1]);
130ebf5d9bcSMike Barcroft 	exit(0);
131ebf5d9bcSMike Barcroft }
132ebf5d9bcSMike Barcroft 
133ebf5d9bcSMike Barcroft static void
134ebf5d9bcSMike Barcroft usage(void)
135ebf5d9bcSMike Barcroft {
136ebf5d9bcSMike Barcroft 
13773d0971bSJamie Gritton 	fprintf(stderr, "%s\n",
13873d0971bSJamie Gritton 		"usage: jexec [-u username | -U username] jail command ...");
139ebf5d9bcSMike Barcroft 	exit(1);
140ebf5d9bcSMike Barcroft }
141