Beispiel #1
0
int
main(int argc, char **argv)
{
	struct jailparam params[MAXPARAMS];
	char ifname[IFNAMSIZ];
	struct ifreq ifreq;
	vi_cmd_t newcmd, cmd;
	int recurse = 0;
	int verbose = 0;
	int jid, i, s, namelen;
	int vst_size, vst_last;
	vstat_t *vst;
	char *str;
	char ch;

	invocname = argv[0];

	newcmd = cmd = VI_SWITCHTO; /* Default if no modifiers specified. */
	while ((ch = getopt(argc, argv, "cdijlmrv")) != -1) {
		switch (ch) {
		case 'c':
			newcmd = VI_CREATE;
			break;
		case 'm':
			newcmd = VI_MODIFY;
			break;
		case 'd':
			newcmd = VI_DESTROY;
			break;
		case 'l':
			newcmd = VI_GET;
			break;
		case 'i':
			newcmd = VI_IFMOVE;
			break;
		case 'r':
			recurse = 1;
			break;
		case 'v':
			verbose++;
			break;
		case 'j':
			verbose = 2;
			break;
		default:
			usage();
		}
		if (cmd == VI_SWITCHTO || cmd == newcmd)
			cmd = newcmd;
		else
			usage();
	}
	argc -= optind;
	argv += optind;

	if ((cmd != VI_GET && (argc == 0 || recurse != 0 || verbose != 0)) ||
	    (cmd == VI_IFMOVE && (argc < 2 || argc > 3)) ||
	    (cmd == VI_MODIFY && argc < 2) || argc >= MAXPARAMS)
		usage();

	switch (cmd) {
	case VI_GET:
		vst_last = 0;
		vst_size = VST_SIZE_STEP;
		if ((vst = malloc(vst_size * sizeof(*vst))) == NULL)
			break;
		if (argc == 1)
			namelen = strlen(argv[0]);
		else
			namelen = 0;
		jid = 0;
		while ((jid = getjail(&vst[vst_last], jid, verbose)) > 0) {
			/* Skip jails which do not own vnets. */
			if (vst[vst_last].vnet != 1)
				continue;
			/* Skip non-matching vnames / hierarchies. */
			if (namelen &&
			    ((strlen(vst[vst_last].name) < namelen ||
			    strncmp(vst[vst_last].name, argv[0], namelen) != 0)
			    || (strlen(vst[vst_last].name) > namelen &&
			    vst[vst_last].name[namelen] != '.')))
				continue;
			/* Skip any sub-trees if -r not requested. */
			if (!recurse &&
			    (strlen(vst[vst_last].name) < namelen ||
			    strchr(&vst[vst_last].name[namelen], '.') != NULL))
				continue;
			/* Grow vst table if necessary. */
			if (++vst_last == vst_size) {
				vst_size += VST_SIZE_STEP;
				vst = realloc(vst, vst_size * sizeof(*vst));
				if (vst == NULL)
					break;
			}
		}
		if (vst == NULL)
			break;
		/* Sort: the key is the 1st field in *vst, i.e. vimage name. */
		qsort(vst, vst_last, sizeof(*vst), (void *) strcmp);
		for (i = 0; i < vst_last; i++) {
			if (!verbose) {
				printf("%s\n", vst[i].name);
				continue;
			}

			printf("%s:\n", vst[i].name);
			printf("    Path: %s\n", vst[i].path);
			printf("    Hostname: %s\n", vst[i].hostname);
			printf("    Domainname: %s\n", vst[i].domainname);
			printf("    Children: %d\n", vst[i].childcnt);

			if (verbose < 2)
				continue;

			printf("    Children limit: %d\n", vst[i].childmax);
			printf("    CPUsetID: %d\n", vst[i].cpuset);
			printf("    JID: %d\n", vst[i].jid);
			printf("    PJID: %d\n", vst[i].parentjid);
			printf("    Raw sockets allowed: %d\n", vst[i].rawsock);
			printf("    All AF allowed: %d\n", vst[i].socket_af);
			printf("    Mount allowed: %d\n", vst[i].mount);
		}
		free(vst);
		exit(0);

	case VI_IFMOVE:
		if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
			break;
		if ((jid = jail_getid(argv[0])) < 0)
			break;
		ifreq.ifr_jid = jid;
		strncpy(ifreq.ifr_name, argv[1], sizeof(ifreq.ifr_name));
		if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0)
			break;
		close(s);
		if (argc == 3)
			snprintf(ifname, sizeof(ifname), "%s", argv[2]);
		else
			snprintf(ifname, sizeof(ifname), "eth0");
		ifreq.ifr_data = ifname;
		/* Do we need to rename the ifnet? */
		if (strcmp(ifreq.ifr_name, ifname) != 0) {
			/* Switch to the context of the target vimage. */
			if (jail_attach(jid) < 0)
				break;
			if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
				break;
			for (namelen = 0; isalpha(ifname[namelen]); namelen++);
			i = 0;
			/* Search for a free ifunit in target vnet.  Unsafe. */
			while (ioctl(s, SIOCSIFNAME, (caddr_t)&ifreq) < 0) {
				snprintf(&ifname[namelen],
				    sizeof(ifname) - namelen, "%d", i);
				/* Emergency brake. */
				if (i++ == IF_MAXUNIT)
					break;
			}
		}
		if (i < IF_MAXUNIT)
			printf("%s@%s\n", ifname, argv[0]);
		else
			printf("%s@%s\n", ifreq.ifr_name, argv[0]);
		exit(0);

	case VI_CREATE:
		if (jail_setv(JAIL_CREATE,
		    "name", argv[0],
		    "vnet", NULL,
		    "host", NULL,
		    "persist", NULL,
		    "allow.raw_sockets", "true",
		    "allow.socket_af", "true",
		    "allow.mount", "true",
		    NULL) < 0)
			break;
		if (argc == 1)
			exit(0);
		/* Not done yet, proceed to apply non-default parameters. */

	case VI_MODIFY:
		jailparam_init(&params[0], "name");
		jailparam_import(&params[0], argv[0]);
		for (i = 1; i < argc; i++) {
			for (str = argv[i]; *str != '=' && *str != 0; str++) {
				/* Do nothing - search for '=' delimeter. */
			}
			if (*str == 0)
				break;
			*str++ = 0;
			if (*str == 0)
				break;
			jailparam_init(&params[i], argv[i]);
			jailparam_import(&params[i], str);
		}
		if (i != argc)
			break;
		if (jailparam_set(params, i, JAIL_UPDATE) < 0)
			break;
		exit(0);

	case VI_DESTROY:
		if ((jid = jail_getid(argv[0])) < 0)
			break;
		if (jail_remove(jid) < 0)
			break;
		exit(0);

	case VI_SWITCHTO:
		if ((jid = jail_getid(argv[0])) < 0)
			break;
		if (jail_attach(jid) < 0)
			break;
		if (argc == 1) {
			printf("Switched to vimage %s\n", argv[0]);
			if ((str = getenv("SHELL")) == NULL)
				execlp("/bin/sh", invocname, NULL);
			else
				execlp(str, invocname, NULL);
		} else 
			execvp(argv[1], &argv[1]);
		break;

	default:
		/* Should be unreachable. */
		break;
	}

	if (jail_errmsg[0])
		fprintf(stderr, "Error: %s\n", jail_errmsg);
	else
		perror("Error");
	exit(1);
}
Beispiel #2
0
int
main(int argc, char **argv)
{
	login_cap_t *lcap = NULL;
	struct passwd *pwd = NULL;
	gid_t *groups;
	size_t sysvallen;
	int ch, cmdarg, i, jail_set_flags, jid, ngroups, sysval;
	int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag;
	long ngroups_max;
	unsigned pi;
	char *jailname, *securelevel, *username, *JidFile;
	char enforce_statfs[4];
	static char *cleanenv;
	const char *shell, *p = NULL;
	FILE *fp;

	hflag = iflag = Jflag = lflag = rflag = uflag = Uflag =
	    jail_set_flags = 0;
	cmdarg = jid = -1;
	jailname = securelevel = username = JidFile = cleanenv = NULL;
	fp = NULL;

	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;	
	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
		err(1, "malloc");

	while ((ch = getopt(argc, argv, "cdhilmn:r:s:u:U:J:")) != -1) {
		switch (ch) {
		case 'd':
			jail_set_flags |= JAIL_DYING;
			break;
		case 'h':
			hflag = 1;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'J':
			JidFile = optarg;
			Jflag = 1;
			break;
		case 'n':
			jailname = optarg;
			break;
		case 's':
			securelevel = optarg;
			break;
		case 'u':
			username = optarg;
			uflag = 1;
			break;
		case 'U':
			username = optarg;
			Uflag = 1;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'c':
			jail_set_flags |= JAIL_CREATE;
			break;
		case 'm':
			jail_set_flags |= JAIL_UPDATE;
			break;
		case 'r':
			jid = jail_getid(optarg);
			if (jid < 0)
				errx(1, "%s", jail_errmsg);
			rflag = 1;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (rflag) {
		if (argc > 0 || iflag || Jflag || lflag || uflag || Uflag)
			usage();
		if (jail_remove(jid) < 0)
			err(1, "jail_remove");
		exit (0);
	}
	if (argc == 0)
		usage();
	if (uflag && Uflag)
		usage();
	if (lflag && username == NULL)
		usage();
	if (uflag)
		GET_USER_INFO;

#ifdef INET6
	ip6_ok = feature_present("inet6");
#endif
#ifdef INET
	ip4_ok = feature_present("inet");
#endif

	if (jailname)
		set_param("name", jailname);
	if (securelevel)
		set_param("securelevel", securelevel);
	if (jail_set_flags) {
		for (i = 0; i < argc; i++) {
			if (!strncmp(argv[i], "command=", 8)) {
				cmdarg = i;
				argv[cmdarg] += 8;
				jail_set_flags |= JAIL_ATTACH;
				break;
			}
			if (hflag) {
#ifdef INET
				if (!strncmp(argv[i], "ip4.addr=", 9)) {
					add_ip_addr(&ip4_addr, argv[i] + 9);
					break;
				}
#endif
#ifdef INET6
				if (!strncmp(argv[i], "ip6.addr=", 9)) {
					add_ip_addr(&ip6_addr, argv[i] + 9);
					break;
				}
#endif
				if (!strncmp(argv[i], "host.hostname=", 14))
					add_ip_addrinfo(0, argv[i] + 14);
			}
			set_param(NULL, argv[i]);
		}
	} else {
		if (argc < 4 || argv[0][0] != '/')
			errx(1, "%s\n%s",
			   "no -c or -m, so this must be an old-style command.",
			   "But it doesn't look like one.");
		set_param("path", argv[0]);
		set_param("host.hostname", argv[1]);
		if (hflag)
			add_ip_addrinfo(0, argv[1]);
#if defined(INET6) || defined(INET)
		if (argv[2][0] != '\0')
#ifdef INET6
			add_ip_addr46(argv[2]);
#else
			add_ip_addr(&ip4_addr, argv[2]);
#endif
#endif
		cmdarg = 3;
		/* Emulate the defaults from security.jail.* sysctls */
		sysvallen = sizeof(sysval);
		if (sysctlbyname("security.jail.jailed", &sysval, &sysvallen,
		    NULL, 0) == 0 && sysval == 0) {
			for (pi = 0; pi < sizeof(perm_sysctl) /
			     sizeof(perm_sysctl[0]); pi++) {
				sysvallen = sizeof(sysval);
				if (sysctlbyname(perm_sysctl[pi][0],
				    &sysval, &sysvallen, NULL, 0) == 0)
					set_param(perm_sysctl[pi]
					    [sysval ? 2 : 1], NULL);
			}
			sysvallen = sizeof(sysval);
			if (sysctlbyname("security.jail.enforce_statfs",
			    &sysval, &sysvallen, NULL, 0) == 0) {
				snprintf(enforce_statfs,
				    sizeof(enforce_statfs), "%d", sysval);
				set_param("enforce_statfs", enforce_statfs);
			}
		}
	}
#ifdef INET
	if (ip4_addr != NULL)
		set_param("ip4.addr", ip4_addr);
#endif
#ifdef INET6
	if (ip6_addr != NULL)
		set_param("ip6.addr", ip6_addr);
#endif

	if (Jflag) {
		fp = fopen(JidFile, "w");
		if (fp == NULL)
			errx(1, "Could not create JidFile: %s", JidFile);
	}
	jid = jailparam_set(params, nparams, 
	    jail_set_flags ? jail_set_flags : JAIL_CREATE | JAIL_ATTACH);
	if (jid < 0)
		errx(1, "%s", jail_errmsg);
	if (iflag) {
		printf("%d\n", jid);
		fflush(stdout);
	}
	if (Jflag) {
		if (jail_set_flags) {
			fprintf(fp, "jid=%d", jid);
			for (i = 0; i < nparams; i++)
				if (strcmp(params[i].jp_name, "jid")) {
					fprintf(fp, " %s",
					    (char *)params[i].jp_name);
					if (param_values[i]) {
						putc('=', fp);
						quoted_print(fp,
						    param_values[i]);
					}
				}
			fprintf(fp, "\n");
		} else {
			for (i = 0; i < nparams; i++)
				if (!strcmp(params[i].jp_name, "path"))
					break;
#if defined(INET6) && defined(INET)
			fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n",
			    jid, i < nparams
			    ? (char *)params[i].jp_value : argv[0],
			    argv[1], ip4_addr ? ip4_addr : "",
			    ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0]
			    ? "," : "", ip6_addr ? ip6_addr : "", argv[3]);
#elif defined(INET6)
			fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
			    jid, i < nparams
			    ?  (char *)params[i].jp_value : argv[0],
			    argv[1], ip6_addr ? ip6_addr : "", argv[3]);
#elif defined(INET)
			fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
			    jid, i < nparams
			    ? (char *)params[i].jp_value : argv[0],
			    argv[1], ip4_addr ? ip4_addr : "", argv[3]);
#endif
		}
		(void)fclose(fp);
	}
	if (cmdarg < 0)
		exit(0);
	if (username != NULL) {
		if (Uflag)
			GET_USER_INFO;
		if (lflag) {
			p = getenv("TERM");
			environ = &cleanenv;
		}
		if (setgroups(ngroups, groups) != 0)
			err(1, "setgroups");
		if (setgid(pwd->pw_gid) != 0)
			err(1, "setgid");
		if (setusercontext(lcap, pwd, pwd->pw_uid,
		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
			err(1, "setusercontext");
		login_close(lcap);
	}
	if (lflag) {
		if (*pwd->pw_shell)
			shell = pwd->pw_shell;
		else
			shell = _PATH_BSHELL;
		if (chdir(pwd->pw_dir) < 0)
			errx(1, "no home directory");
		setenv("HOME", pwd->pw_dir, 1);
		setenv("SHELL", shell, 1);
		setenv("USER", pwd->pw_name, 1);
		if (p)
			setenv("TERM", p, 1);
	}
	execvp(argv[cmdarg], argv + cmdarg);
	err(1, "execvp: %s", argv[cmdarg]);
}