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