xref: /freebsd/usr.sbin/jail/jail.c (revision 927b4810012d83955d93d49fdd282646a782a2b9)
1ce5c1cd1SPoul-Henning Kamp /*
2ce5c1cd1SPoul-Henning Kamp  * ----------------------------------------------------------------------------
3ce5c1cd1SPoul-Henning Kamp  * "THE BEER-WARE LICENSE" (Revision 42):
4ce5c1cd1SPoul-Henning Kamp  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5ce5c1cd1SPoul-Henning Kamp  * can do whatever you want with this stuff. If we meet some day, and you think
6ce5c1cd1SPoul-Henning Kamp  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7ce5c1cd1SPoul-Henning Kamp  * ----------------------------------------------------------------------------
8ce5c1cd1SPoul-Henning Kamp  */
9ce5c1cd1SPoul-Henning Kamp 
1054ede02dSPhilippe Charnier #include <sys/cdefs.h>
1154ede02dSPhilippe Charnier __FBSDID("$FreeBSD$");
1254ede02dSPhilippe Charnier 
13d6131f4bSMaxim Konovalov #include <sys/param.h>
143876038aSDima Dorfman #include <sys/jail.h>
153876038aSDima Dorfman 
163876038aSDima Dorfman #include <netinet/in.h>
173876038aSDima Dorfman #include <arpa/inet.h>
183876038aSDima Dorfman 
193876038aSDima Dorfman #include <err.h>
20927b4810SMaxim Konovalov #include <errno.h>
21d6131f4bSMaxim Konovalov #include <grp.h>
22d6131f4bSMaxim Konovalov #include <login_cap.h>
23d6131f4bSMaxim Konovalov #include <pwd.h>
2475c13541SPoul-Henning Kamp #include <stdio.h>
252694efd4SDima Dorfman #include <stdlib.h>
262694efd4SDima Dorfman #include <string.h>
273876038aSDima Dorfman #include <unistd.h>
2875c13541SPoul-Henning Kamp 
29d6131f4bSMaxim Konovalov static void	usage(void);
30d6131f4bSMaxim Konovalov 
31927b4810SMaxim Konovalov #define GET_USER_INFO do {						\
32927b4810SMaxim Konovalov 	pwd = getpwnam(username);					\
33927b4810SMaxim Konovalov 	if (pwd == NULL) {						\
34927b4810SMaxim Konovalov 		if (errno)						\
35927b4810SMaxim Konovalov 			err(1, "getpwnam: %s", username);		\
36927b4810SMaxim Konovalov 		else							\
37927b4810SMaxim Konovalov 			errx(1, "%s: no such user", username);		\
38927b4810SMaxim Konovalov 	}								\
39927b4810SMaxim Konovalov 	lcap = login_getpwclass(pwd);					\
40927b4810SMaxim Konovalov 	if (lcap == NULL)						\
41927b4810SMaxim Konovalov 		err(1, "getpwclass: %s", username);			\
42927b4810SMaxim Konovalov 	ngroups = NGROUPS;						\
43927b4810SMaxim Konovalov 	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
44927b4810SMaxim Konovalov 		err(1, "getgrouplist: %s", username);			\
45927b4810SMaxim Konovalov } while (0)
46927b4810SMaxim Konovalov 
4775c13541SPoul-Henning Kamp int
4875c13541SPoul-Henning Kamp main(int argc, char **argv)
4975c13541SPoul-Henning Kamp {
50d6131f4bSMaxim Konovalov 	login_cap_t *lcap;
5175c13541SPoul-Henning Kamp 	struct jail j;
52d6131f4bSMaxim Konovalov 	struct passwd *pwd;
5375c13541SPoul-Henning Kamp 	struct in_addr in;
54927b4810SMaxim Konovalov 	int ch, groups[NGROUPS], i, iflag, ngroups, uflag, Uflag;
55d6131f4bSMaxim Konovalov 	char *username;
5675c13541SPoul-Henning Kamp 
57927b4810SMaxim Konovalov 	iflag = uflag = Uflag = 0;
58d6131f4bSMaxim Konovalov 	username = NULL;
59d6131f4bSMaxim Konovalov 
60927b4810SMaxim Konovalov 	while ((ch = getopt(argc, argv, "iu:U:")) != -1) {
61d6131f4bSMaxim Konovalov 		switch (ch) {
62ebf5d9bcSMike Barcroft 		case 'i':
63ebf5d9bcSMike Barcroft 			iflag = 1;
64ebf5d9bcSMike Barcroft 			break;
65d6131f4bSMaxim Konovalov 		case 'u':
66d6131f4bSMaxim Konovalov 			username = optarg;
67927b4810SMaxim Konovalov 			uflag = 1;
68927b4810SMaxim Konovalov 			break;
69927b4810SMaxim Konovalov 		case 'U':
70927b4810SMaxim Konovalov 			username = optarg;
71927b4810SMaxim Konovalov 			Uflag = 1;
72d6131f4bSMaxim Konovalov 			break;
73d6131f4bSMaxim Konovalov 		default:
74d6131f4bSMaxim Konovalov 			usage();
75ebf5d9bcSMike Barcroft 		}
76d6131f4bSMaxim Konovalov 	}
77d6131f4bSMaxim Konovalov 	argc -= optind;
78d6131f4bSMaxim Konovalov 	argv += optind;
79d6131f4bSMaxim Konovalov 	if (argc < 4)
80d6131f4bSMaxim Konovalov 		usage();
81927b4810SMaxim Konovalov 	if (uflag && Uflag)
82927b4810SMaxim Konovalov 		usage();
83927b4810SMaxim Konovalov 	if (uflag)
84927b4810SMaxim Konovalov 		GET_USER_INFO;
85b026ec0eSMaxim Konovalov 	if (chdir(argv[0]) != 0)
86b026ec0eSMaxim Konovalov 		err(1, "chdir: %s", argv[0]);
877248ef86SPoul-Henning Kamp 	memset(&j, 0, sizeof(j));
887248ef86SPoul-Henning Kamp 	j.version = 0;
89d6131f4bSMaxim Konovalov 	j.path = argv[0];
90d6131f4bSMaxim Konovalov 	j.hostname = argv[1];
91b026ec0eSMaxim Konovalov 	if (inet_aton(argv[2], &in) == 0)
92b026ec0eSMaxim Konovalov 		errx(1, "Could not make sense of ip-number: %s", argv[2]);
93ce5c1cd1SPoul-Henning Kamp 	j.ip_number = ntohl(in.s_addr);
94ebf5d9bcSMike Barcroft 	i = jail(&j);
95ebf5d9bcSMike Barcroft 	if (i == -1)
96b026ec0eSMaxim Konovalov 		err(1, "jail");
9725639ca7SMike Barcroft 	if (iflag) {
98ebf5d9bcSMike Barcroft 		printf("%d\n", i);
9925639ca7SMike Barcroft 		fflush(stdout);
10025639ca7SMike Barcroft 	}
101d6131f4bSMaxim Konovalov 	if (username != NULL) {
102927b4810SMaxim Konovalov 		if (Uflag)
103927b4810SMaxim Konovalov 			GET_USER_INFO;
104b026ec0eSMaxim Konovalov 		if (setgroups(ngroups, groups) != 0)
105b026ec0eSMaxim Konovalov 			err(1, "setgroups");
106b026ec0eSMaxim Konovalov 		if (setgid(pwd->pw_gid) != 0)
107b026ec0eSMaxim Konovalov 			err(1, "setgid");
108b026ec0eSMaxim Konovalov 		if (setusercontext(lcap, pwd, pwd->pw_uid,
109b026ec0eSMaxim Konovalov 		    LOGIN_SETALL & ~LOGIN_SETGROUP) != 0)
110b026ec0eSMaxim Konovalov 			err(1, "setusercontext");
1110389572fSMaxim Konovalov 		login_close(lcap);
112d6131f4bSMaxim Konovalov 	}
113b026ec0eSMaxim Konovalov 	if (execv(argv[3], argv + 3) != 0)
114b026ec0eSMaxim Konovalov 		err(1, "execv: %s", argv[3]);
11575c13541SPoul-Henning Kamp 	exit(0);
11675c13541SPoul-Henning Kamp }
117d6131f4bSMaxim Konovalov 
118d6131f4bSMaxim Konovalov static void
119d6131f4bSMaxim Konovalov usage(void)
120d6131f4bSMaxim Konovalov {
121d6131f4bSMaxim Konovalov 
122927b4810SMaxim Konovalov 	(void)fprintf(stderr, "%s%s\n",
123927b4810SMaxim Konovalov 	     "usage: jail [-i] [-u username | -U username]",
124927b4810SMaxim Konovalov 	     " path hostname ip-number command ...");
125b026ec0eSMaxim Konovalov 	exit(1);
126d6131f4bSMaxim Konovalov }
127