src: made sigatomic_t as volatile
[netsniff-ng.git] / src / ct_client.c
blob5b3a36a788ceff589370ad089e10ab1b15ef3988
1 /*
2 * curvetun - the cipherspace wormhole creator
3 * Part of the netsniff-ng project
4 * By Daniel Borkmann <daniel@netsniff-ng.org>
5 * Copyright 2011 Daniel Borkmann <daniel@netsniff-ng.org>,
6 * Subject to the GPL, version 2.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <netdb.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 #include <syslog.h>
17 #include <limits.h>
18 #include <assert.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <sys/poll.h>
26 #include <netinet/tcp.h>
27 #include <netinet/udp.h>
28 #include <linux/if_tun.h>
30 #include "die.h"
31 #include "xio.h"
32 #include "xstring.h"
33 #include "curve.h"
34 #include "mtrand.h"
35 #include "xsys.h"
36 #include "xmalloc.h"
37 #include "curvetun.h"
38 #include "servmgmt.h"
39 #include "usermgmt.h"
40 #include "compiler.h"
41 #include "crypto_auth_hmacsha512256.h"
43 extern volatile sig_atomic_t sigint;
44 static volatile sig_atomic_t closed_by_server = 0;
46 static void handler_udp_tun_to_net(int sfd, int dfd, struct curve25519_proto *p,
47 struct curve25519_struct *c, char *buff,
48 size_t len)
50 int state;
51 char *cbuff;
52 ssize_t rlen, err, clen;
53 struct ct_proto *hdr;
54 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
56 if (!buff || len <= off) {
57 errno = EINVAL;
58 return;
61 errno = 0;
62 memset(buff, 0, len);
63 while ((rlen = read(sfd, buff + off, len - off)) > 0) {
64 hdr = (struct ct_proto *) buff;
65 memset(hdr, 0, sizeof(*hdr));
66 hdr->flags = 0;
68 clen = curve25519_encode(c, p, (unsigned char *) (buff + off -
69 crypto_box_zerobytes), (rlen +
70 crypto_box_zerobytes), (unsigned char **)
71 &cbuff);
72 if (unlikely(clen <= 0)) {
73 syslog(LOG_ERR, "UDP tunnel encrypt error!\n");
74 goto close;
77 hdr->payload = htons((uint16_t) clen);
79 state = 1;
80 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
82 err = write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
83 if (unlikely(err < 0))
84 syslog(LOG_ERR, "Error writing tunnel data to net: %s\n",
85 strerror(errno));
87 err = write_exact(dfd, cbuff, clen, 0);
88 if (unlikely(err < 0))
89 syslog(LOG_ERR, "Error writing tunnel data to net: %s\n",
90 strerror(errno));
92 state = 0;
93 setsockopt(dfd, IPPROTO_UDP, UDP_CORK, &state, sizeof(state));
95 errno = 0;
96 memset(buff, 0, len);
99 return;
100 close:
101 closed_by_server = 1;
104 static void handler_udp_net_to_tun(int sfd, int dfd, struct curve25519_proto *p,
105 struct curve25519_struct *c, char *buff,
106 size_t len)
108 char *cbuff;
109 ssize_t rlen, err, clen;
110 struct ct_proto *hdr;
111 struct sockaddr_storage naddr;
112 socklen_t nlen = sizeof(naddr);
114 if (!buff || !len) {
115 errno = EINVAL;
116 return;
119 memset(&naddr, 0, sizeof(naddr));
121 errno = 0;
122 while ((rlen = recvfrom(sfd, buff, len, 0, (struct sockaddr *) &naddr,
123 &nlen)) > 0) {
124 hdr = (struct ct_proto *) buff;
126 if (unlikely(rlen < sizeof(struct ct_proto)))
127 goto close;
128 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
129 goto close;
130 if (unlikely(ntohs(hdr->payload) == 0))
131 goto close;
132 if (hdr->flags & PROTO_FLAG_EXIT)
133 goto close;
135 clen = curve25519_decode(c, p, (unsigned char *) buff +
136 sizeof(struct ct_proto),
137 rlen - sizeof(struct ct_proto),
138 (unsigned char **) &cbuff, NULL);
139 if (unlikely(clen <= 0)) {
140 syslog(LOG_ERR, "UDP net decrypt error!\n");
141 goto close;
143 cbuff += crypto_box_zerobytes;
144 clen -= crypto_box_zerobytes;
145 err = write(dfd, cbuff, clen);
146 if (unlikely(err < 0))
147 syslog(LOG_ERR, "Error writing net data to tunnel: %s\n",
148 strerror(errno));
150 errno = 0;
153 return;
154 close:
155 closed_by_server = 1;
158 static void handler_tcp_tun_to_net(int sfd, int dfd, struct curve25519_proto *p,
159 struct curve25519_struct *c, char *buff,
160 size_t len)
162 int state;
163 char *cbuff;
164 ssize_t rlen, err, clen;
165 struct ct_proto *hdr;
166 size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes;
168 if (!buff || len <= off) {
169 errno = EINVAL;
170 return;
173 errno = 0;
174 memset(buff, 0, len);
175 while ((rlen = read(sfd, buff + off, len - off)) > 0) {
176 hdr = (struct ct_proto *) buff;
177 memset(hdr, 0, sizeof(*hdr));
178 hdr->flags = 0;
180 clen = curve25519_encode(c, p, (unsigned char *) (buff + off -
181 crypto_box_zerobytes), (rlen +
182 crypto_box_zerobytes), (unsigned char **)
183 &cbuff);
184 if (unlikely(clen <= 0)) {
185 syslog(LOG_ERR, "TCP tunnel encrypt error!\n");
186 goto close;
189 hdr->payload = htons((uint16_t) clen);
191 state = 1;
192 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
194 err = write_exact(dfd, hdr, sizeof(struct ct_proto), 0);
195 if (unlikely(err < 0))
196 syslog(LOG_ERR, "Error writing tunnel data to net: %s\n",
197 strerror(errno));
199 err = write_exact(dfd, cbuff, clen, 0);
200 if (unlikely(err < 0))
201 syslog(LOG_ERR, "Error writing tunnel data to net: %s\n",
202 strerror(errno));
204 state = 0;
205 setsockopt(dfd, IPPROTO_TCP, TCP_CORK, &state, sizeof(state));
207 errno = 0;
208 memset(buff, 0, len);
211 return;
212 close:
213 closed_by_server = 1;
216 extern ssize_t handler_tcp_read(int fd, char *buff, size_t len);
218 static void handler_tcp_net_to_tun(int sfd, int dfd, struct curve25519_proto *p,
219 struct curve25519_struct *c, char *buff,
220 size_t len)
222 char *cbuff;
223 ssize_t rlen, err, clen;
224 struct ct_proto *hdr;
226 if (!buff || !len) {
227 errno = EINVAL;
228 return;
231 errno = 0;
232 while ((rlen = handler_tcp_read(sfd, buff, len)) > 0) {
233 hdr = (struct ct_proto *) buff;
235 if (unlikely(rlen < sizeof(struct ct_proto)))
236 goto close;
237 if (unlikely(rlen - sizeof(*hdr) != ntohs(hdr->payload)))
238 goto close;
239 if (unlikely(ntohs(hdr->payload) == 0))
240 goto close;
241 if (hdr->flags & PROTO_FLAG_EXIT)
242 goto close;
244 clen = curve25519_decode(c, p, (unsigned char *) buff +
245 sizeof(struct ct_proto),
246 rlen - sizeof(struct ct_proto),
247 (unsigned char **) &cbuff, NULL);
248 if (unlikely(clen <= 0)) {
249 syslog(LOG_ERR, "TCP net decrypt error!\n");
250 goto close;
252 cbuff += crypto_box_zerobytes;
253 clen -= crypto_box_zerobytes;
254 err = write(dfd, cbuff, clen);
255 if (unlikely(err < 0))
256 syslog(LOG_ERR, "Error writing net data to tunnel: %s\n",
257 strerror(errno));
259 errno = 0;
262 return;
263 close:
264 closed_by_server = 1;
267 static void notify_init(int fd, int udp, struct curve25519_proto *p,
268 struct curve25519_struct *c, char *home)
270 int state, fd2, i;
271 ssize_t err, clen;
272 size_t us_len, msg_len, pad;
273 struct ct_proto hdr;
274 char username[256], path[PATH_MAX], *us, *cbuff, *msg;
275 unsigned char auth[crypto_auth_hmacsha512256_BYTES], *token;
277 mt_init_by_random_device();
279 memset(&hdr, 0, sizeof(hdr));
280 hdr.flags |= PROTO_FLAG_INIT;
282 memset(path, 0, sizeof(path));
283 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
284 memset(username, 0, sizeof(username));
286 fd2 = open_or_die(path, O_RDONLY);
287 err = read(fd2, username, sizeof(username));
288 username[sizeof(username) - 1] = 0;
289 close(fd2);
291 token = get_serv_store_entry_auth_token();
292 if (!token)
293 syslog_panic("Cannot find auth token for server!\n");
295 us_len = sizeof(struct username_struct) + crypto_box_zerobytes;
296 us = xzmalloc(us_len);
297 err = username_msg(username, strlen(username) + 1,
298 us + crypto_box_zerobytes,
299 us_len - crypto_box_zerobytes);
300 if (unlikely(err))
301 syslog_panic("Cannot create init message!\n");
302 clen = curve25519_encode(c, p, (unsigned char *) us, us_len,
303 (unsigned char **) &cbuff);
304 if (unlikely(clen <= 0))
305 syslog_panic("Init encrypt error!\n");
306 err = crypto_auth_hmacsha512256(auth, (unsigned char *) cbuff, clen, token);
307 if (unlikely(err))
308 syslog_panic("Cannot create init hmac message!\n");
310 assert(132 == clen + sizeof(auth));
312 pad = mt_rand_int32() % 200;
313 msg_len = clen + sizeof(auth) + pad;
314 msg = xzmalloc(msg_len);
315 memcpy(msg, auth, sizeof(auth));
316 memcpy(msg + sizeof(auth), cbuff, clen);
317 for (i = sizeof(auth) + clen; i < msg_len; ++i)
318 msg[i] = (uint8_t) mt_rand_int32();
319 hdr.payload = htons((uint16_t) msg_len);
321 state = 1;
322 setsockopt(fd, udp ? IPPROTO_UDP : IPPROTO_TCP,
323 udp ? UDP_CORK : TCP_CORK, &state, sizeof(state));
325 err = write_exact(fd, &hdr, sizeof(struct ct_proto), 0);
326 if (unlikely(err < 0))
327 syslog(LOG_ERR, "Error writing init data to net: %s\n",
328 strerror(errno));
330 err = write_exact(fd, msg, msg_len, 0);
331 if (unlikely(err < 0))
332 syslog(LOG_ERR, "Error writing init data to net: %s\n",
333 strerror(errno));
335 state = 0;
336 setsockopt(fd, udp ? IPPROTO_UDP : IPPROTO_TCP,
337 udp ? UDP_CORK : TCP_CORK, &state, sizeof(state));
338 xfree(msg);
339 xfree(us);
342 static void notify_close(int fd)
344 ssize_t err;
345 struct ct_proto hdr;
347 memset(&hdr, 0, sizeof(hdr));
348 hdr.flags |= PROTO_FLAG_EXIT;
349 hdr.payload = 0;
351 err = write_exact(fd, &hdr, sizeof(hdr), 0);
352 if (unlikely(err < 0))
353 syslog(LOG_ERR, "Error writing close: %s\n",
354 strerror(errno));
357 int client_main(char *home, char *dev, char *host, char *port, int udp)
359 int fd = -1, tunfd = 0, retry_server = 0;
360 int ret, try = 1, i, one, mtu;
361 struct addrinfo hints, *ahead, *ai;
362 struct sockaddr_in6 *saddr6;
363 struct pollfd fds[2];
364 struct curve25519_proto *p;
365 struct curve25519_struct *c;
366 char *buff;
367 size_t blen = TUNBUFF_SIZ; //FIXME
369 retry:
370 if (!retry_server) {
371 openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);
372 syslog(LOG_INFO, "curvetun client booting!\n");
375 c = xmalloc(sizeof(struct curve25519_struct));
376 ret = curve25519_alloc_or_maybe_die(c);
377 if (ret < 0)
378 syslog_panic("Cannot init curve!\n");
380 p = get_serv_store_entry_proto_inf();
381 if (!p)
382 syslog_panic("Cannot proto!\n");
384 memset(&hints, 0, sizeof(hints));
385 hints.ai_family = PF_UNSPEC;
386 hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
387 hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
388 hints.ai_flags = AI_NUMERICSERV;
390 ret = getaddrinfo(host, port, &hints, &ahead);
391 if (ret < 0) {
392 syslog(LOG_ERR, "Cannot get address info! Retry!\n");
393 curve25519_free(c);
394 xfree(c);
395 fd = -1;
396 retry_server = 1;
397 closed_by_server = 0;
398 sleep(1);
399 goto retry;
402 for (ai = ahead; ai != NULL && fd < 0; ai = ai->ai_next) {
403 if (ai->ai_family == PF_INET6)
404 saddr6 = (struct sockaddr_in6 *) ai->ai_addr;
405 fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
406 if (fd < 0)
407 continue;
408 ret = connect(fd, ai->ai_addr, ai->ai_addrlen);
409 if (ret < 0) {
410 syslog(LOG_ERR, "Cannot connect to remote, try %d: %s!\n",
411 try++, strerror(errno));
412 close(fd);
413 fd = -1;
414 continue;
416 one = 1;
417 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
418 mtu = IP_PMTUDISC_DONT;
419 setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
420 if (!udp) {
421 one = 1;
422 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
423 sizeof(one));
427 freeaddrinfo(ahead);
428 if (fd < 0) {
429 syslog(LOG_ERR, "Cannot create socket! Retry!\n");
430 curve25519_free(c);
431 xfree(c);
432 fd = -1;
433 retry_server = 1;
434 closed_by_server = 0;
435 sleep(1);
436 goto retry;
439 if (!retry_server)
440 tunfd = tun_open_or_die(dev ? dev : DEVNAME_CLIENT,
441 IFF_TUN | IFF_NO_PI);
443 set_nonblocking_sloppy(fd);
444 set_nonblocking_sloppy(tunfd);
446 memset(fds, 0, sizeof(fds));
447 fds[0].fd = fd;
448 fds[1].fd = tunfd;
449 fds[0].events = POLLIN;
450 fds[1].events = POLLIN;
452 buff = xmalloc_aligned(blen, 64);
453 notify_init(fd, udp, p, c, home);
454 syslog(LOG_INFO, "curvetun client ready!\n");
456 while (likely(!sigint && !closed_by_server)) {
457 poll(fds, 2, -1);
458 for (i = 0; i < 2; ++i) {
459 if ((fds[i].revents & POLLIN) != POLLIN)
460 continue;
461 if (fds[i].fd == tunfd) {
462 if (udp)
463 handler_udp_tun_to_net(tunfd, fd, p, c,
464 buff, blen);
465 else
466 handler_tcp_tun_to_net(tunfd, fd, p, c,
467 buff, blen);
468 } else if (fds[i].fd == fd) {
469 if (udp)
470 handler_udp_net_to_tun(fd, tunfd, p, c,
471 buff, blen);
472 else
473 handler_tcp_net_to_tun(fd, tunfd, p, c,
474 buff, blen);
479 syslog(LOG_INFO, "curvetun client prepare shut down!\n");
480 if (!closed_by_server)
481 notify_close(fd);
482 xfree(buff);
483 close(fd);
484 curve25519_free(c);
485 xfree(c);
487 /* tundev still active */
488 if (closed_by_server && !sigint) {
489 syslog(LOG_ERR, "curvetun connection retry attempt!\n");
490 fd = -1;
491 retry_server = 1;
492 closed_by_server = 0;
493 sleep(1);
494 goto retry;
497 close(tunfd);
498 syslog(LOG_INFO, "curvetun client shut down!\n");
499 closelog();
501 return 0;