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_new()) || !DH_generate_parameters_ex(dh
, 512,
753 fprintf(stderr
, "error!\n");
758 fprintf(stderr
, "complete\n");
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",
767 dh
= PEM_read_DHparams(fp
, NULL
, NULL
, NULL
);
770 fprintf(stderr
, "Error, could not parse DH parameters from '%s'\n",
774 fprintf(stderr
, "Info, using DH parameters from file '%s'\n", dh_file
);
776 SSL_CTX_set_tmp_dh(ctx
, dh
);
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
,
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
)
791 SSL_CTX
*ctx
= NULL
, *ret
= NULL
;
792 const SSL_METHOD
*meth
;
795 OpenSSL_add_ssl_algorithms();
796 SSL_load_error_strings();
798 meth
= (server_mode
? SSLv23_server_method() : SSLv23_client_method());
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
);
808 if (!ENGINE_set_default(e
, ENGINE_METHOD_ALL
)) {
809 fprintf(stderr
, "Error assigning '%s' engine, openssl "
810 "errors follow\n", engine_id
);
815 if ((ctx
= SSL_CTX_new(meth
)) == NULL
)
819 if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx
),
821 fprintf(stderr
, "Error loading CA cert(s) in '%s'\n", CAfile
);
824 fprintf(stderr
, "Info, operating with CA cert(s) in '%s'\n", CAfile
);
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");
833 if ((cert
|| key
) && !ctx_set_cert(ctx
, cert
, key
))
836 if ((dcert
|| dkey
) && !ctx_set_cert(ctx
, dcert
, dkey
))
838 /* temporary RSA key generation */
840 SSL_CTX_set_tmp_rsa_callback(ctx
, cb_generate_tmp_rsa
);
844 if (!SSL_CTX_set_cipher_list(ctx
, cipher_list
)) {
845 fprintf(stderr
, "Error setting cipher list '%s'\n", cipher_list
);
848 fprintf(stderr
, "Info, set cipher list '%s'\n", cipher_list
);
850 fprintf(stderr
, "Info, operating with default cipher list\n");
852 /* dh_file & dh_special */
853 if ((dh_file
|| dh_special
) && !ctx_set_dh(ctx
, dh_file
, dh_special
))
857 SSL_CTX_set_options(ctx
, ctx_options
);
859 /* out_state (output of SSL handshake states to screen). */
861 cb_ssl_info_set_output(stderr
);
864 if (out_verify
> 0) {
865 cb_ssl_verify_set_output(stderr
);
866 cb_ssl_verify_set_level(out_verify
);
870 cb_ssl_verify_set_depth(verify_depth
);
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
);
878 ERR_print_errors_fp(stderr
);
889 static void selector_sets_init(select_sets_t
* s
)
894 FD_ZERO(&s
->excepts
);
897 static void selector_init(tunala_selector_t
* selector
)
899 selector_sets_init(&selector
->last_selected
);
900 selector_sets_init(&selector
->next_select
);
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
)
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
);
914 if (s
->next_select
.max
< (fd
+ 1))
915 s
->next_select
.max
= fd
+ 1;
918 static void selector_add_listener(tunala_selector_t
* selector
, int fd
)
920 selector_add_raw_fd(selector
, fd
, SEL_READS
);
923 static void selector_add_tunala(tunala_selector_t
* s
, tunala_item_t
* t
)
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
,
930 ? SEL_EXCEPTS
: SEL_READS
));
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
,
937 ? SEL_EXCEPTS
: SEL_SENDS
));
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
,
944 ? SEL_EXCEPTS
: SEL_READS
));
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
,
951 ? SEL_EXCEPTS
: SEL_SENDS
));
955 static int selector_select(tunala_selector_t
* selector
)
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
);
967 * This returns -1 for error, 0 for no new connections, or 1 for success, in
968 * which case *newfd is populated.
970 static int selector_get_listener(tunala_selector_t
* selector
, int fd
,
973 if (FD_ISSET(fd
, &selector
->last_selected
.excepts
))
975 if (!FD_ISSET(fd
, &selector
->last_selected
.reads
))
977 if ((*newfd
= ip_accept_connection(fd
)) == -1)
982 /************************/
983 /* "Tunala" world stuff */
984 /************************/
986 static int tunala_world_make_room(tunala_world_t
* world
)
988 unsigned int newsize
;
989 tunala_item_t
*newarray
;
991 if (world
->tunnels_used
< world
->tunnels_size
)
993 newsize
= (world
->tunnels_size
== 0 ? 16 :
994 ((world
->tunnels_size
* 3) / 2));
995 if ((newarray
= malloc(newsize
* sizeof(tunala_item_t
))) == NULL
)
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
);
1004 world
->tunnels
= newarray
;
1005 world
->tunnels_size
= newsize
;
1009 static int tunala_world_new_item(tunala_world_t
* world
, int fd
,
1010 const char *ip
, unsigned short port
,
1013 tunala_item_t
*item
;
1015 SSL
*new_ssl
= NULL
;
1017 if (!tunala_world_make_room(world
))
1019 if ((new_ssl
= SSL_new(world
->ssl_ctx
)) == NULL
) {
1020 fprintf(stderr
, "Error creating new SSL\n");
1021 ERR_print_errors_fp(stderr
);
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)
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. :-)
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
;
1040 item
->clean_read
= item
->clean_send
= fd
;
1041 item
->dirty_read
= item
->dirty_send
= newfd
;
1044 * We use the SSL's "app_data" to indicate a call-back induced "kill"
1046 SSL_set_app_data(new_ssl
, NULL
);
1047 if (!state_machine_set_SSL(&item
->sm
, new_ssl
, world
->server_mode
))
1051 tunala_world_del_item(world
, world
->tunnels_used
- 1);
1056 static void tunala_world_del_item(tunala_world_t
* world
, unsigned int idx
)
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
--;
1079 static int tunala_item_io(tunala_selector_t
* selector
, tunala_item_t
* item
)
1081 int c_r
, c_s
, d_r
, d_s
; /* Four boolean flags */
1083 /* Take ourselves out of the gene-pool if there was an except */
1084 if ((item
->clean_read
!= -1) && FD_ISSET(item
->clean_read
,
1086 last_selected
.excepts
))
1088 if ((item
->clean_send
!= -1) && FD_ISSET(item
->clean_send
,
1090 last_selected
.excepts
))
1092 if ((item
->dirty_read
!= -1) && FD_ISSET(item
->dirty_read
,
1094 last_selected
.excepts
))
1096 if ((item
->dirty_send
!= -1) && FD_ISSET(item
->dirty_send
,
1098 last_selected
.excepts
))
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
)
1114 c_r
= (buffer_from_fd(state_machine_get_buffer(&item
->sm
,
1116 item
->clean_read
) <= 0);
1118 c_s
= (buffer_to_fd(state_machine_get_buffer(&item
->sm
,
1120 item
->clean_send
) <= 0);
1122 d_r
= (buffer_from_fd(state_machine_get_buffer(&item
->sm
,
1124 item
->dirty_read
) <= 0);
1126 d_s
= (buffer_to_fd(state_machine_get_buffer(&item
->sm
,
1128 item
->dirty_send
) <= 0);
1129 /* If any of the flags is non-zero, that means they need closing */
1131 close(item
->clean_read
);
1132 if (item
->clean_send
== item
->clean_read
)
1133 item
->clean_send
= -1;
1134 item
->clean_read
= -1;
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;
1143 close(item
->dirty_read
);
1144 if (item
->dirty_send
== item
->dirty_read
)
1145 item
->dirty_send
= -1;
1146 item
->dirty_read
= -1;
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;
1155 * This function name is attributed to the term donated by David Schwartz
1156 * on openssl-dev, message-ID:
1157 * <NCBBLIEPOCbmasEKBEAKEEDGLIAA.davids@webmaster.com>. :-)
1159 if (!state_machine_churn(&item
->sm
))
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.
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)))
1171 * If only one side closed, notify the SSL of this so it can take
1172 * appropriate action.
1174 if ((item
->clean_read
== -1) || (item
->clean_send
== -1)) {
1175 if (!state_machine_close_clean(&item
->sm
))
1178 if ((item
->dirty_read
== -1) || (item
->dirty_send
== -1)) {
1179 if (!state_machine_close_dirty(&item
->sm
))