11a7c5bb1497c5acda050b0c09713dfbfcfb746e
[openssl.git] / demos / tunala / tunala.c
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  */
18 typedef 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  */
45 typedef 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;
50 typedef 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  */
60 typedef 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
85 static 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);
94 static void selector_init(tunala_selector_t * selector);
95 static void selector_add_listener(tunala_selector_t * selector, int fd);
96 static void selector_add_tunala(tunala_selector_t * selector,
97                                 tunala_item_t * t);
98 static 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  */
103 static int selector_get_listener(tunala_selector_t * selector, int fd,
104                                  int *newfd);
105 static int tunala_world_new_item(tunala_world_t * world, int fd,
106                                  const char *ip, unsigned short port,
107                                  int flipped);
108 static void tunala_world_del_item(tunala_world_t * world, unsigned int idx);
109 static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item);
110
111 /*********************************************/
112 /* MAIN FUNCTION (and its utility functions) */
113 /*********************************************/
114
115 static const char *def_proxyhost = "127.0.0.1:443";
116 static const char *def_listenhost = "127.0.0.1:8080";
117 static int def_max_tunnels = 50;
118 static const char *def_cacert = NULL;
119 static const char *def_cert = NULL;
120 static const char *def_key = NULL;
121 static const char *def_dcert = NULL;
122 static const char *def_dkey = NULL;
123 static const char *def_engine_id = NULL;
124 static int def_server_mode = 0;
125 static int def_flipped = 0;
126 static const char *def_cipher_list = NULL;
127 static const char *def_dh_file = NULL;
128 static const char *def_dh_special = NULL;
129 static int def_tmp_rsa = 1;
130 static int def_ctx_options = 0;
131 static int def_verify_mode = 0;
132 static unsigned int def_verify_depth = 10;
133 static int def_out_state = 0;
134 static unsigned int def_out_verify = 0;
135 static int def_out_totals = 0;
136 static int def_out_conns = 0;
137
138 static 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  */
199 static 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
208 static 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  */
216 static 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() */
230 static 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
240 static int err_str0(const char *str0)
241 {
242     fprintf(stderr, "%s\n", str0);
243     return 1;
244 }
245
246 static int err_str1(const char *fmt, const char *str1)
247 {
248     fprintf(stderr, fmt, str1);
249     fprintf(stderr, "\n");
250     return 1;
251 }
252
253 static 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
265 static 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
277 static 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
288 static 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
300 static 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 */
313 static const char *io_stats_dirty =
314     "    SSL traffic;   %8lu bytes in, %8lu bytes out\n";
315 static const char *io_stats_clean =
316     "    clear traffic; %8lu bytes in, %8lu bytes out\n";
317
318 int 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
657 static 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
725 static 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_new()) || !DH_generate_parameters_ex(dh, 512,
751                                                            DH_GENERATOR_5,
752                                                            NULL)) {
753             fprintf(stderr, "error!\n");
754             if (dh)
755                 DH_free(dh);
756             return 0;
757         }
758         fprintf(stderr, "complete\n");
759         goto do_it;
760     }
761     /* So, we're loading dh_file */
762     if ((fp = fopen(dh_file, "r")) == NULL) {
763         fprintf(stderr, "Error, couldn't open '%s' for DH parameters\n",
764                 dh_file);
765         return 0;
766     }
767     dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
768     fclose(fp);
769     if (dh == NULL) {
770         fprintf(stderr, "Error, could not parse DH parameters from '%s'\n",
771                 dh_file);
772         return 0;
773     }
774     fprintf(stderr, "Info, using DH parameters from file '%s'\n", dh_file);
775  do_it:
776     SSL_CTX_set_tmp_dh(ctx, dh);
777     DH_free(dh);
778     return 1;
779 }
780
781 static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id,
782                                    const char *CAfile, const char *cert,
783                                    const char *key, const char *dcert,
784                                    const char *dkey, const char *cipher_list,
785                                    const char *dh_file,
786                                    const char *dh_special, int tmp_rsa,
787                                    int ctx_options, int out_state,
788                                    int out_verify, int verify_mode,
789                                    unsigned int verify_depth)
790 {
791     SSL_CTX *ctx = NULL, *ret = NULL;
792     const SSL_METHOD *meth;
793     ENGINE *e = NULL;
794
795     OpenSSL_add_ssl_algorithms();
796     SSL_load_error_strings();
797
798     meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());
799     if (meth == NULL)
800         goto err;
801     if (engine_id) {
802         ENGINE_load_builtin_engines();
803         if ((e = ENGINE_by_id(engine_id)) == NULL) {
804             fprintf(stderr, "Error obtaining '%s' engine, openssl "
805                     "errors follow\n", engine_id);
806             goto err;
807         }
808         if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
809             fprintf(stderr, "Error assigning '%s' engine, openssl "
810                     "errors follow\n", engine_id);
811             goto err;
812         }
813         ENGINE_free(e);
814     }
815     if ((ctx = SSL_CTX_new(meth)) == NULL)
816         goto err;
817     /* cacert */
818     if (CAfile) {
819         if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),
820                                        CAfile, NULL)) {
821             fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile);
822             goto err;
823         }
824         fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile);
825     } else
826         fprintf(stderr, "Info, operating without a CA cert(-list)\n");
827     if (!SSL_CTX_set_default_verify_paths(ctx)) {
828         fprintf(stderr, "Error setting default verify paths\n");
829         goto err;
830     }
831
832     /* cert and key */
833     if ((cert || key) && !ctx_set_cert(ctx, cert, key))
834         goto err;
835     /* dcert and dkey */
836     if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))
837         goto err;
838     /* temporary RSA key generation */
839     if (tmp_rsa)
840         SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa);
841
842     /* cipher_list */
843     if (cipher_list) {
844         if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
845             fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list);
846             goto err;
847         }
848         fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);
849     } else
850         fprintf(stderr, "Info, operating with default cipher list\n");
851
852     /* dh_file & dh_special */
853     if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))
854         goto err;
855
856     /* ctx_options */
857     SSL_CTX_set_options(ctx, ctx_options);
858
859     /* out_state (output of SSL handshake states to screen). */
860     if (out_state)
861         cb_ssl_info_set_output(stderr);
862
863     /* out_verify */
864     if (out_verify > 0) {
865         cb_ssl_verify_set_output(stderr);
866         cb_ssl_verify_set_level(out_verify);
867     }
868
869     /* verify_depth */
870     cb_ssl_verify_set_depth(verify_depth);
871
872     /* Success! (includes setting verify_mode) */
873     SSL_CTX_set_info_callback(ctx, cb_ssl_info);
874     SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify);
875     ret = ctx;
876  err:
877     if (!ret) {
878         ERR_print_errors_fp(stderr);
879         if (ctx)
880             SSL_CTX_free(ctx);
881     }
882     return ret;
883 }
884
885 /*****************/
886 /* Selector bits */
887 /*****************/
888
889 static void selector_sets_init(select_sets_t * s)
890 {
891     s->max = 0;
892     FD_ZERO(&s->reads);
893     FD_ZERO(&s->sends);
894     FD_ZERO(&s->excepts);
895 }
896
897 static void selector_init(tunala_selector_t * selector)
898 {
899     selector_sets_init(&selector->last_selected);
900     selector_sets_init(&selector->next_select);
901 }
902
903 #define SEL_EXCEPTS 0x00
904 #define SEL_READS   0x01
905 #define SEL_SENDS   0x02
906 static void selector_add_raw_fd(tunala_selector_t * s, int fd, int flags)
907 {
908     FD_SET(fd, &s->next_select.excepts);
909     if (flags & SEL_READS)
910         FD_SET(fd, &s->next_select.reads);
911     if (flags & SEL_SENDS)
912         FD_SET(fd, &s->next_select.sends);
913     /* Adjust "max" */
914     if (s->next_select.max < (fd + 1))
915         s->next_select.max = fd + 1;
916 }
917
918 static void selector_add_listener(tunala_selector_t * selector, int fd)
919 {
920     selector_add_raw_fd(selector, fd, SEL_READS);
921 }
922
923 static void selector_add_tunala(tunala_selector_t * s, tunala_item_t * t)
924 {
925     /* Set clean read if sm.clean_in is not full */
926     if (t->clean_read != -1) {
927         selector_add_raw_fd(s, t->clean_read,
928                             (buffer_full(state_machine_get_buffer(&t->sm,
929                                                                   SM_CLEAN_IN))
930                              ? SEL_EXCEPTS : SEL_READS));
931     }
932     /* Set clean send if sm.clean_out is not empty */
933     if (t->clean_send != -1) {
934         selector_add_raw_fd(s, t->clean_send,
935                             (buffer_empty(state_machine_get_buffer(&t->sm,
936                                                                    SM_CLEAN_OUT))
937                              ? SEL_EXCEPTS : SEL_SENDS));
938     }
939     /* Set dirty read if sm.dirty_in is not full */
940     if (t->dirty_read != -1) {
941         selector_add_raw_fd(s, t->dirty_read,
942                             (buffer_full(state_machine_get_buffer(&t->sm,
943                                                                   SM_DIRTY_IN))
944                              ? SEL_EXCEPTS : SEL_READS));
945     }
946     /* Set dirty send if sm.dirty_out is not empty */
947     if (t->dirty_send != -1) {
948         selector_add_raw_fd(s, t->dirty_send,
949                             (buffer_empty(state_machine_get_buffer(&t->sm,
950                                                                    SM_DIRTY_OUT))
951                              ? SEL_EXCEPTS : SEL_SENDS));
952     }
953 }
954
955 static int selector_select(tunala_selector_t * selector)
956 {
957     memcpy(&selector->last_selected, &selector->next_select,
958            sizeof(select_sets_t));
959     selector_sets_init(&selector->next_select);
960     return select(selector->last_selected.max,
961                   &selector->last_selected.reads,
962                   &selector->last_selected.sends,
963                   &selector->last_selected.excepts, NULL);
964 }
965
966 /*
967  * This returns -1 for error, 0 for no new connections, or 1 for success, in
968  * which case *newfd is populated.
969  */
970 static int selector_get_listener(tunala_selector_t * selector, int fd,
971                                  int *newfd)
972 {
973     if (FD_ISSET(fd, &selector->last_selected.excepts))
974         return -1;
975     if (!FD_ISSET(fd, &selector->last_selected.reads))
976         return 0;
977     if ((*newfd = ip_accept_connection(fd)) == -1)
978         return -1;
979     return 1;
980 }
981
982 /************************/
983 /* "Tunala" world stuff */
984 /************************/
985
986 static int tunala_world_make_room(tunala_world_t * world)
987 {
988     unsigned int newsize;
989     tunala_item_t *newarray;
990
991     if (world->tunnels_used < world->tunnels_size)
992         return 1;
993     newsize = (world->tunnels_size == 0 ? 16 :
994                ((world->tunnels_size * 3) / 2));
995     if ((newarray = malloc(newsize * sizeof(tunala_item_t))) == NULL)
996         return 0;
997     memset(newarray, 0, newsize * sizeof(tunala_item_t));
998     if (world->tunnels_used > 0)
999         memcpy(newarray, world->tunnels,
1000                world->tunnels_used * sizeof(tunala_item_t));
1001     if (world->tunnels_size > 0)
1002         free(world->tunnels);
1003     /* migrate */
1004     world->tunnels = newarray;
1005     world->tunnels_size = newsize;
1006     return 1;
1007 }
1008
1009 static int tunala_world_new_item(tunala_world_t * world, int fd,
1010                                  const char *ip, unsigned short port,
1011                                  int flipped)
1012 {
1013     tunala_item_t *item;
1014     int newfd;
1015     SSL *new_ssl = NULL;
1016
1017     if (!tunala_world_make_room(world))
1018         return 0;
1019     if ((new_ssl = SSL_new(world->ssl_ctx)) == NULL) {
1020         fprintf(stderr, "Error creating new SSL\n");
1021         ERR_print_errors_fp(stderr);
1022         return 0;
1023     }
1024     item = world->tunnels + (world->tunnels_used++);
1025     state_machine_init(&item->sm);
1026     item->clean_read = item->clean_send =
1027         item->dirty_read = item->dirty_send = -1;
1028     if ((newfd = ip_create_connection_split(ip, port)) == -1)
1029         goto err;
1030     /*
1031      * Which way round? If we're a server, "fd" is the dirty side and the
1032      * connection we open is the clean one. For a client, it's the other way
1033      * around. Unless, of course, we're "flipped" in which case everything
1034      * gets reversed. :-)
1035      */
1036     if ((world->server_mode && !flipped) || (!world->server_mode && flipped)) {
1037         item->dirty_read = item->dirty_send = fd;
1038         item->clean_read = item->clean_send = newfd;
1039     } else {
1040         item->clean_read = item->clean_send = fd;
1041         item->dirty_read = item->dirty_send = newfd;
1042     }
1043     /*
1044      * We use the SSL's "app_data" to indicate a call-back induced "kill"
1045      */
1046     SSL_set_app_data(new_ssl, NULL);
1047     if (!state_machine_set_SSL(&item->sm, new_ssl, world->server_mode))
1048         goto err;
1049     return 1;
1050  err:
1051     tunala_world_del_item(world, world->tunnels_used - 1);
1052     return 0;
1053
1054 }
1055
1056 static void tunala_world_del_item(tunala_world_t * world, unsigned int idx)
1057 {
1058     tunala_item_t *item = world->tunnels + idx;
1059     if (item->clean_read != -1)
1060         close(item->clean_read);
1061     if (item->clean_send != item->clean_read)
1062         close(item->clean_send);
1063     item->clean_read = item->clean_send = -1;
1064     if (item->dirty_read != -1)
1065         close(item->dirty_read);
1066     if (item->dirty_send != item->dirty_read)
1067         close(item->dirty_send);
1068     item->dirty_read = item->dirty_send = -1;
1069     state_machine_close(&item->sm);
1070     /* OK, now we fix the item array */
1071     if (idx + 1 < world->tunnels_used)
1072         /* We need to scroll entries to the left */
1073         memmove(world->tunnels + idx,
1074                 world->tunnels + (idx + 1),
1075                 (world->tunnels_used - (idx + 1)) * sizeof(tunala_item_t));
1076     world->tunnels_used--;
1077 }
1078
1079 static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item)
1080 {
1081     int c_r, c_s, d_r, d_s;     /* Four boolean flags */
1082
1083     /* Take ourselves out of the gene-pool if there was an except */
1084     if ((item->clean_read != -1) && FD_ISSET(item->clean_read,
1085                                              &selector->
1086                                              last_selected.excepts))
1087         return 0;
1088     if ((item->clean_send != -1) && FD_ISSET(item->clean_send,
1089                                              &selector->
1090                                              last_selected.excepts))
1091         return 0;
1092     if ((item->dirty_read != -1) && FD_ISSET(item->dirty_read,
1093                                              &selector->
1094                                              last_selected.excepts))
1095         return 0;
1096     if ((item->dirty_send != -1) && FD_ISSET(item->dirty_send,
1097                                              &selector->
1098                                              last_selected.excepts))
1099         return 0;
1100     /* Grab our 4 IO flags */
1101     c_r = c_s = d_r = d_s = 0;
1102     if (item->clean_read != -1)
1103         c_r = FD_ISSET(item->clean_read, &selector->last_selected.reads);
1104     if (item->clean_send != -1)
1105         c_s = FD_ISSET(item->clean_send, &selector->last_selected.sends);
1106     if (item->dirty_read != -1)
1107         d_r = FD_ISSET(item->dirty_read, &selector->last_selected.reads);
1108     if (item->dirty_send != -1)
1109         d_s = FD_ISSET(item->dirty_send, &selector->last_selected.sends);
1110     /* If no IO has happened for us, skip needless data looping */
1111     if (!c_r && !c_s && !d_r && !d_s)
1112         return 1;
1113     if (c_r)
1114         c_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1115                                                        SM_CLEAN_IN),
1116                               item->clean_read) <= 0);
1117     if (c_s)
1118         c_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1119                                                      SM_CLEAN_OUT),
1120                             item->clean_send) <= 0);
1121     if (d_r)
1122         d_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1123                                                        SM_DIRTY_IN),
1124                               item->dirty_read) <= 0);
1125     if (d_s)
1126         d_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1127                                                      SM_DIRTY_OUT),
1128                             item->dirty_send) <= 0);
1129     /* If any of the flags is non-zero, that means they need closing */
1130     if (c_r) {
1131         close(item->clean_read);
1132         if (item->clean_send == item->clean_read)
1133             item->clean_send = -1;
1134         item->clean_read = -1;
1135     }
1136     if (c_s && (item->clean_send != -1)) {
1137         close(item->clean_send);
1138         if (item->clean_send == item->clean_read)
1139             item->clean_read = -1;
1140         item->clean_send = -1;
1141     }
1142     if (d_r) {
1143         close(item->dirty_read);
1144         if (item->dirty_send == item->dirty_read)
1145             item->dirty_send = -1;
1146         item->dirty_read = -1;
1147     }
1148     if (d_s && (item->dirty_send != -1)) {
1149         close(item->dirty_send);
1150         if (item->dirty_send == item->dirty_read)
1151             item->dirty_read = -1;
1152         item->dirty_send = -1;
1153     }
1154     /*
1155      * This function name is attributed to the term donated by David Schwartz
1156      * on openssl-dev, message-ID:
1157      * <NCBBLIEPOCbmasEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
1158      */
1159     if (!state_machine_churn(&item->sm))
1160         /*
1161          * If the SSL closes, it will also zero-out the _in buffers and will
1162          * in future process just outgoing data. As and when the outgoing
1163          * data has gone, it will return zero here to tell us to bail out.
1164          */
1165         return 0;
1166     /* Otherwise, we return zero if both sides are dead. */
1167     if (((item->clean_read == -1) || (item->clean_send == -1)) &&
1168         ((item->dirty_read == -1) || (item->dirty_send == -1)))
1169         return 0;
1170     /*
1171      * If only one side closed, notify the SSL of this so it can take
1172      * appropriate action.
1173      */
1174     if ((item->clean_read == -1) || (item->clean_send == -1)) {
1175         if (!state_machine_close_clean(&item->sm))
1176             return 0;
1177     }
1178     if ((item->dirty_read == -1) || (item->dirty_send == -1)) {
1179         if (!state_machine_close_dirty(&item->sm))
1180             return 0;
1181     }
1182     return 1;
1183 }