xref: /freebsd/usr.sbin/jexec/jexec.c (revision 70b75adf82d1fbf19b46c202048c7602c632d9f3)
1ebf5d9bcSMike Barcroft /*-
2ebf5d9bcSMike Barcroft  * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3ebf5d9bcSMike Barcroft  * All rights reserved.
4ebf5d9bcSMike Barcroft  *
5ebf5d9bcSMike Barcroft  * Redistribution and use in source and binary forms, with or without
6ebf5d9bcSMike Barcroft  * modification, are permitted provided that the following conditions
7ebf5d9bcSMike Barcroft  * are met:
8ebf5d9bcSMike Barcroft  * 1. Redistributions of source code must retain the above copyright
9ebf5d9bcSMike Barcroft  *    notice, this list of conditions and the following disclaimer.
10ebf5d9bcSMike Barcroft  * 2. Redistributions in binary form must reproduce the above copyright
11ebf5d9bcSMike Barcroft  *    notice, this list of conditions and the following disclaimer in the
12ebf5d9bcSMike Barcroft  *    documentation and/or other materials provided with the distribution.
13ebf5d9bcSMike Barcroft  *
14ebf5d9bcSMike Barcroft  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15ebf5d9bcSMike Barcroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16ebf5d9bcSMike Barcroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ebf5d9bcSMike Barcroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18ebf5d9bcSMike Barcroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19ebf5d9bcSMike Barcroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20ebf5d9bcSMike Barcroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21ebf5d9bcSMike Barcroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22ebf5d9bcSMike Barcroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23ebf5d9bcSMike Barcroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24ebf5d9bcSMike Barcroft  * SUCH DAMAGE.
25ebf5d9bcSMike Barcroft  *
26ebf5d9bcSMike Barcroft  * $FreeBSD$
27ebf5d9bcSMike Barcroft  */
28ebf5d9bcSMike Barcroft 
29ebf5d9bcSMike Barcroft #include <sys/param.h>
30ebf5d9bcSMike Barcroft #include <sys/jail.h>
31ebf5d9bcSMike Barcroft 
32ebf5d9bcSMike Barcroft #include <err.h>
3370b75adfSXin LI #include <errno.h>
3470b75adfSXin LI #include <login_cap.h>
35ebf5d9bcSMike Barcroft #include <stdio.h>
36ebf5d9bcSMike Barcroft #include <stdlib.h>
3770b75adfSXin LI #include <pwd.h>
38ebf5d9bcSMike Barcroft #include <unistd.h>
39ebf5d9bcSMike Barcroft 
40ebf5d9bcSMike Barcroft static void	usage(void);
41ebf5d9bcSMike Barcroft 
4270b75adfSXin LI #define GET_USER_INFO do {						\
4370b75adfSXin LI 	pwd = getpwnam(username);					\
4470b75adfSXin LI 	if (pwd == NULL) {						\
4570b75adfSXin LI 		if (errno)						\
4670b75adfSXin LI 			err(1, "getpwnam: %s", username);		\
4770b75adfSXin LI 		else							\
4870b75adfSXin LI 			errx(1, "%s: no such user", username);		\
4970b75adfSXin LI 	}								\
5070b75adfSXin LI 	lcap = login_getpwclass(pwd);					\
5170b75adfSXin LI 	if (lcap == NULL)						\
5270b75adfSXin LI 		err(1, "getpwclass: %s", username);			\
5370b75adfSXin LI 	ngroups = NGROUPS;						\
5470b75adfSXin LI 	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
5570b75adfSXin LI 		err(1, "getgrouplist: %s", username);			\
5670b75adfSXin LI } while (0)
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;
6370b75adfSXin LI 	struct passwd *pwd = NULL;
6470b75adfSXin LI 	gid_t groups[NGROUPS];
6570b75adfSXin LI 	int ch, ngroups, uflag, Uflag;
6670b75adfSXin LI 	char *username;
6770b75adfSXin LI 	ch = uflag = Uflag = 0;
6870b75adfSXin LI 	username = NULL;
69ebf5d9bcSMike Barcroft 
7070b75adfSXin LI 	while ((ch = getopt(argc, argv, "u:U:")) != -1) {
7170b75adfSXin LI 		switch (ch) {
7270b75adfSXin LI 		case 'u':
7370b75adfSXin LI 			username = optarg;
7470b75adfSXin LI 			uflag = 1;
7570b75adfSXin LI 			break;
7670b75adfSXin LI 		case 'U':
7770b75adfSXin LI 			username = optarg;
7870b75adfSXin LI 			Uflag = 1;
7970b75adfSXin LI 			break;
8070b75adfSXin LI 		default:
81ebf5d9bcSMike Barcroft 			usage();
8270b75adfSXin LI 		}
8370b75adfSXin LI 	}
8470b75adfSXin LI 	argc -= optind;
8570b75adfSXin LI 	argv += optind;
8670b75adfSXin LI 	if (argc < 2)
8770b75adfSXin LI 		usage();
8870b75adfSXin LI 	if (uflag && Uflag)
8970b75adfSXin LI 		usage();
9070b75adfSXin LI 	if (uflag)
9170b75adfSXin LI 		GET_USER_INFO;
9270b75adfSXin LI 	jid = (int)strtol(argv[0], NULL, 10);
93ebf5d9bcSMike Barcroft 	if (jail_attach(jid) == -1)
94ebf5d9bcSMike Barcroft 		err(1, "jail_attach(): %d", jid);
95ebf5d9bcSMike Barcroft 	if (chdir("/") == -1)
96ebf5d9bcSMike Barcroft 		err(1, "chdir(): /");
9770b75adfSXin LI 	if (username != NULL) {
9870b75adfSXin LI 		if (Uflag)
9970b75adfSXin LI 			GET_USER_INFO;
10070b75adfSXin LI 		if (setgroups(ngroups, groups) != 0)
10170b75adfSXin LI 			err(1, "setgroups");
10270b75adfSXin LI 		if (setgid(pwd->pw_gid) != 0)
10370b75adfSXin LI 			err(1, "setgid");
10470b75adfSXin LI 		if (setusercontext(lcap, pwd, pwd->pw_uid,
10570b75adfSXin LI 		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
10670b75adfSXin LI 			err(1, "setusercontext");
10770b75adfSXin LI 		login_close(lcap);
10870b75adfSXin LI 	}
10970b75adfSXin LI 	if (execvp(argv[1], argv + 1) == -1)
11070b75adfSXin LI 		err(1, "execvp(): %s", argv[1]);
111ebf5d9bcSMike Barcroft 	exit(0);
112ebf5d9bcSMike Barcroft }
113ebf5d9bcSMike Barcroft 
114ebf5d9bcSMike Barcroft static void
115ebf5d9bcSMike Barcroft usage(void)
116ebf5d9bcSMike Barcroft {
117ebf5d9bcSMike Barcroft 
11870b75adfSXin LI 	fprintf(stderr, "%s%s\n",
11970b75adfSXin LI 		"usage: jexec [-u username | -U username]",
12070b75adfSXin LI 		" jid command [...]");
121ebf5d9bcSMike Barcroft 	exit(1);
122ebf5d9bcSMike Barcroft }
123