tunala.c revision 296465
1#if defined(NO_BUFFER) || defined(NO_IP) || defined(NO_OPENSSL)
2# error "Badness, NO_BUFFER, NO_IP or NO_OPENSSL is defined, turn them *off*"
3#endif
4
5/* Include our bits'n'pieces */
6#include "tunala.h"
7
8/********************************************/
9/* Our local types that specify our "world" */
10/********************************************/
11
12/*
13 * These represent running "tunnels". Eg. if you wanted to do SSL in a
14 * "message-passing" scanario, the "int" file-descriptors might be replaced
15 * by thread or process IDs, and the "select" code might be replaced by
16 * message handling code. Whatever.
17 */
18typedef struct _tunala_item_t {
19    /*
20     * The underlying SSL state machine. This is a data-only processing unit
21     * and we communicate with it by talking to its four "buffers".
22     */
23    state_machine_t sm;
24    /*
25     * The file-descriptors for the "dirty" (encrypted) side of the SSL
26     * setup. In actuality, this is typically a socket and both values are
27     * identical.
28     */
29    int dirty_read, dirty_send;
30    /*
31     * The file-descriptors for the "clean" (unencrypted) side of the SSL
32     * setup. These could be stdin/stdout, a socket (both values the same),
33     * or whatever you like.
34     */
35    int clean_read, clean_send;
36} tunala_item_t;
37
38/*
39 * This structure is used as the data for running the main loop. Namely, in a
40 * network format such as this, it is stuff for select() - but as pointed out,
41 * when moving the real-world to somewhere else, this might be replaced by
42 * something entirely different. It's basically the stuff that controls when
43 * it's time to do some "work".
44 */
45typedef struct _select_sets_t {
46    int max;                    /* As required as the first argument to
47                                 * select() */
48    fd_set reads, sends, excepts; /* As passed to select() */
49} select_sets_t;
50typedef struct _tunala_selector_t {
51    select_sets_t last_selected; /* Results of the last select() */
52    select_sets_t next_select;  /* What we'll next select on */
53} tunala_selector_t;
54
55/*
56 * This structure is *everything*. We do it to avoid the use of globals so
57 * that, for example, it would be easier to shift things around between
58 * async-IO, thread-based, or multi-fork()ed (or combinations thereof).
59 */
60typedef struct _tunala_world_t {
61    /* The file-descriptor we "listen" on for new connections */
62    int listen_fd;
63    /* The array of tunnels */
64    tunala_item_t *tunnels;
65    /* the number of tunnels in use and allocated, respectively */
66    unsigned int tunnels_used, tunnels_size;
67    /* Our outside "loop" context stuff */
68    tunala_selector_t selector;
69    /*
70     * Our SSL_CTX, which is configured as the SSL client or server and has
71     * the various cert-settings and callbacks configured.
72     */
73    SSL_CTX *ssl_ctx;
74    /*
75     * Simple flag with complex logic :-) Indicates whether we're an SSL
76     * server or an SSL client.
77     */
78    int server_mode;
79} tunala_world_t;
80
81/*****************************/
82/* Internal static functions */
83/*****************************/
84
85static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
86                                   const char *CAfile, const char *cert,
87                                   const char *key, const char *dcert,
88                                   const char *dkey, const char *cipher_list,
89                                   const char *dh_file,
90                                   const char *dh_special, int tmp_rsa,
91                                   int ctx_options, int out_state,
92                                   int out_verify, int verify_mode,
93                                   unsigned int verify_depth);
94static void selector_init(tunala_selector_t * selector);
95static void selector_add_listener(tunala_selector_t * selector, int fd);
96static void selector_add_tunala(tunala_selector_t * selector,
97                                tunala_item_t * t);
98static int selector_select(tunala_selector_t * selector);
99/*
100 * This returns -1 for error, 0 for no new connections, or 1 for success, in
101 * which case *newfd is populated.
102 */
103static int selector_get_listener(tunala_selector_t * selector, int fd,
104                                 int *newfd);
105static int tunala_world_new_item(tunala_world_t * world, int fd,
106                                 const char *ip, unsigned short port,
107                                 int flipped);
108static void tunala_world_del_item(tunala_world_t * world, unsigned int idx);
109static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item);
110
111/*********************************************/
112/* MAIN FUNCTION (and its utility functions) */
113/*********************************************/
114
115static const char *def_proxyhost = "127.0.0.1:443";
116static const char *def_listenhost = "127.0.0.1:8080";
117static int def_max_tunnels = 50;
118static const char *def_cacert = NULL;
119static const char *def_cert = NULL;
120static const char *def_key = NULL;
121static const char *def_dcert = NULL;
122static const char *def_dkey = NULL;
123static const char *def_engine_id = NULL;
124static int def_server_mode = 0;
125static int def_flipped = 0;
126static const char *def_cipher_list = NULL;
127static const char *def_dh_file = NULL;
128static const char *def_dh_special = NULL;
129static int def_tmp_rsa = 1;
130static int def_ctx_options = 0;
131static int def_verify_mode = 0;
132static unsigned int def_verify_depth = 10;
133static int def_out_state = 0;
134static unsigned int def_out_verify = 0;
135static int def_out_totals = 0;
136static int def_out_conns = 0;
137
138static const char *helpstring =
139    "\n'Tunala' (A tunneler with a New Zealand accent)\n"
140    "Usage: tunala [options], where options are from;\n"
141    " -listen [host:]<port>  (default = 127.0.0.1:8080)\n"
142    " -proxy <host>:<port>   (default = 127.0.0.1:443)\n"
143    " -maxtunnels <num>      (default = 50)\n"
144    " -cacert <path|NULL>    (default = NULL)\n"
145    " -cert <path|NULL>      (default = NULL)\n"
146    " -key <path|NULL>       (default = whatever '-cert' is)\n"
147    " -dcert <path|NULL>     (usually for DSA, default = NULL)\n"
148    " -dkey <path|NULL>      (usually for DSA, default = whatever '-dcert' is)\n"
149    " -engine <id|NULL>      (default = NULL)\n"
150    " -server <0|1>          (default = 0, ie. an SSL client)\n"
151    " -flipped <0|1>         (makes SSL servers be network clients, and vice versa)\n"
152    " -cipher <list>         (specifies cipher list to use)\n"
153    " -dh_file <path>        (a PEM file containing DH parameters to use)\n"
154    " -dh_special <NULL|generate|standard> (see below: def=NULL)\n"
155    " -no_tmp_rsa            (don't generate temporary RSA keys)\n"
156    " -no_ssl2               (disable SSLv2)\n"
157    " -no_ssl3               (disable SSLv3)\n"
158    " -no_tls1               (disable TLSv1)\n"
159    " -v_peer                (verify the peer certificate)\n"
160    " -v_strict              (do not continue if peer doesn't authenticate)\n"
161    " -v_once                (no verification in renegotiates)\n"
162    " -v_depth <num>         (limit certificate chain depth, default = 10)\n"
163    " -out_conns             (prints client connections and disconnections)\n"
164    " -out_state             (prints SSL handshake states)\n"
165    " -out_verify <0|1|2|3>  (prints certificate verification states: def=1)\n"
166    " -out_totals            (prints out byte-totals when a tunnel closes)\n"
167    " -<h|help|?>            (displays this help screen)\n"
168    "Notes:\n"
169    "(1) It is recommended to specify a cert+key when operating as an SSL server.\n"
170    "    If you only specify '-cert', the same file must contain a matching\n"
171    "    private key.\n"
172    "(2) Either dh_file or dh_special can be used to specify where DH parameters\n"
173    "    will be obtained from (or '-dh_special NULL' for the default choice) but\n"
174    "    you cannot specify both. For dh_special, 'generate' will create new DH\n"
175    "    parameters on startup, and 'standard' will use embedded parameters\n"
176    "    instead.\n"
177    "(3) Normally an ssl client connects to an ssl server - so that an 'ssl client\n"
178    "    tunala' listens for 'clean' client connections and proxies ssl, and an\n"
179    "    'ssl server tunala' listens for ssl connections and proxies 'clean'. With\n"
180    "    '-flipped 1', this behaviour is reversed so that an 'ssl server tunala'\n"
181    "    listens for clean client connections and proxies ssl (but participating\n"
182    "    as an ssl *server* in the SSL/TLS protocol), and an 'ssl client tunala'\n"
183    "    listens for ssl connections (participating as an ssl *client* in the\n"
184    "    SSL/TLS protocol) and proxies 'clean' to the end destination. This can\n"
185    "    be useful for allowing network access to 'servers' where only the server\n"
186    "    needs to authenticate the client (ie. the other way is not required).\n"
187    "    Even with client and server authentication, this 'technique' mitigates\n"
188    "    some DoS (denial-of-service) potential as it will be the network client\n"
189    "    having to perform the first private key operation rather than the other\n"
190    "    way round.\n"
191    "(4) The 'technique' used by setting '-flipped 1' is probably compatible with\n"
192    "    absolutely nothing except another complimentary instance of 'tunala'\n"
193    "    running with '-flipped 1'. :-)\n";
194
195/*
196 * Default DH parameters for use with "-dh_special standard" ... stolen
197 * striaght from s_server.
198 */
199static unsigned char dh512_p[] = {
200    0xDA, 0x58, 0x3C, 0x16, 0xD9, 0x85, 0x22, 0x89, 0xD0, 0xE4, 0xAF, 0x75,
201    0x6F, 0x4C, 0xCA, 0x92, 0xDD, 0x4B, 0xE5, 0x33, 0xB8, 0x04, 0xFB, 0x0F,
202    0xED, 0x94, 0xEF, 0x9C, 0x8A, 0x44, 0x03, 0xED, 0x57, 0x46, 0x50, 0xD3,
203    0x69, 0x99, 0xDB, 0x29, 0xD7, 0x76, 0x27, 0x6B, 0xA2, 0xD3, 0xD4, 0x12,
204    0xE2, 0x18, 0xF4, 0xDD, 0x1E, 0x08, 0x4C, 0xF6, 0xD8, 0x00, 0x3E, 0x7C,
205    0x47, 0x74, 0xE8, 0x33,
206};
207
208static unsigned char dh512_g[] = {
209    0x02,
210};
211
212/*
213 * And the function that parses the above "standard" parameters, again,
214 * straight out of s_server.
215 */
216static DH *get_dh512(void)
217{
218    DH *dh = NULL;
219
220    if ((dh = DH_new()) == NULL)
221        return (NULL);
222    dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
223    dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
224    if ((dh->p == NULL) || (dh->g == NULL))
225        return (NULL);
226    return (dh);
227}
228
229/* Various help/error messages used by main() */
230static int usage(const char *errstr, int isunknownarg)
231{
232    if (isunknownarg)
233        fprintf(stderr, "Error: unknown argument '%s'\n", errstr);
234    else
235        fprintf(stderr, "Error: %s\n", errstr);
236    fprintf(stderr, "%s\n", helpstring);
237    return 1;
238}
239
240static int err_str0(const char *str0)
241{
242    fprintf(stderr, "%s\n", str0);
243    return 1;
244}
245
246static int err_str1(const char *fmt, const char *str1)
247{
248    fprintf(stderr, fmt, str1);
249    fprintf(stderr, "\n");
250    return 1;
251}
252
253static int parse_max_tunnels(const char *s, unsigned int *maxtunnels)
254{
255    unsigned long l;
256    if (!int_strtoul(s, &l) || (l < 1) || (l > 1024)) {
257        fprintf(stderr, "Error, '%s' is an invalid value for "
258                "maxtunnels\n", s);
259        return 0;
260    }
261    *maxtunnels = (unsigned int)l;
262    return 1;
263}
264
265static int parse_server_mode(const char *s, int *servermode)
266{
267    unsigned long l;
268    if (!int_strtoul(s, &l) || (l > 1)) {
269        fprintf(stderr, "Error, '%s' is an invalid value for the "
270                "server mode\n", s);
271        return 0;
272    }
273    *servermode = (int)l;
274    return 1;
275}
276
277static int parse_dh_special(const char *s, const char **dh_special)
278{
279    if ((strcmp(s, "NULL") == 0) || (strcmp(s, "generate") == 0) ||
280        (strcmp(s, "standard") == 0)) {
281        *dh_special = s;
282        return 1;
283    }
284    fprintf(stderr, "Error, '%s' is an invalid value for 'dh_special'\n", s);
285    return 0;
286}
287
288static int parse_verify_level(const char *s, unsigned int *verify_level)
289{
290    unsigned long l;
291    if (!int_strtoul(s, &l) || (l > 3)) {
292        fprintf(stderr, "Error, '%s' is an invalid value for "
293                "out_verify\n", s);
294        return 0;
295    }
296    *verify_level = (unsigned int)l;
297    return 1;
298}
299
300static int parse_verify_depth(const char *s, unsigned int *verify_depth)
301{
302    unsigned long l;
303    if (!int_strtoul(s, &l) || (l < 1) || (l > 50)) {
304        fprintf(stderr, "Error, '%s' is an invalid value for "
305                "verify_depth\n", s);
306        return 0;
307    }
308    *verify_depth = (unsigned int)l;
309    return 1;
310}
311
312/* Some fprintf format strings used when tunnels close */
313static const char *io_stats_dirty =
314    "    SSL traffic;   %8lu bytes in, %8lu bytes out\n";
315static const char *io_stats_clean =
316    "    clear traffic; %8lu bytes in, %8lu bytes out\n";
317
318int main(int argc, char *argv[])
319{
320    unsigned int loop;
321    int newfd;
322    tunala_world_t world;
323    tunala_item_t *t_item;
324    const char *proxy_ip;
325    unsigned short proxy_port;
326    /* Overridables */
327    const char *proxyhost = def_proxyhost;
328    const char *listenhost = def_listenhost;
329    unsigned int max_tunnels = def_max_tunnels;
330    const char *cacert = def_cacert;
331    const char *cert = def_cert;
332    const char *key = def_key;
333    const char *dcert = def_dcert;
334    const char *dkey = def_dkey;
335    const char *engine_id = def_engine_id;
336    int server_mode = def_server_mode;
337    int flipped = def_flipped;
338    const char *cipher_list = def_cipher_list;
339    const char *dh_file = def_dh_file;
340    const char *dh_special = def_dh_special;
341    int tmp_rsa = def_tmp_rsa;
342    int ctx_options = def_ctx_options;
343    int verify_mode = def_verify_mode;
344    unsigned int verify_depth = def_verify_depth;
345    int out_state = def_out_state;
346    unsigned int out_verify = def_out_verify;
347    int out_totals = def_out_totals;
348    int out_conns = def_out_conns;
349
350/* Parse command-line arguments */
351 next_arg:
352    argc--;
353    argv++;
354    if (argc > 0) {
355        if (strcmp(*argv, "-listen") == 0) {
356            if (argc < 2)
357                return usage("-listen requires an argument", 0);
358            argc--;
359            argv++;
360            listenhost = *argv;
361            goto next_arg;
362        } else if (strcmp(*argv, "-proxy") == 0) {
363            if (argc < 2)
364                return usage("-proxy requires an argument", 0);
365            argc--;
366            argv++;
367            proxyhost = *argv;
368            goto next_arg;
369        } else if (strcmp(*argv, "-maxtunnels") == 0) {
370            if (argc < 2)
371                return usage("-maxtunnels requires an argument", 0);
372            argc--;
373            argv++;
374            if (!parse_max_tunnels(*argv, &max_tunnels))
375                return 1;
376            goto next_arg;
377        } else if (strcmp(*argv, "-cacert") == 0) {
378            if (argc < 2)
379                return usage("-cacert requires an argument", 0);
380            argc--;
381            argv++;
382            if (strcmp(*argv, "NULL") == 0)
383                cacert = NULL;
384            else
385                cacert = *argv;
386            goto next_arg;
387        } else if (strcmp(*argv, "-cert") == 0) {
388            if (argc < 2)
389                return usage("-cert requires an argument", 0);
390            argc--;
391            argv++;
392            if (strcmp(*argv, "NULL") == 0)
393                cert = NULL;
394            else
395                cert = *argv;
396            goto next_arg;
397        } else if (strcmp(*argv, "-key") == 0) {
398            if (argc < 2)
399                return usage("-key requires an argument", 0);
400            argc--;
401            argv++;
402            if (strcmp(*argv, "NULL") == 0)
403                key = NULL;
404            else
405                key = *argv;
406            goto next_arg;
407        } else if (strcmp(*argv, "-dcert") == 0) {
408            if (argc < 2)
409                return usage("-dcert requires an argument", 0);
410            argc--;
411            argv++;
412            if (strcmp(*argv, "NULL") == 0)
413                dcert = NULL;
414            else
415                dcert = *argv;
416            goto next_arg;
417        } else if (strcmp(*argv, "-dkey") == 0) {
418            if (argc < 2)
419                return usage("-dkey requires an argument", 0);
420            argc--;
421            argv++;
422            if (strcmp(*argv, "NULL") == 0)
423                dkey = NULL;
424            else
425                dkey = *argv;
426            goto next_arg;
427        } else if (strcmp(*argv, "-engine") == 0) {
428            if (argc < 2)
429                return usage("-engine requires an argument", 0);
430            argc--;
431            argv++;
432            engine_id = *argv;
433            goto next_arg;
434        } else if (strcmp(*argv, "-server") == 0) {
435            if (argc < 2)
436                return usage("-server requires an argument", 0);
437            argc--;
438            argv++;
439            if (!parse_server_mode(*argv, &server_mode))
440                return 1;
441            goto next_arg;
442        } else if (strcmp(*argv, "-flipped") == 0) {
443            if (argc < 2)
444                return usage("-flipped requires an argument", 0);
445            argc--;
446            argv++;
447            if (!parse_server_mode(*argv, &flipped))
448                return 1;
449            goto next_arg;
450        } else if (strcmp(*argv, "-cipher") == 0) {
451            if (argc < 2)
452                return usage("-cipher requires an argument", 0);
453            argc--;
454            argv++;
455            cipher_list = *argv;
456            goto next_arg;
457        } else if (strcmp(*argv, "-dh_file") == 0) {
458            if (argc < 2)
459                return usage("-dh_file requires an argument", 0);
460            if (dh_special)
461                return usage("cannot mix -dh_file with " "-dh_special", 0);
462            argc--;
463            argv++;
464            dh_file = *argv;
465            goto next_arg;
466        } else if (strcmp(*argv, "-dh_special") == 0) {
467            if (argc < 2)
468                return usage("-dh_special requires an argument", 0);
469            if (dh_file)
470                return usage("cannot mix -dh_file with " "-dh_special", 0);
471            argc--;
472            argv++;
473            if (!parse_dh_special(*argv, &dh_special))
474                return 1;
475            goto next_arg;
476        } else if (strcmp(*argv, "-no_tmp_rsa") == 0) {
477            tmp_rsa = 0;
478            goto next_arg;
479        } else if (strcmp(*argv, "-no_ssl2") == 0) {
480            ctx_options |= SSL_OP_NO_SSLv2;
481            goto next_arg;
482        } else if (strcmp(*argv, "-no_ssl3") == 0) {
483            ctx_options |= SSL_OP_NO_SSLv3;
484            goto next_arg;
485        } else if (strcmp(*argv, "-no_tls1") == 0) {
486            ctx_options |= SSL_OP_NO_TLSv1;
487            goto next_arg;
488        } else if (strcmp(*argv, "-v_peer") == 0) {
489            verify_mode |= SSL_VERIFY_PEER;
490            goto next_arg;
491        } else if (strcmp(*argv, "-v_strict") == 0) {
492            verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
493            goto next_arg;
494        } else if (strcmp(*argv, "-v_once") == 0) {
495            verify_mode |= SSL_VERIFY_CLIENT_ONCE;
496            goto next_arg;
497        } else if (strcmp(*argv, "-v_depth") == 0) {
498            if (argc < 2)
499                return usage("-v_depth requires an argument", 0);
500            argc--;
501            argv++;
502            if (!parse_verify_depth(*argv, &verify_depth))
503                return 1;
504            goto next_arg;
505        } else if (strcmp(*argv, "-out_state") == 0) {
506            out_state = 1;
507            goto next_arg;
508        } else if (strcmp(*argv, "-out_verify") == 0) {
509            if (argc < 2)
510                return usage("-out_verify requires an argument", 0);
511            argc--;
512            argv++;
513            if (!parse_verify_level(*argv, &out_verify))
514                return 1;
515            goto next_arg;
516        } else if (strcmp(*argv, "-out_totals") == 0) {
517            out_totals = 1;
518            goto next_arg;
519        } else if (strcmp(*argv, "-out_conns") == 0) {
520            out_conns = 1;
521            goto next_arg;
522        } else if ((strcmp(*argv, "-h") == 0) ||
523                   (strcmp(*argv, "-help") == 0) ||
524                   (strcmp(*argv, "-?") == 0)) {
525            fprintf(stderr, "%s\n", helpstring);
526            return 0;
527        } else
528            return usage(*argv, 1);
529    }
530    /* Run any sanity checks we want here */
531    if (!cert && !dcert && server_mode)
532        fprintf(stderr, "WARNING: you are running an SSL server without "
533                "a certificate - this may not work!\n");
534
535    /* Initialise network stuff */
536    if (!ip_initialise())
537        return err_str0("ip_initialise failed");
538    /* Create the SSL_CTX */
539    if ((world.ssl_ctx = initialise_ssl_ctx(server_mode, engine_id,
540                                            cacert, cert, key, dcert, dkey,
541                                            cipher_list, dh_file, dh_special,
542                                            tmp_rsa, ctx_options, out_state,
543                                            out_verify, verify_mode,
544                                            verify_depth)) == NULL)
545        return err_str1("initialise_ssl_ctx(engine_id=%s) failed",
546                        (engine_id == NULL) ? "NULL" : engine_id);
547    if (engine_id)
548        fprintf(stderr, "Info, engine '%s' initialised\n", engine_id);
549    /* Create the listener */
550    if ((world.listen_fd = ip_create_listener(listenhost)) == -1)
551        return err_str1("ip_create_listener(%s) failed", listenhost);
552    fprintf(stderr, "Info, listening on '%s'\n", listenhost);
553    if (!ip_parse_address(proxyhost, &proxy_ip, &proxy_port, 0))
554        return err_str1("ip_parse_address(%s) failed", proxyhost);
555    fprintf(stderr, "Info, proxying to '%s' (%d.%d.%d.%d:%d)\n", proxyhost,
556            (int)proxy_ip[0], (int)proxy_ip[1],
557            (int)proxy_ip[2], (int)proxy_ip[3], (int)proxy_port);
558    fprintf(stderr, "Info, set maxtunnels to %d\n", (int)max_tunnels);
559    fprintf(stderr, "Info, set to operate as an SSL %s\n",
560            (server_mode ? "server" : "client"));
561    /* Initialise the rest of the stuff */
562    world.tunnels_used = world.tunnels_size = 0;
563    world.tunnels = NULL;
564    world.server_mode = server_mode;
565    selector_init(&world.selector);
566
567/* We're ready to loop */
568 main_loop:
569    /* Should we listen for *new* tunnels? */
570    if (world.tunnels_used < max_tunnels)
571        selector_add_listener(&world.selector, world.listen_fd);
572    /* We should add in our existing tunnels */
573    for (loop = 0; loop < world.tunnels_used; loop++)
574        selector_add_tunala(&world.selector, world.tunnels + loop);
575    /* Now do the select */
576    switch (selector_select(&world.selector)) {
577    case -1:
578        if (errno != EINTR) {
579            fprintf(stderr, "selector_select returned a " "badness error.\n");
580            goto shouldnt_happen;
581        }
582        fprintf(stderr, "Warn, selector interrupted by a signal\n");
583        goto main_loop;
584    case 0:
585        fprintf(stderr, "Warn, selector_select returned 0 - signal?" "?\n");
586        goto main_loop;
587    default:
588        break;
589    }
590    /* Accept new connection if we should and can */
591    if ((world.tunnels_used < max_tunnels)
592        && (selector_get_listener(&world.selector, world.listen_fd, &newfd) ==
593            1)) {
594        /* We have a new connection */
595        if (!tunala_world_new_item(&world, newfd, proxy_ip,
596                                   proxy_port, flipped))
597            fprintf(stderr, "tunala_world_new_item failed\n");
598        else if (out_conns)
599            fprintf(stderr, "Info, new tunnel opened, now up to "
600                    "%d\n", world.tunnels_used);
601    }
602    /*
603     * Give each tunnel its moment, note the while loop is because it makes
604     * the logic easier than with "for" to deal with an array that may shift
605     * because of deletes.
606     */
607    loop = 0;
608    t_item = world.tunnels;
609    while (loop < world.tunnels_used) {
610        if (!tunala_item_io(&world.selector, t_item)) {
611            /*
612             * We're closing whether for reasons of an error or a natural
613             * close. Don't increment loop or t_item because the next item is
614             * moving to us!
615             */
616            if (!out_totals)
617                goto skip_totals;
618            fprintf(stderr, "Tunnel closing, traffic stats follow\n");
619            /* Display the encrypted (over the network) stats */
620            fprintf(stderr, io_stats_dirty,
621                    buffer_total_in(state_machine_get_buffer
622                                    (&t_item->sm, SM_DIRTY_IN)),
623                    buffer_total_out(state_machine_get_buffer
624                                     (&t_item->sm, SM_DIRTY_OUT)));
625            /*
626             * Display the local (tunnelled) stats. NB: Data we *receive* is
627             * data sent *out* of the state_machine on its 'clean' side.
628             * Hence the apparent back-to-front OUT/IN mixup here :-)
629             */
630            fprintf(stderr, io_stats_clean,
631                    buffer_total_out(state_machine_get_buffer
632                                     (&t_item->sm, SM_CLEAN_OUT)),
633                    buffer_total_in(state_machine_get_buffer
634                                    (&t_item->sm, SM_CLEAN_IN)));
635 skip_totals:
636            tunala_world_del_item(&world, loop);
637            if (out_conns)
638                fprintf(stderr, "Info, tunnel closed, down to %d\n",
639                        world.tunnels_used);
640        } else {
641            /* Move to the next item */
642            loop++;
643            t_item++;
644        }
645    }
646    goto main_loop;
647    /* Should never get here */
648 shouldnt_happen:
649    abort();
650    return 1;
651}
652
653/****************/
654/* OpenSSL bits */
655/****************/
656
657static int ctx_set_cert(SSL_CTX *ctx, const char *cert, const char *key)
658{
659    FILE *fp = NULL;
660    X509 *x509 = NULL;
661    EVP_PKEY *pkey = NULL;
662    int toret = 0;              /* Assume an error */
663
664    /* cert */
665    if (cert) {
666        if ((fp = fopen(cert, "r")) == NULL) {
667            fprintf(stderr, "Error opening cert file '%s'\n", cert);
668            goto err;
669        }
670        if (!PEM_read_X509(fp, &x509, NULL, NULL)) {
671            fprintf(stderr, "Error reading PEM cert from '%s'\n", cert);
672            goto err;
673        }
674        if (!SSL_CTX_use_certificate(ctx, x509)) {
675            fprintf(stderr, "Error, cert in '%s' can not be used\n", cert);
676            goto err;
677        }
678        /* Clear the FILE* for reuse in the "key" code */
679        fclose(fp);
680        fp = NULL;
681        fprintf(stderr, "Info, operating with cert in '%s'\n", cert);
682        /*
683         * If a cert was given without matching key, we assume the same file
684         * contains the required key.
685         */
686        if (!key)
687            key = cert;
688    } else {
689        if (key)
690            fprintf(stderr, "Error, can't specify a key without a "
691                    "corresponding certificate\n");
692        else
693            fprintf(stderr, "Error, ctx_set_cert called with " "NULLs!\n");
694        goto err;
695    }
696    /* key */
697    if (key) {
698        if ((fp = fopen(key, "r")) == NULL) {
699            fprintf(stderr, "Error opening key file '%s'\n", key);
700            goto err;
701        }
702        if (!PEM_read_PrivateKey(fp, &pkey, NULL, NULL)) {
703            fprintf(stderr, "Error reading PEM key from '%s'\n", key);
704            goto err;
705        }
706        if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
707            fprintf(stderr, "Error, key in '%s' can not be used\n", key);
708            goto err;
709        }
710        fprintf(stderr, "Info, operating with key in '%s'\n", key);
711    } else
712        fprintf(stderr, "Info, operating without a cert or key\n");
713    /* Success */
714    toret = 1;
715 err:
716    if (x509)
717        X509_free(x509);
718    if (pkey)
719        EVP_PKEY_free(pkey);
720    if (fp)
721        fclose(fp);
722    return toret;
723}
724
725static int ctx_set_dh(SSL_CTX *ctx, const char *dh_file,
726                      const char *dh_special)
727{
728    DH *dh = NULL;
729    FILE *fp = NULL;
730
731    if (dh_special) {
732        if (strcmp(dh_special, "NULL") == 0)
733            return 1;
734        if (strcmp(dh_special, "standard") == 0) {
735            if ((dh = get_dh512()) == NULL) {
736                fprintf(stderr, "Error, can't parse 'standard'"
737                        " DH parameters\n");
738                return 0;
739            }
740            fprintf(stderr, "Info, using 'standard' DH parameters\n");
741            goto do_it;
742        }
743        if (strcmp(dh_special, "generate") != 0)
744            /*
745             * This shouldn't happen - screening values is handled in main().
746             */
747            abort();
748        fprintf(stderr, "Info, generating DH parameters ... ");
749        fflush(stderr);
750        if ((dh = DH_generate_parameters(512, DH_GENERATOR_5,
751                                         NULL, NULL)) == NULL) {
752            fprintf(stderr, "error!\n");
753            return 0;
754        }
755        fprintf(stderr, "complete\n");
756        goto do_it;
757    }
758    /* So, we're loading dh_file */
759    if ((fp = fopen(dh_file, "r")) == NULL) {
760        fprintf(stderr, "Error, couldn't open '%s' for DH parameters\n",
761                dh_file);
762        return 0;
763    }
764    dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
765    fclose(fp);
766    if (dh == NULL) {
767        fprintf(stderr, "Error, could not parse DH parameters from '%s'\n",
768                dh_file);
769        return 0;
770    }
771    fprintf(stderr, "Info, using DH parameters from file '%s'\n", dh_file);
772 do_it:
773    SSL_CTX_set_tmp_dh(ctx, dh);
774    DH_free(dh);
775    return 1;
776}
777
778static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
779                                   const char *CAfile, const char *cert,
780                                   const char *key, const char *dcert,
781                                   const char *dkey, const char *cipher_list,
782                                   const char *dh_file,
783                                   const char *dh_special, int tmp_rsa,
784                                   int ctx_options, int out_state,
785                                   int out_verify, int verify_mode,
786                                   unsigned int verify_depth)
787{
788    SSL_CTX *ctx = NULL, *ret = NULL;
789    SSL_METHOD *meth;
790    ENGINE *e = NULL;
791
792    OpenSSL_add_ssl_algorithms();
793    SSL_load_error_strings();
794
795    meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());
796    if (meth == NULL)
797        goto err;
798    if (engine_id) {
799        ENGINE_load_builtin_engines();
800        if ((e = ENGINE_by_id(engine_id)) == NULL) {
801            fprintf(stderr, "Error obtaining '%s' engine, openssl "
802                    "errors follow\n", engine_id);
803            goto err;
804        }
805        if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
806            fprintf(stderr, "Error assigning '%s' engine, openssl "
807                    "errors follow\n", engine_id);
808            goto err;
809        }
810        ENGINE_free(e);
811    }
812    if ((ctx = SSL_CTX_new(meth)) == NULL)
813        goto err;
814    /* cacert */
815    if (CAfile) {
816        if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),
817                                       CAfile, NULL)) {
818            fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile);
819            goto err;
820        }
821        fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile);
822    } else
823        fprintf(stderr, "Info, operating without a CA cert(-list)\n");
824    if (!SSL_CTX_set_default_verify_paths(ctx)) {
825        fprintf(stderr, "Error setting default verify paths\n");
826        goto err;
827    }
828
829    /* cert and key */
830    if ((cert || key) && !ctx_set_cert(ctx, cert, key))
831        goto err;
832    /* dcert and dkey */
833    if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))
834        goto err;
835    /* temporary RSA key generation */
836    if (tmp_rsa)
837        SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa);
838
839    /* cipher_list */
840    if (cipher_list) {
841        if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
842            fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list);
843            goto err;
844        }
845        fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);
846    } else
847        fprintf(stderr, "Info, operating with default cipher list\n");
848
849    /* dh_file & dh_special */
850    if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))
851        goto err;
852
853    /* ctx_options */
854    SSL_CTX_set_options(ctx, ctx_options);
855
856    /* out_state (output of SSL handshake states to screen). */
857    if (out_state)
858        cb_ssl_info_set_output(stderr);
859
860    /* out_verify */
861    if (out_verify > 0) {
862        cb_ssl_verify_set_output(stderr);
863        cb_ssl_verify_set_level(out_verify);
864    }
865
866    /* verify_depth */
867    cb_ssl_verify_set_depth(verify_depth);
868
869    /* Success! (includes setting verify_mode) */
870    SSL_CTX_set_info_callback(ctx, cb_ssl_info);
871    SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify);
872    ret = ctx;
873 err:
874    if (!ret) {
875        ERR_print_errors_fp(stderr);
876        if (ctx)
877            SSL_CTX_free(ctx);
878    }
879    return ret;
880}
881
882/*****************/
883/* Selector bits */
884/*****************/
885
886static void selector_sets_init(select_sets_t * s)
887{
888    s->max = 0;
889    FD_ZERO(&s->reads);
890    FD_ZERO(&s->sends);
891    FD_ZERO(&s->excepts);
892}
893
894static void selector_init(tunala_selector_t * selector)
895{
896    selector_sets_init(&selector->last_selected);
897    selector_sets_init(&selector->next_select);
898}
899
900#define SEL_EXCEPTS 0x00
901#define SEL_READS   0x01
902#define SEL_SENDS   0x02
903static void selector_add_raw_fd(tunala_selector_t * s, int fd, int flags)
904{
905    FD_SET(fd, &s->next_select.excepts);
906    if (flags & SEL_READS)
907        FD_SET(fd, &s->next_select.reads);
908    if (flags & SEL_SENDS)
909        FD_SET(fd, &s->next_select.sends);
910    /* Adjust "max" */
911    if (s->next_select.max < (fd + 1))
912        s->next_select.max = fd + 1;
913}
914
915static void selector_add_listener(tunala_selector_t * selector, int fd)
916{
917    selector_add_raw_fd(selector, fd, SEL_READS);
918}
919
920static void selector_add_tunala(tunala_selector_t * s, tunala_item_t * t)
921{
922    /* Set clean read if sm.clean_in is not full */
923    if (t->clean_read != -1) {
924        selector_add_raw_fd(s, t->clean_read,
925                            (buffer_full(state_machine_get_buffer(&t->sm,
926                                                                  SM_CLEAN_IN))
927                             ? SEL_EXCEPTS : SEL_READS));
928    }
929    /* Set clean send if sm.clean_out is not empty */
930    if (t->clean_send != -1) {
931        selector_add_raw_fd(s, t->clean_send,
932                            (buffer_empty(state_machine_get_buffer(&t->sm,
933                                                                   SM_CLEAN_OUT))
934                             ? SEL_EXCEPTS : SEL_SENDS));
935    }
936    /* Set dirty read if sm.dirty_in is not full */
937    if (t->dirty_read != -1) {
938        selector_add_raw_fd(s, t->dirty_read,
939                            (buffer_full(state_machine_get_buffer(&t->sm,
940                                                                  SM_DIRTY_IN))
941                             ? SEL_EXCEPTS : SEL_READS));
942    }
943    /* Set dirty send if sm.dirty_out is not empty */
944    if (t->dirty_send != -1) {
945        selector_add_raw_fd(s, t->dirty_send,
946                            (buffer_empty(state_machine_get_buffer(&t->sm,
947                                                                   SM_DIRTY_OUT))
948                             ? SEL_EXCEPTS : SEL_SENDS));
949    }
950}
951
952static int selector_select(tunala_selector_t * selector)
953{
954    memcpy(&selector->last_selected, &selector->next_select,
955           sizeof(select_sets_t));
956    selector_sets_init(&selector->next_select);
957    return select(selector->last_selected.max,
958                  &selector->last_selected.reads,
959                  &selector->last_selected.sends,
960                  &selector->last_selected.excepts, NULL);
961}
962
963/*
964 * This returns -1 for error, 0 for no new connections, or 1 for success, in
965 * which case *newfd is populated.
966 */
967static int selector_get_listener(tunala_selector_t * selector, int fd,
968                                 int *newfd)
969{
970    if (FD_ISSET(fd, &selector->last_selected.excepts))
971        return -1;
972    if (!FD_ISSET(fd, &selector->last_selected.reads))
973        return 0;
974    if ((*newfd = ip_accept_connection(fd)) == -1)
975        return -1;
976    return 1;
977}
978
979/************************/
980/* "Tunala" world stuff */
981/************************/
982
983static int tunala_world_make_room(tunala_world_t * world)
984{
985    unsigned int newsize;
986    tunala_item_t *newarray;
987
988    if (world->tunnels_used < world->tunnels_size)
989        return 1;
990    newsize = (world->tunnels_size == 0 ? 16 :
991               ((world->tunnels_size * 3) / 2));
992    if ((newarray = malloc(newsize * sizeof(tunala_item_t))) == NULL)
993        return 0;
994    memset(newarray, 0, newsize * sizeof(tunala_item_t));
995    if (world->tunnels_used > 0)
996        memcpy(newarray, world->tunnels,
997               world->tunnels_used * sizeof(tunala_item_t));
998    if (world->tunnels_size > 0)
999        free(world->tunnels);
1000    /* migrate */
1001    world->tunnels = newarray;
1002    world->tunnels_size = newsize;
1003    return 1;
1004}
1005
1006static int tunala_world_new_item(tunala_world_t * world, int fd,
1007                                 const char *ip, unsigned short port,
1008                                 int flipped)
1009{
1010    tunala_item_t *item;
1011    int newfd;
1012    SSL *new_ssl = NULL;
1013
1014    if (!tunala_world_make_room(world))
1015        return 0;
1016    if ((new_ssl = SSL_new(world->ssl_ctx)) == NULL) {
1017        fprintf(stderr, "Error creating new SSL\n");
1018        ERR_print_errors_fp(stderr);
1019        return 0;
1020    }
1021    item = world->tunnels + (world->tunnels_used++);
1022    state_machine_init(&item->sm);
1023    item->clean_read = item->clean_send =
1024        item->dirty_read = item->dirty_send = -1;
1025    if ((newfd = ip_create_connection_split(ip, port)) == -1)
1026        goto err;
1027    /*
1028     * Which way round? If we're a server, "fd" is the dirty side and the
1029     * connection we open is the clean one. For a client, it's the other way
1030     * around. Unless, of course, we're "flipped" in which case everything
1031     * gets reversed. :-)
1032     */
1033    if ((world->server_mode && !flipped) || (!world->server_mode && flipped)) {
1034        item->dirty_read = item->dirty_send = fd;
1035        item->clean_read = item->clean_send = newfd;
1036    } else {
1037        item->clean_read = item->clean_send = fd;
1038        item->dirty_read = item->dirty_send = newfd;
1039    }
1040    /*
1041     * We use the SSL's "app_data" to indicate a call-back induced "kill"
1042     */
1043    SSL_set_app_data(new_ssl, NULL);
1044    if (!state_machine_set_SSL(&item->sm, new_ssl, world->server_mode))
1045        goto err;
1046    return 1;
1047 err:
1048    tunala_world_del_item(world, world->tunnels_used - 1);
1049    return 0;
1050
1051}
1052
1053static void tunala_world_del_item(tunala_world_t * world, unsigned int idx)
1054{
1055    tunala_item_t *item = world->tunnels + idx;
1056    if (item->clean_read != -1)
1057        close(item->clean_read);
1058    if (item->clean_send != item->clean_read)
1059        close(item->clean_send);
1060    item->clean_read = item->clean_send = -1;
1061    if (item->dirty_read != -1)
1062        close(item->dirty_read);
1063    if (item->dirty_send != item->dirty_read)
1064        close(item->dirty_send);
1065    item->dirty_read = item->dirty_send = -1;
1066    state_machine_close(&item->sm);
1067    /* OK, now we fix the item array */
1068    if (idx + 1 < world->tunnels_used)
1069        /* We need to scroll entries to the left */
1070        memmove(world->tunnels + idx,
1071                world->tunnels + (idx + 1),
1072                (world->tunnels_used - (idx + 1)) * sizeof(tunala_item_t));
1073    world->tunnels_used--;
1074}
1075
1076static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item)
1077{
1078    int c_r, c_s, d_r, d_s;     /* Four boolean flags */
1079
1080    /* Take ourselves out of the gene-pool if there was an except */
1081    if ((item->clean_read != -1) && FD_ISSET(item->clean_read,
1082                                             &selector->
1083                                             last_selected.excepts))
1084        return 0;
1085    if ((item->clean_send != -1) && FD_ISSET(item->clean_send,
1086                                             &selector->
1087                                             last_selected.excepts))
1088        return 0;
1089    if ((item->dirty_read != -1) && FD_ISSET(item->dirty_read,
1090                                             &selector->
1091                                             last_selected.excepts))
1092        return 0;
1093    if ((item->dirty_send != -1) && FD_ISSET(item->dirty_send,
1094                                             &selector->
1095                                             last_selected.excepts))
1096        return 0;
1097    /* Grab our 4 IO flags */
1098    c_r = c_s = d_r = d_s = 0;
1099    if (item->clean_read != -1)
1100        c_r = FD_ISSET(item->clean_read, &selector->last_selected.reads);
1101    if (item->clean_send != -1)
1102        c_s = FD_ISSET(item->clean_send, &selector->last_selected.sends);
1103    if (item->dirty_read != -1)
1104        d_r = FD_ISSET(item->dirty_read, &selector->last_selected.reads);
1105    if (item->dirty_send != -1)
1106        d_s = FD_ISSET(item->dirty_send, &selector->last_selected.sends);
1107    /* If no IO has happened for us, skip needless data looping */
1108    if (!c_r && !c_s && !d_r && !d_s)
1109        return 1;
1110    if (c_r)
1111        c_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1112                                                       SM_CLEAN_IN),
1113                              item->clean_read) <= 0);
1114    if (c_s)
1115        c_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1116                                                     SM_CLEAN_OUT),
1117                            item->clean_send) <= 0);
1118    if (d_r)
1119        d_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1120                                                       SM_DIRTY_IN),
1121                              item->dirty_read) <= 0);
1122    if (d_s)
1123        d_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1124                                                     SM_DIRTY_OUT),
1125                            item->dirty_send) <= 0);
1126    /* If any of the flags is non-zero, that means they need closing */
1127    if (c_r) {
1128        close(item->clean_read);
1129        if (item->clean_send == item->clean_read)
1130            item->clean_send = -1;
1131        item->clean_read = -1;
1132    }
1133    if (c_s && (item->clean_send != -1)) {
1134        close(item->clean_send);
1135        if (item->clean_send == item->clean_read)
1136            item->clean_read = -1;
1137        item->clean_send = -1;
1138    }
1139    if (d_r) {
1140        close(item->dirty_read);
1141        if (item->dirty_send == item->dirty_read)
1142            item->dirty_send = -1;
1143        item->dirty_read = -1;
1144    }
1145    if (d_s && (item->dirty_send != -1)) {
1146        close(item->dirty_send);
1147        if (item->dirty_send == item->dirty_read)
1148            item->dirty_read = -1;
1149        item->dirty_send = -1;
1150    }
1151    /*
1152     * This function name is attributed to the term donated by David Schwartz
1153     * on openssl-dev, message-ID:
1154     * <NCBBLIEPOCbmasEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
1155     */
1156    if (!state_machine_churn(&item->sm))
1157        /*
1158         * If the SSL closes, it will also zero-out the _in buffers and will
1159         * in future process just outgoing data. As and when the outgoing
1160         * data has gone, it will return zero here to tell us to bail out.
1161         */
1162        return 0;
1163    /* Otherwise, we return zero if both sides are dead. */
1164    if (((item->clean_read == -1) || (item->clean_send == -1)) &&
1165        ((item->dirty_read == -1) || (item->dirty_send == -1)))
1166        return 0;
1167    /*
1168     * If only one side closed, notify the SSL of this so it can take
1169     * appropriate action.
1170     */
1171    if ((item->clean_read == -1) || (item->clean_send == -1)) {
1172        if (!state_machine_close_clean(&item->sm))
1173            return 0;
1174    }
1175    if ((item->dirty_read == -1) || (item->dirty_send == -1)) {
1176        if (!state_machine_close_dirty(&item->sm))
1177            return 0;
1178    }
1179    return 1;
1180}
1181