dissectors: lldp: Highlight invalid frame marker
[netsniff-ng.git] / curvetun.c
blobf629436d7314a99439b8591cca80d635276afac7
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 <sys/fsuid.h>
48 #include <netinet/in.h>
49 #include <unistd.h>
50 #include <signal.h>
52 #include "xutils.h"
53 #include "die.h"
54 #include "xmalloc.h"
55 #include "curvetun.h"
56 #include "curve.h"
57 #include "ct_usermgmt.h"
58 #include "ct_servmgmt.h"
59 #include "xio.h"
60 #include "tprintf.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 #define CURVETUN_ENTROPY_SOURCE "/dev/random"
68 extern void print_stun_probe(char *server, uint16_t sport, uint16_t tunport);
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 volatile sig_atomic_t sigint = 0;
82 static const char *short_options = "kxc::svhp:t:d:uCS46DN";
83 static const struct option long_options[] = {
84 {"client", optional_argument, NULL, 'c'},
85 {"dev", required_argument, NULL, 'd'},
86 {"port", required_argument, NULL, 'p'},
87 {"stun", required_argument, NULL, 't'},
88 {"keygen", no_argument, NULL, 'k'},
89 {"export", no_argument, NULL, 'x'},
90 {"dumpc", no_argument, NULL, 'C'},
91 {"dumps", no_argument, NULL, 'S'},
92 {"no-logging", no_argument, NULL, 'N'},
93 {"server", no_argument, NULL, 's'},
94 {"udp", no_argument, NULL, 'u'},
95 {"ipv4", no_argument, NULL, '4'},
96 {"ipv6", no_argument, NULL, '6'},
97 {"nofork", no_argument, NULL, 'D'},
98 {"version", no_argument, NULL, 'v'},
99 {"help", no_argument, NULL, 'h'},
100 {NULL, 0, NULL, 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 help(void)
116 printf("\ncurvetun %s, lightweight curve25519-based VPN/IP tunnel\n",
117 VERSION_STRING);
118 puts("http://www.netsniff-ng.org\n\n"
119 "Usage: curvetun [options]\n"
120 "Options, general:\n"
121 " -k|--keygen Generate public/private keypair\n"
122 " -x|--export Export your public data for remote servers\n"
123 " -C|--dumpc Dump parsed clients\n"
124 " -S|--dumps Dump parsed servers\n"
125 " -D|--nofork Do not daemonize\n"
126 " -d|--dev <tun> Networking tunnel device, e.g. tun0\n"
127 " -v|--version Print version\n"
128 " -h|--help Print this help\n"
129 " -c|--client[=alias] Client mode, server alias optional\n"
130 " -s|--server Server mode, options follow below\n"
131 " -N|--no-logging Disable server logging (for better anonymity)\n"
132 " -p|--port <num> Server port number (mandatory)\n"
133 " -t|--stun <server> Show public IP/Port mapping via STUN\n"
134 " -u|--udp Use UDP as carrier instead of TCP\n"
135 " -4|--ipv4 Tunnel devices are IPv4\n"
136 " -6|--ipv6 Tunnel devices are IPv6\n"
137 " (default: same as carrier protocol)\n\n"
138 "Example:\n"
139 " See Documentation/Curvetun for a configuration example.\n"
140 " curvetun --keygen\n"
141 " curvetun --export\n"
142 " curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n"
143 " curvetun --client=ethz\n\n"
144 "Note:\n"
145 " There is no default port specified, so that you are forced\n"
146 " to select your own! For client/server status messages see syslog!\n"
147 " This software is an experimental prototype intended for researchers.\n\n"
148 "Secret ingredient: 7647-14-5\n\n"
149 "Please report bugs to <bugs@netsniff-ng.org>\n"
150 "Copyright (C) 2011-2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
151 "License: GNU GPL version 2.0\n"
152 "This is free software: you are free to change and redistribute it.\n"
153 "There is NO WARRANTY, to the extent permitted by law.\n");
154 die();
157 static void version(void)
159 printf("\ncurvetun %s, lightweight curve25519-based VPN/IP tunnel\n",
160 VERSION_STRING);
161 puts("http://www.netsniff-ng.org\n\n"
162 "Please report bugs to <bugs@netsniff-ng.org>\n"
163 "Copyright (C) 2011-2012 Daniel Borkmann <daniel@netsniff-ng.org>\n"
164 "License: GNU GPL version 2.0\n"
165 "This is free software: you are free to change and redistribute it.\n"
166 "There is NO WARRANTY, to the extent permitted by law.\n");
167 die();
170 static void check_file_or_die(char *home, char *file, int maybeempty)
172 char path[PATH_MAX];
173 struct stat st;
175 memset(path, 0, sizeof(path));
176 slprintf(path, sizeof(path), "%s/%s", home, file);
178 if (stat(path, &st))
179 panic("No such file %s! Type --help for further information\n",
180 path);
182 if (!S_ISREG(st.st_mode))
183 panic("%s is not a regular file!\n", path);
185 if ((st.st_mode & ~S_IFREG) != (S_IRUSR | S_IWUSR))
186 panic("You have set too many permissions on %s (%o)!\n",
187 path, st.st_mode);
189 if (maybeempty == 0 && st.st_size == 0)
190 panic("%s is empty!\n", path);
193 static void check_config_exists_or_die(char *home)
195 if (!home)
196 panic("No home dir specified!\n");
198 check_file_or_die(home, FILE_CLIENTS, 1);
199 check_file_or_die(home, FILE_SERVERS, 1);
200 check_file_or_die(home, FILE_PRIVKEY, 0);
201 check_file_or_die(home, FILE_PUBKEY, 0);
202 check_file_or_die(home, FILE_USERNAM, 0);
205 static char *fetch_home_dir(void)
207 char *home = getenv("HOME");
208 if (!home)
209 panic("No HOME defined!\n");
210 return home;
213 static void write_username(char *home)
215 int fd, ret;
216 char path[PATH_MAX];
217 char user[512];
219 memset(path, 0, sizeof(path));
220 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
222 printf("Username: [%s] ", getenv("USER"));
223 fflush(stdout);
225 memset(user, 0, sizeof(user));
226 if (fgets(user, sizeof(user), stdin) == NULL)
227 panic("Could not read from stdin!\n");
228 user[sizeof(user) - 1] = 0;
229 user[strlen(user) - 1] = 0; /* omit last \n */
230 if (strlen(user) == 0)
231 strlcpy(user, getenv("USER"), sizeof(user));
233 fd = open_or_die_m(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
235 ret = write(fd, user, strlen(user));
236 if (ret != strlen(user))
237 panic("Could not write username!\n");
239 close(fd);
241 printf("Username written to %s!\n", path);
244 static void create_curvedir(char *home)
246 int ret;
247 char path[PATH_MAX];
249 memset(path, 0, sizeof(path));
250 slprintf(path, sizeof(path), "%s/%s", home, ".curvetun/");
252 errno = 0;
254 ret = mkdir(path, S_IRWXU);
255 if (ret < 0 && errno != EEXIST)
256 panic("Cannot create curvetun dir!\n");
258 printf("curvetun directory %s created!\n", path);
259 /* We also create empty files for clients and servers! */
261 memset(path, 0, sizeof(path));
262 slprintf(path, sizeof(path), "%s/%s", home, FILE_CLIENTS);
264 create_or_die(path, S_IRUSR | S_IWUSR);
266 printf("Empty client file written to %s!\n", path);
268 memset(path, 0, sizeof(path));
269 slprintf(path, sizeof(path), "%s/%s", home, FILE_SERVERS);
271 create_or_die(path, S_IRUSR | S_IWUSR);
273 printf("Empty server file written to %s!\n", path);
276 static void create_keypair(char *home)
278 int fd, err = 0;
279 ssize_t ret;
280 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
281 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
282 char path[PATH_MAX];
283 const char * errstr = NULL;
285 printf("Reading from %s (this may take a while) ...\n", CURVETUN_ENTROPY_SOURCE);
287 fd = open_or_die(CURVETUN_ENTROPY_SOURCE, O_RDONLY);
289 ret = read_exact(fd, secretkey, sizeof(secretkey), 0);
290 if (ret != sizeof(secretkey)) {
291 err = EIO;
292 errstr = "Cannot read from "CURVETUN_ENTROPY_SOURCE"!\n";
293 goto out;
296 close(fd);
298 crypto_scalarmult_curve25519_base(publickey, secretkey);
300 memset(path, 0, sizeof(path));
301 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
303 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
304 if (fd < 0) {
305 err = EIO;
306 errstr = "Cannot open pubkey file!\n";
307 goto out;
310 ret = write(fd, publickey, sizeof(publickey));
311 if (ret != sizeof(publickey)) {
312 err = EIO;
313 errstr = "Cannot write public key!\n";
314 goto out;
317 close(fd);
319 printf("Public key written to %s!\n", path);
321 memset(path, 0, sizeof(path));
322 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
324 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
325 if (fd < 0) {
326 err = EIO;
327 errstr = "Cannot open privkey file!\n";
328 goto out;
331 ret = write(fd, secretkey, sizeof(secretkey));
332 if (ret != sizeof(secretkey)) {
333 err = EIO;
334 errstr = "Cannot write private key!\n";
335 goto out;
337 out:
338 close(fd);
340 xmemset(publickey, 0, sizeof(publickey));
341 xmemset(secretkey, 0, sizeof(secretkey));
343 if (err)
344 panic("%s: %s", errstr, strerror(errno));
345 else
346 printf("Private key written to %s!\n", path);
349 static void check_config_keypair_or_die(char *home)
351 int fd, err;
352 ssize_t ret;
353 const char * errstr = NULL;
354 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
355 unsigned char publicres[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
356 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
357 char path[PATH_MAX];
359 memset(path, 0, sizeof(path));
360 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
362 fd = open(path, O_RDONLY);
363 if (fd < 0) {
364 err = EIO;
365 errstr = "Cannot open privkey file!\n";
366 goto out;
369 ret = read(fd, secretkey, sizeof(secretkey));
370 if (ret != sizeof(secretkey)) {
371 err = EIO;
372 errstr = "Cannot read private key!\n";
373 goto out;
376 close(fd);
378 memset(path, 0, sizeof(path));
379 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
381 fd = open(path, O_RDONLY);
382 if (fd < 0) {
383 err = EIO;
384 errstr = "Cannot open pubkey file!\n";
385 goto out;
388 ret = read(fd, publickey, sizeof(publickey));
389 if (ret != sizeof(publickey)) {
390 err = EIO;
391 errstr = "Cannot read public key!\n";
392 goto out;
395 crypto_scalarmult_curve25519_base(publicres, secretkey);
397 err = crypto_verify_32(publicres, publickey);
398 if (err) {
399 err = EINVAL;
400 errstr = "WARNING: your keypair is corrupted!!! You need to "
401 "generate new keys!!!\n";
402 goto out;
404 out:
405 close(fd);
407 xmemset(publickey, 0, sizeof(publickey));
408 xmemset(publicres, 0, sizeof(publicres));
409 xmemset(secretkey, 0, sizeof(secretkey));
411 if (err)
412 panic("%s: %s\n", errstr, strerror(errno));
415 static int main_keygen(char *home)
417 create_curvedir(home);
418 write_username(home);
419 create_keypair(home);
420 check_config_keypair_or_die(home);
422 return 0;
425 static int main_export(char *home)
427 int fd, i;
428 ssize_t ret;
429 char path[PATH_MAX], tmp[64];
431 check_config_exists_or_die(home);
432 check_config_keypair_or_die(home);
434 printf("Your exported public information:\n\n");
436 memset(path, 0, sizeof(path));
437 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);
439 fd = open_or_die(path, O_RDONLY);
441 while ((ret = read(fd, tmp, sizeof(tmp))) > 0) {
442 ret = write(STDOUT_FILENO, tmp, ret);
445 close(fd);
447 printf(";");
449 memset(path, 0, sizeof(path));
450 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
452 fd = open_or_die(path, O_RDONLY);
454 ret = read(fd, tmp, sizeof(tmp));
455 if (ret != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
456 panic("Cannot read public key!\n");
458 for (i = 0; i < ret; ++i)
459 if (i == ret - 1)
460 printf("%02x\n\n", (unsigned char) tmp[i]);
461 else
462 printf("%02x:", (unsigned char) tmp[i]);
464 close(fd);
465 fflush(stdout);
467 return 0;
470 static int main_dumpc(char *home)
472 check_config_exists_or_die(home);
473 check_config_keypair_or_die(home);
475 printf("Your clients:\n\n");
477 parse_userfile_and_generate_user_store_or_die(home);
479 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);
497 dump_serv_store();
499 destroy_serv_store();
501 printf("\n");
502 die();
503 return 0;
506 static void daemonize(const char *lockfile)
508 char pidstr[8];
509 mode_t lperm = S_IRWXU | S_IRGRP | S_IXGRP; /* 0750 */
510 int lfp;
512 if (getppid() == 1)
513 return;
515 if (daemon(0, 0))
516 panic("Cannot daemonize: %s", strerror(errno));
518 umask(lperm);
519 if (lockfile) {
520 lfp = open(lockfile, O_RDWR | O_CREAT | O_EXCL,
521 S_IRUSR | S_IWUSR | S_IRGRP);
522 if (lfp < 0)
523 syslog_panic("Cannot create lockfile at %s! "
524 "curvetun server already running?\n",
525 lockfile);
527 slprintf(pidstr, sizeof(pidstr), "%u", getpid());
528 if (write(lfp, pidstr, strlen(pidstr)) <= 0)
529 syslog_panic("Could not write pid to pidfile %s",
530 lockfile);
532 close(lfp);
536 static int main_client(char *home, char *dev, char *alias, int daemon)
538 int ret, udp;
539 char *host, *port;
541 check_config_exists_or_die(home);
542 check_config_keypair_or_die(home);
544 parse_userfile_and_generate_serv_store_or_die(home);
546 get_serv_store_entry_by_alias(alias, alias ? strlen(alias) + 1 : 0,
547 &host, &port, &udp);
548 if (!host || !port || udp < 0)
549 panic("Did not find alias/entry in configuration!\n");
551 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
552 alias ? : "default", host, port, udp ? "udp" : "tcp");
553 if (daemon)
554 daemonize(NULL);
556 ret = client_main(home, dev, host, port, udp);
558 destroy_serv_store();
560 return ret;
563 static int main_server(char *home, char *dev, char *port, int udp,
564 int ipv4, int daemon, int log)
566 int ret;
568 check_config_exists_or_die(home);
569 check_config_keypair_or_die(home);
571 if (daemon)
572 daemonize(LOCKFILE);
574 ret = server_main(home, dev, port, udp, ipv4, log);
576 unlink(LOCKFILE);
578 return ret;
581 int main(int argc, char **argv)
583 int ret = 0, c, opt_index, udp = 0, ipv4 = -1, daemon = 1, log = 1;
584 char *port = NULL, *stun = NULL, *dev = NULL, *home = NULL, *alias = NULL;
585 enum working_mode wmode = MODE_UNKNOW;
587 setfsuid(getuid());
588 setfsgid(getgid());
590 home = fetch_home_dir();
592 while ((c = getopt_long(argc, argv, short_options, long_options,
593 &opt_index)) != EOF) {
594 switch (c) {
595 case 'h':
596 help();
597 break;
598 case 'v':
599 version();
600 break;
601 case 'D':
602 daemon = 0;
603 break;
604 case 'N':
605 log = 0;
606 break;
607 case 'C':
608 wmode = MODE_DUMPC;
609 break;
610 case 'S':
611 wmode = MODE_DUMPS;
612 break;
613 case 'c':
614 wmode = MODE_CLIENT;
615 if (optarg) {
616 if (*optarg == '=')
617 optarg++;
618 alias = xstrdup(optarg);
620 break;
621 case 'd':
622 dev = xstrdup(optarg);
623 break;
624 case 'k':
625 wmode = MODE_KEYGEN;
626 break;
627 case '4':
628 ipv4 = 1;
629 break;
630 case '6':
631 ipv4 = 0;
632 break;
633 case 'x':
634 wmode = MODE_EXPORT;
635 break;
636 case 's':
637 wmode = MODE_SERVER;
638 break;
639 case 'u':
640 udp = 1;
641 break;
642 case 't':
643 stun = xstrdup(optarg);
644 break;
645 case 'p':
646 port = xstrdup(optarg);
647 break;
648 case '?':
649 switch (optopt) {
650 case 't':
651 case 'd':
652 case 'u':
653 case 'p':
654 panic("Option -%c requires an argument!\n",
655 optopt);
656 default:
657 if (isprint(optopt))
658 printf("Unknown option character `0x%X\'!\n", optopt);
659 die();
661 default:
662 break;
666 if (argc < 2)
667 help();
669 register_signal(SIGINT, signal_handler);
670 register_signal(SIGHUP, signal_handler);
671 register_signal(SIGTERM, signal_handler);
672 register_signal(SIGPIPE, signal_handler);
674 curve25519_selftest();
676 switch (wmode) {
677 case MODE_KEYGEN:
678 ret = main_keygen(home);
679 break;
680 case MODE_EXPORT:
681 ret = main_export(home);
682 break;
683 case MODE_DUMPC:
684 ret = main_dumpc(home);
685 break;
686 case MODE_DUMPS:
687 ret = main_dumps(home);
688 break;
689 case MODE_CLIENT:
690 ret = main_client(home, dev, alias, daemon);
691 break;
692 case MODE_SERVER:
693 if (!port)
694 panic("No port specified!\n");
695 if (stun)
696 print_stun_probe(stun, 3478, strtoul(port, NULL, 10));
697 ret = main_server(home, dev, port, udp, ipv4, daemon, log);
698 break;
699 default:
700 die();
703 if (dev)
704 xfree(dev);
705 if (stun)
706 xfree(stun);
707 if (port)
708 xfree(port);
709 if (alias)
710 xfree(alias);
712 return ret;