Пример #1
0
static void
natvDumpRulesHelper(
	PLIST_ENTRY pRuleHead,
	NDIS_SPIN_LOCK	*pRuleLock
	)
{
	FLT_RULE *pRule;
	PLIST_ENTRY pRuleEntry;
	char pubIpAddrStr[30];
	char prvIpAddrStr[30];
	char pubMaskStr[30];
	char prvMaskStr[30];

	NdisAcquireSpinLock(pRuleLock);

	for(pRuleEntry = pRuleHead->Flink; pRuleEntry != pRuleHead; pRuleEntry = pRuleEntry->Flink ){

		pRule = CONTAINING_RECORD(pRuleEntry, FLT_RULE, ListEntry);

		PRINT_IP(pubIpAddrStr, &pRule->pubAddr);
		PRINT_IP(pubMaskStr, &pRule->pubMask);

		PRINT_IP(prvIpAddrStr, &pRule->prvAddr);
		PRINT_IP(prvMaskStr, &pRule->prvMask);

		DbgPrint("%s RULE: ALLOW PUB=%s/%s PRV=%s/%s DST PORT=%u\n",
			pRule->out ? "OUTGOING" : "INCOMING",
			pubIpAddrStr,pubMaskStr,
			prvIpAddrStr,prvMaskStr,
			RtlUshortByteSwap(pRule->port));
	}

	NdisReleaseSpinLock(pRuleLock);

}
Пример #2
0
// configure bridge structure
// - extract ip address and mask from the bridge interface
void net_configure_bridge(Bridge *br, char *dev_name) {
	assert(br);
	assert(dev_name);

	br->dev = dev_name;

	// check the bridge device exists
	char sysbridge[30 + strlen(br->dev)];
	sprintf(sysbridge, "/sys/class/net/%s/bridge", br->dev);
	struct stat s;
	int rv = stat(sysbridge, &s);
	if (rv == 0) {
		// this is a bridge device
		br->macvlan = 0;
	}
	else {
		// is this a regular Ethernet interface
		if (if_nametoindex(br->dev) > 0) {
			br->macvlan = 1;
			char *newname;
			if (asprintf(&newname, "%s-%u", br->devsandbox, getpid()) == -1)
				errExit("asprintf");
			br->devsandbox = newname;
		}			
		else {
			fprintf(stderr, "Error: cannot find network device %s\n", br->dev);
			exit(1);
		}
	}

	// allow unconfigured interfaces
	if (net_get_if_addr(br->dev, &br->ip, &br->mask, br->mac, &br->mtu)) {
		fprintf(stderr, "Warning: the network interface %s is not configured\n", br->dev);
		br->configured = 1;
		br->arg_ip_none = 1;
		return;
	}
	if (arg_debug) {
		if (br->macvlan == 0)
			printf("Bridge device %s at %d.%d.%d.%d/%d\n",
				br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
		else
			printf("macvlan parent device %s at %d.%d.%d.%d/%d\n",
				br->dev, PRINT_IP(br->ip), mask2bits(br->mask));
	}
	
	uint32_t range = ~br->mask + 1;		  // the number of potential addresses
	// this software is not supported for /31 networks
	if (range < 4) {
		fprintf(stderr, "Error: the software is not supported for /31 networks\n");
		exit(1);
	}
	br->configured = 1;
}
Пример #3
0
static void print_arp(const char *fname) {
	FILE *fp = fopen(fname, "r");
	if (!fp)
		return;
	
	printf("  ARP Table:\n");
	char buf[MAXBUF];
	while (fgets(buf, MAXBUF, fp)) {
		// remove blanks, \n
		char *ptr = buf;
		while (*ptr == ' ' || *ptr == '\t')
			ptr++;
		char *start = ptr;
		if (*start == '\0')
			continue;
		ptr = strchr(ptr, '\n');
		if (ptr)
			*ptr = '\0';

		// remove table header
		//IP address       HW type     Flags       HW address            Mask     Device
		if (strncmp(start, "IP address", 10) == 0)
			continue;

		// extract data
		char ip[64];
		char type[64];
		char flags[64];
		char mac[64];
		char mask[64];
		char device[64];
		int rv = sscanf(start, "%s %s %s %s %s %s\n", ip, type, flags, mac, mask, device);
		if (rv != 6)
			continue;
		
		// destination ip
		unsigned a, b, c, d;
		if (sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d) != 4 || a > 255 || b > 255 || c > 255 || d > 255)
			continue;
		uint32_t destip = a * 0x1000000 + b * 0x10000 + c * 0x100 + d;
		if (strcmp(flags, "0x0") == 0)
			printf("     %d.%d.%d.%d dev %s FAILED\n",
				PRINT_IP(destip), device);
		else
			printf("     %d.%d.%d.%d dev %s lladdr %s REACHABLE\n",
				PRINT_IP(destip), device, mac);
	}
	
	fclose(fp);

}
Пример #4
0
// assign a random IP address and check it
// the address needs to be in the range if it --iprange was specified
static uint32_t arp_random(const char *dev, Bridge *br) {
    assert(dev);
    assert(br);
    uint32_t ifip = br->ip;
    uint32_t ifmask = br->mask;
    assert(ifip);
    assert(ifmask);

    if (arg_debug)
        printf("ARP-scan %s, %d.%d.%d.%d/%d\n",
               dev, PRINT_IP(ifip), mask2bits(ifmask));

    // determine the range based on network address
    uint32_t range = ~ifmask + 1; // the number of potential addresses
    // this software is not supported for /31 networks
    if (range < 4)
        return 0; // the user will have to set the IP address manually
    range -= 2; // subtract the network address and the broadcast address
    uint32_t start = (ifip & ifmask) + 1;

    // adjust range based on --iprange params
    if (br->iprange_start && br->iprange_end) {
        start = br->iprange_start;
        range = br->iprange_end - br->iprange_start;
    }

    if (arg_debug)
        printf("IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
               PRINT_IP(start), PRINT_IP(start + range));

    // generate a random address - 10 tries
    uint32_t dest = 0;
    int i = 0;
    for (i = 0; i < 10; i++) {
        dest = start + ((uint32_t) rand()) % range;
        if (dest == ifip)	// do not allow the interface address
            continue;		// try again

        // if we've made it up to here, we have a valid address
        break;
    }
    if (i == 10)	// we failed 10 times
        return 0;

    // check address
    uint32_t rv = arp_check(dev, dest, ifip);
    if (!rv)
        return dest;
    return 0;
}
Пример #5
0
static void sandbox_if_up(Bridge *br) {
	assert(br);
	if (!br->configured)
		return;
		
	char *dev = br->devsandbox;
	net_if_up(dev);

	if (br->arg_ip_none == 1);	// do nothing
	else if (br->arg_ip_none == 0 && br->macvlan == 0) {
		if (br->ipsandbox == br->ip) {
			fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
			exit(1);
		}
		
		// just assign the address
		assert(br->ipsandbox);
		if (arg_debug)
			printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
		net_if_ip(dev, br->ipsandbox, br->mask, br->mtu);
		net_if_up(dev);
	}
	else if (br->arg_ip_none == 0 && br->macvlan == 1) {
		// reassign the macvlan address
		if (br->ipsandbox == 0)
			// ip address assigned by arp-scan for a macvlan device
			br->ipsandbox = arp_assign(dev, br); //br->ip, br->mask);
		else {
			if (br->ipsandbox == br->ip) {
				fprintf(stderr, "Error: %d.%d.%d.%d is interface %s address.\n", PRINT_IP(br->ipsandbox), br->dev);
				exit(1);
			}
			
			uint32_t rv = arp_check(dev, br->ipsandbox, br->ip);
			if (rv) {
				fprintf(stderr, "Error: the address %d.%d.%d.%d is already in use.\n", PRINT_IP(br->ipsandbox));
				exit(1);
			}
		}
			
		if (arg_debug)
			printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev);
		net_if_ip(dev, br->ipsandbox, br->mask, br->mtu);
		net_if_up(dev);
	}
	
	if (br->ip6sandbox)
		 net_if_ip6(dev, br->ip6sandbox);
}
Пример #6
0
void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
	assert(br);
	if (br->configured == 0)
		return;

	// create a veth pair
	char *dev;
	if (br->veth_name == NULL) {
		if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0)
			errExit("asprintf");
	}
	else
		dev = br->veth_name;
		
	char *cstr;
	if (asprintf(&cstr, "%d", child) == -1)
		errExit("asprintf");
	sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 7, PATH_FNET, "create", "veth", dev, ifname, br->dev, cstr);
	free(cstr);

	char *msg;
	if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1)
		errExit("asprintf");
	logmsg(msg);
	fflush(0);
	free(msg);
}
Пример #7
0
static void print_ip(kssl_operation *op, char *ip_string) {
    if (op == NULL) return;
    if (op->is_ip_set) {
        // IPv4 printing
        if (op->ip_len == 4) {
            struct in_addr ip;
            memcpy((void *)&ip.s_addr, op->ip, 4);
            PRINT_IP(AF_INET, &ip, ip_string, INET_ADDRSTRLEN);
        }
        if (op->ip_len == 16) {
            struct in6_addr ip;
            memcpy((void *)ip.s6_addr, op->ip, 16);
            PRINT_IP(AF_INET6, &ip, ip_string, INET6_ADDRSTRLEN);
        }
    }
}
Пример #8
0
// go sequentially trough all IP addresses and assign the first one not in use
static uint32_t arp_sequential(const char *dev, Bridge *br) {
    assert(dev);
    assert(br);
    uint32_t ifip = br->ip;
    uint32_t ifmask = br->mask;
    assert(ifip);
    assert(ifmask);

    // range based on network address
    uint32_t range = ~ifmask + 1; // the number of potential addresses
    // this software is not supported for /31 networks
    if (range < 4)
        return 0; // the user will have to set the IP address manually
    range -= 2; // subtract the network address and the broadcast address

    // try all possible ip addresses in ascending order
    // start address
    uint32_t dest = (ifip & ifmask) + 1;
    if (br->iprange_start)
        dest = br->iprange_start;
    // end address
    uint32_t last = dest + range - 1;
    if (br->iprange_end)
        last = br->iprange_end;

    if (arg_debug)
        printf("Trying IP address range from %d.%d.%d.%d to %d.%d.%d.%d\n",
               PRINT_IP(dest), PRINT_IP(last));

    // loop through addresses and stop as soon as you find an unused one
    while (dest <= last) {
        if (dest == ifip) {
            dest++;
            continue;
        }
        uint32_t rv = arp_check(dev, dest, ifip);
        if (!rv)
            return dest;
        dest++;
    }

    return 0;
}
Пример #9
0
/*print port and addresses based on sock*/
void ant_debug_sock(int sock) {
    struct sockaddr_in addr;
    int olderrno;
    socklen_t  len = sizeof(addr);
    
    olderrno = errno;
    memset(&addr, '\0', sizeof(addr));
    if (getpeername(sock, (struct sockaddr*)&addr, &len) < 0) {
        errno = olderrno;
    }
    PRINT_IP(addr.sin_addr.s_addr);
    fprintf(stderr, "port = %hd\n", ntohs(addr.sin_port));
}
Пример #10
0
void fs_resolvconf(void) {
	if (cfg.dns1 == 0)
		return;

	struct stat s;
	
	// create a new /etc/hostname
	if (stat("/etc/resolv.conf", &s) == 0) {
		if (arg_debug)
			printf("Creating a new /etc/resolv.conf file\n");
		FILE *fp = fopen(RUN_RESOLVCONF_FILE, "w");
		if (!fp) {
			fprintf(stderr, "Error: cannot create %s\n", RUN_RESOLVCONF_FILE);
			exit(1);
		}
		
		if (cfg.dns1)
			fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
		if (cfg.dns2)
			fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
		if (cfg.dns3)
			fprintf(fp, "nameserver %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));

		// mode and owner
		SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);

		fclose(fp);
		
		// bind-mount the file on top of /etc/hostname
		if (mount(RUN_RESOLVCONF_FILE, "/etc/resolv.conf", NULL, MS_BIND|MS_REC, NULL) < 0)
			errExit("mount bind /etc/resolv.conf");
		fs_logger("create /etc/resolv.conf");
	}
	else {
		fprintf(stderr, "Error: cannot set DNS servers, /etc/resolv.conf file is missing\n");
		exit(1);
	}
}
Пример #11
0
void net_check_cfg(void) {
	int net_configured = 0;
	if (cfg.bridge0.configured)
		net_configured++;
	if (cfg.bridge1.configured)
		net_configured++;
	if (cfg.bridge2.configured)
		net_configured++;
	if (cfg.bridge3.configured)
		net_configured++;

	// --defaultgw requires a network
	if (cfg.defaultgw && net_configured == 0) {
		fprintf(stderr, "Error: option --defaultgw requires at least one network to be configured\n");
		exit(1);
	}

	if (net_configured == 0) // nothing to check
		return;

	// --net=none
	if (arg_nonetwork && net_configured) {
		fprintf(stderr, "Error: --net and --net=none are mutually exclusive\n");
		exit(1);
	}

	// check default gateway address or assign one
	assert(cfg.bridge0.configured);
	if (cfg.defaultgw)
		check_default_gw(cfg.defaultgw);
	else {
		// first network is a regular bridge
		if (cfg.bridge0.macvlan == 0)
			cfg.defaultgw = cfg.bridge0.ip;
		// first network is a mac device
		else {
			// get the host default gw
			uint32_t gw = network_get_defaultgw();
			// check the gateway is network range
			if (in_netrange(gw, cfg.bridge0.ip, cfg.bridge0.mask))
				gw = 0;
			cfg.defaultgw = gw;
		}

		if (cfg.defaultgw == 0)
			fprintf(stderr, "Warning: default network gateway not set.\n");
		else
			fprintf(stderr, "Using %d.%d.%d.%d as default gateway.\n", PRINT_IP(cfg.defaultgw));
	}
}
Пример #12
0
void natvLogSession(
    IN const char * prefixStr,
    IN TRACED_CONNECTION* pItem,
    IN ULONG prevState,
    IN const char * sufixStr
)
{
    TIME_FIELDS TimeFields;
    char timeStr[30];
    LARGE_INTEGER time;
    char dstIpAddrStr[30];
    char srcIpAddrStr[30];

    KeQuerySystemTime(&time);
    ExSystemTimeToLocalTime(&time, &time);
    RtlTimeToTimeFields(&time, &TimeFields);

    RtlStringCbPrintfA(timeStr, sizeof(timeStr), "%02d:%02d:%02d.%03d ",
        TimeFields.Hour, TimeFields.Minute,
        TimeFields.Second, TimeFields.Milliseconds);

    PRINT_IP(dstIpAddrStr, &pItem->dstIpAddrOrg);
    PRINT_IP(srcIpAddrStr, &pItem->srcIpAddrOrg);
    DbgPrint("%s %s session %s %s: %s:%u->%s:%u. State %s->%s\n",
        timeStr,
        prefixStr,
        pItem->out ? "OUT" : "IN ",
        sufixStr,
        srcIpAddrStr,
        RtlUshortByteSwap(pItem->srcPortOrg),
        dstIpAddrStr,
        RtlUshortByteSwap(pItem->dstPortOrg),
        natsState2Name(prevState),
        natsState2Name(pItem->state)
    );
}
Пример #13
0
void net_configure_sandbox_ip(Bridge *br) {
	assert(br);
	if (br->configured == 0)
		return;

	if (br->arg_ip_none)
		br->ipsandbox = 0;
	else if (br->ipsandbox) {
		// check network range
		char *rv = in_netrange(br->ipsandbox, br->ip, br->mask);
		if (rv) {
			fprintf(stderr, "%s", rv);
			exit(1);
		}
		// send an ARP request and check if there is anybody on this IP address
		if (arp_check(br->dev, br->ipsandbox, br->ip)) {
			fprintf(stderr, "Error: IP address %d.%d.%d.%d is already in use\n", PRINT_IP(br->ipsandbox));
			exit(1);
		}
	}
	else
		br->ipsandbox = arp_assign(br->dev, br->ip, br->mask);
}
Пример #14
0
void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child) {
	assert(br);
	if (br->configured == 0)
		return;

	// create a veth pair
	char *dev;
	if (asprintf(&dev, "veth%u%s", getpid(), ifname) < 0)
		errExit("asprintf");
	net_create_veth(dev, ifname, child);

	// add interface to the bridge
	net_bridge_add_interface(br->dev, dev);

	// bring up the interface
	net_if_up(dev);

	char *msg;
	if (asprintf(&msg, "%d.%d.%d.%d address assigned to sandbox", PRINT_IP(br->ipsandbox)) == -1)
		errExit("asprintf");
	logmsg(msg);
	fflush(0);
	free(msg);
}
Пример #15
0
int sandbox(void* sandbox_arg) {
	if (arg_debug)
		printf("Initializing child process\n");	

	//****************************
	// wait for the parent to be initialized
	//****************************
	char childstr[BUFLEN + 1];
	FILE* stream;
	close(fds[1]);
	stream = fdopen(fds[0], "r");
	*childstr = '\0';
	if (fgets(childstr, BUFLEN, stream)) {
		// remove \n
		char *ptr = childstr;
		while(*ptr !='\0' && *ptr != '\n')
			ptr++;
		if (*ptr == '\0')
			errExit("fgets");
		*ptr = '\0';
	}
	else {
		fprintf(stderr, "Error: cannot establish communication with the parent, exiting...\n");
		exit(1);
	}
	close(fds[0]);
	if (arg_debug && getpid() == 1)
			printf("PID namespace installed\n");

	//****************************
	// set hostname
	//****************************
	if (cfg.hostname) {
		if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0)
			errExit("sethostname");
	}

	//****************************
	// mount namespace
	//****************************
	// mount events are not forwarded between the host the sandbox
	if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
		// if we are starting firejail inside firejail, we don't care about this
		char *mycont = getenv("container");
		if (mycont == NULL)
			errExit("mounting filesystem as slave");
		if (strcmp(mycont, "firejail") != 0)
			errExit("mounting filesystem as slave");
	}
	
	//****************************
	// trace pre-install
	//****************************
	if (arg_trace)
		fs_trace_preload();

	//****************************
	// configure filesystem
	//****************************
	int drop_caps = 0;
	if (cfg.chrootdir) {
		fs_chroot(cfg.chrootdir);
		// force caps and seccomp if not started as root
		if (getuid() != 0) {
			arg_seccomp = 1;
			arg_caps = 0;
			drop_caps = 1;
			printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
		}
						
		//****************************
		// trace pre-install, this time inside chroot
		//****************************
		if (arg_trace)
			fs_trace_preload();
	}
	else if (arg_overlay)
		fs_overlayfs();
	else
		fs_basic_fs();
	

	//****************************
	// set hostname in /etc/hostname
	//****************************
	if (cfg.hostname) {
		fs_hostname(cfg.hostname);
	}
	
	//****************************
	// apply the profile file
	//****************************
	if (cfg.profile)
		fs_blacklist(cfg.homedir);
	
	//****************************
	// private mode
	//****************************
	if (arg_private) {
		if (cfg.home_private)
			fs_private_home();
		else
			fs_private();
	}
	
	//****************************
	// install trace
	//****************************
	if (arg_trace)
		fs_trace();
		
	//****************************
	// update /proc, /dev, /boot directory
	//****************************
	fs_proc_sys_dev_boot();
	
	//****************************
	// networking
	//****************************
	if (arg_nonetwork) {
		net_if_up("lo");
	}
	else if (arg_noip) {
		net_if_up("lo");
		if (cfg.bridge0.configured)
			net_if_up("eth0");
		if (cfg.bridge1.configured)
			net_if_up("eth1");
		if (cfg.bridge2.configured)
			net_if_up("eth2");
		if (cfg.bridge3.configured)
			net_if_up("eth3");
	}
	else if (any_bridge_configured()) {
		// configure lo and eth0...eth3
		net_if_up("lo");
		if (cfg.bridge0.configured) {
			Bridge *br = &cfg.bridge0;
			net_if_up("eth0");
			assert(br->ipaddress);
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface eth0\n", PRINT_IP(br->ipaddress));
			net_if_ip("eth0", br->ipaddress, br->mask);
			net_if_up("eth0");
		}
		if (cfg.bridge1.configured) {
			Bridge *br = &cfg.bridge1;
			net_if_up("eth1");
			assert(br->ipaddress);
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface eth1\n", PRINT_IP(br->ipaddress));
			net_if_ip("eth1", br->ipaddress, br->mask);
			net_if_up("eth1");
		}
		if (cfg.bridge2.configured) {
			Bridge *br = &cfg.bridge2;
			net_if_up("eth2");
			assert(br->ipaddress);
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface eth2\n", PRINT_IP(br->ipaddress));
			net_if_ip("eth2", br->ipaddress, br->mask);
			net_if_up("eth2");
		}
		if (cfg.bridge3.configured) {
			Bridge *br = &cfg.bridge3;
			net_if_up("eth3");
			assert(br->ipaddress);
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface eth3\n", PRINT_IP(br->ipaddress));
			net_if_ip("eth3", br->ipaddress, br->mask);
			net_if_up("eth3");
		}
		
		// add a default route
		if (!cfg.defaultgw) {
			// set the default route as IP address of first bridge
			cfg.defaultgw = cfg.bridge0.ip;
			if (arg_debug)
				printf("Using first bridge address as default route\n");
		}
		if (net_add_route(0, 0, cfg.defaultgw))
			fprintf(stderr, "Warning: cannot configure default route\n");
			
		if (arg_debug)
			printf("Network namespace enabled\n");
	}
	net_ifprint();
	
	//****************************
	// start executable
	//****************************
	prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
	int cwd = 0;
	if (cfg.cwd) {
		if (chdir(cfg.cwd) == 0)
			cwd = 1;
	}
	
	if (!cwd) {
		if (chdir("/") < 0)
			errExit("chdir");
		if (cfg.homedir) {
			struct stat s;
			if (stat(cfg.homedir, &s) == 0) {
				if (chdir(cfg.homedir) < 0)
					errExit("chdir");
			}
		}
	}
	
	// set environment
	// fix qt 4.8
	if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
		errExit("setenv");
	if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
		errExit("setenv");
	if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0)
		errExit("setenv");
	if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0)
		errExit("setenv");
	if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0)
		errExit("setenv");
	// set prompt color to green
	//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
	if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
		errExit("setenv");
		

	// set capabilities
	if (arg_caps == 1)
		caps_filter();
	if (drop_caps)
		caps_drop_all();

	// set rlimits
	set_rlimits();

	// set seccomp
#ifdef HAVE_SECCOMP
	if (arg_seccomp == 1)
		seccomp_filter();
#endif

	// drop privileges
	drop_privs();
	
		
	// set the shell
	char *sh;
	if (cfg.shell)
 		sh = cfg.shell;
	else if (arg_zsh)
		sh = "/usr/bin/zsh";
	else if (arg_csh)
		sh = "/bin/csh";
	else
		sh = "/bin/bash";
		
	char *arg[4];
	arg[0] = sh;
	arg[1] = "-c";
	assert(cfg.command_line);
	if (arg_debug)
		printf("Starting %s\n", cfg.command_line);
	arg[2] = cfg.command_line;
	arg[3] = NULL;

	if (!arg_command)
		printf("Child process initialized\n");
	if (arg_debug) {
		char *msg;
		if (asprintf(&msg, "child pid %s, execvp into %s", childstr, cfg.command_line) == -1)
			errExit("asprintf");
		logmsg(msg);
		free(msg);
	}
	execvp(sh, arg); 

	perror("execvp");
	return 0;
}
Пример #16
0
int sandbox(void* sandbox_arg) {
	// Get rid of unused parameter warning
	(void)sandbox_arg;

	pid_t child_pid = getpid();
	if (arg_debug)
		printf("Initializing child process\n");	

 	// close each end of the unused pipes
 	close(parent_to_child_fds[1]);
 	close(child_to_parent_fds[0]);
 
 	// wait for parent to do base setup
 	wait_for_other(parent_to_child_fds[0]);

	if (arg_debug && child_pid == 1)
		printf("PID namespace installed\n");

	//****************************
	// set hostname
	//****************************
	if (cfg.hostname) {
		if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0)
			errExit("sethostname");
	}

	//****************************
	// mount namespace
	//****************************
	// mount events are not forwarded between the host the sandbox
	if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
		chk_chroot();
	}
	
	
	//****************************
	// log sandbox data
	//****************************
	if (cfg.name)
		fs_logger2("sandbox name:", cfg.name);
	fs_logger2int("sandbox pid:", (int) sandbox_pid);
	if (cfg.chrootdir)
		fs_logger("sandbox filesystem: chroot");
	else if (arg_overlay)	
		fs_logger("sandbox filesystem: overlay");
	else
		fs_logger("sandbox filesystem: local");
	fs_logger("install mount namespace");
	
	//****************************
	// netfilter etc.
	//****************************
	if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
		netfilter(arg_netfilter_file);
	}
	if (arg_netfilter6 && any_bridge_configured()) { // assuming by default the client filter
		netfilter6(arg_netfilter6_file);
	}

	// load IBUS env variables
	if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) {
		// do nothing - there are problems with ibus version 1.5.11
	}
	else
		env_ibus_load();
	
	// grab a copy of cp command
	fs_build_cp_command();
	
	// trace pre-install
	if (arg_trace || arg_tracelog)
		fs_trace_preload();

	//****************************
	// configure filesystem
	//****************************
#ifdef HAVE_SECCOMP
	int enforce_seccomp = 0;
#endif
#ifdef HAVE_CHROOT		
	if (cfg.chrootdir) {
		fs_chroot(cfg.chrootdir);
		// redo cp command
		fs_build_cp_command();
		
		// force caps and seccomp if not started as root
		if (getuid() != 0) {
			// force default seccomp inside the chroot, no keep or drop list
			// the list build on top of the default drop list is kept intact
			arg_seccomp = 1;
#ifdef HAVE_SECCOMP
			enforce_seccomp = 1;
#endif
			if (cfg.seccomp_list_drop) {
				free(cfg.seccomp_list_drop);
				cfg.seccomp_list_drop = NULL;
			}
			if (cfg.seccomp_list_keep) {
				free(cfg.seccomp_list_keep);
				cfg.seccomp_list_keep = NULL;
			}
			
			// disable all capabilities
			if (arg_caps_default_filter || arg_caps_list)
				fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n");
			arg_caps_drop_all = 1;
			
			// drop all supplementary groups; /etc/group file inside chroot
			// is controlled by a regular usr
			arg_nogroups = 1;
			if (!arg_quiet)
				printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
		}
		else
			arg_seccomp = 1;
						
		//****************************
		// trace pre-install, this time inside chroot
		//****************************
		if (arg_trace || arg_tracelog)
			fs_trace_preload();
	}
	else 
#endif		
	if (arg_overlay)	
		fs_overlayfs();
	else
		fs_basic_fs();
	

	//****************************
	// set hostname in /etc/hostname
	//****************************
	if (cfg.hostname) {
		fs_hostname(cfg.hostname);
	}
	
	//****************************
	// private mode
	//****************************
	if (arg_private) {
		if (cfg.home_private)	// --private=
			fs_private_homedir();
		else // --private
			fs_private();
	}
	
	if (arg_private_dev)
		fs_private_dev();
	if (arg_private_etc) {
		fs_private_etc_list();
		// create /etc/ld.so.preload file again
		if (arg_trace || arg_tracelog)
			fs_trace_preload();
	}
	if (arg_private_bin)
		fs_private_bin_list();
	if (arg_private_tmp)
		fs_private_tmp();
	
	//****************************
	// apply the profile file
	//****************************
	if (cfg.profile) {
		// apply all whitelist commands ... 
		fs_whitelist();
		
		// ... followed by blacklist commands
		fs_blacklist();
	}
	
	//****************************
	// install trace
	//****************************
	if (arg_trace || arg_tracelog)
		fs_trace();
		
	//****************************
	// update /proc, /dev, /boot directorymy
	//****************************
	fs_proc_sys_dev_boot();
	
	//****************************
	// --nosound and fix for pulseaudio 7.0
	//****************************
	if (arg_nosound)
		pulseaudio_disable();
	else
		pulseaudio_init();
	
	//****************************
	// networking
	//****************************
	if (arg_nonetwork) {
		net_if_up("lo");
		if (arg_debug)
			printf("Network namespace enabled, only loopback interface available\n");
	}
	else if (any_bridge_configured() || any_interface_configured()) {
		// configure lo and eth0...eth3
		net_if_up("lo");
		
		if (mac_not_zero(cfg.bridge0.macsandbox))
			net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
		sandbox_if_up(&cfg.bridge0);
		
		if (mac_not_zero(cfg.bridge1.macsandbox))
			net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
		sandbox_if_up(&cfg.bridge1);
		
		if (mac_not_zero(cfg.bridge2.macsandbox))
			net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
		sandbox_if_up(&cfg.bridge2);
		
		if (mac_not_zero(cfg.bridge3.macsandbox))
			net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
		sandbox_if_up(&cfg.bridge3);
		
		// add a default route
		if (cfg.defaultgw) {
			// set the default route
			if (net_add_route(0, 0, cfg.defaultgw))
				fprintf(stderr, "Warning: cannot configure default route\n");
		}
		
		// enable interfaces
		if (cfg.interface0.configured && cfg.interface0.ip) {
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev);
			net_if_ip(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu);
			net_if_up(cfg.interface0.dev);
		}			
		if (cfg.interface1.configured && cfg.interface1.ip) {
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev);
			net_if_ip(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu);
			net_if_up(cfg.interface1.dev);
		}			
		if (cfg.interface2.configured && cfg.interface2.ip) {
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev);
			net_if_ip(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu);
			net_if_up(cfg.interface2.dev);
		}			
		if (cfg.interface3.configured && cfg.interface3.ip) {
			if (arg_debug)
				printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev);
			net_if_ip(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu);
			net_if_up(cfg.interface3.dev);
		}			
			
		if (arg_debug)
			printf("Network namespace enabled\n");
	}
	
	// if any dns server is configured, it is time to set it now
	fs_resolvconf();
	fs_logger_print();
	fs_logger_change_owner();

	// print network configuration
	if (!arg_quiet) {
		if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) {
			printf("\n");
			if (any_bridge_configured() || any_interface_configured())
				net_ifprint();
			if (cfg.defaultgw != 0)
				printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
			if (cfg.dns1 != 0)
				printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
			if (cfg.dns2 != 0)
				printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
			if (cfg.dns3 != 0)
				printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
			printf("\n");
		}
	}
	
	fs_delete_cp_command();

	//****************************
	// set application environment
	//****************************
	prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
	int cwd = 0;
	if (cfg.cwd) {
		if (chdir(cfg.cwd) == 0)
			cwd = 1;
	}
	
	if (!cwd) {
		if (chdir("/") < 0)
			errExit("chdir");
		if (cfg.homedir) {
			struct stat s;
			if (stat(cfg.homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(cfg.homedir) < 0)
					errExit("chdir");
			}
		}
	}
	
	// set environment
	env_defaults();
	
	// set user-supplied environment variables
	env_apply();

	// set nice
	if (arg_nice) {
		errno = 0;
		int rv = nice(cfg.nice);
		(void) rv;
		if (errno) {
			fprintf(stderr, "Warning: cannot set nice value\n");
			errno = 0;
		}
	}
	
	// clean /tmp/.X11-unix sockets
	fs_x11();
	
	//****************************
	// set security filters
	//****************************
	// set capabilities
	if (!arg_noroot)
		set_caps();

	// set rlimits
	set_rlimits();

	// set seccomp
#ifdef HAVE_SECCOMP
	// install protocol filter
	if (cfg.protocol) {
		protocol_filter();	// install filter	
		protocol_filter_save();	// save filter in PROTOCOL_CFG
	}

	// if a keep list is available, disregard the drop list
	if (arg_seccomp == 1) {
		if (cfg.seccomp_list_keep)
			seccomp_filter_keep();
		else if (cfg.seccomp_list_errno)
			seccomp_filter_errno(); 
		else
			seccomp_filter_drop(enforce_seccomp);
	}
#endif

	// set cpu affinity
	if (cfg.cpus) {
		save_cpu(); // save cpu affinity mask to CPU_CFG file
		set_cpu_affinity();
	}
	
	// save cgroup in CGROUP_CFG file
	if (cfg.cgroup)
		save_cgroup();

	//****************************************
	// drop privileges or create a new user namespace
	//****************************************
	save_nogroups();
	if (arg_noroot) {
		int rv = unshare(CLONE_NEWUSER);
		if (rv == -1) {
			fprintf(stderr, "Error: cannot mount a new user namespace\n");
			perror("unshare");
			drop_privs(arg_nogroups);
		}
	}
	else
		drop_privs(arg_nogroups);
 	
	// notify parent that new user namespace has been created so a proper
 	// UID/GID map can be setup
 	notify_other(child_to_parent_fds[1]);
 	close(child_to_parent_fds[1]);
 
 	// wait for parent to finish setting up a proper UID/GID map
 	wait_for_other(parent_to_child_fds[0]);
 	close(parent_to_child_fds[0]);

	// somehow, the new user namespace resets capabilities;
	// we need to do them again
	if (arg_noroot) {
		set_caps();
		if (arg_debug)
			printf("noroot user namespace installed\n");
	}


	//****************************************
	// fork the application and monitor it
	//****************************************
	pid_t app_pid = fork();
	if (app_pid == -1)
		errExit("fork");
		
	if (app_pid == 0) {
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		start_application();	// start app
	}

	monitor_application(app_pid);	// monitor application
	
	return 0;
}
Пример #17
0
// the default address should be in the range of at least on of the bridge devices
void check_default_gw(uint32_t defaultgw) {
	assert(defaultgw);

	if (cfg.bridge0.configured) {
		char *rv = in_netrange(defaultgw, cfg.bridge0.ip, cfg.bridge0.mask);
		if (rv == 0)
			return;
	}
	if (cfg.bridge1.configured) {
		char *rv = in_netrange(defaultgw, cfg.bridge1.ip, cfg.bridge1.mask);
		if (rv == 0)
			return;
	}
	if (cfg.bridge2.configured) {
		char *rv = in_netrange(defaultgw, cfg.bridge2.ip, cfg.bridge2.mask);
		if (rv == 0)
			return;
	}
	if (cfg.bridge3.configured) {
		char *rv = in_netrange(defaultgw, cfg.bridge3.ip, cfg.bridge3.mask);
		if (rv == 0)
			return;
	}

	fprintf(stderr, "Error: default gateway %d.%d.%d.%d is not in the range of any network\n", PRINT_IP(defaultgw));
	exit(1);
}
Пример #18
0
VOID PrintFtlPkt(
    IN char *strPrefix,
    IN FLT_PKT* pFltPkt,
    IN ULONG uNewIp,
    IN BOOLEAN bOut
)
{
    TIME_FIELDS TimeFields;
    char Message[255];
    char MessagePart[30];
    LARGE_INTEGER time;

    KeQuerySystemTime(&time);
    ExSystemTimeToLocalTime(&time, &time);
    RtlTimeToTimeFields(&time, &TimeFields);

    RtlStringCbPrintfA(Message, sizeof(Message), "%02d:%02d:%02d.%03d ",
        TimeFields.Hour, TimeFields.Minute,
        TimeFields.Second, TimeFields.Milliseconds);

    if (!bOut) {
        RtlStringCbCatA(Message, sizeof(Message), "IN  ");
    }
    else {
        RtlStringCbCatA(Message, sizeof(Message), "OUT ");
    }

    RtlStringCbCatA(Message, sizeof(Message), strPrefix);
    RtlStringCbCatA(Message, sizeof(Message), " ");


    if (NULL == pFltPkt->pEth) {
        goto out;
    }

    RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x",
        pFltPkt->pEth->ether_src[0],
        pFltPkt->pEth->ether_src[1],
        pFltPkt->pEth->ether_src[2],
        pFltPkt->pEth->ether_src[3],
        pFltPkt->pEth->ether_src[4],
        pFltPkt->pEth->ether_src[5]);
    RtlStringCbCatA(Message, sizeof(Message), MessagePart);
    RtlStringCbCatA(Message, sizeof(Message), "->");
    RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x",
        pFltPkt->pEth->ether_dst[0],
        pFltPkt->pEth->ether_dst[1],
        pFltPkt->pEth->ether_dst[2],
        pFltPkt->pEth->ether_dst[3],
        pFltPkt->pEth->ether_dst[4],
        pFltPkt->pEth->ether_dst[5]);
    RtlStringCbCatA(Message, sizeof(Message), MessagePart);

    switch (pFltPkt->pEth->ether_type) {
    case ETHERNET_TYPE_ARP_NET:
        RtlStringCbCatA(Message, sizeof(Message), " ARP ");

        if (NULL == pFltPkt->pArp)
            goto out;

        if (ARP_REQUEST_CODE == pFltPkt->pArp->ea_hdr.ar_op) {
            RtlStringCbCatA(Message, sizeof(Message), "Request ");
        }
        else if (pFltPkt->pArp->ea_hdr.ar_op == ARP_REPLY_CODE) {
            RtlStringCbCatA(Message, sizeof(Message), "Reply   ");
        }

        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%d.%d.%d.%d",
            pFltPkt->pArp->arp_spa[0],
            pFltPkt->pArp->arp_spa[1],
            pFltPkt->pArp->arp_spa[2],
            pFltPkt->pArp->arp_spa[3]);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);

        RtlStringCbCatA(Message, sizeof(Message), "->");

        PRINT_IP(MessagePart, pFltPkt->pArp->arp_tpa);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;

    case ETHERNET_TYPE_IP_NET:

        RtlStringCbCatA(Message, sizeof(Message), " IP  ");

        if (NULL == pFltPkt->pIp)
            goto out;

        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "ID %04x ", RtlUshortByteSwap(pFltPkt->pIp->ip_id));
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);

        PRINT_IP(MessagePart, &pFltPkt->pIp->ip_src);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        if (uNewIp && bOut) {
            RtlStringCbCatA(Message, sizeof(Message), "[");
            PRINT_IP(MessagePart, &uNewIp);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            RtlStringCbCatA(Message, sizeof(Message), "]");
        }
        RtlStringCbCatA(Message, sizeof(Message), "->");
        PRINT_IP(MessagePart, &pFltPkt->pIp->ip_dst);
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        if (uNewIp && !bOut) {
            RtlStringCbCatA(Message, sizeof(Message), "[");
            PRINT_IP(MessagePart, &uNewIp);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            RtlStringCbCatA(Message, sizeof(Message), "]");
        }

        switch (pFltPkt->pIp->ip_proto) {
        case IPPROTO_TCP:
            RtlStringCbCatA(Message, sizeof(Message), " TCP");
            break;
        case IPPROTO_ICMP:
            RtlStringCbCatA(Message, sizeof(Message), " ICMP");
            break;
        case IPPROTO_UDP:
            RtlStringCbCatA(Message, sizeof(Message), " UDP");
            break;
        default:
            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " proto=%04x", pFltPkt->pIp->ip_proto);
            RtlStringCbCatA(Message, sizeof(Message), MessagePart);
            break;
        }

        if (pFltPkt->pTcp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d ",
                RtlUshortByteSwap(pFltPkt->pTcp->th_sport),
                RtlUshortByteSwap(pFltPkt->pTcp->th_dport));

            if (pFltPkt->pTcp->th_flags & TCP_FIN_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "F");
            if (pFltPkt->pTcp->th_flags & TCP_SYN_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "S");
            if (pFltPkt->pTcp->th_flags & TCP_RST_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "R");
            if (pFltPkt->pTcp->th_flags & TCP_PSH_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "P");
            if (pFltPkt->pTcp->th_flags & TCP_URG_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "U");
            if (pFltPkt->pTcp->th_flags & TCP_ACK_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "A");
            // https://tools.ietf.org/html/rfc3168
            if (pFltPkt->pTcp->th_flags & TCP_ECE_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "E");
            if (pFltPkt->pTcp->th_flags & TCP_CWR_FLAG)
                RtlStringCbCatA(MessagePart, sizeof(MessagePart), "C");

            RtlStringCbCatA(Message, sizeof(Message), MessagePart);

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " SEQ:%u",
                RtlUlongByteSwap(pFltPkt->pTcp->th_seq));

            RtlStringCbCatA(Message, sizeof(Message), MessagePart);

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " ACK:%u",
                RtlUlongByteSwap(pFltPkt->pTcp->th_ack));

        }
        else if (pFltPkt->pUdp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d",
                RtlUshortByteSwap(pFltPkt->pUdp->uh_sport),
                RtlUshortByteSwap(pFltPkt->pUdp->uh_dport));

        }
        else if (pFltPkt->pIcmp) {

            RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d",
                RtlUshortByteSwap(pFltPkt->pIcmp->icmp_hun.idseq.id));

        }
        else {
            MessagePart[0] = 0;
        }
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;
    default:
        RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " UNK %04x", RtlUshortByteSwap(pFltPkt->pEth->ether_type));
        RtlStringCbCatA(Message, sizeof(Message), MessagePart);
        break;
    }

out:
    RtlStringCbCatA(Message, sizeof(Message), "\n");

    DbgPrint(Message);
    return;
}
Пример #19
0
// returns 0 if the address is not in use, -1 otherwise
int arp_check(const char *dev, uint32_t destaddr, uint32_t srcaddr) {
    if (strlen(dev) > IFNAMSIZ) {
        fprintf(stderr, "Error: invalid network device name %s\n", dev);
        exit(1);
    }

    if (arg_debug)
        printf("Trying %d.%d.%d.%d ...\n", PRINT_IP(destaddr));

    // find interface address
    int sock;
    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        errExit("socket");

    srcaddr = htonl(srcaddr);
    destaddr = htonl(destaddr);

    // Find interface MAC address
    struct ifreq ifr;
    memset(&ifr, 0, sizeof (ifr));
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
        errExit("ioctl");
    close(sock);

    // configure layer2 socket address information
    struct sockaddr_ll addr;
    memset(&addr, 0, sizeof(addr));
    if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
        errExit("if_nametoindex");
    addr.sll_family = AF_PACKET;
    memcpy (addr.sll_addr, ifr.ifr_hwaddr.sa_data, 6);
    addr.sll_halen = htons(6);

    // build the arp packet header
    ArpHdr hdr;
    memset(&hdr, 0, sizeof(hdr));
    hdr.htype = htons(1);
    hdr.ptype = htons(ETH_P_IP);
    hdr.hlen = 6;
    hdr.plen = 4;
    hdr.opcode = htons(1); //ARPOP_REQUEST
    memcpy(hdr.sender_mac, ifr.ifr_hwaddr.sa_data, 6);
    memcpy(hdr.sender_ip, (uint8_t *)&srcaddr, 4);
    memcpy(hdr.target_ip, (uint8_t *)&destaddr, 4);

    // buiild ethernet frame
    uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
    memset(frame, 0, sizeof(frame));
    frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
    memcpy(frame + 6, ifr.ifr_hwaddr.sa_data, 6);
    frame[12] = ETH_P_ARP / 256;
    frame[13] = ETH_P_ARP % 256;
    memcpy (frame + 14, &hdr, sizeof(hdr));

    // open layer2 socket
    if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
        errExit("socket");

    int len;
    if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
        errExit("send");
    fflush(0);

    // wait not more than one second for an answer
    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
    int maxfd = sock;
    struct timeval ts;
    ts.tv_sec = 1; // 1 second wait time
    ts.tv_usec = 0;
    while (1) {
        int nready = select(maxfd + 1,  &fds, (fd_set *) 0, (fd_set *) 0, &ts);
        if (nready < 0)
            errExit("select");
        else if (nready == 0) { // timeout
            close(sock);
            return 0;
        }
        else {
            // read the incoming packet
            int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
            if (len < 0) {
                perror("recvfrom");
                close(sock);
                return -1;
            }

            // parse the incomming packet
            if ((unsigned int) len < 14 + sizeof(ArpHdr))
                continue;
            if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
                continue;
            memcpy(&hdr, frame + 14, sizeof(ArpHdr));
            if (hdr.opcode == htons(1))
                continue;
            if (hdr.opcode == htons(2)) {
                // check my mac and my address
                if (memcmp(ifr.ifr_hwaddr.sa_data, hdr.target_mac, 6) != 0)
                    continue;
                uint32_t ip;
                memcpy(&ip, hdr.target_ip, 4);
                if (ip != srcaddr) {
                    continue;
                }
                close(sock);
                return -1;
            }
        }
    }

    // it will never get here!
    close(sock);
    return -1;
}
Пример #20
0
// scan interface (--scan option)
void arp_scan(const char *dev, uint32_t ifip, uint32_t ifmask) {
    assert(dev);
    assert(ifip);

//	printf("Scanning interface %s (%d.%d.%d.%d/%d)\n",
//		dev, PRINT_IP(ifip & ifmask), mask2bits(ifmask));

    if (strlen(dev) > IFNAMSIZ) {
        fprintf(stderr, "Error: invalid network device name %s\n", dev);
        exit(1);
    }

    // find interface mac address
    int sock;
    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
        errExit("socket");
    struct ifreq ifr;
    memset(&ifr, 0, sizeof (ifr));
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
        errExit("ioctl");
    close(sock);
    uint8_t mac[6];
    memcpy (mac, ifr.ifr_hwaddr.sa_data, 6);

    // open layer2 socket
    if ((sock = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
        errExit("socket");

    // try all possible ip addresses in ascending order
    uint32_t range = ~ifmask + 1; // the number of potential addresses
    // this software is not supported for /31 networks
    if (range < 4) {
        fprintf(stderr, "Warning: this option is not supported for /31 networks\n");
        close(sock);
        return;
    }

    uint32_t dest = (ifip & ifmask) + 1;
    uint32_t last = dest + range - 1;
    uint32_t src = htonl(ifip);

    // wait not more than one second for an answer
    int header_printed = 0;
    uint32_t last_ip = 0;
    struct timeval ts;
    ts.tv_sec = 2; // 2 seconds receive timeout
    ts.tv_usec = 0;

    while (1) {
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(sock, &rfds);
        fd_set wfds;
        FD_ZERO(&wfds);
        FD_SET(sock, &wfds);
        int maxfd = sock;

        uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
        memset(frame, 0, ETH_FRAME_LEN);

        int nready;
        if (dest < last)
            nready = select(maxfd + 1,  &rfds, &wfds, (fd_set *) 0, NULL);
        else
            nready = select(maxfd + 1,  &rfds,  (fd_set *) 0, (fd_set *) 0, &ts);

        if (nready < 0)
            errExit("select");

        if (nready == 0) { // timeout
            break;
        }

        if (FD_ISSET(sock, &wfds) && dest < last) {
            // configure layer2 socket address information
            struct sockaddr_ll addr;
            memset(&addr, 0, sizeof(addr));
            if ((addr.sll_ifindex = if_nametoindex(dev)) == 0)
                errExit("if_nametoindex");
            addr.sll_family = AF_PACKET;
            memcpy (addr.sll_addr, mac, 6);
            addr.sll_halen = htons(6);

            // build the arp packet header
            ArpHdr hdr;
            memset(&hdr, 0, sizeof(hdr));
            hdr.htype = htons(1);
            hdr.ptype = htons(ETH_P_IP);
            hdr.hlen = 6;
            hdr.plen = 4;
            hdr.opcode = htons(1); //ARPOP_REQUEST
            memcpy(hdr.sender_mac, mac, 6);
            memcpy(hdr.sender_ip, (uint8_t *)&src, 4);
            uint32_t dst = htonl(dest);
            memcpy(hdr.target_ip, (uint8_t *)&dst, 4);

            // buiild ethernet frame
            uint8_t frame[ETH_FRAME_LEN]; // includes eht header, vlan, and crc
            memset(frame, 0, sizeof(frame));
            frame[0] = frame[1] = frame[2] = frame[3] = frame[4] = frame[5] = 0xff;
            memcpy(frame + 6, mac, 6);
            frame[12] = ETH_P_ARP / 256;
            frame[13] = ETH_P_ARP % 256;
            memcpy (frame + 14, &hdr, sizeof(hdr));

            // send packet
            int len;
            if ((len = sendto (sock, frame, 14 + sizeof(ArpHdr), 0, (struct sockaddr *) &addr, sizeof (addr))) <= 0)
                errExit("send");
//printf("send %d bytes to %d.%d.%d.%d\n", len, PRINT_IP(dest));
            fflush(0);
            dest++;
        }

        if (FD_ISSET(sock, &rfds)) {
            // read the incoming packet
            int len = recvfrom(sock, frame, ETH_FRAME_LEN, 0, NULL, NULL);
            if (len < 0) {
                perror("recvfrom");
            }

            // parse the incomming packet
            if ((unsigned int) len < 14 + sizeof(ArpHdr))
                continue;

            // look only at ARP packets
            if (frame[12] != (ETH_P_ARP / 256) || frame[13] != (ETH_P_ARP % 256))
                continue;

            ArpHdr hdr;
            memcpy(&hdr, frame + 14, sizeof(ArpHdr));

            if (hdr.opcode == htons(2)) {
                // check my mac and my address
                if (memcmp(mac, hdr.target_mac, 6) != 0)
                    continue;
                uint32_t ip;
                memcpy(&ip, hdr.target_ip, 4);
                if (ip != src)
                    continue;
                memcpy(&ip, hdr.sender_ip, 4);
                ip = ntohl(ip);

                if (ip == last_ip) // filter duplicates
                    continue;
                last_ip = ip;

                // printing
                if (header_printed == 0) {
                    printf("   Network scan:\n");

                    // print parent interface
                    if (cfg.bridge0.configured && cfg.bridge0.ip && cfg.bridge0.macvlan &&
                            (cfg.bridge0.ip & cfg.bridge0.mask) == (ifip & cfg.bridge0.mask))
                        printf("   %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
                               PRINT_MAC(cfg.bridge0.mac), PRINT_IP(cfg.bridge0.ip));

                    if (cfg.bridge1.configured && cfg.bridge1.ip &&  cfg.bridge1.macvlan &&
                            (cfg.bridge1.ip & cfg.bridge1.mask) == (ifip & cfg.bridge1.mask))
                        printf("   %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
                               PRINT_MAC(cfg.bridge1.mac), PRINT_IP(cfg.bridge1.ip));

                    if (cfg.bridge2.configured && cfg.bridge2.ip &&  cfg.bridge2.macvlan &&
                            (cfg.bridge2.ip & cfg.bridge2.mask) == (ifip & cfg.bridge2.mask))
                        printf("   %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
                               PRINT_MAC(cfg.bridge2.mac), PRINT_IP(cfg.bridge2.ip));

                    if (cfg.bridge3.configured && cfg.bridge3.ip &&  cfg.bridge3.macvlan &&
                            (cfg.bridge3.ip & cfg.bridge3.mask) == (ifip & cfg.bridge3.mask))
                        printf("   %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
                               PRINT_MAC(cfg.bridge3.mac), PRINT_IP(cfg.bridge3.ip));

                    header_printed = 1;
                }
                printf("   %02x:%02x:%02x:%02x:%02x:%02x\t%d.%d.%d.%d\n",
                       PRINT_MAC(hdr.sender_mac), PRINT_IP(ip));
            }
        }
    }

    close(sock);
}
Пример #21
0
// print IP addresses for all interfaces
static void net_ifprint(void) {
	uint32_t ip;
	uint32_t mask;
	struct ifaddrs *ifaddr, *ifa;

	if (getifaddrs(&ifaddr) == -1)
		errExit("getifaddrs");

	// walk through the linked list
	printf("  Link status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_PACKET) {
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) {
				if (ifa->ifa_data != NULL) {
					struct rtnl_link_stats *stats = ifa->ifa_data;
					printf("     %s UP - tx/rx: %u/%u packets,  %u/%u bytes\n",
						ifa->ifa_name, 
						stats->tx_packets, stats->rx_packets,
						stats->tx_bytes, stats->rx_bytes);
				}
			}
			else
				printf("     %s DOWN\n", ifa->ifa_name);
		}			
	}


	// walk through the linked list
	printf("  IPv4 status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_INET) {
			struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
			mask = ntohl(si->sin_addr.s_addr);
			si = (struct sockaddr_in *) ifa->ifa_addr;
			ip = ntohl(si->sin_addr.s_addr);

			char *status;
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
				status = "UP";
			else
				status = "DOWN";

			printf("     %s %s, %d.%d.%d.%d/%u\n",
				ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask));
		}
	}


	// walk through the linked list
	printf("  IPv6 status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_INET6) {
			char host[NI_MAXHOST];
			int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
				host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
			if (s == 0) {
				char *ptr;
				if ((ptr = strchr(host, '%')) != NULL)
					*ptr = '\0';
				char *status;
				if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
					status = "UP";
				else
					status = "DOWN";

				printf("     %s %s, %s\n", ifa->ifa_name, status, host);
			}
		}
	}

	freeifaddrs(ifaddr);
}
Пример #22
0
// print IP addresses for all interfaces
static void net_ifprint(void) {
	uint32_t ip;
	uint32_t mask;
	struct ifaddrs *ifaddr, *ifa;

	int fd;
	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		fprintf(stderr, "Error: cannot open AF_INET socket\n");
		exit(1);
	}

	if (getifaddrs(&ifaddr) == -1)
		errExit("getifaddrs");

	// walk through the linked list
	printf("  Link status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_PACKET) {
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) {
				if (ifa->ifa_data != NULL) {
					struct rtnl_link_stats *stats = ifa->ifa_data;

					// extract mac address
					struct ifreq ifr;
					memset(&ifr, 0, sizeof(ifr));
					strncpy(ifr.ifr_name,  ifa->ifa_name, IFNAMSIZ);
					int rv = ioctl (fd, SIOCGIFHWADDR, &ifr);
					
					if (rv == 0)
						printf("     %s UP, %02x:%02x:%02x:%02x:%02x:%02x\n",
							ifa->ifa_name, PRINT_MAC((unsigned char *) &ifr.ifr_hwaddr.sa_data));
					else
						printf("     %s UP\n", ifa->ifa_name);
					
					printf("          tx/rx: %u/%u packets,  %u/%u bytes\n",
						stats->tx_packets, stats->rx_packets,
						stats->tx_bytes, stats->rx_bytes);
				}
			}
			else
				printf("     %s DOWN\n", ifa->ifa_name);
		}			
	}


	// walk through the linked list
	printf("  IPv4 status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_INET) {
			struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
			mask = ntohl(si->sin_addr.s_addr);
			si = (struct sockaddr_in *) ifa->ifa_addr;
			ip = ntohl(si->sin_addr.s_addr);

			char *status;
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
				status = "UP";
			else
				status = "DOWN";

			printf("     %s %s, %d.%d.%d.%d/%u\n",
				ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask));
		}
	}


	// walk through the linked list
	printf("  IPv6 status:\n");
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_INET6) {
			char host[NI_MAXHOST];
			int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),
				host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
			if (s == 0) {
				char *ptr;
				if ((ptr = strchr(host, '%')) != NULL)
					*ptr = '\0';
				char *status;
				if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
					status = "UP";
				else
					status = "DOWN";

				printf("     %s %s, %s\n", ifa->ifa_name, status, host);
			}
		}
	}

	freeifaddrs(ifaddr);
	close(fd);
}
Пример #23
0
// scan interfaces in current namespace and print IP address/mask for each interface
void net_ifprint(void) {
	uint32_t ip;
	uint32_t mask;
	struct ifaddrs *ifaddr, *ifa;

	if (getifaddrs(&ifaddr) == -1)
		errExit("getifaddrs");

	printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
		"Interface", "MAC", "IP", "Mask", "Status");
	// walk through the linked list
	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr == NULL)
			continue;

		if (ifa->ifa_addr->sa_family == AF_INET) {
			struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask;
			mask = ntohl(si->sin_addr.s_addr);
			si = (struct sockaddr_in *) ifa->ifa_addr;
			ip = ntohl(si->sin_addr.s_addr);

			// interface status
			char *status;
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
				status = "UP";
			else
				status = "DOWN";

			// ip address and mask
			char ipstr[30];
			sprintf(ipstr, "%d.%d.%d.%d", PRINT_IP(ip));
			char maskstr[30];
			sprintf(maskstr, "%d.%d.%d.%d", PRINT_IP(mask));
			
			// mac address
			unsigned char mac[6];
			net_get_mac(ifa->ifa_name, mac);
			char macstr[30];
			if (strcmp(ifa->ifa_name, "lo") == 0)
				macstr[0] = '\0';
			else
				sprintf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac));

			// print				
			printf("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n",
				ifa->ifa_name, macstr, ipstr, maskstr, status);

			// network scanning
			if (!arg_scan)				// scanning disabled
				continue;
			if (strcmp(ifa->ifa_name, "lo") == 0)	// no loopbabck scanning
				continue;
			if (mask2bits(mask) < 16)		// not scanning large networks
				continue;
			if (!ip)					// if not configured
				continue;
			// only if the interface is up and running
			if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP)
				arp_scan(ifa->ifa_name, ip, mask);
		}
	}
	freeifaddrs(ifaddr);
}
Пример #24
0
int sandbox(void* sandbox_arg) {
	// Get rid of unused parameter warning
	(void)sandbox_arg;

	pid_t child_pid = getpid();
	if (arg_debug)
		printf("Initializing child process\n");	

 	// close each end of the unused pipes
 	close(parent_to_child_fds[1]);
 	close(child_to_parent_fds[0]);
 
 	// wait for parent to do base setup
 	wait_for_other(parent_to_child_fds[0]);

	if (arg_debug && child_pid == 1)
		printf("PID namespace installed\n");

	//****************************
	// set hostname
	//****************************
	if (cfg.hostname) {
		if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0)
			errExit("sethostname");
	}

	//****************************
	// mount namespace
	//****************************
	// mount events are not forwarded between the host the sandbox
	if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
		chk_chroot();
	}
	
	//****************************
	// netfilter
	//****************************
	if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
		netfilter(arg_netfilter_file);
	}

	//****************************
	// trace pre-install
	//****************************
	if (arg_trace)
		fs_trace_preload();

	//****************************
	// configure filesystem
	//****************************
	
#ifdef HAVE_CHROOT		
	if (cfg.chrootdir) {
		fs_chroot(cfg.chrootdir);
		// force caps and seccomp if not started as root
		if (getuid() != 0) {
			// force default seccomp inside the chroot, no keep or drop list
			// the list build on top of the default drop list is kept intact
			arg_seccomp = 1;
			if (arg_seccomp_list_drop) {
				free(arg_seccomp_list_drop);
				arg_seccomp_list_drop = NULL;
			}
			if (arg_seccomp_list_keep) {
				free(arg_seccomp_list_keep);
				arg_seccomp_list_keep = NULL;
			}
			
			// disable all capabilities
			if (arg_caps_default_filter || arg_caps_list)
				fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n");
			arg_caps_drop_all = 1;
			
			// drop all supplementary groups; /etc/group file inside chroot
			// is controlled by a regular usr
			arg_nogroups = 1;
			printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
		}
						
		//****************************
		// trace pre-install, this time inside chroot
		//****************************
		if (arg_trace)
			fs_trace_preload();
	}
	else 
#endif		
	if (arg_overlay)
		fs_overlayfs();
	else
		fs_basic_fs();
	

	//****************************
	// set hostname in /etc/hostname
	//****************************
	if (cfg.hostname) {
		fs_hostname(cfg.hostname);
	}
	
	//****************************
	// apply the profile file
	//****************************
	if (cfg.profile)
		fs_blacklist(cfg.homedir);
	
	//****************************
	// private mode
	//****************************
	if (arg_private) {
		if (cfg.home_private)	// --private=
			fs_private_homedir();
		else if (cfg.home_private_keep) // --private-home=
			fs_private_home_list();
		else // --private
			fs_private();
	}
	
	if (arg_private_dev)
		fs_private_dev();
	if (arg_private_etc)
		fs_private_etc_list();
	
	//****************************
	// install trace
	//****************************
	if (arg_trace)
		fs_trace();
		
	//****************************
	// update /proc, /dev, /boot directorymy
	//****************************
	fs_proc_sys_dev_boot();
	
	//****************************
	// networking
	//****************************
	if (arg_nonetwork) {
		net_if_up("lo");
		if (arg_debug)
			printf("Network namespace enabled, only loopback interface available\n");
	}
	else if (any_bridge_configured()) {
		// configure lo and eth0...eth3
		net_if_up("lo");
		
		if (mac_not_zero(cfg.bridge0.macsandbox))
			net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
		sandbox_if_up(&cfg.bridge0);
		
		if (mac_not_zero(cfg.bridge1.macsandbox))
			net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
		sandbox_if_up(&cfg.bridge1);
		
		if (mac_not_zero(cfg.bridge2.macsandbox))
			net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
		sandbox_if_up(&cfg.bridge2);
		
		if (mac_not_zero(cfg.bridge3.macsandbox))
			net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
		sandbox_if_up(&cfg.bridge3);
		
		// add a default route
		if (cfg.defaultgw) {
			// set the default route
			if (net_add_route(0, 0, cfg.defaultgw))
				fprintf(stderr, "Warning: cannot configure default route\n");
		}
			
		if (arg_debug)
			printf("Network namespace enabled\n");
	}
	
	// if any dns server is configured, it is time to set it now
	fs_resolvconf();

	// print network configuration
	if (any_bridge_configured() || cfg.defaultgw || cfg.dns1) {
		printf("\n");
		if (any_bridge_configured())
			net_ifprint();
		if (cfg.defaultgw != 0)
			printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
		if (cfg.dns1 != 0)
			printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
		if (cfg.dns2 != 0)
			printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
		if (cfg.dns3 != 0)
			printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
		printf("\n");
	}
	
	

	//****************************
	// start executable
	//****************************
	prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
	int cwd = 0;
	if (cfg.cwd) {
		if (chdir(cfg.cwd) == 0)
			cwd = 1;
	}
	
	if (!cwd) {
		if (chdir("/") < 0)
			errExit("chdir");
		if (cfg.homedir) {
			struct stat s;
			if (stat(cfg.homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(cfg.homedir) < 0)
					errExit("chdir");
			}
		}
	}
	
	// set environment
	// fix qt 4.8
	if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
		errExit("setenv");
	if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
		errExit("setenv");
	if (arg_zsh && setenv("SHELL", "/usr/bin/zsh", 1) < 0)
		errExit("setenv");
	if (arg_csh && setenv("SHELL", "/bin/csh", 1) < 0)
		errExit("setenv");
	if (cfg.shell && setenv("SHELL", cfg.shell, 1) < 0)
		errExit("setenv");
	// set prompt color to green
	//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
	if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
		errExit("setenv");
	// set user-supplied environment variables
	env_apply();

	// set capabilities
	if (!arg_noroot)
		set_caps();

	// set rlimits
	set_rlimits();

	// set seccomp
#ifdef HAVE_SECCOMP
	// if a keep list is available, disregard the drop list
	if (arg_seccomp == 1) {
		if (arg_seccomp_list_keep)
			seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file
		else
			seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file
	}
#endif

	// set cpu affinity
	if (cfg.cpus) {
		save_cpu(); // save cpu affinity mask to MNT_DIR/cpu file
		set_cpu_affinity();
	}
	
	// save cgroup in MNT_DIR/cgroup file
	if (cfg.cgroup)
		save_cgroup();

	//****************************************
	// drop privileges or create a new user namespace
	//****************************************
	save_nogroups();
	if (arg_noroot) {
		int rv = unshare(CLONE_NEWUSER);
		if (rv == -1) {
			fprintf(stderr, "Error: cannot mount a new user namespace\n");
			perror("unshare");
			drop_privs(arg_nogroups);
		}
	}
	else
		drop_privs(arg_nogroups);
 	
	// notify parent that new user namespace has been created so a proper
 	// UID/GID map can be setup
 	notify_other(child_to_parent_fds[1]);
 	close(child_to_parent_fds[1]);
 
 	// wait for parent to finish setting up a proper UID/GID map
 	wait_for_other(parent_to_child_fds[0]);
 	close(parent_to_child_fds[0]);

	// somehow, the new user namespace resets capabilities;
	// we need to do them again
	if (arg_noroot) {
		set_caps();
		if (arg_debug)
			printf("User namespace (noroot) installed\n");
	}


	//****************************************
	// start the program without using a shell
	//****************************************
	if (arg_shell_none) {
		if (arg_debug) {
			int i;
			for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
				if (cfg.original_argv[i] == NULL)
					break;
				printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]);
			}
		}

		if (!arg_command)
			printf("Child process initialized\n");
		execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
	}
	//****************************************
	// start the program using a shell
	//****************************************
	else {
		// choose the shell requested by the user, or use bash as default
		char *sh;
		if (cfg.shell)
	 		sh = cfg.shell;
		else if (arg_zsh)
			sh = "/usr/bin/zsh";
		else if (arg_csh)
			sh = "/bin/csh";
		else
			sh = "/bin/bash";
			
		char *arg[5];
		int index = 0;
		arg[index++] = sh;
		arg[index++] = "-c";
		assert(cfg.command_line);
		if (arg_debug)
			printf("Starting %s\n", cfg.command_line);
		if (arg_doubledash) 
			arg[index++] = "--";
		arg[index++] = cfg.command_line;
		arg[index] = NULL;
		assert(index < 5);
		
		if (arg_debug) {
			char *msg;
			if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
				errExit("asprintf");
			logmsg(msg);
			free(msg);
		}
		
		if (arg_debug) {
			int i;
			for (i = 0; i < 5; i++) {
				if (arg[i] == NULL)
					break;
				printf("execvp argument %d: %s\n", i, arg[i]);
			}
		}
		
		if (!arg_command)
			printf("Child process initialized\n");
		execvp(sh, arg);
	}
	

	perror("execvp");
	return 0;
}
Пример #25
0
static void print_route(const char *fname) {
	FILE *fp = fopen(fname, "r");
	if (!fp)
		return;
	
	printf("  Route table:\n");
	char buf[MAXBUF];
	while (fgets(buf, MAXBUF, fp)) {
		// remove blanks, \n
		char *ptr = buf;
		while (*ptr == ' ' || *ptr == '\t')
			ptr++;
		char *start = ptr;
		if (*start == '\0')
			continue;
		ptr = strchr(ptr, '\n');
		if (ptr)
			*ptr = '\0';

		// remove table header
		//Iface	Destination	Gateway 	Flags	RefCnt	Use	Metric	Mask		MTU	Window	IRTT
		if (strncmp(start, "Iface", 5) == 0)
			continue;

		// extract data
		char ifname[64];
		char destination[64];
		char gateway[64];
		char flags[64];
		char refcnt[64];
		char use[64];
		char metric[64];
		char mask[64];
		int rv = sscanf(start, "%s %s %s %s %s %s %s %s\n", ifname, destination, gateway, flags, refcnt, use, metric, mask);
		if (rv != 8)
			continue;
		
		// destination ip
		uint32_t destip;
		sscanf(destination, "%x", &destip);
		destip = ntohl(destip);
		uint32_t destmask;
		sscanf(mask, "%x", &destmask);
		destmask = ntohl(destmask);
		uint32_t gw;
		sscanf(gateway, "%x", &gw);
		gw = ntohl(gw);
		
//		printf("#%s# #%s# #%s# #%s# #%s# #%s# #%s# #%s#\n", ifname, destination, gateway, flags, refcnt, use, metric, mask);
		if (gw != 0)
			printf("     %u.%u.%u.%u/%u via %u.%u.%u.%u, dev %s, metric %s\n",
				PRINT_IP(destip), mask2bits(destmask),
				PRINT_IP(gw),
				ifname,
				metric);
		else { // this is an interface
			IfList *ifentry = list_find(destip, destmask);
			if (ifentry) {
				printf("     %u.%u.%u.%u/%u, dev %s, scope link src %d.%d.%d.%d\n",
					PRINT_IP(destip), mask2bits(destmask),
					ifname,
					PRINT_IP(ifentry->ip));
			}
		}
	}
	
	fclose(fp);

}