예제 #1
0
int main(int argc, char **argv)
{

	uint32_t ip;
	if(atoip(argv[1], &ip)) {
		printf("Invalid IP address\n");
		return -1;
	}

	uint8_t mac[6];
	if (atomac(mac, argv[2])) {
		printf("Invalid mac address\n");
		return -1;

	}
	if(kernel_set_arp(ip, mac)) {
		printf("Arp entry not active\n");
	}

	return 0;

}
예제 #2
0
// standard ACL
int cliAclIcmpCmd(CliMode mode, int argc, char **argv) {
	char *data = (char *) pktout + sizeof(RcpPkt);
	*data = '\0';
	
	//
	// store incoming data in a temporary structure
	//
	RcpAclIcmp in;
	memset(&in, 0, sizeof(RcpAclIcmp));
	
	// no form
	int noform = 0;
	int index = 1;
	if (strcmp(argv[0], "no") == 0) {
		noform = 1;
		index++;
	}
		
	// list number
	uint8_t list_number = atoi(argv[index++]);
	
	// action
	uint8_t action;
	if (strcmp(argv[index++], "deny") == 0)
		action = RCPACL_ACTION_DENY;
	else
		action = RCPACL_ACTION_PERMIT;
	
	// mac address
	uint8_t mac[6];
	if (atomac(argv[index], mac) == 0) {
		memcpy(in.mac, mac, 6);
		index++;
	}
	else

	// skip "icmp"
	index++;

	// source address
	if (strcmp(argv[index], "any") == 0)
		;
	else {
		uint32_t ip;
		uint32_t mask;
		if (atocidr(argv[index], &ip, &mask)) {
			sprintf(data, "Error: invalid source IP address\n");
			return RCPERR;
		}
		uint8_t mask_bits = mask2bits(mask);
		in.ip = ip;
		in.mask_bits = mask_bits;
	}
	index++;
	
	// destination address/output interface
	if (strcmp(argv[index], "any") == 0)
		;
	else {
		uint32_t ip;
		uint32_t mask;
		if (atocidr(argv[index], &ip, &mask)) {
			sprintf(data, "Error: invalid destination IP address\n");
			return RCPERR;
		}
		uint8_t mask_bits = mask2bits(mask);
		in.dest_ip = ip;
		in.dest_mask_bits = mask_bits;
	}
	index++;

	// icmp type
	if ((argc - 1) == index)
		in.icmp_type = atoi(argv[index]);
	
	//
	// process acl
	//
	
	// find if this is an existing acl
	RcpAcl *found = acl_find(&in, RCP_ACL_TYPE_ICMP, action, list_number);
	
	// process command
	if (noform) {
		if (found == NULL)
			return 0;
			
		// remove acl
		found->valid = 0;
	}
	else {
		// already there?
		if (found != NULL)
			return 0;

		// allocate new acl
		RcpAcl *newacl = acl_find_empty();
		if (newacl == NULL) {
			strcpy(data, "Error: cannot configure ACL entry, limit reached");
			return RCPERR;
		}

		// copy the data
		memcpy(&newacl->u.icmp, &in, sizeof(RcpAclIcmp));
		newacl->valid = 1;
		newacl->type = RCP_ACL_TYPE_ICMP;
		newacl->action = action;
		newacl->list_number = list_number;
	}		
		
	// trigger netfilter configuration update
	netfilter_update = 2; 
	
	return 0;
}
예제 #3
0
// extended ACL
int cliAclCmd(CliMode mode, int argc, char **argv) {
	char *data = (char *) pktout + sizeof(RcpPkt);
	*data = '\0';
	
	//
	// store incoming data in a temporary structure
	//
	RcpAclExtended in;
	memset(&in, 0, sizeof(RcpAclExtended));
	
	// no form
	int noform = 0;
	int index = 1;
	if (strcmp(argv[0], "no") == 0) {
		noform = 1;
		index++;
	}
		
	// list number
	uint8_t list_number = atoi(argv[index++]);
	
	// action
	uint8_t action;
	if (strcmp(argv[index++], "deny") == 0)
		action = RCPACL_ACTION_DENY;
	else
		action = RCPACL_ACTION_PERMIT;
	

	// mac address
	uint8_t mac[6];
	if (atomac(argv[index], mac) == 0) {
		memcpy(in.mac, mac, 6);
		index++;
	}

	// protocol
	if (isnum(argv[index]))
		in.protocol = atoi(argv[index++]);
	else if (strcmp(argv[index], "tcp") == 0) {
		in.protocol = RCPACL_PROTOCOL_TCP;
		index++;
	}
	else if (strcmp(argv[index], "udp") == 0) {
		in.protocol = RCPACL_PROTOCOL_UDP;
		index++;
	}
	else
		in.protocol = RCPACL_PROTOCOL_ANY;
		
	// source address
	if (strcmp(argv[index], "any") == 0)
		;
	else {
		uint32_t ip;
		uint32_t mask;
		if (atocidr(argv[index], &ip, &mask)) {
			sprintf(data, "Error: invalid source IP address\n");
			return RCPERR;
		}
		uint8_t mask_bits = mask2bits(mask);
		in.ip = ip;
		in.mask_bits = mask_bits;
	}
	index++;
	
	// source port
	if (isnum(argv[index]))
		in.port = atoi(argv[index++]);
	
	// destination address/output interface
	if (strcmp(argv[index], "any") == 0)
		;
	else if (strcmp(argv[index], "out-interface") == 0) {
		strncpy(in.out_interface, argv[index + 1], RCP_MAX_IF_NAME);
		index++;
	}
	else {
		uint32_t ip;
		uint32_t mask;
		if (atocidr(argv[index], &ip, &mask)) {
			sprintf(data, "Error: invalid destination IP address\n");
			return RCPERR;
		}
		uint8_t mask_bits = mask2bits(mask);
		in.dest_ip = ip;
		in.dest_mask_bits = mask_bits;
	}
	index++;

	// destination port
	if (index < argc && isnum(argv[index]))
		in.dest_port = atoi(argv[index++]);
	
	// connection state
	if (index < argc) {
		// parsing
		char *str = argv[index];
		char *ptr = strtok(str, ",");
		in.constate = 0;
		while(ptr != NULL) {
			if (strcmp(ptr, "new") == 0)
				in.constate |= RCP_ACL_CONSTATE_NEW;
			else if (strcmp(ptr, "established") == 0)
				in.constate |= RCP_ACL_CONSTATE_ESTABLISHED;
			else if (strcmp(ptr, "related") == 0)
				in.constate |= RCP_ACL_CONSTATE_RELATED;
			else if (strcmp(ptr, "invalid") == 0)
				in.constate |= RCP_ACL_CONSTATE_INVALID;
			else {
				sprintf(data, "Error: invalid connecton state\n");
				return RCPERR;
			}
			
			ptr = strtok(NULL, ",");
		}
	} // this should be the last one, argv was modified by strtok


	//
	// process acl
	//
	
	// find if this is an existing acl
	RcpAcl *found = acl_find(&in, RCP_ACL_TYPE_EXTENDED, action, list_number);
	
	// process command
	if (noform) {
		if (found == NULL)
			return 0;
			
		// remove acl
		found->valid = 0;
	}
	else {
		// already there?
		if (found != NULL)
			return 0;

		// allocate new acl
		RcpAcl *newacl = acl_find_empty();
		if (newacl == NULL) {
			strcpy(data, "Error: cannot configure ACL entry, limit reached");
			return RCPERR;
		}

		// copy the data
		memcpy(&newacl->u.extended, &in, sizeof(RcpAclExtended));
		newacl->valid = 1;
		newacl->type = RCP_ACL_TYPE_EXTENDED;
		newacl->action = action;
		newacl->list_number = list_number;
	}		
		
	// trigger netfilter configuration update
	netfilter_update = 2; 
	
	return 0;
}
예제 #4
0
// check profile line; if line == 0, this was generated from a command line option
// return 1 if the command is to be added to the linked list of profile commands
// return 0 if the command was already executed inside the function
int profile_check_line(char *ptr, int lineno, const char *fname) {
	EUID_ASSERT();

	// check ignore list
	int i;
	for (i = 0; i < MAX_PROFILE_IGNORE; i++) {
		if (cfg.profile_ignore[i] == NULL)
			break;

		if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0)
			return 0;	// ignore line
	}

	if (strncmp(ptr, "ignore ", 7) == 0) {
		char *str = strdup(ptr + 7);
		if (*str == '\0') {
			fprintf(stderr, "Error: invalid ignore option\n");
			exit(1);
		}
		// find an empty entry in profile_ignore array
		int j;
		for (j = 0; j < MAX_PROFILE_IGNORE; j++) {
			if (cfg.profile_ignore[j] == NULL)
				break;
		}
		if (j >= MAX_PROFILE_IGNORE) {
			fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE);
			exit(1);
		}
		// ... and configure it
		else
			cfg.profile_ignore[j] = str;

		return 0;
	}

	// mkdir
	if (strncmp(ptr, "mkdir ", 6) == 0) {
		fs_mkdir(ptr + 6);
		return 1;	// process mkdir again while applying blacklists
	}
	// mkfile
	if (strncmp(ptr, "mkfile ", 7) == 0) {
		fs_mkfile(ptr + 7);
		return 1;	// process mkfile again while applying blacklists
	}
	// sandbox name
	else if (strncmp(ptr, "name ", 5) == 0) {
		cfg.name = ptr + 5;
		if (strlen(cfg.name) == 0) {
			fprintf(stderr, "Error: invalid sandbox name\n");
			exit(1);
		}
		return 0;
	}
	else if (strcmp(ptr, "ipc-namespace") == 0) {
		arg_ipc = 1;
		return 0;
	}
	// seccomp, caps, private, user namespace
	else if (strcmp(ptr, "noroot") == 0) {
#if HAVE_USERNS
		if (checkcfg(CFG_USERNS))
			check_user_namespace();
		else
			warning_feature_disabled("noroot");
#endif

		return 0;
	}
	else if (strcmp(ptr, "nonewprivs") == 0) {
		arg_nonewprivs = 1;
		return 0;
	}
	else if (strcmp(ptr, "seccomp") == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP))
			arg_seccomp = 1;
		else
			warning_feature_disabled("seccomp");
#endif
		return 0;
	}
	else if (strcmp(ptr, "caps") == 0) {
		arg_caps_default_filter = 1;
		return 0;
	}
	else if (strcmp(ptr, "caps.drop all") == 0) {
		arg_caps_drop_all = 1;
		return 0;
	}
	else if (strcmp(ptr, "shell none") == 0) {
		arg_shell_none = 1;
		return 0;
	}
	else if (strcmp(ptr, "tracelog") == 0) {
		arg_tracelog = 1;
		return 0;
	}
	else if (strcmp(ptr, "private") == 0) {
		arg_private = 1;
		return 0;
	}
	if (strncmp(ptr, "private-home ", 13) == 0) {
#ifdef HAVE_PRIVATE_HOME
		if (checkcfg(CFG_PRIVATE_HOME)) {
			if (cfg.home_private_keep) {
				if ( asprintf(&cfg.home_private_keep, "%s,%s", cfg.home_private_keep, ptr + 13) < 0 )
					errExit("asprintf");
			} else
				cfg.home_private_keep = ptr + 13;
			arg_private = 1;
		}
		else
			warning_feature_disabled("private-home");
#endif
		return 0;
	}
	else if (strcmp(ptr, "allusers") == 0) {
		arg_allusers = 1;
		return 0;
	}
	else if (strcmp(ptr, "private-dev") == 0) {
		arg_private_dev = 1;
		return 0;
	}
	else if (strcmp(ptr, "private-tmp") == 0) {
		arg_private_tmp = 1;
		return 0;
	}
	else if (strcmp(ptr, "nogroups") == 0) {
		arg_nogroups = 1;
		return 0;
	}
	else if (strcmp(ptr, "nosound") == 0) {
		arg_nosound = 1;
		return 0;
	}
	else if (strcmp(ptr, "novideo") == 0) {
		arg_novideo = 1;
		return 0;
	}
	else if (strcmp(ptr, "no3d") == 0) {
		arg_no3d = 1;
		return 0;
	}
	else if (strcmp(ptr, "allow-private-blacklist") == 0) {
		arg_allow_private_blacklist = 1;
		return 0;
	}
	else if (strcmp(ptr, "netfilter") == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK))
			arg_netfilter = 1;
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}
	else if (strncmp(ptr, "netfilter ", 10) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_netfilter = 1;
			arg_netfilter_file = strdup(ptr + 10);
			if (!arg_netfilter_file)
				errExit("strdup");
			check_netfilter_file(arg_netfilter_file);
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}
	else if (strncmp(ptr, "netfilter6 ", 11) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_netfilter6 = 1;
			arg_netfilter6_file = strdup(ptr + 11);
			if (!arg_netfilter6_file)
				errExit("strdup");
			check_netfilter_file(arg_netfilter6_file);
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}
	else if (strcmp(ptr, "net none") == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_nonetwork  = 1;
			cfg.bridge0.configured = 0;
			cfg.bridge1.configured = 0;
			cfg.bridge2.configured = 0;
			cfg.bridge3.configured = 0;
			cfg.interface0.configured = 0;
			cfg.interface1.configured = 0;
			cfg.interface2.configured = 0;
			cfg.interface3.configured = 0;
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}
	else if (strncmp(ptr, "net ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
#ifdef HAVE_NETWORK_RESTRICTED
			// compile time restricted networking
			if (getuid() != 0) {
				fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n");
				exit(1);
			}
#endif
			// run time restricted networking
			if (checkcfg(CFG_RESTRICTED_NETWORK) && getuid() != 0) {
				fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n");
				exit(1);
			}

			if (strcmp(ptr + 4, "lo") == 0) {
				fprintf(stderr, "Error: cannot attach to lo device\n");
				exit(1);
			}

			Bridge *br;
			if (cfg.bridge0.configured == 0)
				br = &cfg.bridge0;
			else if (cfg.bridge1.configured == 0)
				br = &cfg.bridge1;
			else if (cfg.bridge2.configured == 0)
				br = &cfg.bridge2;
			else if (cfg.bridge3.configured == 0)
				br = &cfg.bridge3;
			else {
				fprintf(stderr, "Error: maximum 4 network devices are allowed\n");
				exit(1);
			}
			net_configure_bridge(br, ptr + 4);
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "veth-name ", 10) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}

			br->veth_name = strdup(ptr + 10);
			if (br->veth_name == NULL)
				errExit("strdup");
			if (*br->veth_name == '\0') {
				fprintf(stderr, "Error: no veth-name configured\n");
				exit(1);
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "iprange ", 8) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->iprange_start || br->iprange_end) {
				fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n");
				exit(1);
			}

			// parse option arguments
			char *firstip = ptr + 8;
			char *secondip = firstip;
			while (*secondip != '\0') {
				if (*secondip == ',')
					break;
				secondip++;
			}
			if (*secondip == '\0') {
				fprintf(stderr, "Error: invalid IP range\n");
				exit(1);
			}
			*secondip = '\0';
			secondip++;

			// check addresses
			if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) ||
			    br->iprange_start >= br->iprange_end) {
				fprintf(stderr, "Error: invalid IP range\n");
				exit(1);
			}
			if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) {
				fprintf(stderr, "Error: IP range addresses not in network range\n");
				exit(1);
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}


	else if (strncmp(ptr, "mac ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}

			if (mac_not_zero(br->macsandbox)) {
				fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n");
				exit(1);
			}

			// read the address
			if (atomac(ptr + 4, br->macsandbox)) {
				fprintf(stderr, "Error: invalid MAC address\n");
				exit(1);
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "mtu ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}

			if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) {
				fprintf(stderr, "Error: invalid mtu value\n");
				exit(1);
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "ip ", 3) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->arg_ip_none || br->ipsandbox) {
				fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
				exit(1);
			}

			// configure this IP address for the last bridge defined
			if (strcmp(ptr + 3, "none") == 0)
				br->arg_ip_none = 1;
			else {
				if (atoip(ptr + 3, &br->ipsandbox)) {
					fprintf(stderr, "Error: invalid IP address\n");
					exit(1);
				}
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "ip6 ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->arg_ip_none || br->ip6sandbox) {
				fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
				exit(1);
			}

			// configure this IP address for the last bridge defined
			// todo: verify ipv6 syntax
			br->ip6sandbox = ptr + 4;
//			if (atoip(argv[i] + 5, &br->ipsandbox)) {
//				fprintf(stderr, "Error: invalid IP address\n");
//				exit(1);
//			}

		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	else if (strncmp(ptr, "defaultgw ", 10) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			if (atoip(ptr + 10, &cfg.defaultgw)) {
				fprintf(stderr, "Error: invalid IP address\n");
				exit(1);
			}
		}
		else
			warning_feature_disabled("networking");
#endif
		return 0;
	}

	if (strcmp(ptr, "apparmor") == 0) {
#ifdef HAVE_APPARMOR
		arg_apparmor = 1;
#endif
		return 0;
	}

	if (strncmp(ptr, "protocol ", 9) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			if (cfg.protocol) {
				fwarning("a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9);
				return 0;
			}

			// store list
			cfg.protocol = strdup(ptr + 9);
			if (!cfg.protocol)
				errExit("strdup");
		}
		else
			warning_feature_disabled("seccomp");
#endif
		return 0;
	}

	if (strncmp(ptr, "env ", 4) == 0) {
		env_store(ptr + 4, SETENV);
		return 0;
	}
	if (strncmp(ptr, "rmenv ", 6) == 0) {
		env_store(ptr + 6, RMENV);
		return 0;
	}

	// seccomp drop list on top of default list
	if (strncmp(ptr, "seccomp ", 8) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list = seccomp_check_list(ptr + 8);
		}
		else if (!arg_quiet)
			warning_feature_disabled("seccomp");
#endif

		return 0;
	}

	// seccomp drop list without default list
	if (strncmp(ptr, "seccomp.drop ", 13) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list_drop = seccomp_check_list(ptr + 13);
		}
		else
			warning_feature_disabled("seccomp");
#endif
		return 0;
	}

	// seccomp keep list
	if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list_keep= seccomp_check_list(ptr + 13);
		}
		else
			warning_feature_disabled("seccomp");
#endif
		return 0;
	}

	// caps drop list
	if (strncmp(ptr, "caps.drop ", 10) == 0) {
		arg_caps_drop = 1;
		arg_caps_list = strdup(ptr + 10);
		if (!arg_caps_list)
			errExit("strdup");
		// verify caps list and exit if problems
		caps_check_list(arg_caps_list, NULL);
		return 0;
	}

	// caps keep list
	if (strncmp(ptr, "caps.keep ", 10) == 0) {
		arg_caps_keep = 1;
		arg_caps_list = strdup(ptr + 10);
		if (!arg_caps_list)
			errExit("strdup");
		// verify caps list and exit if problems
		caps_check_list(arg_caps_list, NULL);
		return 0;
	}

	// hostname
	if (strncmp(ptr, "hostname ", 9) == 0) {
		cfg.hostname = ptr + 9;
		return 0;
	}

	// hosts-file
	if (strncmp(ptr, "hosts-file ", 11) == 0) {
		cfg.hosts_file = fs_check_hosts_file(ptr + 11);
		return 0;
	}

	// dns
	if (strncmp(ptr, "dns ", 4) == 0) {
		uint32_t dns;
		if (atoip(ptr + 4, &dns)) {
			fprintf(stderr, "Error: invalid DNS server IP address\n");
			return 1;
		}

		if (cfg.dns1 == 0)
			cfg.dns1 = dns;
		else if (cfg.dns2 == 0)
			cfg.dns2 = dns;
		else if (cfg.dns3 == 0)
			cfg.dns3 = dns;
		else {
			fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
			return 1;
		}
		return 0;
	}

	// cpu affinity
	if (strncmp(ptr, "cpu ", 4) == 0) {
		read_cpu_list(ptr + 4);
		return 0;
	}

	// nice value
	if (strncmp(ptr, "nice ", 4) == 0) {
		cfg.nice = atoi(ptr + 5);
		if (getuid() != 0 &&cfg.nice < 0)
			cfg.nice = 0;
		arg_nice = 1;
		return 0;
	}

	// cgroup
	if (strncmp(ptr, "cgroup ", 7) == 0) {
		set_cgroup(ptr + 7);
		return 0;
	}

	// writable-etc
	if (strcmp(ptr, "writable-etc") == 0) {
		if (cfg.etc_private_keep) {
			fprintf(stderr, "Error: private-etc and writable-etc are mutually exclusive\n");
			exit(1);
		}
		arg_writable_etc = 1;
		return 0;
	}

	if (strcmp(ptr, "machine-id") == 0) {
		arg_machineid = 1;
		return 0;
	}
	// writable-var
	if (strcmp(ptr, "writable-var") == 0) {
		arg_writable_var = 1;
		return 0;
	}
	if (strcmp(ptr, "writable-var-log") == 0) {
		arg_writable_var_log = 1;
		return 0;
	}

	// private directory
	if (strncmp(ptr, "private ", 8) == 0) {
		cfg.home_private = ptr + 8;
		fs_check_private_dir();
		arg_private = 1;
		return 0;
	}

	if (strcmp(ptr, "x11 none") == 0) {
		arg_x11_block = 1;
		return 0;
	}

	if (strcmp(ptr, "x11 xephyr") == 0) {
#ifdef HAVE_X11
		if (checkcfg(CFG_X11)) {
			char *x11env = getenv("FIREJAIL_X11");
			if (x11env && strcmp(x11env, "yes") == 0) {
				return 0;
			}
			else {
				// start x11
				x11_start_xephyr(cfg.original_argc, cfg.original_argv);
				exit(0);
			}
		}
		else
			warning_feature_disabled("x11");
#endif
		return 0;
	}

	if (strcmp(ptr, "x11 xorg") == 0) {
#ifdef HAVE_X11
		if (checkcfg(CFG_X11))
			arg_x11_xorg = 1;
		else
			warning_feature_disabled("x11");
#endif
		return 0;
	}

	if (strcmp(ptr, "x11 xpra") == 0) {
#ifdef HAVE_X11
		if (checkcfg(CFG_X11)) {
			char *x11env = getenv("FIREJAIL_X11");
			if (x11env && strcmp(x11env, "yes") == 0) {
				return 0;
			}
			else {
				// start x11
				x11_start_xpra(cfg.original_argc, cfg.original_argv);
				exit(0);
			}
		}
		else
			warning_feature_disabled("x11");
#endif
		return 0;
	}

	if (strcmp(ptr, "x11 xvfb") == 0) {
#ifdef HAVE_X11
		if (checkcfg(CFG_X11)) {
			char *x11env = getenv("FIREJAIL_X11");
			if (x11env && strcmp(x11env, "yes") == 0) {
				return 0;
			}
			else {
				// start x11
				x11_start_xvfb(cfg.original_argc, cfg.original_argv);
				exit(0);
			}
		}
		else
			warning_feature_disabled("x11");
#endif
		return 0;
	}

	if (strcmp(ptr, "x11") == 0) {
#ifdef HAVE_X11
		if (checkcfg(CFG_X11)) {
			char *x11env = getenv("FIREJAIL_X11");
			if (x11env && strcmp(x11env, "yes") == 0) {
				return 0;
			}
			else {
				// start x11
				x11_start(cfg.original_argc, cfg.original_argv);
				exit(0);
			}
		}
		else
			warning_feature_disabled("x11");
#endif
		return 0;
	}

	// private /etc list of files and directories
	if (strncmp(ptr, "private-etc ", 12) == 0) {
		if (arg_writable_etc) {
			fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n");
			exit(1);
		}
		if (cfg.etc_private_keep) {
			if ( asprintf(&cfg.etc_private_keep, "%s,%s", cfg.etc_private_keep, ptr + 12) < 0 )
				errExit("asprintf");
		} else {
			cfg.etc_private_keep = ptr + 12;
		}
		arg_private_etc = 1;

		return 0;
	}

	// private /opt list of files and directories
	if (strncmp(ptr, "private-opt ", 12) == 0) {
		if (cfg.opt_private_keep) {
			if ( asprintf(&cfg.opt_private_keep, "%s,%s", cfg.opt_private_keep, ptr + 12) < 0 )
				errExit("asprintf");
		} else {
			cfg.opt_private_keep = ptr + 12;
		}
		arg_private_opt = 1;

		return 0;
	}

	// private /srv list of files and directories
	if (strncmp(ptr, "private-srv ", 12) == 0) {
		if (cfg.srv_private_keep) {
			if ( asprintf(&cfg.srv_private_keep, "%s,%s", cfg.srv_private_keep, ptr + 12) < 0 )
				errExit("asprintf");
		} else {
			cfg.srv_private_keep = ptr + 12;
		}
		arg_private_srv = 1;

		return 0;
	}

	// private /bin list of files
	if (strncmp(ptr, "private-bin ", 12) == 0) {
		if (cfg.bin_private_keep) {
			if ( asprintf(&cfg.bin_private_keep, "%s,%s", cfg.bin_private_keep, ptr + 12) < 0 )
				errExit("asprintf");
		} else {
			cfg.bin_private_keep = ptr + 12;
		}
		arg_private_bin = 1;
		return 0;
	}


#ifdef HAVE_OVERLAYFS
	if (strncmp(ptr, "overlay-named ", 14) == 0) {
		if (checkcfg(CFG_OVERLAYFS)) {
			if (cfg.chrootdir) {
				fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
				exit(1);
			}
			struct stat s;
			if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
				fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
				exit(1);
			}
			arg_overlay = 1;
			arg_overlay_keep = 1;
			arg_overlay_reuse = 1;

			char *subdirname = ptr + 14;
			if (subdirname == '\0') {
				fprintf(stderr, "Error: invalid overlay option\n");
				exit(1);
			}

			// check name
			invalid_filename(subdirname);
			if (strstr(subdirname, "..") || strstr(subdirname, "/")) {
				fprintf(stderr, "Error: invalid overlay name\n");
				exit(1);
			}
			cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);
		}

		return 0;
	} else if (strcmp(ptr, "overlay-tmpfs") == 0) {
		if (checkcfg(CFG_OVERLAYFS)) {
			if (cfg.chrootdir) {
				fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
				exit(1);
			}
			struct stat s;
			if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
				fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
				exit(1);
			}
			arg_overlay = 1;

			return 0;
		}
	} else if (strcmp(ptr, "overlay") == 0) {
		if (checkcfg(CFG_OVERLAYFS)) {
			if (cfg.chrootdir) {
				fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
				exit(1);
			}
			struct stat s;
			if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
				fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
				exit(1);
			}
			arg_overlay = 1;
			arg_overlay_keep = 1;

			char *subdirname;
			if (asprintf(&subdirname, "%d", getpid()) == -1)
				errExit("asprintf");
			cfg.overlay_dir = fs_check_overlay_dir(subdirname, arg_overlay_reuse);

			free(subdirname);

			return 0;
		}
	}
#endif

	// filesystem bind
	if (strncmp(ptr, "bind ", 5) == 0) {
#ifdef HAVE_BIND
		if (checkcfg(CFG_BIND)) {
			if (getuid() != 0) {
				fprintf(stderr, "Error: --bind option is available only if running as root\n");
				exit(1);
			}

			// extract two directories
			char *dname1 = ptr + 5;
			char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories
			if (dname2 == NULL) {
				fprintf(stderr, "Error: missing second directory for bind\n");
				exit(1);
			}

			// check directories
			invalid_filename(dname1);
			invalid_filename(dname2);
			if (strstr(dname1, "..") || strstr(dname2, "..")) {
				fprintf(stderr, "Error: invalid file name.\n");
				exit(1);
			}
			if (is_link(dname1) || is_link(dname2)) {
				fprintf(stderr, "Symbolic links are not allowed for bind command\n");
				exit(1);
			}

			// insert comma back
			*(dname2 - 1) = ',';
			return 1;
		}
		else
			warning_feature_disabled("bind");
#endif
		return 0;
	}

	// rlimit
	if (strncmp(ptr, "rlimit", 6) == 0) {
		if (strncmp(ptr, "rlimit-nofile ", 14) == 0) {
			check_unsigned(ptr + 14, "Error: invalid rlimit in profile file: ");
			sscanf(ptr + 14, "%llu", &cfg.rlimit_nofile);
			arg_rlimit_nofile = 1;
		}
		else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) {
			check_unsigned(ptr + 13, "Error: invalid rlimit in profile file: ");
			sscanf(ptr + 13, "%llu", &cfg.rlimit_nproc);
			arg_rlimit_nproc = 1;
		}
		else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) {
			check_unsigned(ptr + 13, "Error: invalid rlimit in profile file: ");
			sscanf(ptr + 13, "%llu", &cfg.rlimit_fsize);
			arg_rlimit_fsize = 1;
		}
		else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) {
			check_unsigned(ptr + 18, "Error: invalid rlimit in profile file: ");
			sscanf(ptr + 18, "%llu", &cfg.rlimit_sigpending);
			arg_rlimit_sigpending = 1;
		}
		else {
			fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
			exit(1);
		}

		return 0;
	}

	if (strncmp(ptr, "join-or-start ", 14) == 0) {
		// try to join by name only
		pid_t pid;
		if (!name2pid(ptr + 14, &pid)) {
			if (!cfg.shell && !arg_shell_none)
				cfg.shell = guess_shell();

			// find first non-option arg
			int i;
			for (i = 1; i < cfg.original_argc && strncmp(cfg.original_argv[i], "--", 2) != 0; i++);

			join(pid, cfg.original_argc,cfg.original_argv, i + 1);
			exit(0);
		}

		// set sandbox name and start normally
		cfg.name = ptr + 14;
		if (strlen(cfg.name) == 0) {
			fprintf(stderr, "Error: invalid sandbox name\n");
			exit(1);
		}
		return 0;
	}

	// rest of filesystem
	if (strncmp(ptr, "blacklist ", 10) == 0)
		ptr += 10;
	else if (strncmp(ptr, "blacklist-nolog ", 16) == 0)
		ptr += 16;
	else if (strncmp(ptr, "noblacklist ", 12) == 0)
		ptr += 12;
	else if (strncmp(ptr, "whitelist ", 10) == 0) {
#ifdef HAVE_WHITELIST
		if (checkcfg(CFG_WHITELIST)) {
			arg_whitelist = 1;
			ptr += 10;
		}
		else
			return 0;
#else
		return 0;
#endif
	}
	else if (strncmp(ptr, "nowhitelist ", 12) == 0)
		ptr += 12;
	else if (strncmp(ptr, "read-only ", 10) == 0)
		ptr += 10;
	else if (strncmp(ptr, "read-write ", 11) == 0)
		ptr += 11;
	else if (strncmp(ptr, "noexec ", 7) == 0)
		ptr += 7;
	else if (strncmp(ptr, "tmpfs ", 6) == 0) {
		if (getuid() != 0) {
			fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n");
			exit(1);
		}
		ptr += 6;
	}
	else {
		if (lineno == 0)
			fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr);
		else if (fname != NULL)
			fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname);
		else
			fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
		exit(1);
	}

	// some characters just don't belong in filenames
	invalid_filename(ptr);
	if (strstr(ptr, "..")) {
		if (lineno == 0)
			fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
		else if (fname != NULL)
			fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname);
		else
			fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
		exit(1);
	}
	return 1;
}
예제 #5
0
파일: http.c 프로젝트: Bob4ik888/WebRadio
void http_settings(char *rx, unsigned int rx_len)
{
  unsigned int item, found, len;
  int i;
  char buf[16];
  MAC_Addr mac;
  IP_Addr ip;
  unsigned int rgb;

  for(; rx_len!=0;)
  {
    len = strlen("restartwebradio=");
    if(strncmpi(rx, "restartwebradio=", len) == 0)
    {
      rx += len; rx_len -= len;
      cpu_reset();
    }

    for(item=0, found=0; item<SETTINGSITEMS; item++)
    {
      if(settingsmenu[item].ini[0] == 0)
      {
        continue;
      }
      len = sprintf(buf, "%s=", settingsmenu[item].ini);
      if(strncmpi(rx, buf, len) == 0)
      {
        rx += len; rx_len -= len;
        len = url_decode(rx, rx, rx_len);
        i   = 0;
        switch(settingsmenu[item].format)
        {
          case F_NR:  //p1-p2, p3=step size
            i = atoi(rx);
                 if(i < settingsmenu[item].p1){ i = settingsmenu[item].p1; }
            else if(i > settingsmenu[item].p2){ i = settingsmenu[item].p2; }
            itoa(i, buf, 10);
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf);
            if(settingsmenu[item].set){ settingsmenu[item].set((void*)(int)i); }
            break;

          case F_OR:  //p1 or p2
            i = atoi(rx);
            if((i != settingsmenu[item].p1) && 
               (i != settingsmenu[item].p2)){ i = settingsmenu[item].p1; }
            itoa(i, buf, 10);
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf);
            if(settingsmenu[item].set){ settingsmenu[item].set((void*)(int)i); }
            break;

          case F_STR: //p1=max len
            if((settingsmenu[item].p1 != 0) &&
              (strlen(rx) > (unsigned)settingsmenu[item].p1))
            {
              rx[settingsmenu[item].p1] = 0;
            }
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, rx);
            if(settingsmenu[item].set){ settingsmenu[item].set(rx); }
            break;

          case F_MAC:
            mac = atomac(rx);
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, mactoa(mac));
            //if(settingsmenu[item].set){ settingsmenu[item].set((void*)(MAC_Addr)mac); }
            break;

          case F_IP:
            ip = atoip(rx);
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, iptoa(ip));
            if(settingsmenu[item].set){ settingsmenu[item].set((void*)(IP_Addr)atoip(rx)); }
            break;

          case F_RGB:
            rgb = atorgb(rx);
            sprintf(buf, "%03i,%03i,%03i", GET_RED(rgb), GET_GREEN(rgb), GET_BLUE(rgb));
            ini_setentry(SETTINGS_FILE, settingsmenu[item].ini, buf);
            if(settingsmenu[item].set){ settingsmenu[item].set((void*)(unsigned int)rgb); }
            break;
        }
        rx += len; rx_len -= len;
        found = 1;
        break;
      }
    }
    if(found == 0)
    {
      rx++; rx_len--;
    }
  }

  menu_drawwnd(1);

  return;
}
예제 #6
0
// check profile line; if line == 0, this was generated from a command line option
// return 1 if the command is to be added to the linked list of profile commands
// return 0 if the command was already executed inside the function
int profile_check_line(char *ptr, int lineno, const char *fname) {
	EUID_ASSERT();
	
	// check ignore list
	int i;
	for (i = 0; i < MAX_PROFILE_IGNORE; i++) {
		if (cfg.profile_ignore[i] == NULL)
			break;
		
		if (strncmp(ptr, cfg.profile_ignore[i], strlen(cfg.profile_ignore[i])) == 0)
			return 0;	// ignore line
	}
	
	if (strncmp(ptr, "ignore ", 7) == 0) {
		char *str = strdup(ptr + 7);
		if (*str == '\0') {
			fprintf(stderr, "Error: invalid ignore option\n");
			exit(1);
		}
		// find an empty entry in profile_ignore array
		int j;
		for (j = 0; j < MAX_PROFILE_IGNORE; j++) {
			if (cfg.profile_ignore[j] == NULL) 
				break;
		}
		if (j >= MAX_PROFILE_IGNORE) {
			fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE);
			exit(1);
		}
		// ... and configure it
		else 
			cfg.profile_ignore[j] = str;

		return 0;
	}

	// mkdir 
	if (strncmp(ptr, "mkdir ", 6) == 0) {
		fs_mkdir(ptr + 6);
		return 0;
	}
	// sandbox name
	else if (strncmp(ptr, "name ", 5) == 0) {
		cfg.name = ptr + 5;
		if (strlen(cfg.name) == 0) {
			fprintf(stderr, "Error: invalid sandbox name\n");
			exit(1);
		}
		return 0;
	}
	else if (strcmp(ptr, "ipc-namespace") == 0) {
		arg_ipc = 1;
		return 0;
	}
	// seccomp, caps, private, user namespace
	else if (strcmp(ptr, "noroot") == 0) {
#if HAVE_USERNS
		if (checkcfg(CFG_USERNS))
			check_user_namespace();
		else
			fprintf(stderr, "Warning: user namespace feature is disabled in Firejail configuration file\n");
#endif

		return 0;
	}
	else if (strcmp(ptr, "nonewprivs") == 0) {
		arg_nonewprivs = 1;
		return 0;
	}
	else if (strcmp(ptr, "seccomp") == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP))
			arg_seccomp = 1;
		else
			fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	else if (strcmp(ptr, "caps") == 0) {
		arg_caps_default_filter = 1;
		return 0;
	}
	else if (strcmp(ptr, "caps.drop all") == 0) {
		arg_caps_drop_all = 1;
		return 0;
	}
	else if (strcmp(ptr, "shell none") == 0) {
		arg_shell_none = 1;
		return 0;
	}	
	else if (strcmp(ptr, "tracelog") == 0) {
		arg_tracelog = 1;
		return 0;
	}
	else if (strcmp(ptr, "private") == 0) {
		arg_private = 1;
		return 0;
	}
	else if (strcmp(ptr, "private-dev") == 0) {
		arg_private_dev = 1;
		return 0;
	}
	else if (strcmp(ptr, "private-tmp") == 0) {
		arg_private_tmp = 1;
		return 0;
	}
	else if (strcmp(ptr, "nogroups") == 0) {
		arg_nogroups = 1;
		return 0;
	}
	else if (strcmp(ptr, "nosound") == 0) {
		arg_nosound = 1;
		arg_private_dev = 1;
		return 0;
	}
	else if (strcmp(ptr, "netfilter") == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK))
			arg_netfilter = 1;
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	else if (strncmp(ptr, "netfilter ", 10) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_netfilter = 1;
			arg_netfilter_file = strdup(ptr + 10);
			if (!arg_netfilter_file)
				errExit("strdup");
			check_netfilter_file(arg_netfilter_file);
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	else if (strncmp(ptr, "netfilter6 ", 11) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_netfilter6 = 1;
			arg_netfilter6_file = strdup(ptr + 11);
			if (!arg_netfilter6_file)
				errExit("strdup");
			check_netfilter_file(arg_netfilter6_file);
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	else if (strcmp(ptr, "net none") == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			arg_nonetwork  = 1;
			cfg.bridge0.configured = 0;
			cfg.bridge1.configured = 0;
			cfg.bridge2.configured = 0;
			cfg.bridge3.configured = 0;
			cfg.interface0.configured = 0;
			cfg.interface1.configured = 0;
			cfg.interface2.configured = 0;
			cfg.interface3.configured = 0;
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	else if (strncmp(ptr, "net ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
#ifdef HAVE_NETWORK_RESTRICTED
			// compile time restricted networking
			if (getuid() != 0) {
				fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n");
				exit(1);
			}
#endif
			// run time restricted networking
			if (checkcfg(CFG_RESTRICTED_NETWORK) && getuid() != 0) {
				fprintf(stderr, "Error: only \"net none\" is allowed to non-root users\n");
				exit(1);
			}
			
			if (strcmp(ptr + 4, "lo") == 0) {
				fprintf(stderr, "Error: cannot attach to lo device\n");
				exit(1);
			}

			Bridge *br;
			if (cfg.bridge0.configured == 0)
				br = &cfg.bridge0;
			else if (cfg.bridge1.configured == 0)
				br = &cfg.bridge1;
			else if (cfg.bridge2.configured == 0)
				br = &cfg.bridge2;
			else if (cfg.bridge3.configured == 0)
				br = &cfg.bridge3;
			else {
				fprintf(stderr, "Error: maximum 4 network devices are allowed\n");
				exit(1);
			}
			net_configure_bridge(br, ptr + 4);
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	
	else if (strncmp(ptr, "iprange ", 8) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->iprange_start || br->iprange_end) {
				fprintf(stderr, "Error: cannot configure the IP range twice for the same interface\n");
				exit(1);
			}

			// parse option arguments
			char *firstip = ptr + 8;
			char *secondip = firstip;
			while (*secondip != '\0') {
				if (*secondip == ',')
					break;
				secondip++;
			}
			if (*secondip == '\0') {
				fprintf(stderr, "Error: invalid IP range\n");
				exit(1);
			}
			*secondip = '\0';
			secondip++;
			
			// check addresses
			if (atoip(firstip, &br->iprange_start) || atoip(secondip, &br->iprange_end) ||
			    br->iprange_start >= br->iprange_end) {
				fprintf(stderr, "Error: invalid IP range\n");
				exit(1);
			}
			if (in_netrange(br->iprange_start, br->ip, br->mask) || in_netrange(br->iprange_end, br->ip, br->mask)) {
				fprintf(stderr, "Error: IP range addresses not in network range\n");
				exit(1);
			}
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}


// from here
	else if (strncmp(ptr, "mac ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			
			if (mac_not_zero(br->macsandbox)) {
				fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n");
				exit(1);
			}

			// read the address
			if (atomac(ptr + 4, br->macsandbox)) {
				fprintf(stderr, "Error: invalid MAC address\n");
				exit(1);
			}
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}

	else if (strncmp(ptr, "mtu ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			
			if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) {
				fprintf(stderr, "Error: invalid mtu value\n");
				exit(1);
			}
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}

	else if (strncmp(ptr, "ip ", 3) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->arg_ip_none || br->ipsandbox) {
				fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
				exit(1);
			}

			// configure this IP address for the last bridge defined
			if (strcmp(ptr + 3, "none") == 0)
				br->arg_ip_none = 1;
			else {
				if (atoip(ptr + 3, &br->ipsandbox)) {
					fprintf(stderr, "Error: invalid IP address\n");
					exit(1);
				}
			}
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}

	else if (strncmp(ptr, "ip6 ", 4) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			Bridge *br = last_bridge_configured();
			if (br == NULL) {
				fprintf(stderr, "Error: no network device configured\n");
				exit(1);
			}
			if (br->arg_ip_none || br->ip6sandbox) {
				fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n");
				exit(1);
			}

			// configure this IP address for the last bridge defined
			// todo: verify ipv6 syntax
			br->ip6sandbox = ptr + 4;
//			if (atoip(argv[i] + 5, &br->ipsandbox)) {
//				fprintf(stderr, "Error: invalid IP address\n");
//				exit(1);
//			}
			
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}

	else if (strncmp(ptr, "defaultgw ", 10) == 0) {
#ifdef HAVE_NETWORK
		if (checkcfg(CFG_NETWORK)) {
			if (atoip(ptr + 10, &cfg.defaultgw)) {
				fprintf(stderr, "Error: invalid IP address\n");
				exit(1);
			}
		}
		else
			fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n");
#endif
		return 0;
	}

	if (strncmp(ptr, "protocol ", 9) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP))
			protocol_store(ptr + 9);
		else
			fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
#endif
		return 0;
	}
	
	if (strncmp(ptr, "env ", 4) == 0) {
		env_store(ptr + 4);
		return 0;
	}
	
	// seccomp drop list on top of default list
	if (strncmp(ptr, "seccomp ", 8) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list = strdup(ptr + 8);
			if (!cfg.seccomp_list)
				errExit("strdup");
		}
		else
			fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
#endif

		return 0;
	}
	
	// seccomp drop list without default list
	if (strncmp(ptr, "seccomp.drop ", 13) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list_drop = strdup(ptr + 13);
			if (!cfg.seccomp_list_drop)
				errExit("strdup");
		}
		else
			fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
#endif		
		return 0;
	}

	// seccomp keep list
	if (strncmp(ptr, "seccomp.keep ", 13) == 0) {
#ifdef HAVE_SECCOMP
		if (checkcfg(CFG_SECCOMP)) {
			arg_seccomp = 1;
			cfg.seccomp_list_keep= strdup(ptr + 13);
			if (!cfg.seccomp_list_keep)
				errExit("strdup");
		}
		else
			fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
#endif		
		return 0;
	}
	
	// caps drop list
	if (strncmp(ptr, "caps.drop ", 10) == 0) {
		arg_caps_drop = 1;
		arg_caps_list = strdup(ptr + 10);
		if (!arg_caps_list)
			errExit("strdup");
		// verify seccomp list and exit if problems
		if (caps_check_list(arg_caps_list, NULL))
			exit(1);
		return 0;
	}
	
	// caps keep list
	if (strncmp(ptr, "caps.keep ", 10) == 0) {
		arg_caps_keep = 1;
		arg_caps_list = strdup(ptr + 10);
		if (!arg_caps_list)
			errExit("strdup");
		// verify seccomp list and exit if problems
		if (caps_check_list(arg_caps_list, NULL))
			exit(1);
		return 0;
	}

	// hostname
	if (strncmp(ptr, "hostname ", 9) == 0) {
		cfg.hostname = ptr + 9;
		return 0;
	}
	
	// dns
	if (strncmp(ptr, "dns ", 4) == 0) {
		uint32_t dns;
		if (atoip(ptr + 4, &dns)) {
			fprintf(stderr, "Error: invalid DNS server IP address\n");
			return 1;
		}
		
		if (cfg.dns1 == 0)
			cfg.dns1 = dns;
		else if (cfg.dns2 == 0)
			cfg.dns2 = dns;
		else if (cfg.dns3 == 0)
			cfg.dns3 = dns;
		else {
			fprintf(stderr, "Error: up to 3 DNS servers can be specified\n");
			return 1;
		}
		return 0;
	}
	
	// cpu affinity
	if (strncmp(ptr, "cpu ", 4) == 0) {
		read_cpu_list(ptr + 4);
		return 0;
	}
	
	// nice value
	if (strncmp(ptr, "nice ", 4) == 0) {
		cfg.nice = atoi(ptr + 5);
		if (getuid() != 0 &&cfg.nice < 0)
			cfg.nice = 0;
		arg_nice = 1;
		return 0;
	}

	// cgroup
	if (strncmp(ptr, "cgroup ", 7) == 0) {
		set_cgroup(ptr + 7);
		return 0;
	}
	
	// writable-etc
	if (strcmp(ptr, "writable-etc") == 0) {
		if (cfg.etc_private_keep) {
			fprintf(stderr, "Error: private-etc and writable-etc are mutually exclusive\n");
			exit(1);
		}
		arg_writable_etc = 1;
		return 0;
	}
	
	// writable-var
	if (strcmp(ptr, "writable-var") == 0) {
		arg_writable_var = 1;
		return 0;
	}
	
	// private directory
	if (strncmp(ptr, "private ", 8) == 0) {
		cfg.home_private = ptr + 8;
		fs_check_private_dir();
		arg_private = 1;
		return 0;
	}

	// private /etc list of files and directories
	if (strncmp(ptr, "private-etc ", 12) == 0) {
		if (arg_writable_etc) {
			fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n");
			exit(1);
		}
		cfg.etc_private_keep = ptr + 12;
		fs_check_etc_list();
		arg_private_etc = 1;
		
		return 0;
	}

	// private /bin list of files
	if (strncmp(ptr, "private-bin ", 12) == 0) {
		cfg.bin_private_keep = ptr + 12;
		arg_private_bin = 1;
		fs_check_bin_list();
		return 0;
	}

	// filesystem bind
	if (strncmp(ptr, "bind ", 5) == 0) {
#ifdef HAVE_BIND		
		if (checkcfg(CFG_BIND)) {
			if (getuid() != 0) {
				fprintf(stderr, "Error: --bind option is available only if running as root\n");
				exit(1);
			}
	
			// extract two directories
			char *dname1 = ptr + 5;
			char *dname2 = split_comma(dname1); // this inserts a '0 to separate the two dierctories
			if (dname2 == NULL) {
				fprintf(stderr, "Error: missing second directory for bind\n");
				exit(1);
			}
			
			// check directories
			invalid_filename(dname1);
			invalid_filename(dname2);
			if (strstr(dname1, "..") || strstr(dname2, "..")) {
				fprintf(stderr, "Error: invalid file name.\n");
				exit(1);
			}
			if (is_link(dname1) || is_link(dname2)) {
				fprintf(stderr, "Symbolic links are not allowed for bind command\n");
				exit(1);
			}
			
			// insert comma back
			*(dname2 - 1) = ',';
			return 1;
		}
		else {
			fprintf(stderr, "Warning: bind feature is disabled in Firejail configuration file\n");
			return 0;			
		}
#else
		return 0;
#endif		
	}

	// rlimit
	if (strncmp(ptr, "rlimit", 6) == 0) {
		if (strncmp(ptr, "rlimit-nofile ", 14) == 0) {
			ptr += 14;
			if (not_unsigned(ptr)) {
				fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
				exit(1);
			}
			sscanf(ptr, "%u", &cfg.rlimit_nofile);
			arg_rlimit_nofile = 1;
		}
		else if (strncmp(ptr, "rlimit-nproc ", 13) == 0) {
			ptr += 13;
			if (not_unsigned(ptr)) {
				fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
				exit(1);
			}
			sscanf(ptr, "%u", &cfg.rlimit_nproc);
			arg_rlimit_nproc = 1;
		}
		else if (strncmp(ptr, "rlimit-fsize ", 13) == 0) {
			ptr += 13;
			if (not_unsigned(ptr)) {
				fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
				exit(1);
			}
			sscanf(ptr, "%u", &cfg.rlimit_fsize);
			arg_rlimit_fsize = 1;
		}
		else if (strncmp(ptr, "rlimit-sigpending ", 18) == 0) {
			ptr += 18;
			if (not_unsigned(ptr)) {
				fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
				exit(1);
			}
			sscanf(ptr, "%u", &cfg.rlimit_sigpending);
			arg_rlimit_sigpending = 1;
		}
		else {
			fprintf(stderr, "Invalid rlimit option on line %d\n", lineno);
			exit(1);
		}
		
		return 0;		
	}

	// read-write
	if (strncmp(ptr, "read-write ", 11) == 0) {
		if (getuid() != 0) {
			fprintf(stderr, "Error: read-write command is available only for root user\n");
			exit(1);
		}
		fs_rdwr_add(ptr + 11);
		return 0;
	}

	// rest of filesystem
	if (strncmp(ptr, "blacklist ", 10) == 0)
		ptr += 10;
	else if (strncmp(ptr, "blacklist-nolog ", 16) == 0)
		ptr += 16;
	else if (strncmp(ptr, "noblacklist ", 12) == 0)
		ptr += 12;
	else if (strncmp(ptr, "whitelist ", 10) == 0) {
#ifdef HAVE_WHITELIST		
		if (checkcfg(CFG_WHITELIST)) {
			arg_whitelist = 1;
			ptr += 10;
		}
		else
			return 0;
#else		
		return 0;
#endif
	}
	else if (strncmp(ptr, "read-only ", 10) == 0)
		ptr += 10;
	else if (strncmp(ptr, "tmpfs ", 6) == 0) {
		if (getuid() != 0) {
			fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n");
			exit(1);
		}
		ptr += 6;
	}
	else {
		if (lineno == 0)
			fprintf(stderr, "Error: \"%s\" as a command line option is invalid\n", ptr);
		else if (fname != NULL)
			fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname);
		else
			fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
		exit(1);
	}

	// some characters just don't belong in filenames
	invalid_filename(ptr);
	if (strstr(ptr, "..")) {
		if (lineno == 0)
			fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr);
		else if (fname != NULL)
			fprintf(stderr, "Error: line %d in %s is invalid\n", lineno, fname);
		else
			fprintf(stderr, "Error: line %d in the custom profile is invalid\n", lineno);
		exit(1);
	}
	return 1;
}
예제 #7
0
int setup_borph(struct getap_state *gs)
{
  struct in_addr in;
  uint32_t v;
  int flags;
  unsigned int i;

  if(gs->s_verbose > 1){
    fprintf(stderr, "setup: opening register file %s\n", gs->s_borph_name);
  }

  flags = O_RDWR;
  if(gs->s_testing){
    flags |= O_CREAT | O_TRUNC;
  }

  gs->s_bfd = open(gs->s_borph_name, flags, S_IRUSR | S_IWUSR);
  if(gs->s_bfd < 0){
    fprintf(stderr, "setup: unable to access %s register file %s: %s\n", gs->s_testing  ? "testing" : "borph", gs->s_borph_name, strerror(errno));
    return -1;
  }

  if(atomac(gs->s_mac_binary, gs->s_mac_name) < 0){
    fprintf(stderr, "setup: unable to convert %s to mac\n", gs->s_mac_name);
    return -1;
  }
  if(write_mac_borph(gs, GO_MAC, gs->s_mac_binary) < 0){
    fprintf(stderr, "setup: unable to set own mac\n");
    return -1;
  }

  memcpy(gs->s_txb + 6, gs->s_mac_binary, 6);
  gs->s_txb[FRAME_TYPE1] = 0x08;
  gs->s_txb[FRAME_TYPE2] = 0x00;

  if(gs->s_gateway_name[0] != '\0'){
    if(inet_aton(gs->s_gateway_name, &in) == 0){
      fprintf(stderr, "setup: unable to convert <%s> to ip address\n", gs->s_gateway_name);
      return -1;
    }
    v = (in.s_addr) & 0xff;
    if(write_u32_borph(gs, GO_GATEWAY, v)){
      return -1;
    }
  }

  if(inet_aton(gs->s_address_name, &in) == 0){
    fprintf(stderr, "setup: unable to convert <%s> to ip address\n", gs->s_address_name);
    return -1;
  }
  if(sizeof(in.s_addr) != 4){
    fprintf(stderr, "setup: logic problem: ip address not 4 bytes\n");
    return -1;
  }
  v = in.s_addr;

  gs->s_address_binary = v; /* in network byte order */
  gs->s_mask_binary = htonl(0xffffff00); /* fixed mask */
  gs->s_network_binary = gs->s_mask_binary & gs->s_address_binary;

  gs->s_index = ntohl(~(gs->s_mask_binary) & gs->s_address_binary);

  /* assumes plain big endian value */
  if(write_u32_borph(gs, GO_ADDRESS, v)){
    return -1;
  }

  if(gs->s_port){
    /* assumes plain big endian value */
    v = gs->s_port;
    if(write_u16_borph(gs, GO_PORT, v)){
      return -1;
    }
  }

  for(i = 0; i < ARP_CACHE; i++){
    set_entry_arp(gs, i, broadcast_const);
  }

  /* know thyself */
  set_entry_arp(gs, gs->s_index, gs->s_mac_binary);

  if(write_u8_borph(gs, GO_ENABLE, 1)){
    return -1;
  }

  return 0;
}