1 /* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 */ 9 10 #include <sys/cdefs.h> 11 __FBSDID("$FreeBSD$"); 12 13 #include <sys/param.h> 14 #include <sys/jail.h> 15 16 #include <netinet/in.h> 17 #include <arpa/inet.h> 18 19 #include <err.h> 20 #include <errno.h> 21 #include <grp.h> 22 #include <login_cap.h> 23 #include <pwd.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 static void usage(void); 30 31 #define GET_USER_INFO do { \ 32 pwd = getpwnam(username); \ 33 if (pwd == NULL) { \ 34 if (errno) \ 35 err(1, "getpwnam: %s", username); \ 36 else \ 37 errx(1, "%s: no such user", username); \ 38 } \ 39 lcap = login_getpwclass(pwd); \ 40 if (lcap == NULL) \ 41 err(1, "getpwclass: %s", username); \ 42 ngroups = NGROUPS; \ 43 if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ 44 err(1, "getgrouplist: %s", username); \ 45 } while (0) 46 47 int 48 main(int argc, char **argv) 49 { 50 login_cap_t *lcap; 51 struct jail j; 52 struct passwd *pwd; 53 struct in_addr in; 54 int ch, groups[NGROUPS], i, iflag, ngroups, uflag, Uflag; 55 char path[PATH_MAX], *username; 56 57 iflag = uflag = Uflag = 0; 58 username = NULL; 59 60 while ((ch = getopt(argc, argv, "iu:U:")) != -1) { 61 switch (ch) { 62 case 'i': 63 iflag = 1; 64 break; 65 case 'u': 66 username = optarg; 67 uflag = 1; 68 break; 69 case 'U': 70 username = optarg; 71 Uflag = 1; 72 break; 73 default: 74 usage(); 75 } 76 } 77 argc -= optind; 78 argv += optind; 79 if (argc < 4) 80 usage(); 81 if (uflag && Uflag) 82 usage(); 83 if (uflag) 84 GET_USER_INFO; 85 if (realpath(argv[0], path) == NULL) 86 err(1, "realpath: %s", argv[0]); 87 if (chdir(path) != 0) 88 err(1, "chdir: %s", path); 89 memset(&j, 0, sizeof(j)); 90 j.version = 0; 91 j.path = path; 92 j.hostname = argv[1]; 93 if (inet_aton(argv[2], &in) == 0) 94 errx(1, "Could not make sense of ip-number: %s", argv[2]); 95 j.ip_number = ntohl(in.s_addr); 96 i = jail(&j); 97 if (i == -1) 98 err(1, "jail"); 99 if (iflag) { 100 printf("%d\n", i); 101 fflush(stdout); 102 } 103 if (username != NULL) { 104 if (Uflag) 105 GET_USER_INFO; 106 if (setgroups(ngroups, groups) != 0) 107 err(1, "setgroups"); 108 if (setgid(pwd->pw_gid) != 0) 109 err(1, "setgid"); 110 if (setusercontext(lcap, pwd, pwd->pw_uid, 111 LOGIN_SETALL & ~LOGIN_SETGROUP) != 0) 112 err(1, "setusercontext"); 113 login_close(lcap); 114 } 115 if (execv(argv[3], argv + 3) != 0) 116 err(1, "execv: %s", argv[3]); 117 exit(0); 118 } 119 120 static void 121 usage(void) 122 { 123 124 (void)fprintf(stderr, "%s%s\n", 125 "usage: jail [-i] [-u username | -U username]", 126 " path hostname ip-number command ..."); 127 exit(1); 128 } 129