Example #1
0
static
int route_adddel(struct main_server_st* s, proc_st *proc,
		 const char* pattern, const char* route, const char* dev)
{
int ret;
char *cmd = NULL;

	if (pattern == 0) {
		mslog(s, NULL, LOG_WARNING, "route-add-cmd or route-del-cmd are not set.");
		return 0;
	}

	ret = replace_cmd(s, proc, &cmd, pattern, route, dev);
	if (ret < 0)
		return ret;

	ret = call_script(s, proc, cmd);
	if (ret < 0) {
		int e = errno;
		mslog(s, NULL, LOG_INFO, "failed to spawn cmd: %s: %s", cmd, strerror(e));
		ret = ERR_EXEC;
		goto fail;
	}

	ret = 0;
 fail:
 	talloc_free(cmd);
	return ret;
}
Example #2
0
int get_ip_leases(main_server_st* s, struct proc_st* proc)
{
int ret;
char buf[128];

	if (proc->ipv4 == NULL) {
		ret = get_ipv4_lease(s, proc);
		if (ret < 0)
			return ret;

		if (proc->ipv4) {
			if (htable_add(&s->ip_leases.ht, rehash(proc->ipv4, NULL), proc->ipv4) == 0) {
				mslog(s, proc, LOG_ERR, "could not add IPv4 lease to hash table.");
				return -1;
			}
		}
	}

	if (proc->ipv6 == NULL) {
		ret = get_ipv6_lease(s, proc);
		if (ret < 0)
			return ret;

		if (proc->ipv6) {
			if (htable_add(&s->ip_leases.ht, rehash(proc->ipv6, NULL), proc->ipv6) == 0) {
				mslog(s, proc, LOG_ERR, "could not add IPv6 lease to hash table.");
				return -1;
			}
		}
	}

	if (proc->ipv4 == 0 && proc->ipv6 == 0) {
		mslog(s, proc, LOG_ERR, "no IPv4 or IPv6 addresses are configured. Cannot obtain lease.");
		return -1;
	}
	
	if (proc->ipv4)
		mslog(s, proc, LOG_INFO, "assigned IPv4 to '%s': %s", proc->username,
			human_addr((void*)&proc->ipv4->rip, proc->ipv4->rip_len, buf, sizeof(buf)));

	if (proc->ipv6)
		mslog(s, proc, LOG_INFO, "assigned IPv6 to '%s': %s", proc->username,
			human_addr((void*)&proc->ipv6->rip, proc->ipv6->rip_len, buf, sizeof(buf)));
		
	return 0;
}
Example #3
0
int handle_resume_store_req(main_server_st * s, struct proc_st *proc,
			    const SessionResumeStoreReqMsg * req)
{
	tls_cache_st *cache;
	size_t key;
	unsigned int max;

	if (req->session_id.len > GNUTLS_MAX_SESSION_ID)
		return -1;
	if (req->session_data.len > MAX_SESSION_DATA_SIZE)
		return -1;

	max = MAX(2 * s->config->max_clients, DEFAULT_MAX_CACHED_TLS_SESSIONS);
	if (s->tls_db.entries >= max) {
		mslog(s, NULL, LOG_INFO,
		      "maximum number of stored TLS sessions reached (%u)",
		      max);
		need_maintenance = 1;
		return -1;
	}

	key = hash_any(req->session_id.data, req->session_id.len, 0);

	cache = talloc(s->tls_db.ht, tls_cache_st);
	if (cache == NULL)
		return -1;

	cache->session_id_size = req->session_id.len;
	cache->session_data_size = req->session_data.len;
	cache->remote_addr_len = proc->remote_addr_len;

	memcpy(cache->session_id, req->session_id.data, req->session_id.len);
	memcpy(cache->session_data, req->session_data.data,
	       req->session_data.len);
	memcpy(&cache->remote_addr, &proc->remote_addr, proc->remote_addr_len);

	htable_add(s->tls_db.ht, key, cache);
	s->tls_db.entries++;

	mslog_hex(s, proc, LOG_DEBUG, "TLS session DB storing",
				req->session_id.data,
				req->session_id.len, 0);

	return 0;
}
Example #4
0
static
int call_script(main_server_st *s, proc_st *proc, const char *cmd)
{
pid_t pid;
int ret, status = 0;

	if (cmd == NULL)
		return 0;

	pid = fork();
	if (pid == 0) {
		sigprocmask(SIG_SETMASK, &sig_default_set, NULL);

		mslog(s, proc, LOG_DEBUG, "executing route script %s", cmd);
		ret = execl("/bin/sh", "sh", "-c", cmd, NULL);
		if (ret == -1) {
			mslog(s, proc, LOG_ERR, "Could not execute route script %s", cmd);
			exit(1);
		}

		exit(77);
	} else if (pid == -1) {
		mslog(s, proc, LOG_ERR, "Could not fork()");
		return ERR_EXEC;
	}

	ret = waitpid(pid, &status, 0);
	if (ret == -1) {
		mslog(s, proc, LOG_ERR, "Could not waitpid()");
		return ERR_EXEC;
	}

	if (!WIFEXITED(status)) {
		mslog(s, proc, LOG_INFO, "cmd: %s: exited abnormally", cmd);
		return ERR_EXEC;
	}

	if (WEXITSTATUS(status)) {
		mslog(s, proc, LOG_INFO, "cmd: %s: exited with error %d", cmd, WEXITSTATUS(ret));
		return ERR_EXEC;
	}

	return 0;
}
Example #5
0
static
int call_script(main_server_st *s, struct proc_st* proc, unsigned up)
{
pid_t pid;
int ret;
const char* script;

	if (up != 0)
		script = s->config->connect_script;
	else
		script = s->config->disconnect_script;

	if (script == NULL)
		return 0;

	pid = fork();
	if (pid == 0) {
		char real[64];
		char local[64];
		char remote[64];

		if (proc->ipv4 == NULL && proc->ipv6 == NULL)
			exit(1);
		
		if (getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, real, sizeof(real), NULL, 0, NI_NUMERICHOST) != 0)
			exit(1);

		if (proc->ipv4 && proc->ipv4->lip_len > 0) {
			if (getnameinfo((void*)&proc->ipv4->lip, proc->ipv4->lip_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
				exit(1);
		} else {
			if (getnameinfo((void*)&proc->ipv6->lip, proc->ipv6->lip_len, local, sizeof(local), NULL, 0, NI_NUMERICHOST) != 0)
				exit(1);
		}

		if (proc->ipv4 && proc->ipv4->rip_len > 0) {
			if (getnameinfo((void*)&proc->ipv4->rip, proc->ipv4->rip_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
				exit(1);
		} else {
			if (getnameinfo((void*)&proc->ipv6->rip, proc->ipv6->rip_len, remote, sizeof(remote), NULL, 0, NI_NUMERICHOST) != 0)
				exit(1);
		}

		setenv("USERNAME", proc->username, 1);
		setenv("GROUPNAME", proc->groupname, 1);
		setenv("HOSTNAME", proc->hostname, 1);
		setenv("DEVICE", proc->tun_lease.name, 1);
		setenv("IP_REAL", real, 1);
		setenv("IP_LOCAL", local, 1);
		setenv("IP_REMOTE", remote, 1);
		if (up)
			setenv("REASON", "connect", 1);
		else
			setenv("REASON", "disconnect", 1);

		mslog(s, proc, LOG_DEBUG, "executing script %s", script);
		ret = execl(script, script, NULL);
		if (ret == -1) {
			mslog(s, proc, LOG_ERR, "Could not execute script %s", script);
			exit(1);
		}
			
		exit(77);
	} else if (pid == -1) {
		mslog(s, proc, LOG_ERR, "Could not fork()");
		return -1;
	}
	
	if (up) {
		add_to_script_list(s, pid, up, proc);
		return ERR_WAIT_FOR_SCRIPT;
	} else {
		return 0;
	}
}
Example #6
0
static
int get_ipv6_lease(main_server_st* s, struct proc_st* proc)
{

	struct sockaddr_storage tmp, mask, network, rnd;
	unsigned i, max_loops = MAX_IP_TRIES;
	int ret;
	const char* c_network, *c_netmask;
	char buf[64];

	if (proc->config.ipv6_network && proc->config.ipv6_netmask) {
		c_network = proc->config.ipv6_network;
		c_netmask = proc->config.ipv6_netmask;
	} else {
		c_network = s->config->network.ipv6;
		c_netmask = s->config->network.ipv6_netmask;
	}

	if (c_network && c_netmask) {
		ret =
		    inet_pton(AF_INET6, c_network, SA_IN6_P(&network));

		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
			return -1;
		}

		ret =
		    inet_pton(AF_INET6, c_netmask, SA_IN6_P(&mask));
	
		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
			return -1;
		}
		
		proc->ipv6 = calloc(1, sizeof(*proc->ipv6));
		if (proc->ipv6 == NULL)
			return ERR_MEM;

		/* mask the network */
		for (i=0;i<sizeof(struct in6_addr);i++)
			SA_IN6_U8_P(&network)[i] &= (SA_IN6_U8_P(&mask)[i]);
		((struct sockaddr_in6*)&network)->sin6_family = AF_INET6;
		((struct sockaddr_in6*)&network)->sin6_port = 0;

       		memcpy(&tmp, &network, sizeof(tmp));
        	((struct sockaddr_in6*)&tmp)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&tmp)->sin6_port = AF_INET6;

        	((struct sockaddr_in6*)&rnd)->sin6_family = AF_INET6;
        	((struct sockaddr_in6*)&rnd)->sin6_port = AF_INET6;

		do {
			if (max_loops == 0) {
				mslog(s, NULL, LOG_ERR, "could not figure out a valid IPv6 IP.");
				ret = ERR_NO_IP;
				goto fail;
			}
			
			if (max_loops == MAX_IP_TRIES) {
				uint32_t t = hash_any(proc->username, strlen(proc->username), 0);
				memset(SA_IN6_U8_P(&rnd), 0, sizeof(struct in6_addr));
				memcpy(SA_IN6_U8_P(&rnd)+sizeof(struct in6_addr)-5, &t, 4);
			} else
				gnutls_rnd(GNUTLS_RND_NONCE, SA_IN6_U8_P(&rnd), sizeof(struct in6_addr));
			max_loops--;
			
			/* Mask the random number with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] &= ~(SA_IN6_U8_P(&mask)[i]);

			SA_IN6_U8_P(&rnd)[sizeof(struct in6_addr)-1] &= 0xFE;

			/* Now add the network to the masked random number */
        		for (i=0;i<sizeof(struct in6_addr);i++)
        			SA_IN6_U8_P(&rnd)[i] |= (SA_IN6_U8_P(&network)[i]);
        			
 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign local IP %s to '%s'; it is in use.", 
				      human_addr((void*)&rnd, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->lip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->lip, &rnd, proc->ipv6->lip_len);

        		/* RIP = LIP + 1 */
        		memcpy(&tmp, &proc->ipv6->lip, proc->ipv6->rip_len);

	        	bignum_add(SA_IN6_U8_P(&tmp), sizeof(struct in6_addr), 1);

 			/* check if it exists in the hash table */
			if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in6)) != 0) {
				mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.", 
				      human_addr((void*)&tmp, sizeof(struct sockaddr_in6), buf, sizeof(buf)), 
				      proc->username);
				continue;
			}

        		proc->ipv6->rip_len = sizeof(struct sockaddr_in6);
        		memcpy(&proc->ipv6->rip, &tmp, proc->ipv6->rip_len);

        		/* mask the last IP with the netmask */
        		for (i=0;i<sizeof(struct in6_addr);i++)
	        		SA_IN6_U8_P(&tmp)[i] &= (SA_IN6_U8_P(&mask)[i]);

        		/* the result should match the network */
	        	if (memcmp(SA_IN6_U8_P(&network), SA_IN6_U8_P(&tmp), sizeof(struct in6_addr)) != 0) {
		        	continue;
	        	}

			mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username,
			      human_addr((void*)&proc->ipv6->lip, proc->ipv6->lip_len, buf, sizeof(buf)));

	        	if (icmp_ping6(s, (void*)&proc->ipv6->lip, (void*)&proc->ipv6->rip) == 0)
	        		break;
                } while(1);
	}

	return 0;
fail:
	free(proc->ipv6);
	proc->ipv6 = NULL;

	return ret;

}
Example #7
0
static
int get_ipv4_lease(main_server_st* s, struct proc_st* proc)
{

	struct sockaddr_storage tmp, mask, network, rnd;
	unsigned i;
	unsigned max_loops = MAX_IP_TRIES;
	int ret;
	const char* c_network, *c_netmask;
	char buf[64];

	/* Our IP accounting */
	if (proc->config.ipv4_network && proc->config.ipv4_netmask) {
		c_network = proc->config.ipv4_network;
		c_netmask = proc->config.ipv4_netmask;
	} else {
		c_network = s->config->network.ipv4;
		c_netmask = s->config->network.ipv4_netmask;
	}

	if (c_network == NULL || c_netmask == NULL) {
		mslog(s, NULL, LOG_DEBUG, "there is no IPv4 network assigned");
		return 0;
	}

	ret =
	    inet_pton(AF_INET, c_network, SA_IN_P(&network));
	if (ret != 1) {
		mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network);
		return -1;
	}

	ret =
	    inet_pton(AF_INET, c_netmask, SA_IN_P(&mask));
	if (ret != 1) {
		mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask);
		return -1;
	}

	/* mask the network (just in case it is wrong) */
	for (i=0;i<sizeof(struct in_addr);i++)
		SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]);
       	((struct sockaddr_in*)&network)->sin_family = AF_INET;
       	((struct sockaddr_in*)&network)->sin_port = 0;

	if (proc->config.explicit_ipv4) {
		/* if an explicit IP is given for that client, then
		 * do implicit IP accounting. Require the address
		 * to be odd, so we use the next even address as PtP. */
		ret =
		    inet_pton(AF_INET, proc->config.explicit_ipv4, SA_IN_P(&tmp));

		if (ret != 1) {
			mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config.explicit_ipv4);
			return -1;
		}

		proc->ipv4 = talloc_zero(proc, struct ip_lease_st);
		if (proc->ipv4 == NULL)
			return ERR_MEM;

        	((struct sockaddr_in*)&tmp)->sin_family = AF_INET;
        	((struct sockaddr_in*)&tmp)->sin_port = 0;
		memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in));
       		proc->ipv4->rip_len = sizeof(struct sockaddr_in);

		if (is_ipv4_ok(s, &proc->ipv4->rip, &network, &mask) == 0) {
			mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use or invalid", 
			      human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)));
			ret = ERR_NO_IP;
			goto fail;
		}

		/* LIP = network address + 1 */
		memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in));
		proc->ipv4->lip_len = sizeof(struct sockaddr_in);
		SA_IN_U8_P(&proc->ipv4->lip)[3] |= 1;

		if (ip_cmp(&proc->ipv4->lip, &proc->ipv4->rip) == 0) {
			mslog(s, NULL, LOG_ERR, "cannot assign explicit IP %s; network: %s", proc->config.explicit_ipv4, c_network);
			ret = ERR_NO_IP;
			goto fail;
		}

		return 0;
	}