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