Esempio n. 1
0
static void handler_udp_net_to_tun(int sfd, int dfd, struct curve25519_proto *p,
				   struct curve25519_struct *c, char *buff,
				   size_t len)
{
	char *cbuff;
	ssize_t rlen, clen;
	struct ct_proto *hdr;
	struct sockaddr_storage naddr;

	socklen_t nlen = sizeof(naddr);

	if (!buff || !len)
		return;

	memset(&naddr, 0, sizeof(naddr));
	while ((rlen = recvfrom(sfd, buff, len, 0, (struct sockaddr *) &naddr,
				&nlen)) > 0) {
		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT)
			goto close;

		clen = curve25519_decode(c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
		if (unlikely(clen <= 0))
			goto close;

                cbuff += crypto_box_zerobytes;
                clen -= crypto_box_zerobytes;

		if (write(dfd, cbuff, clen)) { ; }
	}

	return;
close:
	closed_by_server = 1;
}
Esempio n. 2
0
static void handler_tcp_net_to_tun(int sfd, int dfd, struct curve25519_proto *p,
				   struct curve25519_struct *c, char *buff,
				   size_t len)
{
	char *cbuff;
	ssize_t rlen, clen;
	struct ct_proto *hdr;

	if (!buff || !len)
		return;

	while ((rlen = handler_tcp_read(sfd, buff, len)) > 0) {
		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT)
			goto close;

		clen = curve25519_decode(c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
		if (unlikely(clen <= 0))
			goto close;

		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;

		if (write(dfd, cbuff, clen));
	}

	return;
close:
	closed_by_server = 1;
}
static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int keep = 1, count = 0;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;

	if (!buff || !len)
		return 0;

	while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
		p = NULL;

		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT) {
close:
			remove_user_by_socket(fd);
			trie_addr_remove(fd);
			handler_tcp_notify_close(fd);
			rlen = write(ws->parent.efd, &fd, sizeof(fd));

			keep = 0;
			return keep;
		}
		if (hdr->flags & PROTO_FLAG_INIT) {
			syslog_maybe(auth_log, LOG_INFO, "Got initial userhash "
				     "from remote end!\n");

			if (unlikely(rlen - sizeof(*hdr) <
				     sizeof(struct username_struct)))
				goto close;

			err = try_register_user_by_socket(ws->c,
					buff + sizeof(struct ct_proto),
					rlen - sizeof(struct ct_proto),
					fd, auth_log);
			if (unlikely(err))
				goto close;

			continue;
		}

		err = get_user_by_socket(fd, &p);
		if (unlikely(err || !p))
			continue;

		clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
                if (unlikely(clen <= 0))
			continue;

		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;

		err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
					     fd, NULL, 0);
		if (unlikely(err))
			continue;

		err = write(ws->parent.tunfd, cbuff, clen);

		count++;
		if (count == 10) {
			write_exact(ws->efd[1], &fd, sizeof(fd), 1);
			/* Read later next data and let others process */
			return keep;
		}
	}

	return keep;
}
static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int keep = 1;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;
	struct sockaddr_storage naddr;
	socklen_t nlen = sizeof(naddr);

	if (!buff || !len)
		return 0;

	memset(&naddr, 0, sizeof(naddr));
	while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
				&nlen)) > 0) {
		p = NULL;

		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT) {
close:
			remove_user_by_sockaddr(&naddr, nlen);
			trie_addr_remove_addr(&naddr, nlen);
			handler_udp_notify_close(fd, &naddr);

			return keep;
		}
		if (hdr->flags & PROTO_FLAG_INIT) {
			syslog_maybe(auth_log, LOG_INFO, "Got initial userhash "
				     "from remote end!\n");

			if (unlikely(rlen - sizeof(*hdr) <
				     sizeof(struct username_struct)))
				goto close;

			err = try_register_user_by_sockaddr(ws->c,
					buff + sizeof(struct ct_proto),
					rlen - sizeof(struct ct_proto),
					&naddr, nlen, auth_log);
			if (unlikely(err))
				goto close;

			goto next;
		}

		err = get_user_by_sockaddr(&naddr, nlen, &p);
		if (unlikely(err || !p))
			goto close;

		clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
                if (unlikely(clen <= 0))
			goto close;

		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;

		err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
					     fd, &naddr, nlen);
		if (unlikely(err))
			goto next;

		err = write(ws->parent.tunfd, cbuff, clen);
next:
		nlen = sizeof(naddr);
		memset(&naddr, 0, sizeof(naddr));
	}

	return keep;
}
Esempio n. 5
0
int try_register_user_by_sockaddr(struct curve25519_struct *c,
				  char *src, size_t slen,
				  struct sockaddr_storage *sa,
				  size_t sa_len, int log)
{
	int ret = -1;
	char *cbuff = NULL;
	struct user_store *elem;
	ssize_t clen;
	size_t real_len = 132;
	enum is_user_enum err;
	unsigned char auth[crypto_auth_hmacsha512256_BYTES];
	struct taia arrival_taia;

	/* assert(132 == clen + sizeof(auth)); */
	/*
	 * Check hmac first, if malicious, drop immediately before we
	 * investigate more efforts.
	 */
	if (slen < real_len)
		return -1;

	taia_now(&arrival_taia);

	memcpy(auth, src, sizeof(auth));

	src += sizeof(auth);
	real_len -= sizeof(auth);

	if (crypto_auth_hmacsha512256_verify(auth, (unsigned char *) src,
					     real_len, token)) {
		syslog(LOG_ERR, "Got bad packet hmac! Dropping!\n");
		return -1;
	} else {
		if (log)
			syslog(LOG_INFO, "Got good packet hmac!\n");
	}

	rwlock_rd_lock(&store_lock);

	elem = store;
	while (elem) {
		clen = curve25519_decode(c, &elem->proto_inf,
					 (unsigned char *) src, real_len,
					 (unsigned char **) &cbuff,
					 &arrival_taia);
		if (clen <= 0) {
			elem = elem->next;
			continue;
		}

		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;

		if (log)
			syslog(LOG_INFO, "Packet decoded successfully!\n");

		err = username_msg_is_user(cbuff, clen, elem->username,
					   strlen(elem->username) + 1);
		if (err == USERNAMES_OK) {
			if (log)
				syslog(LOG_INFO, "Found user %s! Registering ...\n",
				       elem->username);
			ret = register_user_by_sockaddr(sa, sa_len,
							&elem->proto_inf);
			break;
		}

		elem = elem->next;
	}

	rwlock_unlock(&store_lock);

	if (ret == -1)
		syslog(LOG_ERR, "User not found! Dropping connection!\n");

	return ret;
}
Esempio n. 6
0
static int handler_tcp_net_to_tun(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int keep = 1, count = 0;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;

	if (!buff || !len)  {
		errno = EINVAL;
		return 0;
	}

	errno = 0;
	while ((rlen = handler_tcp_read(fd, buff, len)) > 0) {
		p = NULL;
		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT) {
close:
			remove_user_by_socket(fd);
			trie_addr_remove(fd);
			handler_tcp_notify_close(fd);
			rlen = write(ws->parent.efd, &fd, sizeof(fd));
			if (rlen != sizeof(fd))
				syslog(LOG_ERR, "CPU%u: TCP event write error: %s\n",
				       ws->cpu, strerror(errno));
			keep = 0;
			return keep;
		}
		if (hdr->flags & PROTO_FLAG_INIT) {
			if (auth_log)
				syslog(LOG_INFO, "Got initial userhash from remote end!\n");
			if (unlikely(rlen - sizeof(*hdr) <
				     sizeof(struct username_struct)))
				goto close;
			err = try_register_user_by_socket(ws->c, buff + sizeof(struct ct_proto),
							  rlen - sizeof(struct ct_proto),
							  fd, auth_log);
			if (unlikely(err))
				goto close;
			continue;
		}

		err = get_user_by_socket(fd, &p);
		if (unlikely(err || !p)) {
			syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
			       "Dropping connection!\n", ws->cpu);
			goto close;
		}
		clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
                if (unlikely(clen <= 0)) {
			syslog(LOG_ERR, "CPU%u: TCP net decryption error: %zd\n",
			       ws->cpu, clen);
			goto close;
		}
		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;
		err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
					     fd, NULL, 0);
		if (unlikely(err)) {
			syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
			       "from id %d\n", ws->cpu, fd);
			continue;
		}

		err = write(ws->parent.tunfd, cbuff, clen);
		if (unlikely(err < 0))
			syslog(LOG_ERR, "CPU%u: TCP net write error: %s\n",
			       ws->cpu, strerror(errno));

		count++;
		if (count == 10) {
			err = write_exact(ws->efd[1], &fd, sizeof(fd), 1);
			if (unlikely(err != sizeof(fd)))
				syslog(LOG_ERR, "CPU%u: TCP net put fd back in "
				       "pipe error: %s\n", ws->cpu, strerror(errno));
			return keep;
		}

		errno = 0;
	}

	if (unlikely(rlen < 0 && errno != EAGAIN && errno != EBADF))
		syslog(LOG_ERR, "CPU%u: TCP net read error: %s\n",
		       ws->cpu, strerror(errno));

	return keep;
}
Esempio n. 7
0
static int handler_udp_net_to_tun(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int keep = 1;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;
	struct sockaddr_storage naddr;
	socklen_t nlen = sizeof(naddr);

	if (!buff || !len) {
		errno = EINVAL;
		return 0;
	}

	memset(&naddr, 0, sizeof(naddr));

	errno = 0;
	while ((rlen = recvfrom(fd, buff, len, 0, (struct sockaddr *) &naddr,
				&nlen)) > 0) {
		p = NULL;
		hdr = (struct ct_proto *) buff;

		if (unlikely(rlen < sizeof(struct ct_proto)))
			goto close;
		if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
			goto close;
		if (unlikely(ntohs(hdr->payload) == 0))
			goto close;
		if (hdr->flags & PROTO_FLAG_EXIT) {
close:
			remove_user_by_sockaddr(&naddr, nlen);
			trie_addr_remove_addr(&naddr, nlen);
			handler_udp_notify_close(fd, &naddr);
			return keep;
		}
		if (hdr->flags & PROTO_FLAG_INIT) {
			if (auth_log)
				syslog(LOG_INFO, "Got initial userhash from remote end!\n");
			if (unlikely(rlen - sizeof(*hdr) <
				     sizeof(struct username_struct)))
				goto close;
			err = try_register_user_by_sockaddr(ws->c, buff + sizeof(struct ct_proto),
							    rlen - sizeof(struct ct_proto),
							    &naddr, nlen, auth_log);
			if (unlikely(err))
				goto close;
			goto next;
		}

		err = get_user_by_sockaddr(&naddr, nlen, &p);
		if (unlikely(err || !p)) {
			syslog(LOG_ERR, "CPU%u: User protocol not in cache! "
			       "Dropping connection!\n", ws->cpu);
			goto close;
		}
		clen = curve25519_decode(ws->c, p, (unsigned char *) buff +
					 sizeof(struct ct_proto),
					 rlen - sizeof(struct ct_proto),
					 (unsigned char **) &cbuff, NULL);
                if (unlikely(clen <= 0)) {
			syslog(LOG_ERR, "CPU%u: UDP net decryption error: %zd\n",
			       ws->cpu, clen);
			goto close;
		}
		cbuff += crypto_box_zerobytes;
		clen -= crypto_box_zerobytes;
		err = trie_addr_maybe_update(cbuff, clen, ws->parent.ipv4,
					     fd, &naddr, nlen);
		if (unlikely(err)) {
			syslog(LOG_INFO, "CPU%u: Malicious packet dropped "
			       "from id %d\n", ws->cpu, fd);
			goto next;
		}

		err = write(ws->parent.tunfd, cbuff, clen);
		if (unlikely(err < 0))
			syslog(LOG_ERR, "CPU%u: UDP net write error: %s\n",
			       ws->cpu, strerror(errno));

next:
		nlen = sizeof(naddr);
		memset(&naddr, 0, sizeof(naddr));
		errno = 0;
	}

	if (unlikely(rlen < 0 && errno != EAGAIN))
		syslog(LOG_ERR, "CPU%u: UDP net read error: %s\n",
		       ws->cpu, strerror(errno));

	return keep;
}