[svn-upgrade] Integrating new upstream version, iodine (0.4.2)
[debian/iodine.git] / src / iodined.c
1 /*
2  * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <sys/time.h>
26 #include <sys/socket.h>
27 #include <fcntl.h>
28 #include <err.h>
29 #include <grp.h>
30 #include <time.h>
31 #include <pwd.h>
32 #include <arpa/inet.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <zlib.h>
37 #include <arpa/nameser.h>
38 #ifdef DARWIN
39 #include <arpa/nameser8_compat.h>
40 #endif
41
42 #include "common.h"
43 #include "dns.h"
44 #include "encoding.h"
45 #include "base32.h"
46 #include "user.h"
47 #include "login.h"
48 #include "tun.h"
49 #include "version.h"
50
51 static int running = 1;
52 static char *topdomain;
53 static char password[33];
54 static struct encoder *b32;
55
56 static int check_ip;
57 static int my_mtu;
58 static in_addr_t my_ip;
59
60 static int debug;
61
62 #if !defined(BSD) && !defined(__GLIBC__)
63 static char *__progname;
64 #endif
65
66 static int read_dns(int, struct query *);
67 static void write_dns(int, struct query *, char *, int);
68
69 static void
70 sigint(int sig) 
71 {
72         running = 0;
73 }
74
75 static int
76 ip_cmp(int userid, struct query *q)
77 {
78         struct sockaddr_in *tempin;
79
80         tempin = (struct sockaddr_in *) &(q->from);
81         return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
82 }
83
84 static int
85 tunnel_tun(int tun_fd, int dns_fd)
86 {
87         unsigned long outlen;
88         struct ip *header;
89         char out[64*1024];
90         char in[64*1024];
91         int userid;
92         int read;
93
94         if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
95                 return 0;
96         
97         /* find target ip in packet, in is padded with 4 bytes TUN header */
98         header = (struct ip*) (in + 4);
99         userid = find_user_by_ip(header->ip_dst.s_addr);
100         if (userid < 0)
101                 return 0;
102
103         outlen = sizeof(out);
104         compress2((uint8_t*)out, &outlen, (uint8_t*)in, read, 9);
105
106         /* if another packet is queued, throw away this one. TODO build queue */
107         if (users[userid].outpacket.len == 0) {
108                 memcpy(users[userid].outpacket.data, out, outlen);
109                 users[userid].outpacket.len = outlen;
110                 return outlen;
111         } else {
112                 return 0;
113         }
114 }
115
116 typedef enum {
117         VERSION_ACK,
118         VERSION_NACK,
119         VERSION_FULL
120 } version_ack_t;
121
122 static void
123 send_version_response(int fd, version_ack_t ack, uint32_t payload, struct user *u)
124 {
125         char out[9];
126         
127         switch (ack) {
128         case VERSION_ACK:
129                 strncpy(out, "VACK", sizeof(out));
130                 break;
131         case VERSION_NACK:
132                 strncpy(out, "VNAK", sizeof(out));
133                 break;
134         case VERSION_FULL:
135                 strncpy(out, "VFUL", sizeof(out));
136                 break;
137         }
138         
139         out[4] = ((payload >> 24) & 0xff);
140         out[5] = ((payload >> 16) & 0xff);
141         out[6] = ((payload >> 8) & 0xff);
142         out[7] = ((payload) & 0xff);
143         if (u) {
144                 out[8] = u->id;
145         } else {
146                 out[8] = 0;
147         }
148
149
150         write_dns(fd, &u->q, out, sizeof(out));
151 }
152
153 static void
154 handle_null_request(int tun_fd, int dns_fd, struct query *q)
155 {
156         struct in_addr tempip;
157         struct ip *hdr;
158         unsigned long outlen;
159         char in[64*1024];
160         char logindata[16];
161         char out[64*1024];
162         char unpacked[64*1024];
163         char *tmp[2];
164         char *domain;
165         int userid;
166         int touser;
167         int version;
168         int code;
169         int read;
170
171         userid = -1;
172         domain = strstr(q->name, topdomain);
173         if (!domain) {
174                 /* Not for us, discard */
175                 return;
176         }
177         
178         read = (int) (domain - q->name); 
179         memcpy(in, q->name, MIN(read, sizeof(in)));
180
181         if(in[0] == 'V' || in[0] == 'v') {
182                 read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
183                 /* Version greeting, compare and send ack/nak */
184                 if (read > 4) { 
185                         /* Received V + 32bits version */
186                         version = (((unpacked[0] & 0xff) << 24) |
187                                            ((unpacked[1] & 0xff) << 16) |
188                                            ((unpacked[2] & 0xff) << 8) |
189                                            ((unpacked[3] & 0xff)));
190                 }
191
192                 if (version == VERSION) {
193                         userid = find_available_user();
194                         if (userid >= 0) {
195                                 struct sockaddr_in *tempin;
196
197                                 users[userid].seed = rand();
198                                 /* Store remote IP number */
199                                 tempin = (struct sockaddr_in *) &(q->from);
200                                 memcpy(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
201                                 
202                                 memcpy(&(users[userid].q), q, sizeof(struct query));
203                                 users[userid].encoder = get_base32_encoder();
204                                 send_version_response(dns_fd, VERSION_ACK, users[userid].seed, &users[userid]);
205                                 users[userid].q.id = 0;
206                         } else {
207                                 /* No space for another user */
208                                 send_version_response(dns_fd, VERSION_FULL, USERS, NULL);
209                         }
210                 } else {
211                         send_version_response(dns_fd, VERSION_NACK, VERSION, NULL);
212                 }
213         } else if(in[0] == 'L' || in[0] == 'l') {
214                 read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
215                 /* Login phase, handle auth */
216                 userid = unpacked[0];
217                 if (userid < 0 || userid >= USERS) {
218                         write_dns(dns_fd, q, "BADIP", 5);
219                         return; /* illegal id */
220                 }
221                 users[userid].last_pkt = time(NULL);
222                 login_calculate(logindata, 16, password, users[userid].seed);
223
224                 if (check_ip && ip_cmp(userid, q) != 0) {
225                         write_dns(dns_fd, q, "BADIP", 5);
226                 } else {
227                         if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
228                                 /* Login ok, send ip/mtu info */
229
230                                 tempip.s_addr = my_ip;
231                                 tmp[0] = strdup(inet_ntoa(tempip));
232                                 tempip.s_addr = users[userid].tun_ip;
233                                 tmp[1] = strdup(inet_ntoa(tempip));
234
235                                 read = snprintf(out, sizeof(out), "%s-%s-%d", 
236                                                 tmp[0], tmp[1], my_mtu);
237
238                                 write_dns(dns_fd, q, out, read);
239                                 q->id = 0;
240
241                                 free(tmp[1]);
242                                 free(tmp[0]);
243                         } else {
244                                 write_dns(dns_fd, q, "LNAK", 4);
245                         }
246                 }
247         } else if(in[0] == 'P' || in[0] == 'p') {
248                 read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, b32);
249                 /* Ping packet, store userid */
250                 userid = unpacked[0];
251                 if (userid < 0 || userid >= USERS || ip_cmp(userid, q) != 0) {
252                         write_dns(dns_fd, q, "BADIP", 5);
253                         return; /* illegal id */
254                 }
255                 memcpy(&(users[userid].q), q, sizeof(struct query));
256                 users[userid].last_pkt = time(NULL);
257         } else if(in[0] == 'Z' || in[0] == 'z') {
258                 /* Case conservation check */
259
260                 /* Reply with received hostname as data */
261                 write_dns(dns_fd, q, in, read);
262                 return;
263         } else if((in[0] >= '0' && in[0] <= '9')
264                         || (in[0] >= 'a' && in[0] <= 'f')
265                         || (in[0] >= 'A' && in[0] <= 'F')) {
266                 if ((in[0] >= '0' && in[0] <= '9'))
267                         code = in[0] - '0';
268                 if ((in[0] >= 'a' && in[0] <= 'f'))
269                         code = in[0] - 'a' + 10;
270                 if ((in[0] >= 'A' && in[0] <= 'F'))
271                         code = in[0] - 'A' + 10;
272
273                 userid = code >> 1;
274                 if (userid < 0 || userid >= USERS) {
275                         write_dns(dns_fd, q, "BADIP", 5);
276                         return; /* illegal id */
277                 }
278
279                 /* Check sending ip number */
280                 if (check_ip && ip_cmp(userid, q) != 0) {
281                         write_dns(dns_fd, q, "BADIP", 5);
282                 } else {
283                         /* decode with this users encoding */
284                         read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), read - 1, 
285                                            users[userid].encoder);
286
287                         users[userid].last_pkt = time(NULL);
288                         memcpy(&(users[userid].q), q, sizeof(struct query));
289                         memcpy(users[userid].inpacket.data + users[userid].inpacket.offset, unpacked, read);
290                         users[userid].inpacket.len += read;
291                         users[userid].inpacket.offset += read;
292
293                         if (code & 1) {
294                                 outlen = sizeof(out);
295                                 uncompress((uint8_t*)out, &outlen, 
296                                                    (uint8_t*)users[userid].inpacket.data, users[userid].inpacket.len);
297
298                                 hdr = (struct ip*) (out + 4);
299                                 touser = find_user_by_ip(hdr->ip_dst.s_addr);
300
301                                 if (touser == -1) {
302                                         /* send the uncompressed packet to tun device */
303                                         write_tun(tun_fd, out, outlen);
304                                 } else {
305                                         /* send the compressed packet to other client
306                                          * if another packet is queued, throw away this one. TODO build queue */
307                                         if (users[touser].outpacket.len == 0) {
308                                                 memcpy(users[touser].outpacket.data, users[userid].inpacket.data, users[userid].inpacket.len);
309                                                 users[touser].outpacket.len = users[userid].inpacket.len;
310                                         }
311                                 }
312                                 users[userid].inpacket.len = users[userid].inpacket.offset = 0;
313                         }
314                 }
315         }
316         /* userid must be set for a reply to be sent */
317         if (userid >= 0 && userid < USERS && ip_cmp(userid, q) == 0 && users[userid].outpacket.len > 0) {
318                 write_dns(dns_fd, q, users[userid].outpacket.data, users[userid].outpacket.len);
319                 users[userid].outpacket.len = 0;
320                 users[userid].q.id = 0;
321         }
322 }
323
324 static int
325 tunnel_dns(int tun_fd, int dns_fd)
326 {
327         struct query q;
328         int read;
329
330         if ((read = read_dns(dns_fd, &q)) <= 0)
331                 return 0;
332
333         if (debug >= 1) {
334                 struct sockaddr_in *tempin;
335                 tempin = (struct sockaddr_in *) &(q.from);
336                 printf("RX: client %s, type %d, name %s\n", inet_ntoa(tempin->sin_addr), q.type, q.name);
337         }
338         
339         switch (q.type) {
340         case T_NULL:
341                 handle_null_request(tun_fd, dns_fd, &q);
342                 break;
343         default:
344                 break;
345         }
346
347         return 0;
348 }
349
350 static int
351 tunnel(int tun_fd, int dns_fd)
352 {
353         struct timeval tv;
354         fd_set fds;
355         int i;
356         int j;
357
358         while (running) {
359                 if (users_waiting_on_reply()) {
360                         tv.tv_sec = 0;
361                         tv.tv_usec = 5000;
362                 } else {
363                         tv.tv_sec = 1;
364                         tv.tv_usec = 0;
365                 }
366
367                 FD_ZERO(&fds);
368                 /* TODO : use some kind of packet queue */
369                 if(!all_users_waiting_to_send()) {
370                         FD_SET(tun_fd, &fds);
371                 }
372                 FD_SET(dns_fd, &fds);
373
374                 i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv);
375                 
376                 if(i < 0) {
377                         if (running) 
378                                 warn("select");
379                         return 1;
380                 }
381         
382                 if (i==0) {     
383                         for (j = 0; j < USERS; j++) {
384                                 if (users[j].q.id != 0) {
385                                         write_dns(dns_fd, &(users[j].q), users[j].outpacket.data, users[j].outpacket.len);
386                                         users[j].outpacket.len = 0;
387                                         users[j].q.id = 0;
388                                 }
389                         }
390                 } else {
391                         if(FD_ISSET(tun_fd, &fds)) {
392                                 tunnel_tun(tun_fd, dns_fd);
393                                 continue;
394                         }
395                         if(FD_ISSET(dns_fd, &fds)) {
396                                 tunnel_dns(tun_fd, dns_fd);
397                                 continue;
398                         } 
399                 }
400         }
401
402         return 0;
403 }
404
405 static int
406 read_dns(int fd, struct query *q)
407 {
408         struct sockaddr_in from;
409         char packet[64*1024];
410         socklen_t addrlen;
411         int r;
412
413         addrlen = sizeof(struct sockaddr);
414         r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
415
416         if (r > 0) {
417                 dns_decode(NULL, 0, q, QR_QUERY, packet, r);
418                 memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
419                 q->fromlen = addrlen;
420
421                 return strlen(q->name);
422         } else if (r < 0) { 
423                 /* Error */
424                 warn("read dns");
425         }
426
427         return 0;
428 }
429
430 static void
431 write_dns(int fd, struct query *q, char *data, int datalen)
432 {
433         char buf[64*1024];
434         int len;
435
436         len = dns_encode(buf, sizeof(buf), q, QR_ANSWER, data, datalen);
437         
438         if (debug >= 1) {
439                 struct sockaddr_in *tempin;
440                 tempin = (struct sockaddr_in *) &(q->from);
441                 printf("TX: client %s, type %d, name %s, %d bytes data\n", 
442                         inet_ntoa(tempin->sin_addr), q->type, q->name, datalen);
443         }
444
445         sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
446 }
447
448 static void
449 usage() {
450         extern char *__progname;
451
452         printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] "
453                 "[-l ip address to listen on] [-p port] [-P password]"
454                 " tunnel_ip topdomain\n", __progname);
455         exit(2);
456 }
457
458 static void
459 help() {
460         extern char *__progname;
461
462         printf("iodine IP over DNS tunneling server\n");
463         printf("Usage: %s [-v] [-h] [-c] [-s] [-f] [-D] [-u user] [-t chrootdir] [-d device] [-m mtu] "
464                 "[-l ip address to listen on] [-p port] [-P password]"
465                 " tunnel_ip topdomain\n", __progname);
466         printf("  -v to print version info and exit\n");
467         printf("  -h to print this help and exit\n");
468         printf("  -c to disable check of client IP/port on each request\n");
469         printf("  -s to skip creating and configuring the tun device which then has to be created manually\n");
470         printf("  -f to keep running in foreground\n");
471         printf("  -D to increase debug level\n");
472         printf("  -u name to drop privileges and run as user 'name'\n");
473         printf("  -t dir to chroot to directory dir\n");
474         printf("  -d device to set tunnel device name\n");
475         printf("  -m mtu to set tunnel device mtu\n");
476         printf("  -l ip address to listen on for incoming dns traffic (default 0.0.0.0)\n");
477         printf("  -p port to listen on for incoming dns traffic (default 53)\n");
478         printf("  -P password used for authentication (max 32 chars will be used)\n");
479         printf("tunnel_ip is the IP number of the local tunnel interface.\n");
480         printf("topdomain is the FQDN that is delegated to this server.\n");
481         exit(0);
482 }
483
484 static void
485 version() {
486         printf("iodine IP over DNS tunneling server\n");
487         printf("version: 0.4.2 from 2008-08-06\n");
488         exit(0);
489 }
490
491 int
492 main(int argc, char **argv)
493 {
494         in_addr_t listen_ip;
495         struct passwd *pw;
496         int foreground;
497         char *username;
498         char *newroot;
499         char *device;
500         int dnsd_fd;
501         int tun_fd;
502         int choice;
503         int port;
504         int mtu;
505         int skipipconfig;
506
507         username = NULL;
508         newroot = NULL;
509         device = NULL;
510         foreground = 0;
511         mtu = 1024;
512         listen_ip = INADDR_ANY;
513         port = 53;
514         check_ip = 1;
515         skipipconfig = 0;
516         debug = 0;
517
518         b32 = get_base32_encoder();
519
520 #if !defined(BSD) && !defined(__GLIBC__)
521         __progname = strrchr(argv[0], '/');
522         if (__progname == NULL)
523                 __progname = argv[0];
524         else
525                 __progname++;
526 #endif
527
528         memset(password, 0, sizeof(password));
529         srand(time(NULL));
530         
531         while ((choice = getopt(argc, argv, "vcsfhDu:t:d:m:l:p:P:")) != -1) {
532                 switch(choice) {
533                 case 'v':
534                         version();
535                         break;
536                 case 'c':
537                         check_ip = 0;
538                         break;
539                 case 's':
540                         skipipconfig = 1;
541                         break;
542                 case 'f':
543                         foreground = 1;
544                         break;
545                 case 'h':
546                         help();
547                         break;
548                 case 'D':
549                         debug++;
550                         break;
551                 case 'u':
552                         username = optarg;
553                         break;
554                 case 't':
555                         newroot = optarg;
556                         break;
557                 case 'd':
558                         device = optarg;
559                         break;
560                 case 'm':
561                         mtu = atoi(optarg);
562                         break;
563                 case 'l':
564                         listen_ip = inet_addr(optarg);
565                         break;
566                 case 'p':
567                         port = atoi(optarg);
568                         break;
569                 case 'P':
570                         strncpy(password, optarg, sizeof(password));
571                         password[sizeof(password)-1] = 0;
572                         
573                         /* XXX: find better way of cleaning up ps(1) */
574                         memset(optarg, 0, strlen(optarg)); 
575                         break;
576                 default:
577                         usage();
578                         break;
579                 }
580         }
581
582         argc -= optind;
583         argv += optind;
584
585         if (geteuid() != 0) {
586                 warnx("Run as root and you'll be happy.\n");
587                 usage();
588         }
589
590         if (argc != 2) 
591                 usage();
592
593         topdomain = strdup(argv[1]);
594         if(strlen(topdomain) <= 128) {
595                 if(check_topdomain(topdomain)) {
596                         warnx("Topdomain contains invalid characters.\n");
597                         usage();
598                 }
599         } else {
600                 warnx("Use a topdomain max 128 chars long.\n");
601                 usage();
602         }
603
604         if (username != NULL) {
605                 if ((pw = getpwnam(username)) == NULL) {
606                         warnx("User %s does not exist!\n", username);
607                         usage();
608                 }
609         }
610
611         if (mtu <= 0) {
612                 warnx("Bad MTU given.\n");
613                 usage();
614         }
615         
616         if(port < 1 || port > 65535) {
617                 warnx("Bad port number given.\n");
618                 usage();
619         }
620         
621         if (port != 53) {
622                 printf("ALERT! Other dns servers expect you to run on port 53.\n");
623                 printf("You must manually forward port 53 to port %d for things to work.\n", port);
624         }
625
626         if (debug) {
627                 printf("Debug level %d enabled, will stay in foreground.\n", debug);
628                 printf("Add more -D switches to set higher debug level.\n");
629                 foreground = 1;
630         }
631
632         if (listen_ip == INADDR_NONE) {
633                 warnx("Bad IP address to listen on.\n");
634                 usage();
635         }
636
637         if (strlen(password) == 0)
638                 read_password(password, sizeof(password));
639
640         if ((tun_fd = open_tun(device)) == -1)
641                 goto cleanup0;
642         if (!skipipconfig)
643                 if (tun_setip(argv[0]) != 0 || tun_setmtu(mtu) != 0)
644                         goto cleanup1;
645         if ((dnsd_fd = open_dns(port, listen_ip)) == -1) 
646                 goto cleanup2;
647
648         my_ip = inet_addr(argv[0]);
649         my_mtu = mtu;
650         init_users(my_ip);
651
652         printf("Listening to dns for domain %s\n", topdomain);
653
654         if (foreground == 0) 
655                 do_detach();
656         
657         if (newroot != NULL)
658                 do_chroot(newroot);
659
660         signal(SIGINT, sigint);
661         if (username != NULL) {
662                 gid_t gids[1];
663                 gids[0] = pw->pw_gid;
664                 if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
665                         warnx("Could not switch to user %s!\n", username);
666                         usage();
667                 }
668         }
669         
670         tunnel(tun_fd, dnsd_fd);
671
672 cleanup2:
673         close_dns(dnsd_fd);
674 cleanup1:
675         close_tun(tun_fd);      
676 cleanup0:
677
678         return 0;
679 }