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*"
5 /* Include our bits'n'pieces */
8 /********************************************/
9 /* Our local types that specify our "world" */
10 /********************************************/
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.
18 typedef struct _tunala_item_t {
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".
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
29 int dirty_read, dirty_send;
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.
35 int clean_read, clean_send;
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".
45 typedef struct _select_sets_t {
46 int max; /* As required as the first argument to
48 fd_set reads, sends, excepts; /* As passed to select() */
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 */
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).
60 typedef struct _tunala_world_t {
61 /* The file-descriptor we "listen" on for new connections */
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;
70 * Our SSL_CTX, which is configured as the SSL client or server and has
71 * the various cert-settings and callbacks configured.
75 * Simple flag with complex logic :-) Indicates whether we're an SSL
76 * server or an SSL client.
81 /*****************************/
82 /* Internal static functions */
83 /*****************************/
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,
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,
98 static int selector_select(tunala_selector_t * selector);
100 * This returns -1 for error, 0 for no new connections, or 1 for success, in
101 * which case *newfd is populated.
103 static int selector_get_listener(tunala_selector_t * selector, int fd,
105 static int tunala_world_new_item(tunala_world_t * world, int fd,
106 const char *ip, unsigned short port,
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);
111 /*********************************************/
112 /* MAIN FUNCTION (and its utility functions) */
113 /*********************************************/
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;
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"
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"
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"
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"
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";
196 * Default DH parameters for use with "-dh_special standard" ... stolen
197 * striaght from s_server.
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,
208 static unsigned char dh512_g[] = {
213 * And the function that parses the above "standard" parameters, again,
214 * straight out of s_server.
216 static DH *get_dh512(void)
220 if ((dh = DH_new()) == 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))
229 /* Various help/error messages used by main() */
230 static int usage(const char *errstr, int isunknownarg)
233 fprintf(stderr, "Error: unknown argument '%s'\n", errstr);
235 fprintf(stderr, "Error: %s\n", errstr);
236 fprintf(stderr, "%s\n", helpstring);
240 static int err_str0(const char *str0)
242 fprintf(stderr, "%s\n", str0);
246 static int err_str1(const char *fmt, const char *str1)
248 fprintf(stderr, fmt, str1);
249 fprintf(stderr, "\n");
253 static int parse_max_tunnels(const char *s, unsigned int *maxtunnels)
256 if (!int_strtoul(s, &l) || (l < 1) || (l > 1024)) {
257 fprintf(stderr, "Error, '%s' is an invalid value for "
261 *maxtunnels = (unsigned int)l;
265 static int parse_server_mode(const char *s, int *servermode)
268 if (!int_strtoul(s, &l) || (l > 1)) {
269 fprintf(stderr, "Error, '%s' is an invalid value for the "
273 *servermode = (int)l;
277 static int parse_dh_special(const char *s, const char **dh_special)
279 if ((strcmp(s, "NULL") == 0) || (strcmp(s, "generate") == 0) ||
280 (strcmp(s, "standard") == 0)) {
284 fprintf(stderr, "Error, '%s' is an invalid value for 'dh_special'\n", s);
288 static int parse_verify_level(const char *s, unsigned int *verify_level)
291 if (!int_strtoul(s, &l) || (l > 3)) {
292 fprintf(stderr, "Error, '%s' is an invalid value for "
296 *verify_level = (unsigned int)l;
300 static int parse_verify_depth(const char *s, unsigned int *verify_depth)
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);
308 *verify_depth = (unsigned int)l;
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";
318 int main(int argc, char *argv[])
322 tunala_world_t world;
323 tunala_item_t *t_item;
324 const char *proxy_ip;
325 unsigned short proxy_port;
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;
350 /* Parse command-line arguments */
355 if (strcmp(*argv, "-listen") == 0) {
357 return usage("-listen requires an argument", 0);
362 } else if (strcmp(*argv, "-proxy") == 0) {
364 return usage("-proxy requires an argument", 0);
369 } else if (strcmp(*argv, "-maxtunnels") == 0) {
371 return usage("-maxtunnels requires an argument", 0);
374 if (!parse_max_tunnels(*argv, &max_tunnels))
377 } else if (strcmp(*argv, "-cacert") == 0) {
379 return usage("-cacert requires an argument", 0);
382 if (strcmp(*argv, "NULL") == 0)
387 } else if (strcmp(*argv, "-cert") == 0) {
389 return usage("-cert requires an argument", 0);
392 if (strcmp(*argv, "NULL") == 0)
397 } else if (strcmp(*argv, "-key") == 0) {
399 return usage("-key requires an argument", 0);
402 if (strcmp(*argv, "NULL") == 0)
407 } else if (strcmp(*argv, "-dcert") == 0) {
409 return usage("-dcert requires an argument", 0);
412 if (strcmp(*argv, "NULL") == 0)
417 } else if (strcmp(*argv, "-dkey") == 0) {
419 return usage("-dkey requires an argument", 0);
422 if (strcmp(*argv, "NULL") == 0)
427 } else if (strcmp(*argv, "-engine") == 0) {
429 return usage("-engine requires an argument", 0);
434 } else if (strcmp(*argv, "-server") == 0) {
436 return usage("-server requires an argument", 0);
439 if (!parse_server_mode(*argv, &server_mode))
442 } else if (strcmp(*argv, "-flipped") == 0) {
444 return usage("-flipped requires an argument", 0);
447 if (!parse_server_mode(*argv, &flipped))
450 } else if (strcmp(*argv, "-cipher") == 0) {
452 return usage("-cipher requires an argument", 0);
457 } else if (strcmp(*argv, "-dh_file") == 0) {
459 return usage("-dh_file requires an argument", 0);
461 return usage("cannot mix -dh_file with " "-dh_special", 0);
466 } else if (strcmp(*argv, "-dh_special") == 0) {
468 return usage("-dh_special requires an argument", 0);
470 return usage("cannot mix -dh_file with " "-dh_special", 0);
473 if (!parse_dh_special(*argv, &dh_special))
476 } else if (strcmp(*argv, "-no_tmp_rsa") == 0) {
479 } else if (strcmp(*argv, "-no_ssl2") == 0) {
480 ctx_options |= SSL_OP_NO_SSLv2;
482 } else if (strcmp(*argv, "-no_ssl3") == 0) {
483 ctx_options |= SSL_OP_NO_SSLv3;
485 } else if (strcmp(*argv, "-no_tls1") == 0) {
486 ctx_options |= SSL_OP_NO_TLSv1;
488 } else if (strcmp(*argv, "-v_peer") == 0) {
489 verify_mode |= SSL_VERIFY_PEER;
491 } else if (strcmp(*argv, "-v_strict") == 0) {
492 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
494 } else if (strcmp(*argv, "-v_once") == 0) {
495 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
497 } else if (strcmp(*argv, "-v_depth") == 0) {
499 return usage("-v_depth requires an argument", 0);
502 if (!parse_verify_depth(*argv, &verify_depth))
505 } else if (strcmp(*argv, "-out_state") == 0) {
508 } else if (strcmp(*argv, "-out_verify") == 0) {
510 return usage("-out_verify requires an argument", 0);
513 if (!parse_verify_level(*argv, &out_verify))
516 } else if (strcmp(*argv, "-out_totals") == 0) {
519 } else if (strcmp(*argv, "-out_conns") == 0) {
522 } else if ((strcmp(*argv, "-h") == 0) ||
523 (strcmp(*argv, "-help") == 0) ||
524 (strcmp(*argv, "-?") == 0)) {
525 fprintf(stderr, "%s\n", helpstring);
528 return usage(*argv, 1);
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");
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);
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);
567 /* We're ready to 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)) {
578 if (errno != EINTR) {
579 fprintf(stderr, "selector_select returned a " "badness error.\n");
580 goto shouldnt_happen;
582 fprintf(stderr, "Warn, selector interrupted by a signal\n");
585 fprintf(stderr, "Warn, selector_select returned 0 - signal?" "?\n");
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) ==
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");
599 fprintf(stderr, "Info, new tunnel opened, now up to "
600 "%d\n", world.tunnels_used);
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.
608 t_item = world.tunnels;
609 while (loop < world.tunnels_used) {
610 if (!tunala_item_io(&world.selector, t_item)) {
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
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)));
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 :-)
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)));
636 tunala_world_del_item(&world, loop);
638 fprintf(stderr, "Info, tunnel closed, down to %d\n",
641 /* Move to the next item */
647 /* Should never get here */
657 static int ctx_set_cert(SSL_CTX *ctx, const char *cert, const char *key)
661 EVP_PKEY *pkey = NULL;
662 int toret = 0; /* Assume an error */
666 if ((fp = fopen(cert, "r")) == NULL) {
667 fprintf(stderr, "Error opening cert file '%s'\n", cert);
670 if (!PEM_read_X509(fp, &x509, NULL, NULL)) {
671 fprintf(stderr, "Error reading PEM cert from '%s'\n", cert);
674 if (!SSL_CTX_use_certificate(ctx, x509)) {
675 fprintf(stderr, "Error, cert in '%s' can not be used\n", cert);
678 /* Clear the FILE* for reuse in the "key" code */
681 fprintf(stderr, "Info, operating with cert in '%s'\n", cert);
683 * If a cert was given without matching key, we assume the same file
684 * contains the required key.
690 fprintf(stderr, "Error, can't specify a key without a "
691 "corresponding certificate\n");
693 fprintf(stderr, "Error, ctx_set_cert called with " "NULLs!\n");
698 if ((fp = fopen(key, "r")) == NULL) {
699 fprintf(stderr, "Error opening key file '%s'\n", key);
702 if (!PEM_read_PrivateKey(fp, &pkey, NULL, NULL)) {
703 fprintf(stderr, "Error reading PEM key from '%s'\n", key);
706 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
707 fprintf(stderr, "Error, key in '%s' can not be used\n", key);
710 fprintf(stderr, "Info, operating with key in '%s'\n", key);
712 fprintf(stderr, "Info, operating without a cert or key\n");
725 static int ctx_set_dh(SSL_CTX *ctx, const char *dh_file,
726 const char *dh_special)
732 if (strcmp(dh_special, "NULL") == 0)
734 if (strcmp(dh_special, "standard") == 0) {
735 if ((dh = get_dh512()) == NULL) {
736 fprintf(stderr, "Error, can't parse 'standard'"
740 fprintf(stderr, "Info, using 'standard' DH parameters\n");
743 if (strcmp(dh_special, "generate") != 0)
745 * This shouldn't happen - screening values is handled in main().
748 fprintf(stderr, "Info, generating DH parameters ... ");
750 if ((dh = DH_generate_parameters(512, DH_GENERATOR_5,
751 NULL, NULL)) == NULL) {
752 fprintf(stderr, "error!\n");
755 fprintf(stderr, "complete\n");
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",
764 dh = PEM_read_DHparams(fp, NULL, NULL, NULL);
767 fprintf(stderr, "Error, could not parse DH parameters from '%s'\n",
771 fprintf(stderr, "Info, using DH parameters from file '%s'\n", dh_file);
773 SSL_CTX_set_tmp_dh(ctx, dh);
778 static 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,
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)
788 SSL_CTX *ctx = NULL, *ret = NULL;
792 OpenSSL_add_ssl_algorithms();
793 SSL_load_error_strings();
795 meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method());
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);
805 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
806 fprintf(stderr, "Error assigning '%s' engine, openssl "
807 "errors follow\n", engine_id);
812 if ((ctx = SSL_CTX_new(meth)) == NULL)
816 if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx),
818 fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile);
821 fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile);
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");
830 if ((cert || key) && !ctx_set_cert(ctx, cert, key))
833 if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey))
835 /* temporary RSA key generation */
837 SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa);
841 if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) {
842 fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list);
845 fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list);
847 fprintf(stderr, "Info, operating with default cipher list\n");
849 /* dh_file & dh_special */
850 if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special))
854 SSL_CTX_set_options(ctx, ctx_options);
856 /* out_state (output of SSL handshake states to screen). */
858 cb_ssl_info_set_output(stderr);
861 if (out_verify > 0) {
862 cb_ssl_verify_set_output(stderr);
863 cb_ssl_verify_set_level(out_verify);
867 cb_ssl_verify_set_depth(verify_depth);
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);
875 ERR_print_errors_fp(stderr);
886 static void selector_sets_init(select_sets_t * s)
891 FD_ZERO(&s->excepts);
894 static void selector_init(tunala_selector_t * selector)
896 selector_sets_init(&selector->last_selected);
897 selector_sets_init(&selector->next_select);
900 #define SEL_EXCEPTS 0x00
901 #define SEL_READS 0x01
902 #define SEL_SENDS 0x02
903 static void selector_add_raw_fd(tunala_selector_t * s, int fd, int flags)
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);
911 if (s->next_select.max < (fd + 1))
912 s->next_select.max = fd + 1;
915 static void selector_add_listener(tunala_selector_t * selector, int fd)
917 selector_add_raw_fd(selector, fd, SEL_READS);
920 static void selector_add_tunala(tunala_selector_t * s, tunala_item_t * t)
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,
927 ? SEL_EXCEPTS : SEL_READS));
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,
934 ? SEL_EXCEPTS : SEL_SENDS));
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,
941 ? SEL_EXCEPTS : SEL_READS));
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,
948 ? SEL_EXCEPTS : SEL_SENDS));
952 static int selector_select(tunala_selector_t * selector)
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);
964 * This returns -1 for error, 0 for no new connections, or 1 for success, in
965 * which case *newfd is populated.
967 static int selector_get_listener(tunala_selector_t * selector, int fd,
970 if (FD_ISSET(fd, &selector->last_selected.excepts))
972 if (!FD_ISSET(fd, &selector->last_selected.reads))
974 if ((*newfd = ip_accept_connection(fd)) == -1)
979 /************************/
980 /* "Tunala" world stuff */
981 /************************/
983 static int tunala_world_make_room(tunala_world_t * world)
985 unsigned int newsize;
986 tunala_item_t *newarray;
988 if (world->tunnels_used < world->tunnels_size)
990 newsize = (world->tunnels_size == 0 ? 16 :
991 ((world->tunnels_size * 3) / 2));
992 if ((newarray = malloc(newsize * sizeof(tunala_item_t))) == NULL)
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);
1001 world->tunnels = newarray;
1002 world->tunnels_size = newsize;
1006 static int tunala_world_new_item(tunala_world_t * world, int fd,
1007 const char *ip, unsigned short port,
1010 tunala_item_t *item;
1012 SSL *new_ssl = NULL;
1014 if (!tunala_world_make_room(world))
1016 if ((new_ssl = SSL_new(world->ssl_ctx)) == NULL) {
1017 fprintf(stderr, "Error creating new SSL\n");
1018 ERR_print_errors_fp(stderr);
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)
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. :-)
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;
1037 item->clean_read = item->clean_send = fd;
1038 item->dirty_read = item->dirty_send = newfd;
1041 * We use the SSL's "app_data" to indicate a call-back induced "kill"
1043 SSL_set_app_data(new_ssl, NULL);
1044 if (!state_machine_set_SSL(&item->sm, new_ssl, world->server_mode))
1048 tunala_world_del_item(world, world->tunnels_used - 1);
1053 static void tunala_world_del_item(tunala_world_t * world, unsigned int idx)
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--;
1076 static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item)
1078 int c_r, c_s, d_r, d_s; /* Four boolean flags */
1080 /* Take ourselves out of the gene-pool if there was an except */
1081 if ((item->clean_read != -1) && FD_ISSET(item->clean_read,
1083 last_selected.excepts))
1085 if ((item->clean_send != -1) && FD_ISSET(item->clean_send,
1087 last_selected.excepts))
1089 if ((item->dirty_read != -1) && FD_ISSET(item->dirty_read,
1091 last_selected.excepts))
1093 if ((item->dirty_send != -1) && FD_ISSET(item->dirty_send,
1095 last_selected.excepts))
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)
1111 c_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1113 item->clean_read) <= 0);
1115 c_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1117 item->clean_send) <= 0);
1119 d_r = (buffer_from_fd(state_machine_get_buffer(&item->sm,
1121 item->dirty_read) <= 0);
1123 d_s = (buffer_to_fd(state_machine_get_buffer(&item->sm,
1125 item->dirty_send) <= 0);
1126 /* If any of the flags is non-zero, that means they need closing */
1128 close(item->clean_read);
1129 if (item->clean_send == item->clean_read)
1130 item->clean_send = -1;
1131 item->clean_read = -1;
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;
1140 close(item->dirty_read);
1141 if (item->dirty_send == item->dirty_read)
1142 item->dirty_send = -1;
1143 item->dirty_read = -1;
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;
1152 * This function name is attributed to the term donated by David Schwartz
1153 * on openssl-dev, message-ID:
1154 * <NCBBLIEPOCbmasEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
1156 if (!state_machine_churn(&item->sm))
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.
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)))
1168 * If only one side closed, notify the SSL of this so it can take
1169 * appropriate action.
1171 if ((item->clean_read == -1) || (item->clean_send == -1)) {
1172 if (!state_machine_close_clean(&item->sm))
1175 if ((item->dirty_read == -1) || (item->dirty_send == -1)) {
1176 if (!state_machine_close_dirty(&item->sm))