source: src/iodine.c @ 85be9b

Revision 85be9b, 9.0 KB checked in by Pavel Pergamenshchik <ppergame@…>, 4 months ago (diff)

Missing break in iodine.c command-line parsing

Bug-Ubuntu:  https://bugs.launchpad.net/bugs/880508
Author: Pavel Pergamenshchik <ppergame@…>
Reviewed-by: gregor herrmann <gregoa@…>
Last-Update: 2011-10-23

  • Property mode set to 100644
Line 
1/*
2 * Copyright (c) 2006-2009 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 <fcntl.h>
27#include <time.h>
28
29#ifdef WINDOWS32
30#include "windows.h"
31#include <winsock2.h>
32#else
33#include <grp.h>
34#include <pwd.h>
35#endif
36
37#include "common.h"
38#include "tun.h"
39#include "client.h"
40#include "util.h"
41
42#ifdef WINDOWS32
43WORD req_version = MAKEWORD(2, 2);
44WSADATA wsa_data;
45#endif
46
47#if !defined(BSD) && !defined(__GLIBC__)
48static char *__progname;
49#endif
50
51#define PASSWORD_ENV_VAR "IODINE_PASS"
52
53static void
54sighandler(int sig)
55{
56        client_stop();
57}
58
59static void
60usage() {
61        extern char *__progname;
62
63        fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
64                        "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
65                        "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
66        exit(2);
67}
68
69static void
70help() {
71        extern char *__progname;
72
73        fprintf(stderr, "iodine IP over DNS tunneling client\n");
74        fprintf(stderr, "Usage: %s [-v] [-h] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
75                        "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec] "
76                        "[-z context] [-F pidfile] [nameserver] topdomain\n", __progname);
77        fprintf(stderr, "Options to try if connection doesn't work:\n");
78        fprintf(stderr, "  -T force dns type: NULL, TXT, SRV, MX, CNAME, A (default: autodetect)\n");
79        fprintf(stderr, "  -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n");
80        fprintf(stderr, "     Base128, or (only for TXT:) Raw  (default: autodetect)\n");
81        fprintf(stderr, "  -I max interval between requests (default 4 sec) to prevent DNS timeouts\n");
82        fprintf(stderr, "  -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
83        fprintf(stderr, "  -m max size of downstream fragments (default: autodetect)\n");
84        fprintf(stderr, "  -M max size of upstream hostnames (~100-255, default: 255)\n");
85        fprintf(stderr, "  -r to skip raw UDP mode attempt\n");
86        fprintf(stderr, "  -P password used for authentication (max 32 chars will be used)\n");
87        fprintf(stderr, "Other options:\n");
88        fprintf(stderr, "  -v to print version info and exit\n");
89        fprintf(stderr, "  -h to print this help and exit\n");
90        fprintf(stderr, "  -f to keep running in foreground\n");
91        fprintf(stderr, "  -u name to drop privileges and run as user 'name'\n");
92        fprintf(stderr, "  -t dir to chroot to directory dir\n");
93        fprintf(stderr, "  -d device to set tunnel device name\n");
94        fprintf(stderr, "  -z context, to apply specified SELinux context after initialization\n");
95        fprintf(stderr, "  -F pidfile to write pid to a file\n");
96        fprintf(stderr, "nameserver is the IP number/hostname of the relaying nameserver. if absent, /etc/resolv.conf is used\n");
97        fprintf(stderr, "topdomain is the FQDN that is delegated to the tunnel endpoint.\n");
98
99        exit(0);
100}
101
102static void
103version() {
104        char *svnver;
105
106        svnver = "$Rev$ from $Date$";
107
108        fprintf(stderr, "iodine IP over DNS tunneling client\n");
109        fprintf(stderr, "SVN version: %s\n", svnver);
110
111        exit(0);
112}
113
114int
115main(int argc, char **argv)
116{
117        char *nameserv_addr;
118        char *topdomain;
119#ifndef WINDOWS32
120        struct passwd *pw;
121#endif
122        char *username;
123        char password[33];
124        int foreground;
125        char *newroot;
126        char *context;
127        char *device;
128        char *pidfile;
129        int choice;
130        int tun_fd;
131        int dns_fd;
132        int max_downstream_frag_size;
133        int autodetect_frag_size;
134        int retval;
135        int raw_mode;
136        int lazymode;
137        int selecttimeout;
138        int hostname_maxlen;
139        int rtable = 0;
140
141        nameserv_addr = NULL;
142        topdomain = NULL;
143#ifndef WINDOWS32
144        pw = NULL;
145#endif
146        username = NULL;
147        memset(password, 0, 33);
148        srand(time(NULL));
149        foreground = 0;
150        newroot = NULL;
151        context = NULL;
152        device = NULL;
153        pidfile = NULL;
154
155        autodetect_frag_size = 1;
156        max_downstream_frag_size = 3072;
157        retval = 0;
158        raw_mode = 1;
159        lazymode = 1;
160        selecttimeout = 4;
161        hostname_maxlen = 0xFF;
162
163#ifdef WINDOWS32
164        WSAStartup(req_version, &wsa_data);
165#endif
166
167        srand((unsigned) time(NULL));
168        client_init();
169       
170#if !defined(BSD) && !defined(__GLIBC__)
171        __progname = strrchr(argv[0], '/');
172        if (__progname == NULL)
173                __progname = argv[0];
174        else
175                __progname++;
176#endif
177
178        while ((choice = getopt(argc, argv, "vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) {
179                switch(choice) {
180                case 'v':
181                        version();
182                        /* NOTREACHED */
183                        break;
184                case 'f':
185                        foreground = 1;
186                        break;
187                case 'h':
188                        help();
189                        /* NOTREACHED */
190                        break;
191                case 'r':
192                        raw_mode = 0;
193                        break;
194                case 'u':
195                        username = optarg;
196                        break;
197                case 't':
198                        newroot = optarg;
199                        break;
200                case 'd':
201                        device = optarg;
202                        break;
203                case 'R':
204                        rtable = atoi(optarg);
205                        break;
206                case 'P':
207                        strncpy(password, optarg, sizeof(password));
208                        password[sizeof(password)-1] = 0;
209                       
210                        /* XXX: find better way of cleaning up ps(1) */
211                        memset(optarg, 0, strlen(optarg));
212                        break;
213                case 'm':
214                        autodetect_frag_size = 0;
215                        max_downstream_frag_size = atoi(optarg);
216                        break;
217                case 'M':
218                        hostname_maxlen = atoi(optarg);
219                        if (hostname_maxlen > 255)
220                                hostname_maxlen = 255;
221                        if (hostname_maxlen < 10)
222                                hostname_maxlen = 10;
223                        break;
224                case 'z':
225                        context = optarg;
226                        break;
227                case 'F':
228                        pidfile = optarg;
229                        break;   
230                case 'T':
231                        set_qtype(optarg);
232                        break;
233                case 'O':       /* not -D, is Debug in server */
234                        set_downenc(optarg);
235                        break;
236                case 'L':
237                        lazymode = atoi(optarg);
238                        if (lazymode > 1)
239                                lazymode = 1;
240                        if (lazymode < 0)
241                                lazymode = 0;
242                        if (!lazymode)
243                                selecttimeout = 1;
244                        break;
245                case 'I':
246                        selecttimeout = atoi(optarg);
247                        if (selecttimeout < 1)
248                                selecttimeout = 1;
249                        break;
250                default:
251                        usage();
252                        /* NOTREACHED */
253                }
254        }
255       
256        check_superuser(usage);
257
258        argc -= optind;
259        argv += optind;
260
261        switch (argc) {
262        case 1:
263                nameserv_addr = get_resolvconf_addr();
264                topdomain = strdup(argv[0]);
265                break;
266        case 2:
267                nameserv_addr = argv[0];
268                topdomain = strdup(argv[1]);
269                break;
270        default:
271                usage();
272                /* NOTREACHED */
273        }
274
275        if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) {
276                warnx("Use a max frag size between 1 and 65535 bytes.\n");
277                usage();
278                /* NOTREACHED */
279        }
280
281        if (nameserv_addr) {
282                client_set_nameserver(nameserv_addr, DNS_PORT);
283        } else {
284                warnx("No nameserver found - not connected to any network?\n");
285                usage();
286                /* NOTREACHED */
287        }       
288
289        if (strlen(topdomain) <= 128) {
290                if(check_topdomain(topdomain)) {
291                        warnx("Topdomain contains invalid characters.\n");
292                        usage();
293                        /* NOTREACHED */
294                }
295        } else {
296                warnx("Use a topdomain max 128 chars long.\n");
297                usage();
298                /* NOTREACHED */
299        }
300
301        client_set_selecttimeout(selecttimeout);
302        client_set_lazymode(lazymode);
303        client_set_topdomain(topdomain);
304        client_set_hostname_maxlen(hostname_maxlen);
305       
306        if (username != NULL) {
307#ifndef WINDOWS32
308                if ((pw = getpwnam(username)) == NULL) {
309                        warnx("User %s does not exist!\n", username);
310                        usage();
311                        /* NOTREACHED */
312                }
313#endif
314        }
315       
316        if (strlen(password) == 0) {
317                if (NULL != getenv(PASSWORD_ENV_VAR))
318                        snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR));
319                else
320                        read_password(password, sizeof(password));
321        }
322       
323        client_set_password(password);
324
325        if ((tun_fd = open_tun(device)) == -1) {
326                retval = 1;
327                goto cleanup1;
328        }
329        if ((dns_fd = open_dns(0, INADDR_ANY)) == -1) {
330                retval = 1;
331                goto cleanup2;
332        }
333#ifdef OPENBSD
334        if (rtable > 0)
335                socket_setrtable(dns_fd, rtable);
336#endif
337
338        signal(SIGINT, sighandler);
339        signal(SIGTERM, sighandler);
340
341        fprintf(stderr, "Sending DNS queries for %s to %s\n",
342                topdomain, nameserv_addr);
343
344        if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) {
345                retval = 1;
346                goto cleanup2;
347        }
348       
349        if (client_get_conn() == CONN_RAW_UDP) {
350                fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr());
351        }
352
353        fprintf(stderr, "Connection setup complete, transmitting data.\n");
354
355        if (foreground == 0)
356                do_detach();
357       
358        if (pidfile != NULL)
359                do_pidfile(pidfile);
360
361        if (newroot != NULL)
362                do_chroot(newroot);
363       
364        if (username != NULL) {
365#ifndef WINDOWS32
366                gid_t gids[1];
367                gids[0] = pw->pw_gid;
368                if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) {
369                        warnx("Could not switch to user %s!\n", username);
370                        usage();
371                        /* NOTREACHED */
372                }
373#endif
374        }
375
376        if (context != NULL)
377                do_setcon(context);
378
379        client_tunnel(tun_fd, dns_fd);
380
381cleanup2:
382        close_dns(dns_fd);
383        close_tun(tun_fd);
384cleanup1:
385
386        return retval;
387}
388
Note: See TracBrowser for help on using the repository browser.