static int handler_tcp_tun_to_net(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int dfd, keep = 1;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;
	socklen_t nlen;
	size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;

	if (!buff || len <= off)
		return 0;

	memset(buff, 0, len);
	while ((rlen = read(fd, buff + off, len - off)) > 0) {
		dfd = -1; p = NULL;

		hdr = (struct ct_proto *) buff;
		memset(hdr, 0, sizeof(*hdr));
		hdr->flags = 0;

		trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, NULL,
				 (size_t *) &nlen);
		if (unlikely(dfd < 0)) {
			memset(buff, 0, len);
			continue;
		}

		err = get_user_by_socket(dfd, &p);
		if (unlikely(err || !p)) {
			memset(buff, 0, len);
			continue;
		}

		clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
					 crypto_box_zerobytes), (rlen +
					 crypto_box_zerobytes), (unsigned char **)
					 &cbuff);
		if (unlikely(clen <= 0)) {
			memset(buff, 0, len);
			continue;
		}

		hdr->payload = htons((uint16_t) clen);

		set_tcp_cork(dfd);

		write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
		write_exact(dfd, cbuff, clen, 0);

		set_tcp_uncork(dfd);

		memset(buff, 0, len);
	}

	return keep;
}
Exemple #2
0
static void handler_udp_tun_to_net(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;
	size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;

	if (!buff || len <= off)
		return;

	memset(buff, 0, len);
	while ((rlen = read(sfd, buff + off, len - off)) > 0) {
		hdr = (struct ct_proto *) buff;

		memset(hdr, 0, sizeof(*hdr));
		hdr->flags = 0;

		clen = curve25519_encode(c, p, (unsigned char *) (buff + off -
					 crypto_box_zerobytes), (rlen +
					 crypto_box_zerobytes), (unsigned char **)
					 &cbuff);
		if (unlikely(clen <= 0))
			goto close;

		hdr->payload = htons((uint16_t) clen);

		set_udp_cork(dfd);

		write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
		write_exact(dfd, cbuff, clen, 0);

		set_udp_uncork(dfd);

		memset(buff, 0, len);
	}

	return;
close:
	closed_by_server = 1;
}
Exemple #3
0
static void notify_init(int fd, int udp, struct curve25519_proto *p,
			struct curve25519_struct *c, char *home)
{
	int fd2, i;
	ssize_t err, clen;
	size_t us_len, msg_len, pad;
	struct ct_proto hdr;
	char username[256], path[PATH_MAX], *us, *cbuff, *msg;
	unsigned char auth[crypto_auth_hmacsha512256_BYTES], *token;

	mt_init_by_random_device();

	memset(&hdr, 0, sizeof(hdr));
	hdr.flags |= PROTO_FLAG_INIT;

	memset(path, 0, sizeof(path));
	slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);

	fd2 = open_or_die(path, O_RDONLY);

	memset(username, 0, sizeof(username));
	err = read(fd2, username, sizeof(username));
	username[sizeof(username) - 1] = 0;

	close(fd2);

	token = get_serv_store_entry_auth_token();
	if (!token)
		syslog_panic("Cannot find auth token for server!\n");

	us_len = sizeof(struct username_struct) + crypto_box_zerobytes;
	us = xzmalloc(us_len);

	err = username_msg(username, strlen(username) + 1,
			   us + crypto_box_zerobytes,
			   us_len - crypto_box_zerobytes);
	if (unlikely(err))
		syslog_panic("Cannot create init message!\n");

	clen = curve25519_encode(c, p, (unsigned char *) us, us_len,
				 (unsigned char **) &cbuff);
	if (unlikely(clen <= 0))
		syslog_panic("Init encrypt error!\n");

	err = crypto_auth_hmacsha512256(auth, (unsigned char *) cbuff, clen, token);
	if (unlikely(err))
		syslog_panic("Cannot create init hmac message!\n");

	pad = mt_rand_int32() % 200;
	msg_len = clen + sizeof(auth) + pad;

	msg = xzmalloc(msg_len);
	memcpy(msg, auth, sizeof(auth));
	memcpy(msg + sizeof(auth), cbuff, clen);

	for (i = sizeof(auth) + clen; i < msg_len; ++i)
		msg[i] = (uint8_t) mt_rand_int32();

	hdr.payload = htons((uint16_t) msg_len);

	set_sock_cork(fd, udp);

	write_exact(fd, &hdr, sizeof(struct ct_proto), 0);
	write_exact(fd, msg, msg_len, 0);

	set_sock_uncork(fd, udp);

	xfree(msg);
	xfree(us);
}
Exemple #4
0
static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws,
				  char *buff, size_t len)
{
	int dfd, state, keep = 1;
	char *cbuff;
	ssize_t rlen, err, clen;
	struct ct_proto *hdr;
	struct curve25519_proto *p;
	struct sockaddr_storage naddr;
	socklen_t nlen;
	size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;

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

	errno = 0;
	memset(buff, 0, len);
	while ((rlen = read(fd, buff + off, len - off)) > 0) {
		dfd = -1;
		nlen = 0;
		p = NULL;
		memset(&naddr, 0, sizeof(naddr));

		hdr = (struct ct_proto *) buff;
		memset(hdr, 0, sizeof(*hdr));
		hdr->flags = 0;

		trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr,
				 (size_t *) &nlen);
		if (unlikely(dfd < 0 || nlen == 0)) {
			syslog(LOG_INFO, "CPU%u: UDP tunnel lookup failed: "
			       "unknown destination\n", ws->cpu);
			memset(buff, 0, len);
			continue;
		}
		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);
			memset(buff, 0, len);
			continue;
		}
		clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off -
					 crypto_box_zerobytes), (rlen +
					 crypto_box_zerobytes), (unsigned char **)
					 &cbuff);
		if (unlikely(clen <= 0)) {
			syslog(LOG_ERR, "CPU%u: UDP tunnel encrypt error: %zd\n",
			       ws->cpu, clen);
			memset(buff, 0, len);
			continue;
		}

		hdr->payload = htons((uint16_t) clen);

		state = 1;
		setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));

		err = sendto(dfd, hdr, sizeof(struct ct_proto), 0,
			     (struct sockaddr *) &naddr, nlen);
		if (unlikely(err < 0))
			syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
			       ws->cpu, strerror(errno));

		err = sendto(dfd, cbuff, clen, 0, (struct sockaddr *) &naddr,
			     nlen);
		if (unlikely(err < 0))
			syslog(LOG_ERR, "CPU%u: UDP tunnel write error: %s\n",
			       ws->cpu, strerror(errno));

		state = 0;
		setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));

		errno = 0;
		memset(buff, 0, len);
	}

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

	return keep;
}