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; }
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; }
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); }
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; }