[svn-upgrade] Integrating new upstream version, iodine (0.4.1)
[debian/iodine.git] / src / iodine.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 <netdb.h>
24 #include <netinet/in.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/socket.h>
28 #include <fcntl.h>
29 #include <err.h>
30 #include <pwd.h>
31 #include <arpa/inet.h>
32 #include <zlib.h>
33 #include <arpa/nameser.h>
34 #ifdef DARWIN
35 #include <arpa/nameser8_compat.h>
36 #endif
37
38 #include "common.h"
39 #include "encoding.h"
40 #include "base32.h"
41 #include "dns.h"
42 #include "login.h"
43 #include "tun.h"
44 #include "version.h"
45
46 static void send_ping(int fd);
47 static void send_chunk(int fd);
48 static int build_hostname(char *buf, size_t buflen, 
49         const char *data, const size_t datalen, 
50         const char *topdomain, struct encoder *encoder);
51
52 static int running = 1;
53 static char password[33];
54
55 static struct sockaddr_in nameserv;
56 static char *topdomain;
57
58 static uint16_t rand_seed;
59
60 /* Current IP packet */
61 static struct packet packet;
62
63 /* My userid at the server */
64 static char userid;
65
66 /* DNS id for next packet */
67 static uint16_t chunkid;
68
69 /* Base32 encoder used for non-data packets */
70 static struct encoder *b32;
71
72 /* The encoder used for data packets
73  * Defaults to Base32, can be changed after handshake */
74 static struct encoder *dataenc;
75
76 /* result of case preservation check done after login */
77 static int case_preserved;
78
79 static void
80 sighandler(int sig) 
81 {
82         running = 0;
83 }
84
85 static void
86 send_query(int fd, char *hostname)
87 {
88         char packet[4096];
89         struct query q;
90         size_t len;
91
92         q.id = ++chunkid;
93         q.type = T_NULL;
94
95         len = dns_encode(packet, sizeof(packet), &q, QR_QUERY, hostname, strlen(hostname));
96
97         sendto(fd, packet, len, 0, (struct sockaddr*)&nameserv, sizeof(nameserv));
98 }
99
100 static void
101 send_packet(int fd, char cmd, const char *data, const size_t datalen)
102 {
103         char buf[4096];
104
105         buf[0] = cmd;
106         
107         build_hostname(buf + 1, sizeof(buf) - 1, data, datalen, topdomain, b32);
108         send_query(fd, buf);
109 }
110
111 static int
112 build_hostname(char *buf, size_t buflen, 
113                 const char *data, const size_t datalen, 
114                 const char *topdomain, struct encoder *encoder)
115 {
116         int encsize;
117         size_t space;
118         char *b;
119
120
121         space = MIN(0xFF, buflen) - strlen(topdomain) - 2;
122         if (!encoder->places_dots())
123                 space -= (space / 62); /* space for dots */
124
125         memset(buf, 0, buflen);
126         
127         encsize = encoder->encode(buf, &space, data, datalen);
128
129         if (!encoder->places_dots())
130                 inline_dotify(buf, buflen);
131
132         b = buf;
133         b += strlen(buf);
134
135         if (*b != '.') 
136                 *b++ = '.';
137
138         strncpy(b, topdomain, strlen(topdomain)+1);
139
140         return space;
141 }
142
143 int
144 is_sending()
145 {
146         return (packet.len != 0);
147 }
148
149 int
150 read_dns(int fd, char *buf, int buflen)
151 {
152         struct sockaddr_in from;
153         char data[64*1024];
154         socklen_t addrlen;
155         struct query q;
156         int rv;
157         int r;
158
159         addrlen = sizeof(struct sockaddr);
160         if ((r = recvfrom(fd, data, sizeof(data), 0, 
161                           (struct sockaddr*)&from, &addrlen)) == -1) {
162                 warn("recvfrom");
163                 return 0;
164         }
165
166         rv = dns_decode(buf, buflen, &q, QR_ANSWER, data, r);
167
168         if (is_sending() && chunkid == q.id) {
169                 /* Got ACK on sent packet */
170                 packet.offset += packet.sentlen;
171                 if (packet.offset == packet.len) {
172                         /* Packet completed */
173                         packet.offset = 0;
174                         packet.len = 0;
175                         packet.sentlen = 0;
176                 } else {
177                         /* More to send */
178                         send_chunk(fd);
179                 }
180         }
181         return rv;
182 }
183
184
185 static int
186 tunnel_tun(int tun_fd, int dns_fd)
187 {
188         unsigned long outlen;
189         unsigned long inlen;
190         char out[64*1024];
191         char in[64*1024];
192         size_t read;
193
194         if ((read = read_tun(tun_fd, in, sizeof(in))) <= 0)
195                 return -1;
196
197         outlen = sizeof(out);
198         inlen = read;
199         compress2((uint8_t*)out, &outlen, (uint8_t*)in, inlen, 9);
200
201         memcpy(packet.data, out, MIN(outlen, sizeof(packet.data)));
202         packet.sentlen = 0;
203         packet.offset = 0;
204         packet.len = outlen;
205
206         send_chunk(dns_fd);
207
208         return read;
209 }
210
211 static int
212 tunnel_dns(int tun_fd, int dns_fd)
213 {
214         unsigned long outlen;
215         unsigned long inlen;
216         char out[64*1024];
217         char in[64*1024];
218         size_t read;
219
220         if ((read = read_dns(dns_fd, in, sizeof(in))) <= 0) 
221                 return -1;
222                 
223         outlen = sizeof(out);
224         inlen = read;
225         if (uncompress((uint8_t*)out, &outlen, (uint8_t*)in, inlen) != Z_OK)
226                 return -1;
227
228         write_tun(tun_fd, out, outlen);
229         if (!is_sending()) 
230                 send_ping(dns_fd);
231         
232         return read;
233 }
234
235 static int
236 tunnel(int tun_fd, int dns_fd)
237 {
238         struct timeval tv;
239         fd_set fds;
240         int rv;
241         int i;
242
243         rv = 0;
244
245         while (running) {
246                 tv.tv_sec = 1;
247                 tv.tv_usec = 0;
248
249                 FD_ZERO(&fds);
250                 if (!is_sending()) 
251                         FD_SET(tun_fd, &fds);
252                 FD_SET(dns_fd, &fds);
253
254                 i = select(MAX(tun_fd, dns_fd) + 1, &fds, NULL, NULL, &tv);
255                 
256                 if (running == 0)
257                         break;
258
259                 if (i < 0) 
260                         err(1, "select");
261
262                 if (i == 0) /* timeout */
263                         send_ping(dns_fd);
264                 else {
265                         if (FD_ISSET(tun_fd, &fds)) {
266                                 if (tunnel_tun(tun_fd, dns_fd) <= 0)
267                                         continue;
268                         }
269                         if (FD_ISSET(dns_fd, &fds)) {
270                                 if (tunnel_dns(tun_fd, dns_fd) <= 0)
271                                         continue;
272                         } 
273                 }
274         }
275
276         return rv;
277 }
278
279 static void
280 send_chunk(int fd)
281 {
282         char hex[] = "0123456789ABCDEF";
283         char buf[4096];
284         int avail;
285         int code;
286         char *p;
287
288         p = packet.data;
289         p += packet.offset;
290         avail = packet.len - packet.offset;
291
292         packet.sentlen = build_hostname(buf + 1, sizeof(buf) - 1, p, avail, topdomain, dataenc);
293
294         if (packet.sentlen == avail)
295                 code = 1;
296         else
297                 code = 0;
298                 
299         code |= (userid << 1);
300         buf[0] = hex[code];
301
302         send_query(fd, buf);
303 }
304
305 void
306 send_login(int fd, char *login, int len)
307 {
308         char data[19];
309
310         memset(data, 0, sizeof(data));
311         data[0] = userid;
312         memcpy(&data[1], login, MIN(len, 16));
313
314         data[17] = (rand_seed >> 8) & 0xff;
315         data[18] = (rand_seed >> 0) & 0xff;
316         
317         rand_seed++;
318
319         send_packet(fd, 'L', data, sizeof(data));
320 }
321
322 static void
323 send_ping(int fd)
324 {
325         char data[3];
326         
327         if (is_sending()) {
328                 packet.sentlen = 0;
329                 packet.offset = 0;
330                 packet.len = 0;
331         }
332
333         data[0] = userid;
334         data[1] = (rand_seed >> 8) & 0xff;
335         data[2] = (rand_seed >> 0) & 0xff;
336         
337         rand_seed++;
338
339         send_packet(fd, 'P', data, sizeof(data));
340 }
341
342 void 
343 send_version(int fd, uint32_t version)
344 {
345         char data[6];
346
347         data[0] = (version >> 24) & 0xff;
348         data[1] = (version >> 16) & 0xff;
349         data[2] = (version >> 8) & 0xff;
350         data[3] = (version >> 0) & 0xff;
351
352         data[4] = (rand_seed >> 8) & 0xff;
353         data[5] = (rand_seed >> 0) & 0xff;
354         
355         rand_seed++;
356
357         send_packet(fd, 'V', data, sizeof(data));
358 }
359
360 void
361 send_case_check(int fd)
362 {
363         char buf[512] = "zZaAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyY123-4560789.";
364
365         strncat(buf, topdomain, 512 - strlen(buf));
366         send_query(fd, buf);
367 }
368
369 static int
370 handshake(int dns_fd)
371 {
372         struct timeval tv;
373         uint32_t payload;
374         char server[65];
375         char client[65];
376         char login[16];
377         char in[4096];
378         fd_set fds;
379         int read;
380         int mtu;
381         int seed;
382         int i;
383         int r;
384
385         for (i = 0; running && i < 5; i++) {
386                 tv.tv_sec = i + 1;
387                 tv.tv_usec = 0;
388
389                 send_version(dns_fd, VERSION);
390                 
391                 FD_ZERO(&fds);
392                 FD_SET(dns_fd, &fds);
393
394                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
395
396                 if(r > 0) {
397                         read = read_dns(dns_fd, in, sizeof(in));
398                         
399                         if(read < 0) {
400                                 warn("handshake read");
401                                 continue;
402                         }
403
404                         if (read >= 9) {
405                                 payload =  (((in[4] & 0xff) << 24) |
406                                                 ((in[5] & 0xff) << 16) |
407                                                 ((in[6] & 0xff) << 8) |
408                                                 ((in[7] & 0xff)));
409
410                                 if (strncmp("VACK", in, 4) == 0) {
411                                         seed = payload;
412                                         userid = in[8];
413
414                                         printf("Version ok, both running 0x%08x. You are user #%d\n", VERSION, userid);
415                                         goto perform_login;
416                                 } else if (strncmp("VNAK", in, 4) == 0) {
417                                         errx(1, "you run 0x%08x, server runs 0x%08x. giving up\n", 
418                                                         VERSION, payload);
419                                         /* NOTREACHED */
420                                 } else if (strncmp("VFUL", in, 4) == 0) {
421                                         errx(1, "server full, all %d slots are taken. try again later\n", payload);
422                                         /* NOTREACHED */
423                                 }
424                         } else 
425                                 warnx("did not receive proper login challenge\n");
426                 }
427                 
428                 printf("Retrying version check...\n");
429         }
430         errx(1, "couldn't connect to server");
431         /* NOTREACHED */
432         
433 perform_login:
434         login_calculate(login, 16, password, seed);
435         
436         for (i=0; running && i<5 ;i++) {
437                 tv.tv_sec = i + 1;
438                 tv.tv_usec = 0;
439
440                 send_login(dns_fd, login, 16);
441                 
442                 FD_ZERO(&fds);
443                 FD_SET(dns_fd, &fds);
444
445                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
446
447                 if(r > 0) {
448                         read = read_dns(dns_fd, in, sizeof(in));
449                         
450                         if(read <= 0) {
451                                 warn("read");
452                                 continue;
453                         }
454
455                         if (read > 0) {
456                                 if (strncmp("LNAK", in, 4) == 0) {
457                                         printf("Bad password\n");
458                                         return 1;
459                                 } else if (sscanf(in, "%64[^-]-%64[^-]-%d", 
460                                         server, client, &mtu) == 3) {
461                                         
462                                         server[64] = 0;
463                                         client[64] = 0;
464                                         if (tun_setip(client) == 0 && 
465                                                 tun_setmtu(mtu) == 0) {
466                                                 goto perform_case_check;
467                                         } else {
468                                                 warnx("Received handshake with bad data");
469                                         }
470                                 } else {
471                                         printf("Received bad handshake\n");
472                                 }
473                         }
474                 }
475
476                 printf("Retrying login...\n");
477         }
478         errx(1, "couldn't login to server");
479         /* NOTREACHED */
480
481 perform_case_check:
482         case_preserved = 0;
483         for (i=0; running && i<5 ;i++) {
484                 tv.tv_sec = i + 1;
485                 tv.tv_usec = 0;
486
487                 send_case_check(dns_fd);
488                 
489                 FD_ZERO(&fds);
490                 FD_SET(dns_fd, &fds);
491
492                 r = select(dns_fd + 1, &fds, NULL, NULL, &tv);
493
494                 if(r > 0) {
495                         read = read_dns(dns_fd, in, sizeof(in));
496                         
497                         if(read <= 0) {
498                                 warn("read");
499                                 continue;
500                         }
501
502                         if (read > 0) {
503                                 if (in[0] == 'z' || in[0] == 'Z') {
504                                         if (read < (26 * 2)) {
505                                                 printf("Received short case reply...\n");
506                                         } else {
507                                                 int k;
508
509                                                 case_preserved = 1;
510                                                 for (k = 0; k < 26 && case_preserved; k += 2) {
511                                                         if (in[k] == in[k+1]) {
512                                                                 /* test string: zZaAbBcCdD... */
513                                                                 case_preserved = 0;
514                                                         }
515                                                 }
516                                                 return 0;
517                                         }
518                                 } else {
519                                         printf("Received bad case check reply\n");
520                                 }
521                         }
522                 }
523
524                 printf("Retrying case check...\n");
525         }
526
527         printf("No reply on case check, continuing\n");
528         return 0;
529 }
530                 
531 static char *
532 get_resolvconf_addr()
533 {
534         static char addr[16];
535         char buf[80];
536         char *rv;
537         FILE *fp;
538         
539         rv = NULL;
540
541         if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) 
542                 err(1, "/etc/resolve.conf");
543         
544         while (feof(fp) == 0) {
545                 fgets(buf, sizeof(buf), fp);
546
547                 if (sscanf(buf, "nameserver %15s", addr) == 1) {
548                         rv = addr;
549                         break;
550                 }
551         }
552         
553         fclose(fp);
554
555         return rv;
556 }
557
558 static void
559 set_nameserver(const char *cp) 
560 {
561         struct in_addr addr;
562
563         if (inet_aton(cp, &addr) != 1)
564                 errx(1, "error parsing nameserver address: '%s'", cp);
565
566         memset(&nameserv, 0, sizeof(nameserv));
567         nameserv.sin_family = AF_INET;
568         nameserv.sin_port = htons(53);
569         nameserv.sin_addr = addr;
570 }
571
572 static void
573 usage() {
574         extern char *__progname;
575
576         printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
577                         "[nameserver] topdomain\n", __progname);
578         exit(2);
579 }
580
581 static void
582 help() {
583         extern char *__progname;
584
585         printf("iodine IP over DNS tunneling client\n");
586         printf("Usage: %s [-v] [-h] [-f] [-u user] [-t chrootdir] [-d device] "
587                         "[-P password] [nameserver] topdomain\n", __progname);
588         printf("  -v to print version info and exit\n");
589         printf("  -h to print this help and exit\n");
590         printf("  -f to keep running in foreground\n");
591         printf("  -u name to drop privileges and run as user 'name'\n");
592         printf("  -t dir to chroot to directory dir\n");
593         printf("  -d device to set tunnel device name\n");
594         printf("  -P password used for authentication (max 32 chars will be used)\n");
595         printf("nameserver is the IP number of the relaying nameserver, if absent /etc/resolv.conf is used\n");
596         printf("topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
597
598         exit(0);
599 }
600
601 static void
602 version() {
603
604         printf("iodine IP over DNS tunneling client\n");
605         printf("version: 0.4.1 from 2007-11-30\n");
606
607         exit(0);
608 }
609
610 int
611 main(int argc, char **argv)
612 {
613         char *nameserv_addr;
614         struct passwd *pw;
615         char *username;
616         int foreground;
617         char *newroot;
618         char *device;
619         int choice;
620         int tun_fd;
621         int dns_fd;
622
623         memset(password, 0, 33);
624         username = NULL;
625         foreground = 0;
626         newroot = NULL;
627         device = NULL;
628         chunkid = 0;
629
630         b32 = get_base32_encoder();
631         dataenc = get_base32_encoder();
632         
633         while ((choice = getopt(argc, argv, "vfhu:t:d:P:")) != -1) {
634                 switch(choice) {
635                 case 'v':
636                         version();
637                         break;
638                 case 'f':
639                         foreground = 1;
640                         break;
641                 case 'h':
642                         help();
643                         break;
644                 case 'u':
645                         username = optarg;
646                         break;
647                 case 't':
648                         newroot = optarg;
649                         break;
650                 case 'd':
651                         device = optarg;
652                         break;
653                 case 'P':
654                         strncpy(password, optarg, sizeof(password));
655                         password[sizeof(password)-1] = 0;
656                         
657                         /* XXX: find better way of cleaning up ps(1) */
658                         memset(optarg, 0, strlen(optarg)); 
659                         break;
660                 default:
661                         usage();
662                         /* NOTREACHED */
663                 }
664         }
665         
666         if (geteuid() != 0) {
667                 warnx("Run as root and you'll be happy.\n");
668                 usage();
669         }
670
671         argc -= optind;
672         argv += optind;
673
674         switch (argc) {
675         case 1:
676                 nameserv_addr = get_resolvconf_addr();
677                 topdomain = strdup(argv[0]);
678                 break;
679         case 2:
680                 nameserv_addr = argv[0];
681                 topdomain = strdup(argv[1]);
682                 break;
683         default:
684                 usage();
685                 /* NOTREACHED */
686         }
687
688         set_nameserver(nameserv_addr);
689
690         if (strlen(topdomain) > 128 || topdomain[0] == '.') {
691                 warnx("Use a topdomain max 128 chars long. Do not start it with a dot.\n");
692                 usage();
693         }
694
695         if (username != NULL) {
696                 if ((pw = getpwnam(username)) == NULL) {
697                         warnx("User %s does not exist!\n", username);
698                         usage();
699                 }
700         }
701         
702         if (strlen(password) == 0) 
703                 read_password(password, sizeof(password));
704
705         if ((tun_fd = open_tun(device)) == -1)
706                 goto cleanup1;
707         if ((dns_fd = open_dns(0, INADDR_ANY)) == -1)
708                 goto cleanup2;
709
710         signal(SIGINT, sighandler);
711         signal(SIGTERM, sighandler);
712
713         if(handshake(dns_fd))
714                 goto cleanup2;
715         
716         printf("Sending queries for %s to %s\n", topdomain, nameserv_addr);
717
718         if (foreground == 0) 
719                 do_detach();
720
721         if (newroot != NULL)
722                 do_chroot(newroot);
723         
724         if (username != NULL) {
725                 if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
726                         warnx("Could not switch to user %s!\n", username);
727                         usage();
728                 }
729         }
730         
731         tunnel(tun_fd, dns_fd);
732
733 cleanup2:
734         close_dns(dns_fd);
735         close_tun(tun_fd);
736 cleanup1:
737
738         return 0;
739 }