2 * curvetun - the cipherspace wormhole creator
3 * Part of the netsniff-ng project
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Copyright 2011 Emmanuel Roullit.
6 * Subject to the GPL, version 2.
19 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/ptrace.h>
23 #include <sys/fsuid.h>
24 #include <netinet/in.h>
38 #include "curvetun_mgmt.h"
53 volatile sig_atomic_t sigint
= 0;
55 static const char *short_options
= "kxc::svhp:t:d:uCS46DN";
56 static const struct option long_options
[] = {
57 {"client", optional_argument
, NULL
, 'c'},
58 {"dev", required_argument
, NULL
, 'd'},
59 {"port", required_argument
, NULL
, 'p'},
60 {"stun", required_argument
, NULL
, 't'},
61 {"keygen", no_argument
, NULL
, 'k'},
62 {"export", no_argument
, NULL
, 'x'},
63 {"dumpc", no_argument
, NULL
, 'C'},
64 {"dumps", no_argument
, NULL
, 'S'},
65 {"no-logging", no_argument
, NULL
, 'N'},
66 {"server", no_argument
, NULL
, 's'},
67 {"udp", no_argument
, NULL
, 'u'},
68 {"ipv4", no_argument
, NULL
, '4'},
69 {"ipv6", no_argument
, NULL
, '6'},
70 {"nofork", no_argument
, NULL
, 'D'},
71 {"version", no_argument
, NULL
, 'v'},
72 {"help", no_argument
, NULL
, 'h'},
76 static void signal_handler(int number
)
88 static void __noreturn
help(void)
90 printf("\ncurvetun %s, lightweight curve25519-based IP tunnel\n", VERSION_STRING
);
91 puts("http://www.netsniff-ng.org\n\n"
92 "Usage: curvetun [options]\n"
94 " -d|--dev <tun> Networking tunnel device, e.g. tun0\n"
95 " -p|--port <num> Server port number (mandatory)\n"
96 " -t|--stun <server> Show public IP/Port mapping via STUN\n"
97 " -c|--client[=alias] Client mode, server alias optional\n"
98 " -k|--keygen Generate public/private keypair\n"
99 " -x|--export Export your public data for remote servers\n"
100 " -C|--dumpc Dump parsed clients\n"
101 " -S|--dumps Dump parsed servers\n"
102 " -D|--nofork Do not daemonize\n"
103 " -s|--server Server mode, options follow below\n"
104 " -N|--no-logging Disable server logging (for better anonymity)\n"
105 " -u|--udp Use UDP as carrier instead of TCP\n"
106 " -4|--ipv4 Tunnel devices are IPv4\n"
107 " -6|--ipv6 Tunnel devices are IPv6\n"
108 " -v|--version Print version and exit\n"
109 " -h|--help Print this help and exit\n\n"
111 " See curvetun's man page for a configuration example.\n"
112 " curvetun --server -4 -u -N --port 6666 --stun stunserver.org\n"
113 " curvetun --client=ethz\n\n"
114 " curvetun --keygen\n"
115 " curvetun --export\n"
117 " There is no default port specified, so that you are forced\n"
118 " to select your own! For client/server status messages see syslog!\n"
119 " This software is an experimental prototype intended for researchers.\n\n"
120 "Secret ingredient: 7647-14-5\n\n"
121 "Please report bugs to <bugs@netsniff-ng.org>\n"
122 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
123 "Swiss federal institute of technology (ETH Zurich)\n"
124 "License: GNU GPL version 2.0\n"
125 "This is free software: you are free to change and redistribute it.\n"
126 "There is NO WARRANTY, to the extent permitted by law.\n");
130 static void __noreturn
version(void)
132 printf("\ncurvetun %s, Git id: %s\n", VERSION_LONG
, GITVERSION
);
133 puts("lightweight curve25519-based IP tunnel\n"
134 "Note: Einstein-Rosen bridge not yet supported\n"
135 "http://www.netsniff-ng.org\n\n"
136 "Please report bugs to <bugs@netsniff-ng.org>\n"
137 "Copyright (C) 2011-2013 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,\n"
138 "Swiss federal institute of technology (ETH Zurich)\n"
139 "License: GNU GPL version 2.0\n"
140 "This is free software: you are free to change and redistribute it.\n"
141 "There is NO WARRANTY, to the extent permitted by law.\n");
145 static void check_file_or_die(char *home
, char *file
, int maybeempty
)
150 memset(path
, 0, sizeof(path
));
151 slprintf(path
, sizeof(path
), "%s/%s", home
, file
);
154 panic("No such file %s! Type --help for further information\n",
157 if (!S_ISREG(st
.st_mode
))
158 panic("%s is not a regular file!\n", path
);
160 if ((st
.st_mode
& ~S_IFREG
) != (S_IRUSR
| S_IWUSR
))
161 panic("You have set too many permissions on %s (%o)!\n",
164 if (maybeempty
== 0 && st
.st_size
== 0)
165 panic("%s is empty!\n", path
);
168 static void check_config_exists_or_die(char *home
)
171 panic("No home dir specified!\n");
173 check_file_or_die(home
, FILE_CLIENTS
, 1);
174 check_file_or_die(home
, FILE_SERVERS
, 1);
175 check_file_or_die(home
, FILE_PRIVKEY
, 0);
176 check_file_or_die(home
, FILE_PUBKEY
, 0);
177 check_file_or_die(home
, FILE_USERNAM
, 0);
180 static char *fetch_home_dir(void)
182 char *home
= getenv("HOME");
184 panic("No HOME defined!\n");
188 static void write_username(char *home
)
194 memset(path
, 0, sizeof(path
));
195 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
197 printf("Username: [%s] ", getenv("USER"));
200 memset(user
, 0, sizeof(user
));
201 if (fgets(user
, sizeof(user
), stdin
) == NULL
)
202 panic("Could not read from stdin!\n");
203 user
[sizeof(user
) - 1] = 0;
204 user
[strlen(user
) - 1] = 0; /* omit last \n */
205 if (strlen(user
) == 0)
206 strlcpy(user
, getenv("USER"), sizeof(user
));
208 fd
= open_or_die_m(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
210 ret
= write(fd
, user
, strlen(user
));
211 if (ret
!= strlen(user
))
212 panic("Could not write username!\n");
216 printf("Username written to %s!\n", path
);
219 static void create_curvedir(char *home
)
224 memset(path
, 0, sizeof(path
));
225 slprintf(path
, sizeof(path
), "%s/%s", home
, ".curvetun/");
229 ret
= mkdir(path
, S_IRWXU
);
230 if (ret
< 0 && errno
!= EEXIST
)
231 panic("Cannot create curvetun dir!\n");
233 printf("curvetun directory %s created!\n", path
);
234 /* We also create empty files for clients and servers! */
236 memset(path
, 0, sizeof(path
));
237 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_CLIENTS
);
239 create_or_die(path
, S_IRUSR
| S_IWUSR
);
241 printf("Empty client file written to %s!\n", path
);
243 memset(path
, 0, sizeof(path
));
244 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_SERVERS
);
246 create_or_die(path
, S_IRUSR
| S_IWUSR
);
248 printf("Empty server file written to %s!\n", path
);
251 static void create_keypair(char *home
)
255 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
] = { 0 };
256 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
] = { 0 };
258 const char * errstr
= NULL
;
260 printf("Reading from %s (this may take a while) ...\n", HIG_ENTROPY_SOURCE
);
262 gen_key_bytes(secretkey
, sizeof(secretkey
));
263 crypto_scalarmult_curve25519_base(publickey
, secretkey
);
265 memset(path
, 0, sizeof(path
));
266 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
268 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
271 errstr
= "Cannot open pubkey file!\n";
275 ret
= write(fd
, publickey
, sizeof(publickey
));
276 if (ret
!= sizeof(publickey
)) {
278 errstr
= "Cannot write public key!\n";
284 printf("Public key written to %s!\n", path
);
286 memset(path
, 0, sizeof(path
));
287 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
289 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
292 errstr
= "Cannot open privkey file!\n";
296 ret
= write(fd
, secretkey
, sizeof(secretkey
));
297 if (ret
!= sizeof(secretkey
)) {
299 errstr
= "Cannot write private key!\n";
305 xmemset(publickey
, 0, sizeof(publickey
));
306 xmemset(secretkey
, 0, sizeof(secretkey
));
309 panic("%s: %s", errstr
, strerror(errno
));
311 printf("Private key written to %s!\n", path
);
314 static void check_config_keypair_or_die(char *home
)
318 const char * errstr
= NULL
;
319 unsigned char publickey
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
320 unsigned char publicres
[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
];
321 unsigned char secretkey
[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
];
324 memset(path
, 0, sizeof(path
));
325 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PRIVKEY
);
327 fd
= open(path
, O_RDONLY
);
330 errstr
= "Cannot open privkey file!\n";
334 ret
= read(fd
, secretkey
, sizeof(secretkey
));
335 if (ret
!= sizeof(secretkey
)) {
337 errstr
= "Cannot read private key!\n";
343 memset(path
, 0, sizeof(path
));
344 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
346 fd
= open(path
, O_RDONLY
);
349 errstr
= "Cannot open pubkey file!\n";
353 ret
= read(fd
, publickey
, sizeof(publickey
));
354 if (ret
!= sizeof(publickey
)) {
356 errstr
= "Cannot read public key!\n";
360 crypto_scalarmult_curve25519_base(publicres
, secretkey
);
362 err
= crypto_verify_32(publicres
, publickey
);
365 errstr
= "WARNING: your keypair is corrupted!!! You need to "
366 "generate new keys!!!\n";
372 xmemset(publickey
, 0, sizeof(publickey
));
373 xmemset(publicres
, 0, sizeof(publicres
));
374 xmemset(secretkey
, 0, sizeof(secretkey
));
377 panic("%s: %s\n", errstr
, strerror(errno
));
380 static int main_keygen(char *home
)
382 create_curvedir(home
);
383 write_username(home
);
384 create_keypair(home
);
385 check_config_keypair_or_die(home
);
390 static int main_export(char *home
)
394 char path
[PATH_MAX
], tmp
[64];
396 check_config_exists_or_die(home
);
397 check_config_keypair_or_die(home
);
399 printf("Your exported public information:\n\n");
401 memset(path
, 0, sizeof(path
));
402 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_USERNAM
);
404 fd
= open_or_die(path
, O_RDONLY
);
406 while ((ret
= read(fd
, tmp
, sizeof(tmp
))) > 0) {
407 ret
= write(STDOUT_FILENO
, tmp
, ret
);
414 memset(path
, 0, sizeof(path
));
415 slprintf(path
, sizeof(path
), "%s/%s", home
, FILE_PUBKEY
);
417 fd
= open_or_die(path
, O_RDONLY
);
419 ret
= read(fd
, tmp
, sizeof(tmp
));
420 if (ret
!= crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
)
421 panic("Cannot read public key!\n");
423 for (i
= 0; i
< ret
; ++i
)
425 printf("%02x\n\n", (unsigned char) tmp
[i
]);
427 printf("%02x:", (unsigned char) tmp
[i
]);
435 static int main_dumpc(char *home
)
437 check_config_exists_or_die(home
);
438 check_config_keypair_or_die(home
);
440 printf("Your clients:\n\n");
442 parse_userfile_and_generate_user_store_or_die(home
);
446 destroy_user_store();
453 static int main_dumps(char *home
)
455 check_config_exists_or_die(home
);
456 check_config_keypair_or_die(home
);
458 printf("Your servers:\n\n");
460 parse_userfile_and_generate_serv_store_or_die(home
);
464 destroy_serv_store();
471 static void daemonize(const char *lockfile
)
474 mode_t lperm
= S_IRWXU
| S_IRGRP
| S_IXGRP
; /* 0750 */
481 panic("Cannot daemonize: %s", strerror(errno
));
488 lfp
= open(lockfile
, O_RDWR
| O_CREAT
| O_EXCL
,
489 S_IRUSR
| S_IWUSR
| S_IRGRP
);
491 syslog_panic("Cannot create lockfile at %s! "
492 "curvetun server already running?\n",
495 slprintf(pidstr
, sizeof(pidstr
), "%u", getpid());
496 if (write(lfp
, pidstr
, strlen(pidstr
)) <= 0)
497 syslog_panic("Could not write pid to pidfile %s",
504 static int main_client(char *home
, char *dev
, char *alias
, int daemon
)
509 check_config_exists_or_die(home
);
510 check_config_keypair_or_die(home
);
512 parse_userfile_and_generate_serv_store_or_die(home
);
514 get_serv_store_entry_by_alias(alias
, alias
? strlen(alias
) + 1 : 0,
516 if (!host
|| !port
|| udp
< 0)
517 panic("Did not find alias/entry in configuration!\n");
519 printf("Using [%s] -> %s:%s via %s as endpoint!\n",
520 alias
? : "default", host
, port
, udp
? "udp" : "tcp");
524 ret
= client_main(home
, dev
, host
, port
, udp
);
526 destroy_serv_store();
531 static int main_server(char *home
, char *dev
, char *port
, int udp
,
532 int ipv4
, int daemon
, int log
)
536 check_config_exists_or_die(home
);
537 check_config_keypair_or_die(home
);
542 ret
= server_main(home
, dev
, port
, udp
, ipv4
, log
);
549 int main(int argc
, char **argv
)
551 int ret
= 0, c
, opt_index
, udp
= 0, ipv4
= -1, daemon
= 1, log
= 1;
552 char *port
= NULL
, *stun
= NULL
, *dev
= NULL
, *home
= NULL
, *alias
= NULL
;
553 enum working_mode wmode
= MODE_UNKNOW
;
558 home
= fetch_home_dir();
560 while ((c
= getopt_long(argc
, argv
, short_options
, long_options
,
561 &opt_index
)) != EOF
) {
586 alias
= xstrdup(optarg
);
590 dev
= xstrdup(optarg
);
611 stun
= xstrdup(optarg
);
614 port
= xstrdup(optarg
);
622 panic("Option -%c requires an argument!\n",
626 printf("Unknown option character `0x%X\'!\n", optopt
);
637 register_signal(SIGINT
, signal_handler
);
638 register_signal(SIGHUP
, signal_handler
);
639 register_signal(SIGTERM
, signal_handler
);
640 register_signal(SIGPIPE
, signal_handler
);
642 curve25519_selftest();
646 ret
= main_keygen(home
);
649 ret
= main_export(home
);
652 ret
= main_dumpc(home
);
655 ret
= main_dumps(home
);
658 ret
= main_client(home
, dev
, alias
, daemon
);
662 panic("No port specified!\n");
664 print_stun_probe(stun
, 3478, strtoul(port
, NULL
, 10));
665 ret
= main_server(home
, dev
, port
, udp
, ipv4
, daemon
, log
);