Added BPF attach/detach support check.
[netsniff-ng.git] / src / curvetun.c
blob6999765e512453cf011a62f5cc3d98162d568b06
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 <dborkma@tik.ee.ethz.ch>,
6 * Copyright 2011 Emmanuel Roullit.
7 * Subject to the GPL, version 2.
9 * This is curvetun, a lightweight, high-speed ECDH multiuser IP tunnel for
10 * Linux that is based on epoll(2). curvetun uses the Linux TUN/TAP interface
11 * and supports {IPv4,IPv6} over {IPv4,IPv6} with UDP or TCP as carrier
12 * protocols. It has an integrated packet forwarding trie, thus multiple
13 * users with different IPs can be handled via a single tunnel device on the
14 * server side and flows are scheduled for processing in a CPU-local manner.
15 * For transmission, packets are being compressed and encrypted by both, the
16 * client and the server side. As an appropriate key management, public-key
17 * cryptography based on elliptic curves are being used and packets are
18 * encrypted by a symmetric stream cipher (Salsa20) and authenticated by a MAC
19 * (Poly1305), where keys have previously been computed with the ECDH key
20 * agreement protocol (Curve25519). Cryptography is based on Daniel J.
21 * Bernsteins Networking and Cryptography library (NaCl).
23 * He used often to say there was only one Road; that it was like a great
24 * river: it's springs were at every doorstep and every path was it's
25 * tributary. "It's a dangerous business, Frodo, going out of your door,"
26 * he used to say. "You step into the Road, and if you don't keep your
27 * feet, there is no telling where you might be swept off to."
29 * -- The Lord of the Rings, Frodo about his uncle Bilbo Baggins,
30 * Chapter 'Three is Company'.
33 #define _GNU_SOURCE
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <getopt.h>
40 #include <errno.h>
41 #include <stdbool.h>
42 #include <limits.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/socket.h>
46 #include <sys/ptrace.h>
47 #include <netinet/in.h>
48 #include <unistd.h>
50 #include "netdev.h"
51 #include "version.h"
52 #include "stun.h"
53 #include "die.h"
54 #include "strlcpy.h"
55 #include "signals.h"
56 #include "curvetun.h"
57 #include "curve.h"
58 #include "usermgmt.h"
59 #include "servmgmt.h"
60 #include "write_or_die.h"
61 #include "crypto_verify_32.h"
62 #include "crypto_box_curve25519xsalsa20poly1305.h"
63 #include "crypto_scalarmult_curve25519.h"
64 #include "crypto_auth_hmacsha512256.h"
66 noinline void *memset(void *__s, int __c, size_t __n);
68 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
70 enum working_mode {
71 MODE_UNKNOW,
72 MODE_KEYGEN,
73 MODE_EXPORT,
74 MODE_DUMPC,
75 MODE_DUMPS,
76 MODE_CLIENT,
77 MODE_SERVER,
80 sig_atomic_t sigint = 0;
82 static const char *short_options = "kxc::svhp:t:d:uCS46D";
84 static struct option long_options[] = {
85 {"client", optional_argument, 0, 'c'},
86 {"dev", required_argument, 0, 'd'},
87 {"port", required_argument, 0, 'p'},
88 {"stun", required_argument, 0, 't'},
89 {"keygen", no_argument, 0, 'k'},
90 {"export", no_argument, 0, 'x'},
91 {"dumpc", no_argument, 0, 'C'},
92 {"dumps", no_argument, 0, 'S'},
93 {"server", no_argument, 0, 's'},
94 {"udp", no_argument, 0, 'u'},
95 {"ipv4", no_argument, 0, '4'},
96 {"ipv6", no_argument, 0, '6'},
97 {"nofork", no_argument, 0, 'D'},
98 {"version", no_argument, 0, 'v'},
99 {"help", no_argument, 0, 'h'},
100 {0, 0, 0, 0}
103 static void signal_handler(int number)
105 switch (number) {
106 case SIGINT:
107 sigint = 1;
108 break;
109 default:
110 break;
114 static void header(void)
116 printf("%s%s%s\n", colorize_start(bold), "curvetun "
117 VERSION_STRING, colorize_end());
120 static void help(void)
122 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
123 VERSION_STRING);
124 printf("http://www.netsniff-ng.org\n\n");
125 printf("Usage: curvetun [options]\n");
126 printf("Options:\n");
127 printf(" -k|--keygen Generate public/private keypair\n");
128 printf(" -x|--export Export your public data for remote servers\n");
129 printf(" -C|--dumpc Dump parsed clients\n");
130 printf(" -S|--dumps Dump parsed servers\n");
131 printf(" -D|--nofork Do not daemonize\n");
132 printf(" -d|--dev <tun> Networking tunnel device, e.g. tun0\n");
133 printf(" -v|--version Print version\n");
134 printf(" -h|--help Print this help\n");
135 printf(" Client settings:\n");
136 printf(" -c|--client[=alias] Client mode, server alias optional\n");
137 printf(" Server settings:\n");
138 printf(" -s|--server Server mode\n");
139 printf(" -p|--port <num> Port number (mandatory)\n");
140 printf(" -t|--stun <server> Show public IP/Port mapping via STUN\n");
141 printf(" -u|--udp Use UDP as carrier instead of TCP\n");
142 printf(" -4|--ipv4 Tunnel devices are IPv4\n");
143 printf(" -6|--ipv6 Tunnel devices are IPv6\n");
144 printf(" (default: same as carrier protocol)\n");
145 printf("\n");
146 printf("Example:\n");
147 printf(" See README.curvetun for a configuration example.\n");
148 printf(" curvetun --keygen\n");
149 printf(" curvetun --export\n");
150 printf(" curvetun --server -4 -u --port 6666 --stun stunserver.org\n");
151 printf(" curvetun --client=ethz\n");
152 printf("\n");
153 printf("Note:\n");
154 printf(" There is no default port specified, so that you are forced\n");
155 printf(" to select your own! For client/server status messages see syslog!\n");
156 printf("\n");
157 printf("Secret ingredient: 7647-14-5\n");
158 printf("\n");
159 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
160 printf("Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
161 printf("License: GNU GPL version 2\n");
162 printf("This is free software: you are free to change and redistribute it.\n");
163 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
165 die();
168 static void version(void)
170 printf("\ncurvetun %s, lightweight curve25519-based multiuser IP tunnel\n",
171 VERSION_STRING);
172 printf("Build: %s\n", BUILD_STRING);
173 printf("http://www.netsniff-ng.org\n\n");
174 printf("Please report bugs to <bugs@netsniff-ng.org>\n");
175 printf("Copyright (C) 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n");
176 printf("License: GNU GPL version 2\n");
177 printf("This is free software: you are free to change and redistribute it.\n");
178 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
180 die();
183 static void check_file_or_die(char *home, char *file, int maybeempty)
185 char path[PATH_MAX];
186 struct stat st;
188 memset(path, 0, sizeof(path));
189 slprintf(path, sizeof(path), "%s/%s", home, file);
191 if (stat(path, &st))
192 panic("No such file %s! Type --help for further information\n",
193 path);
195 if (!S_ISREG(st.st_mode))
196 panic("%s is not a regular file!\n", path);
198 if ((st.st_mode & ~S_IFREG) != (S_IRUSR | S_IWUSR))
199 panic("You have set too many permissions on %s (%o)!\n",
200 path, st.st_mode);
202 if (maybeempty == 0 && st.st_size == 0)
203 panic("%s is empty!\n", path);
206 static void check_config_exists_or_die(char *home)
208 if (!home)
209 panic("No home dir specified!\n");
210 check_file_or_die(home, FILE_CLIENTS, 1);
211 check_file_or_die(home, FILE_SERVERS, 1);
212 check_file_or_die(home, FILE_PRIVKEY, 0);
213 check_file_or_die(home, FILE_PUBKEY, 0);
214 check_file_or_die(home, FILE_USERNAM, 0);
217 static char *fetch_home_dir(void)
219 char *home = getenv("HOME");
220 if (!home)
221 panic("No HOME defined!\n");
222 return home;
225 static void write_username(char *home)
227 int fd, ret;
228 char path[PATH_MAX], *eof;
229 char user[512];
231 memset(path, 0, sizeof(path));
232 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
234 printf("Username: [%s] ", getenv("USER"));
235 fflush(stdout);
237 memset(user, 0, sizeof(user));
238 eof = fgets(user, sizeof(user), stdin);
239 user[sizeof(user) - 1] = 0;
240 user[strlen(user) - 1] = 0; /* omit last \n */
242 if (strlen(user) == 0)
243 strlcpy(user, getenv("USER"), sizeof(user));
245 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
246 if (fd < 0)
247 panic("Cannot open your username file!\n");
248 ret = write(fd, user, strlen(user));
249 if (ret != strlen(user))
250 panic("Could not write username!\n");
251 close(fd);
253 info("Username written to %s!\n", path);
256 static void create_curvedir(char *home)
258 int ret, fd;
259 char path[PATH_MAX];
261 memset(path, 0, sizeof(path));
262 slprintf(path, sizeof(path), "%s/%s", home, ".curvetun/");
264 errno = 0;
265 ret = mkdir(path, S_IRWXU);
266 if (ret < 0 && errno != EEXIST)
267 panic("Cannot create curvetun dir!\n");
269 info("curvetun directory %s created!\n", path);
271 /* We also create empty files for clients and servers! */
272 memset(path, 0, sizeof(path));
273 slprintf(path, sizeof(path), "%s/%s", home, FILE_CLIENTS);
275 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
276 if (fd < 0)
277 panic("Cannot open clients file!\n");
278 close(fd);
280 info("Empty client file written to %s!\n", path);
282 memset(path, 0, sizeof(path));
283 slprintf(path, sizeof(path), "%s/%s", home, FILE_SERVERS);
285 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
286 if (fd < 0)
287 panic("Cannot open servers file!\n");
288 close(fd);
290 info("Empty server file written to %s!\n", path);
293 static void create_keypair(char *home)
295 int fd;
296 ssize_t ret;
297 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
298 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
299 char path[PATH_MAX];
300 const char * errstr = NULL;
301 int err = 0;
303 info("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE);
305 fd = open_or_die(CURVETUN_ENTROPY_SOURCE, O_RDONLY);
306 ret = read_exact(fd, secretkey, sizeof(secretkey), 0);
307 if (ret != sizeof(secretkey)) {
308 err = EIO;
309 errstr = "Cannot read from "CURVETUN_ENTROPY_SOURCE"!\n";
310 goto out;
312 close(fd);
314 crypto_scalarmult_curve25519_base(publickey, secretkey);
316 memset(path, 0, sizeof(path));
317 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
319 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
320 if (fd < 0) {
321 err = EIO;
322 errstr = "Cannot open pubkey file!\n";
323 goto out;
325 ret = write(fd, publickey, sizeof(publickey));
326 if (ret != sizeof(publickey)) {
327 err = EIO;
328 errstr = "Cannot write public key!\n";
329 goto out;
331 close(fd);
333 info("Public key written to %s!\n", path);
335 memset(path, 0, sizeof(path));
336 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
338 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
339 if (fd < 0) {
340 err = EIO;
341 errstr = "Cannot open privkey file!\n";
342 goto out;
345 ret = write(fd, secretkey, sizeof(secretkey));
346 if (ret != sizeof(secretkey)) {
347 err = EIO;
348 errstr = "Cannot write private key!\n";
349 goto out;
351 out:
352 close(fd);
354 memset(publickey, 0, sizeof(publickey));
355 memset(secretkey, 0, sizeof(secretkey));
356 if (err)
357 panic("%s: %s", errstr, strerror(errno));
358 else
359 info("Private key written to %s!\n", path);
362 static void check_config_keypair_or_die(char *home)
364 int fd;
365 ssize_t ret;
366 int err;
367 const char * errstr = NULL;
368 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
369 unsigned char publicres[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
370 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
371 char path[PATH_MAX];
373 memset(path, 0, sizeof(path));
374 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
376 fd = open(path, O_RDONLY);
377 if (fd < 0) {
378 err = EIO;
379 errstr = "Cannot open privkey file!\n";
380 goto out;
382 ret = read(fd, secretkey, sizeof(secretkey));
383 if (ret != sizeof(secretkey)) {
384 err = EIO;
385 errstr = "Cannot read private key!\n";
386 goto out;
388 close(fd);
390 memset(path, 0, sizeof(path));
391 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
393 fd = open(path, O_RDONLY);
394 if (fd < 0) {
395 err = EIO;
396 errstr = "Cannot open pubkey file!\n";
397 goto out;
399 ret = read(fd, publickey, sizeof(publickey));
400 if (ret != sizeof(publickey)) {
401 err = EIO;
402 errstr = "Cannot read public key!\n";
403 goto out;
406 crypto_scalarmult_curve25519_base(publicres, secretkey);
407 err = crypto_verify_32(publicres, publickey);
408 if (err) {
409 err = EINVAL;
410 errstr = "WARNING: your keypair is corrupted!!! You need to "
411 "generate new keys!!!\n";
412 goto out;
414 out:
415 close(fd);
416 memset(publickey, 0, sizeof(publickey));
417 memset(publicres, 0, sizeof(publicres));
418 memset(secretkey, 0, sizeof(secretkey));
419 if (err)
420 panic("%s: %s\n", errstr, strerror(errno));
423 static int main_keygen(char *home)
425 create_curvedir(home);
426 write_username(home);
427 create_keypair(home);
428 check_config_keypair_or_die(home);
429 return 0;
432 static int main_export(char *home)
434 int fd, i;
435 ssize_t ret;
436 char path[PATH_MAX], tmp[64];
438 check_config_exists_or_die(home);
439 check_config_keypair_or_die(home);
441 printf("Your exported public information:\n\n");
443 memset(path, 0, sizeof(path));
444 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
446 fd = open_or_die(path, O_RDONLY);
447 while ((ret = read(fd, tmp, sizeof(tmp))) > 0) {
448 ret = write(STDOUT_FILENO, tmp, ret);
450 close(fd);
452 printf(";");
454 memset(path, 0, sizeof(path));
455 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
457 fd = open_or_die(path, O_RDONLY);
458 ret = read(fd, tmp, sizeof(tmp));
459 if (ret != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
460 panic("Cannot read public key!\n");
461 for (i = 0; i < ret; ++i)
462 if (i == ret - 1)
463 printf("%02x\n\n", (unsigned char) tmp[i]);
464 else
465 printf("%02x:", (unsigned char) tmp[i]);
466 close(fd);
467 fflush(stdout);
469 return 0;
472 static int main_dumpc(char *home)
474 check_config_exists_or_die(home);
475 check_config_keypair_or_die(home);
477 printf("Your clients:\n\n");
479 parse_userfile_and_generate_user_store_or_die(home);
480 dump_user_store();
481 destroy_user_store();
483 printf("\n");
484 die();
485 return 0;
488 static int main_dumps(char *home)
490 check_config_exists_or_die(home);
491 check_config_keypair_or_die(home);
493 printf("Your servers:\n\n");
495 parse_userfile_and_generate_serv_store_or_die(home);
496 dump_serv_store();
497 destroy_serv_store();
499 printf("\n");
500 die();
501 return 0;
504 static void daemonize(const char *lockfile)
506 char pidstr[8];
507 mode_t lperm = S_IRWXU | S_IRGRP | S_IXGRP; /* 0750 */
508 int lfp;
510 if (getppid() == 1)
511 return;
513 if (daemon(0, 0))
514 panic("Cannot daemonize: %s", strerror(errno));
516 umask(lperm);
518 if (lockfile) {
519 lfp = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0640);
520 if (lfp < 0)
521 syslog_panic("Cannot create lockfile at %s! "
522 "curvetun server already running?\n",
523 lockfile);
525 slprintf(pidstr, sizeof(pidstr), "%u", getpid());
526 if (write(lfp, pidstr, strlen(pidstr)) <= 0)
527 syslog_panic("Could not write pid to pidfile %s",
528 lockfile);
529 close(lfp);
533 static int main_client(char *home, char *dev, char *alias, int daemon)
535 int ret, udp;
536 char *host, *port;
538 check_config_exists_or_die(home);
539 check_config_keypair_or_die(home);
541 parse_userfile_and_generate_serv_store_or_die(home);
542 get_serv_store_entry_by_alias(alias, alias ? strlen(alias) + 1 : 0,
543 &host, &port, &udp);
544 if (!host || !port || udp < 0)
545 panic("Did not find alias/entry in configuration!\n");
546 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
547 alias ? : "default", host, port, udp ? "udp" : "tcp");
549 if (daemon)
550 daemonize(NULL);
551 ret = client_main(home, dev, host, port, udp);
552 destroy_serv_store();
554 return ret;
557 static int main_server(char *home, char *dev, char *port, int udp,
558 int ipv4, int daemon)
560 int ret;
562 check_config_exists_or_die(home);
563 check_config_keypair_or_die(home);
564 if (daemon)
565 daemonize(LOCKFILE);
566 ret = server_main(home, dev, port, udp, ipv4);
567 unlink(LOCKFILE);
569 return ret;
572 int main(int argc, char **argv)
574 int ret = 0, c, opt_index, udp = 0, ipv4 = -1, daemon = 1;
575 char *port = NULL, *stun = NULL, *dev = NULL, *home = NULL, *alias=NULL;
576 enum working_mode wmode = MODE_UNKNOW;
578 if (getuid() != geteuid())
579 seteuid(getuid());
580 if (getenv("LD_PRELOAD"))
581 panic("curvetun cannot be preloaded!\n");
582 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0)
583 panic("curvetun cannot be ptraced!\n");
585 home = fetch_home_dir();
587 while ((c = getopt_long(argc, argv, short_options, long_options,
588 &opt_index)) != EOF) {
589 switch (c) {
590 case 'h':
591 help();
592 break;
593 case 'v':
594 version();
595 break;
596 case 'D':
597 daemon = 0;
598 break;
599 case 'C':
600 wmode = MODE_DUMPC;
601 break;
602 case 'S':
603 wmode = MODE_DUMPS;
604 break;
605 case 'c':
606 wmode = MODE_CLIENT;
607 if (optarg) {
608 if (*optarg == '=')
609 optarg++;
610 alias = xstrdup(optarg);
612 break;
613 case 'd':
614 dev = xstrdup(optarg);
615 break;
616 case 'k':
617 wmode = MODE_KEYGEN;
618 break;
619 case '4':
620 ipv4 = 1;
621 break;
622 case '6':
623 ipv4 = 0;
624 break;
625 case 'x':
626 wmode = MODE_EXPORT;
627 break;
628 case 's':
629 wmode = MODE_SERVER;
630 break;
631 case 'u':
632 udp = 1;
633 break;
634 case 't':
635 stun = xstrdup(optarg);
636 break;
637 case 'p':
638 port = xstrdup(optarg);
639 break;
640 case '?':
641 switch (optopt) {
642 case 't':
643 case 'd':
644 case 'u':
645 case 'p':
646 panic("Option -%c requires an argument!\n",
647 optopt);
648 default:
649 if (isprint(optopt))
650 whine("Unknown option character "
651 "`0x%X\'!\n", optopt);
652 die();
654 default:
655 break;
659 if (argc < 2)
660 help();
662 register_signal(SIGINT, signal_handler);
663 register_signal(SIGHUP, signal_handler);
664 register_signal(SIGTERM, signal_handler);
665 register_signal(SIGPIPE, signal_handler);
667 header();
668 curve25519_selftest();
670 switch (wmode) {
671 case MODE_KEYGEN:
672 ret = main_keygen(home);
673 break;
674 case MODE_EXPORT:
675 ret = main_export(home);
676 break;
677 case MODE_DUMPC:
678 ret = main_dumpc(home);
679 break;
680 case MODE_DUMPS:
681 ret = main_dumps(home);
682 break;
683 case MODE_CLIENT:
684 ret = main_client(home, dev, alias, daemon);
685 break;
686 case MODE_SERVER:
687 if (!port)
688 panic("No port specified!\n");
689 if (stun)
690 print_stun_probe(stun, 3478, strtoul(port, NULL, 10));
691 ret = main_server(home, dev, port, udp, ipv4, daemon);
692 break;
693 default:
694 die();
697 if (dev)
698 xfree(dev);
699 if (stun)
700 xfree(stun);
701 if (port)
702 xfree(port);
703 if (alias)
704 xfree(alias);
705 return ret;