Further cleanups, removed die.h
[transsip.git] / src / transsip.c
blob1a0557896e3fc32eb9bbd2d8f467a26aa5c96dab
1 /*
2 * transsip - the telephony network
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
5 * Swiss federal institute of technology (ETH Zurich)
6 * Subject to the GPL, version 2.
8 * This is transsip, a minimalistic, high-speed ECDH peer-to-peer telephony
9 * network. It supports IPv4 and IPv6. As an appropriate key management,
10 * public-key cryptography based on elliptic curves are being used and
11 * packets are encrypted by a symmetric stream cipher (Salsa20) and
12 * authenticated by a MAC (Poly1305), where keys have previously been
13 * computed with the ECDH key agreement protocol (Curve25519). Cryptography
14 * is based on Daniel J. Bernsteins Networking and Cryptography library (NaCl).
15 * Our motivation: Privacy is necessary for an open society in the electronic
16 * age. Privacy is not secrecy. A private matter is something one doesn't
17 * want the whole world to know, but a secret matter is something one doesn't
18 * want anybody to know. Privacy is the power to selectively reveal oneself
19 * to the world. [...] We must defend our own privacy if we expect to have any.
21 * Let folly be our cloak, a veil before the eyes of the Enemy! For he is
22 * very wise, and weighs all things to a nicety in the scales of his malice.
23 * But the only measure that he knows is desire, desire for power; and so he
24 * judges all hearts. Into his heart the thought will not enter that any will
25 * refuse it, that having the Ring we may seek to destroy it. If we seek this,
26 * we shall put him out of reckoning.
28 * -- The Lord of the Rings, Gandalf, Chapter 'The Council of Elrond'.
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <pthread.h>
37 #include <signal.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/stat.h>
41 #include <sys/poll.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <netdb.h>
45 #include <celt/celt.h>
46 #include <sys/ptrace.h>
47 #include <speex/speex_jitter.h>
48 #include <speex/speex_echo.h>
49 #include <sched.h>
51 #include "conf.h"
52 #include "version.h"
53 #include "curve.h"
54 #include "compiler.h"
55 #include "alsa.h"
56 #include "xmalloc.h"
57 #include "xutils.h"
58 #include "crypto_verify_32.h"
59 #include "crypto_box_curve25519xsalsa20poly1305.h"
60 #include "crypto_scalarmult_curve25519.h"
61 #include "crypto_auth_hmacsha512256.h"
63 noinline void *memset(void *__s, int __c, size_t __n);
64 extern void enter_shell_loop(void);
65 int show_key_export(char *home);
67 static pthread_t ptid;
69 static char *port = "30111";
70 static char *stun_server = "stunserver.org";
71 static char *alsadev = "plughw:0,0";
73 extern sig_atomic_t quit;
74 sig_atomic_t did_stun = 0;
75 static sig_atomic_t incoming_call = 0;
77 static struct pollfd *pfds = NULL;
78 static struct alsa_dev *dev = NULL;
79 static CELTEncoder *encoder = NULL;
80 static CELTDecoder *decoder = NULL;
81 static JitterBuffer *jitter = NULL;
82 static SpeexEchoState *echostate = NULL;
84 static void check_file_or_die(char *home, char *file, int maybeempty)
86 char path[PATH_MAX];
87 struct stat st;
88 memset(path, 0, sizeof(path));
89 slprintf(path, sizeof(path), "%s/%s", home, file);
90 if (stat(path, &st))
91 panic("No such file %s! Type --keygen to generate initial config!\n",
92 path);
93 if (!S_ISREG(st.st_mode))
94 panic("%s is not a regular file!\n", path);
95 if ((st.st_mode & ~S_IFREG) != (S_IRUSR | S_IWUSR))
96 panic("You have set too many permissions on %s (%o)!\n",
97 path, st.st_mode);
98 if (maybeempty == 0 && st.st_size == 0)
99 panic("%s is empty!\n", path);
102 static void check_config_exists_or_die(char *home)
104 if (!home)
105 panic("No home dir specified!\n");
106 check_file_or_die(home, FILE_CONTACTS, 1);
107 check_file_or_die(home, FILE_SETTINGS, 0);
108 check_file_or_die(home, FILE_PRIVKEY, 0);
109 check_file_or_die(home, FILE_PUBKEY, 0);
110 check_file_or_die(home, FILE_USERNAME, 0);
113 static char *fetch_home_dir(void)
115 char *home = getenv("HOME");
116 if (!home)
117 panic("No HOME defined!\n");
118 return home;
121 static void write_username(char *home)
123 int fd, ret;
124 char path[PATH_MAX], *eof;
125 char user[512];
126 memset(path, 0, sizeof(path));
127 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAME);
128 printf("Username: [%s] ", getenv("USER"));
129 fflush(stdout);
130 memset(user, 0, sizeof(user));
131 eof = fgets(user, sizeof(user), stdin);
132 user[sizeof(user) - 1] = 0;
133 user[strlen(user) - 1] = 0; /* omit last \n */
134 if (strlen(user) == 0)
135 strlcpy(user, getenv("USER"), sizeof(user));
136 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
137 if (fd < 0)
138 panic("Cannot open your username file!\n");
139 ret = write(fd, user, strlen(user));
140 if (ret != strlen(user))
141 panic("Could not write username!\n");
142 close(fd);
143 info("Username written to %s!\n", path);
146 static void create_transsipdir(char *home)
148 int ret, fd;
149 char path[PATH_MAX];
150 memset(path, 0, sizeof(path));
151 slprintf(path, sizeof(path), "%s/%s", home, ".transsip/");
152 errno = 0;
153 ret = mkdir(path, S_IRWXU);
154 if (ret < 0 && errno != EEXIST)
155 panic("Cannot create transsip dir!\n");
156 info("transsip directory %s created!\n", path);
157 /* We also create empty files for contacts and settings! */
158 memset(path, 0, sizeof(path));
159 slprintf(path, sizeof(path), "%s/%s", home, FILE_CONTACTS);
160 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
161 if (fd < 0)
162 panic("Cannot open contacts file!\n");
163 close(fd);
164 info("Empty contacts file written to %s!\n", path);
165 memset(path, 0, sizeof(path));
166 slprintf(path, sizeof(path), "%s/%s", home, FILE_SETTINGS);
167 fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
168 if (fd < 0)
169 panic("Cannot open settings file!\n");
170 close(fd);
171 info("Empty settings file written to %s!\n", path);
174 static void create_keypair(char *home)
176 int fd;
177 ssize_t ret;
178 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES] = { 0 };
179 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES] = { 0 };
180 char path[PATH_MAX];
181 const char * errstr = NULL;
182 int err = 0;
183 info("Reading from %s (this may take a while) ...\n", ENTROPY_SOURCE);
184 fd = open_or_die(ENTROPY_SOURCE, O_RDONLY);
185 ret = read_exact(fd, secretkey, sizeof(secretkey), 0);
186 if (ret != sizeof(secretkey)) {
187 err = EIO;
188 errstr = "Cannot read from "ENTROPY_SOURCE"!\n";
189 goto out;
191 close(fd);
192 crypto_scalarmult_curve25519_base(publickey, secretkey);
193 memset(path, 0, sizeof(path));
194 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
195 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
196 if (fd < 0) {
197 err = EIO;
198 errstr = "Cannot open pubkey file!\n";
199 goto out;
201 ret = write(fd, publickey, sizeof(publickey));
202 if (ret != sizeof(publickey)) {
203 err = EIO;
204 errstr = "Cannot write public key!\n";
205 goto out;
207 close(fd);
208 info("Public key written to %s!\n", path);
209 memset(path, 0, sizeof(path));
210 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
211 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
212 if (fd < 0) {
213 err = EIO;
214 errstr = "Cannot open privkey file!\n";
215 goto out;
217 ret = write(fd, secretkey, sizeof(secretkey));
218 if (ret != sizeof(secretkey)) {
219 err = EIO;
220 errstr = "Cannot write private key!\n";
221 goto out;
223 out:
224 close(fd);
225 memset(publickey, 0, sizeof(publickey));
226 memset(secretkey, 0, sizeof(secretkey));
227 if (err)
228 panic("%s: %s", errstr, strerror(errno));
229 else
230 info("Private key written to %s!\n", path);
233 static void check_config_keypair_or_die(char *home)
235 int fd;
236 ssize_t ret;
237 int err;
238 const char * errstr = NULL;
239 unsigned char publickey[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
240 unsigned char publicres[crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES];
241 unsigned char secretkey[crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES];
242 char path[PATH_MAX];
243 memset(path, 0, sizeof(path));
244 slprintf(path, sizeof(path), "%s/%s", home, FILE_PRIVKEY);
245 fd = open(path, O_RDONLY);
246 if (fd < 0) {
247 err = EIO;
248 errstr = "Cannot open privkey file!\n";
249 goto out;
251 ret = read(fd, secretkey, sizeof(secretkey));
252 if (ret != sizeof(secretkey)) {
253 err = EIO;
254 errstr = "Cannot read private key!\n";
255 goto out;
257 close(fd);
258 memset(path, 0, sizeof(path));
259 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
260 fd = open(path, O_RDONLY);
261 if (fd < 0) {
262 err = EIO;
263 errstr = "Cannot open pubkey file!\n";
264 goto out;
266 ret = read(fd, publickey, sizeof(publickey));
267 if (ret != sizeof(publickey)) {
268 err = EIO;
269 errstr = "Cannot read public key!\n";
270 goto out;
272 crypto_scalarmult_curve25519_base(publicres, secretkey);
273 err = crypto_verify_32(publicres, publickey);
274 if (err) {
275 err = EINVAL;
276 errstr = "WARNING: your keypair is corrupted!!! You need to "
277 "generate new keys!!!\n";
278 goto out;
280 out:
281 close(fd);
282 memset(publickey, 0, sizeof(publickey));
283 memset(publicres, 0, sizeof(publicres));
284 memset(secretkey, 0, sizeof(secretkey));
285 if (err)
286 panic("%s: %s\n", errstr, strerror(errno));
289 static int keygen(char *home)
291 create_transsipdir(home);
292 write_username(home);
293 create_keypair(home);
294 check_config_keypair_or_die(home);
295 printf("\nNow edit your .transsip/settings file before starting i.e.:\n");
296 printf(" port <your-transsip-port>\n");
297 printf(" stun stunserver.org\n");
298 printf(" alsa plughw:0,0\n");
299 printf("To add contacts, add a new line into .transsip/contacts with:\n");
300 printf(" <user> <pubkey>\n");
301 return 0;
304 static void do_call_duplex(void)
306 #if 0
307 int ret, recv_started = 0;
309 alsa_start(dev);
310 while (likely(!quit)) {
311 ret = poll(pfds, nfds + 1, -1);
312 if (ret < 0)
313 panic("Poll returned with %d!\n", ret);
315 /* Received packets */
316 if (pfds[nfds].revents & POLLIN) {
317 n = recv(sd, msg, MAX_MSG, 0);
318 int recv_timestamp = ((int*) msg)[0];
320 JitterBufferPacket packet;
321 packet.data = msg + 4;
322 packet.len = n - 4;
323 packet.timestamp = recv_timestamp;
324 packet.span = FRAME_SIZE;
325 packet.sequence = 0;
327 jitter_buffer_put(jitter, &packet);
328 recv_started = 1;
331 /* Ready to play a frame (playback) */
332 if (alsa_play_ready(dev, pfds, nfds)) {
333 short pcm[FRAME_SIZE * CHANNELS];
334 if (recv_started) {
335 JitterBufferPacket packet;
336 /* Get audio from the jitter buffer */
337 packet.data = msg;
338 packet.len = MAX_MSG;
339 jitter_buffer_tick(jitter);
340 jitter_buffer_get(jitter, &packet, FRAME_SIZE,
341 NULL);
342 if (packet.len == 0)
343 packet.data=NULL;
344 celt_decode(dec_state, (const unsigned char *)
345 packet.data, packet.len, pcm);
346 } else {
347 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
348 pcm[i] = 0;
351 /* Playback the audio and reset the echo canceller
352 if we got an underrun */
354 if (alsa_write(dev, pcm, FRAME_SIZE))
355 speex_echo_state_reset(echo_state);
356 /* Put frame into playback buffer */
357 speex_echo_playback(echo_state, pcm);
360 /* Audio available from the soundcard (capture) */
361 if (alsa_cap_ready(dev, pfds, nfds)) {
362 short pcm[FRAME_SIZE * CHANNELS],
363 pcm2[FRAME_SIZE * CHANNELS];
364 char outpacket[MAX_MSG];
366 alsa_read(dev, pcm, FRAME_SIZE);
368 /* Perform echo cancellation */
369 speex_echo_capture(echo_state, pcm, pcm2);
370 for (i = 0; i < FRAME_SIZE * CHANNELS; ++i)
371 pcm[i] = pcm2[i];
373 celt_encode(enc_state, pcm, NULL, (unsigned char *)
374 (outpacket + 4), PACKETSIZE);
376 /* Pseudo header: four null bytes and a 32-bit
377 timestamp */
378 ((int*)outpacket)[0] = send_timestamp;
379 send_timestamp += FRAME_SIZE;
381 rc = sendto(sd, outpacket, PACKETSIZE + 4, 0,
382 (struct sockaddr *) &remote_addr,
383 sizeof(remote_addr));
384 if (rc < 0)
385 panic("cannot send to socket");
388 #endif
391 void call_out(char *host, char *port)
393 /* send notify */
394 /* wait for accept */
395 /* transfer data */
397 printf("Trying to call %s:%s ...\n", host, port);
398 do_call_duplex();
401 void call_in(int take)
403 /* lookup addrbook */
404 /* send notify */
405 /* transfer data */
407 barrier();
408 if (incoming_call == 0) {
409 printf("No incoming call right now!\n");
410 return;
413 printf("Trying to take incoming call ...\n");
414 do_call_duplex();
417 static void *thread(void *null)
419 int sock = -1, ret, mtu, nfds, tmp;
420 struct addrinfo hints, *ahead, *ai;
421 CELTMode *mode;
423 while (did_stun == 0)
424 barrier();
425 memset(&hints, 0, sizeof(hints));
426 hints.ai_family = PF_UNSPEC;
427 hints.ai_socktype = SOCK_DGRAM;
428 hints.ai_protocol = IPPROTO_UDP;
429 hints.ai_flags = AI_PASSIVE;
430 ret = getaddrinfo(NULL, port, &hints, &ahead);
431 if (ret < 0)
432 panic("Cannot get address info!\n");
433 for (ai = ahead; ai != NULL && sock < 0; ai = ai->ai_next) {
434 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
435 if (sock < 0)
436 continue;
437 if (ai->ai_family == AF_INET6) {
438 int one = 1;
439 #ifdef IPV6_V6ONLY
440 ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
441 &one, sizeof(one));
442 if (ret < 0) {
443 close(sock);
444 sock = -1;
445 continue;
447 #else
448 close(sock);
449 sock = -1;
450 continue;
451 #endif /* IPV6_V6ONLY */
453 mtu = IP_PMTUDISC_DONT;
454 setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu));
455 ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
456 if (ret < 0) {
457 close(sock);
458 sock = -1;
459 continue;
462 freeaddrinfo(ahead);
463 if (sock < 0)
464 panic("Cannot open socket!\n");
465 dev = alsa_open(alsadev, SAMPLING_RATE, CHANNELS, FRAME_SIZE);
466 if (!dev)
467 panic("Cannot open ALSA device %s!\n", alsadev);
468 mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL);
469 encoder = celt_encoder_create(mode, CHANNELS, NULL);
470 decoder = celt_decoder_create(mode, CHANNELS, NULL);
471 nfds = alsa_nfds(dev);
472 pfds = xmalloc(sizeof(*pfds) * (nfds + 1));
473 alsa_getfds(dev, pfds, nfds);
474 pfds[nfds].fd = sock;
475 pfds[nfds].events = POLLIN;
476 jitter = jitter_buffer_init(FRAME_SIZE);
477 tmp = FRAME_SIZE;
478 jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp);
479 echostate = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE);
480 tmp = SAMPLING_RATE;
481 speex_echo_ctl(echostate, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp);
482 while (likely(!quit)) {
483 ret = poll(&pfds[nfds], 1, -1);
484 if (ret < 0)
485 panic("Poll returned with %d!\n", ret);
486 if (pfds[nfds].revents & POLLIN) {
487 /* Check for Auth pkt, if yes, set current caller and notifiy cli */
488 /* cli user must call take, that triggers call_in() */
489 printf(".\n");
492 xfree(pfds);
493 alsa_close(dev);
494 close(sock);
495 pthread_exit(0);
498 static void start_server(void)
500 int ret = pthread_create(&ptid, NULL, thread, NULL);
501 if (ret)
502 panic("Cannot create server thread!\n");
505 static void stop_server(void)
507 /* pthread_join(ptid, NULL);*/
510 static void help(void)
512 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
513 "telephony network\n", VERSION_STRING);
514 printf("http://www.transsip.org\n\n");
515 printf("Usage: transsip [options]\n");
516 printf("Options:\n");
517 printf(" -k|--keygen Generate public/private keypair\n");
518 printf(" -v|--version Show version\n");
519 printf(" -h|--help Guess what?!\n\n");
520 printf("Note:\n");
521 printf(" There is no default port specified, so that you are forced\n");
522 printf(" to select your own!\n");
523 printf("\n");
524 printf("Secret ingredient: 7647-14-5\n");
525 printf("\n");
526 printf("Please report bugs to <bugs@transsip.org>\n");
527 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
528 printf("License: GNU GPL version 2\n");
529 printf("This is free software: you are free to change and redistribute it.\n");
530 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
531 die();
534 static void version(void)
536 printf("\ntranssip %s, peer-to-peer elliptic-curve-crypto-based "
537 "telephony network\n", VERSION_STRING);
538 printf("Build: %s\n", BUILD_STRING);
539 printf("http://www.transsip.org\n\n");
540 printf("Please report bugs to <bugs@transsip.org>\n");
541 printf("Copyright (C) 2011 Daniel Borkmann <daniel@transsip.org>,\n");
542 printf("License: GNU GPL version 2\n");
543 printf("This is free software: you are free to change and redistribute it.\n");
544 printf("There is NO WARRANTY, to the extent permitted by law.\n\n");
545 die();
548 int main(int argc, char **argv)
550 char *home = fetch_home_dir();
551 if (getuid() != geteuid())
552 seteuid(getuid());
553 if (getenv("LD_PRELOAD"))
554 panic("transsip cannot be preloaded!\n");
555 if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0)
556 panic("transsip cannot be ptraced!\n");
557 curve25519_selftest();
558 if (argc == 2 && (!strncmp("-k", argv[1], strlen("-k")) ||
559 !strncmp("--keygen", argv[1], strlen("--keygen")))) {
560 keygen(home);
561 show_key_export(home);
562 return 0;
564 if (argc == 2 && (!strncmp("-v", argv[1], strlen("-v")) ||
565 !strncmp("--version", argv[1], strlen("--version"))))
566 version();
567 if (argc == 2 && (!strncmp("-h", argv[1], strlen("-h")) ||
568 !strncmp("--help", argv[1], strlen("--help"))))
569 help();
570 check_config_exists_or_die(home);
571 check_config_keypair_or_die(home);
572 start_server();
573 enter_shell_loop();
574 stop_server();
575 return 0;
578 int get_port(void)
580 return atoi(port);
583 char *get_stun_server(void)
585 return stun_server;
588 int show_key_export(char *home)
590 int fd, i;
591 ssize_t ret;
592 char path[PATH_MAX], tmp[64];
593 check_config_keypair_or_die(home);
594 printf("Your public peer information:\n ");
595 fflush(stdout);
596 memset(path, 0, sizeof(path));
597 slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAME);
598 fd = open_or_die(path, O_RDONLY);
599 while ((ret = read(fd, tmp, sizeof(tmp))) > 0) {
600 ret = write(STDOUT_FILENO, tmp, ret);
602 close(fd);
603 printf(" ");
604 memset(path, 0, sizeof(path));
605 slprintf(path, sizeof(path), "%s/%s", home, FILE_PUBKEY);
606 fd = open_or_die(path, O_RDONLY);
607 ret = read(fd, tmp, sizeof(tmp));
608 if (ret != crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES)
609 panic("Cannot read public key!\n");
610 for (i = 0; i < ret; ++i)
611 if (i == ret - 1)
612 printf("%02x\n\n", (unsigned char) tmp[i]);
613 else
614 printf("%02x:", (unsigned char) tmp[i]);
615 close(fd);
616 fflush(stdout);
617 return 0;