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