diff options
Diffstat (limited to 'demos/tunala/tunala.c')
-rw-r--r-- | demos/tunala/tunala.c | 1923 |
1 files changed, 998 insertions, 925 deletions
diff --git a/demos/tunala/tunala.c b/demos/tunala/tunala.c index e918cba2ce..2354b7a42d 100644 --- a/demos/tunala/tunala.c +++ b/demos/tunala/tunala.c @@ -1,65 +1,81 @@ #if defined(NO_BUFFER) || defined(NO_IP) || defined(NO_OPENSSL) -#error "Badness, NO_BUFFER, NO_IP or NO_OPENSSL is defined, turn them *off*" +# error "Badness, NO_BUFFER, NO_IP or NO_OPENSSL is defined, turn them *off*" #endif /* Include our bits'n'pieces */ #include "tunala.h" - /********************************************/ /* Our local types that specify our "world" */ /********************************************/ -/* These represent running "tunnels". Eg. if you wanted to do SSL in a - * "message-passing" scanario, the "int" file-descriptors might be replaced by - * thread or process IDs, and the "select" code might be replaced by message - * handling code. Whatever. */ +/* + * These represent running "tunnels". Eg. if you wanted to do SSL in a + * "message-passing" scanario, the "int" file-descriptors might be replaced + * by thread or process IDs, and the "select" code might be replaced by + * message handling code. Whatever. + */ typedef struct _tunala_item_t { - /* The underlying SSL state machine. This is a data-only processing unit - * and we communicate with it by talking to its four "buffers". */ - state_machine_t sm; - /* The file-descriptors for the "dirty" (encrypted) side of the SSL - * setup. In actuality, this is typically a socket and both values are - * identical. */ - int dirty_read, dirty_send; - /* The file-descriptors for the "clean" (unencrypted) side of the SSL - * setup. These could be stdin/stdout, a socket (both values the same), - * or whatever you like. */ - int clean_read, clean_send; + /* + * The underlying SSL state machine. This is a data-only processing unit + * and we communicate with it by talking to its four "buffers". + */ + state_machine_t sm; + /* + * The file-descriptors for the "dirty" (encrypted) side of the SSL + * setup. In actuality, this is typically a socket and both values are + * identical. + */ + int dirty_read, dirty_send; + /* + * The file-descriptors for the "clean" (unencrypted) side of the SSL + * setup. These could be stdin/stdout, a socket (both values the same), + * or whatever you like. + */ + int clean_read, clean_send; } tunala_item_t; -/* This structure is used as the data for running the main loop. Namely, in a +/* + * This structure is used as the data for running the main loop. Namely, in a * network format such as this, it is stuff for select() - but as pointed out, * when moving the real-world to somewhere else, this might be replaced by * something entirely different. It's basically the stuff that controls when - * it's time to do some "work". */ + * it's time to do some "work". + */ typedef struct _select_sets_t { - int max; /* As required as the first argument to select() */ - fd_set reads, sends, excepts; /* As passed to select() */ + int max; /* As required as the first argument to + * select() */ + fd_set reads, sends, excepts; /* As passed to select() */ } select_sets_t; typedef struct _tunala_selector_t { - select_sets_t last_selected; /* Results of the last select() */ - select_sets_t next_select; /* What we'll next select on */ + select_sets_t last_selected; /* Results of the last select() */ + select_sets_t next_select; /* What we'll next select on */ } tunala_selector_t; -/* This structure is *everything*. We do it to avoid the use of globals so that, - * for example, it would be easier to shift things around between async-IO, - * thread-based, or multi-fork()ed (or combinations thereof). */ +/* + * This structure is *everything*. We do it to avoid the use of globals so + * that, for example, it would be easier to shift things around between + * async-IO, thread-based, or multi-fork()ed (or combinations thereof). + */ typedef struct _tunala_world_t { - /* The file-descriptor we "listen" on for new connections */ - int listen_fd; - /* The array of tunnels */ - tunala_item_t *tunnels; - /* the number of tunnels in use and allocated, respectively */ - unsigned int tunnels_used, tunnels_size; - /* Our outside "loop" context stuff */ - tunala_selector_t selector; - /* Our SSL_CTX, which is configured as the SSL client or server and has - * the various cert-settings and callbacks configured. */ - SSL_CTX *ssl_ctx; - /* Simple flag with complex logic :-) Indicates whether we're an SSL - * server or an SSL client. */ - int server_mode; + /* The file-descriptor we "listen" on for new connections */ + int listen_fd; + /* The array of tunnels */ + tunala_item_t *tunnels; + /* the number of tunnels in use and allocated, respectively */ + unsigned int tunnels_used, tunnels_size; + /* Our outside "loop" context stuff */ + tunala_selector_t selector; + /* + * Our SSL_CTX, which is configured as the SSL client or server and has + * the various cert-settings and callbacks configured. + */ + SSL_CTX *ssl_ctx; + /* + * Simple flag with complex logic :-) Indicates whether we're an SSL + * server or an SSL client. + */ + int server_mode; } tunala_world_t; /*****************************/ @@ -67,22 +83,30 @@ typedef struct _tunala_world_t { /*****************************/ static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id, - const char *CAfile, const char *cert, const char *key, - const char *dcert, const char *dkey, const char *cipher_list, - const char *dh_file, const char *dh_special, int tmp_rsa, - int ctx_options, int out_state, int out_verify, int verify_mode, - unsigned int verify_depth); -static void selector_init(tunala_selector_t *selector); -static void selector_add_listener(tunala_selector_t *selector, int fd); -static void selector_add_tunala(tunala_selector_t *selector, tunala_item_t *t); -static int selector_select(tunala_selector_t *selector); -/* This returns -1 for error, 0 for no new connections, or 1 for success, in - * which case *newfd is populated. */ -static int selector_get_listener(tunala_selector_t *selector, int fd, int *newfd); -static int tunala_world_new_item(tunala_world_t *world, int fd, - const char *ip, unsigned short port, int flipped); -static void tunala_world_del_item(tunala_world_t *world, unsigned int idx); -static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item); + const char *CAfile, const char *cert, + const char *key, const char *dcert, + const char *dkey, const char *cipher_list, + const char *dh_file, + const char *dh_special, int tmp_rsa, + int ctx_options, int out_state, + int out_verify, int verify_mode, + unsigned int verify_depth); +static void selector_init(tunala_selector_t * selector); +static void selector_add_listener(tunala_selector_t * selector, int fd); +static void selector_add_tunala(tunala_selector_t * selector, + tunala_item_t * t); +static int selector_select(tunala_selector_t * selector); +/* + * This returns -1 for error, 0 for no new connections, or 1 for success, in + * which case *newfd is populated. + */ +static int selector_get_listener(tunala_selector_t * selector, int fd, + int *newfd); +static int tunala_world_new_item(tunala_world_t * world, int fd, + const char *ip, unsigned short port, + int flipped); +static void tunala_world_del_item(tunala_world_t * world, unsigned int idx); +static int tunala_item_io(tunala_selector_t * selector, tunala_item_t * item); /*********************************************/ /* MAIN FUNCTION (and its utility functions) */ @@ -112,492 +136,518 @@ static int def_out_totals = 0; static int def_out_conns = 0; static const char *helpstring = -"\n'Tunala' (A tunneler with a New Zealand accent)\n" -"Usage: tunala [options], where options are from;\n" -" -listen [host:]<port> (default = 127.0.0.1:8080)\n" -" -proxy <host>:<port> (default = 127.0.0.1:443)\n" -" -maxtunnels <num> (default = 50)\n" -" -cacert <path|NULL> (default = NULL)\n" -" -cert <path|NULL> (default = NULL)\n" -" -key <path|NULL> (default = whatever '-cert' is)\n" -" -dcert <path|NULL> (usually for DSA, default = NULL)\n" -" -dkey <path|NULL> (usually for DSA, default = whatever '-dcert' is)\n" -" -engine <id|NULL> (default = NULL)\n" -" -server <0|1> (default = 0, ie. an SSL client)\n" -" -flipped <0|1> (makes SSL servers be network clients, and vice versa)\n" -" -cipher <list> (specifies cipher list to use)\n" -" -dh_file <path> (a PEM file containing DH parameters to use)\n" -" -dh_special <NULL|generate|standard> (see below: def=NULL)\n" -" -no_tmp_rsa (don't generate temporary RSA keys)\n" -" -no_ssl2 (disable SSLv2)\n" -" -no_ssl3 (disable SSLv3)\n" -" -no_tls1 (disable TLSv1)\n" -" -v_peer (verify the peer certificate)\n" -" -v_strict (do not continue if peer doesn't authenticate)\n" -" -v_once (no verification in renegotiates)\n" -" -v_depth <num> (limit certificate chain depth, default = 10)\n" -" -out_conns (prints client connections and disconnections)\n" -" -out_state (prints SSL handshake states)\n" -" -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n" -" -out_totals (prints out byte-totals when a tunnel closes)\n" -" -<h|help|?> (displays this help screen)\n" -"Notes:\n" -"(1) It is recommended to specify a cert+key when operating as an SSL server.\n" -" If you only specify '-cert', the same file must contain a matching\n" -" private key.\n" -"(2) Either dh_file or dh_special can be used to specify where DH parameters\n" -" will be obtained from (or '-dh_special NULL' for the default choice) but\n" -" you cannot specify both. For dh_special, 'generate' will create new DH\n" -" parameters on startup, and 'standard' will use embedded parameters\n" -" instead.\n" -"(3) Normally an ssl client connects to an ssl server - so that an 'ssl client\n" -" tunala' listens for 'clean' client connections and proxies ssl, and an\n" -" 'ssl server tunala' listens for ssl connections and proxies 'clean'. With\n" -" '-flipped 1', this behaviour is reversed so that an 'ssl server tunala'\n" -" listens for clean client connections and proxies ssl (but participating\n" -" as an ssl *server* in the SSL/TLS protocol), and an 'ssl client tunala'\n" -" listens for ssl connections (participating as an ssl *client* in the\n" -" SSL/TLS protocol) and proxies 'clean' to the end destination. This can\n" -" be useful for allowing network access to 'servers' where only the server\n" -" needs to authenticate the client (ie. the other way is not required).\n" -" Even with client and server authentication, this 'technique' mitigates\n" -" some DoS (denial-of-service) potential as it will be the network client\n" -" having to perform the first private key operation rather than the other\n" -" way round.\n" -"(4) The 'technique' used by setting '-flipped 1' is probably compatible with\n" -" absolutely nothing except another complimentary instance of 'tunala'\n" -" running with '-flipped 1'. :-)\n"; + "\n'Tunala' (A tunneler with a New Zealand accent)\n" + "Usage: tunala [options], where options are from;\n" + " -listen [host:]<port> (default = 127.0.0.1:8080)\n" + " -proxy <host>:<port> (default = 127.0.0.1:443)\n" + " -maxtunnels <num> (default = 50)\n" + " -cacert <path|NULL> (default = NULL)\n" + " -cert <path|NULL> (default = NULL)\n" + " -key <path|NULL> (default = whatever '-cert' is)\n" + " -dcert <path|NULL> (usually for DSA, default = NULL)\n" + " -dkey <path|NULL> (usually for DSA, default = whatever '-dcert' is)\n" + " -engine <id|NULL> (default = NULL)\n" + " -server <0|1> (default = 0, ie. an SSL client)\n" + " -flipped <0|1> (makes SSL servers be network clients, and vice versa)\n" + " -cipher <list> (specifies cipher list to use)\n" + " -dh_file <path> (a PEM file containing DH parameters to use)\n" + " -dh_special <NULL|generate|standard> (see below: def=NULL)\n" + " -no_tmp_rsa (don't generate temporary RSA keys)\n" + " -no_ssl2 (disable SSLv2)\n" + " -no_ssl3 (disable SSLv3)\n" + " -no_tls1 (disable TLSv1)\n" + " -v_peer (verify the peer certificate)\n" + " -v_strict (do not continue if peer doesn't authenticate)\n" + " -v_once (no verification in renegotiates)\n" + " -v_depth <num> (limit certificate chain depth, default = 10)\n" + " -out_conns (prints client connections and disconnections)\n" + " -out_state (prints SSL handshake states)\n" + " -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n" + " -out_totals (prints out byte-totals when a tunnel closes)\n" + " -<h|help|?> (displays this help screen)\n" + "Notes:\n" + "(1) It is recommended to specify a cert+key when operating as an SSL server.\n" + " If you only specify '-cert', the same file must contain a matching\n" + " private key.\n" + "(2) Either dh_file or dh_special can be used to specify where DH parameters\n" + " will be obtained from (or '-dh_special NULL' for the default choice) but\n" + " you cannot specify both. For dh_special, 'generate' will create new DH\n" + " parameters on startup, and 'standard' will use embedded parameters\n" + " instead.\n" + "(3) Normally an ssl client connects to an ssl server - so that an 'ssl client\n" + " tunala' listens for 'clean' client connections and proxies ssl, and an\n" + " 'ssl server tunala' listens for ssl connections and proxies 'clean'. With\n" + " '-flipped 1', this behaviour is reversed so that an 'ssl server tunala'\n" + " listens for clean client connections and proxies ssl (but participating\n" + " as an ssl *server* in the SSL/TLS protocol), and an 'ssl client tunala'\n" + " listens for ssl connections (participating as an ssl *client* in the\n" + " SSL/TLS protocol) and proxies 'clean' to the end destination. This can\n" + " be useful for allowing network access to 'servers' where only the server\n" + " needs to authenticate the client (ie. the other way is not required).\n" + " Even with client and server authentication, this 'technique' mitigates\n" + " some DoS (denial-of-service) potential as it will be the network client\n" + " having to perform the first private key operation rather than the other\n" + " way round.\n" + "(4) The 'technique' used by setting '-flipped 1' is probably compatible with\n" + " absolutely nothing except another complimentary instance of 'tunala'\n" + " running with '-flipped 1'. :-)\n"; + +/* + * Default DH parameters for use with "-dh_special standard" ... stolen + * striaght from s_server. + */ +static unsigned char dh512_p[] = { + 0xDA, 0x58, 0x3C, 0x16, 0xD9, 0x85, 0x22, 0x89, 0xD0, 0xE4, 0xAF, 0x75, + 0x6F, 0x4C, 0xCA, 0x92, 0xDD, 0x4B, 0xE5, 0x33, 0xB8, 0x04, 0xFB, 0x0F, + 0xED, 0x94, 0xEF, 0x9C, 0x8A, 0x44, 0x03, 0xED, 0x57, 0x46, 0x50, 0xD3, + 0x69, 0x99, 0xDB, 0x29, 0xD7, 0x76, 0x27, 0x6B, 0xA2, 0xD3, 0xD4, 0x12, + 0xE2, 0x18, 0xF4, 0xDD, 0x1E, 0x08, 0x4C, 0xF6, 0xD8, 0x00, 0x3E, 0x7C, + 0x47, 0x74, 0xE8, 0x33, +}; -/* Default DH parameters for use with "-dh_special standard" ... stolen striaght - * from s_server. */ -static unsigned char dh512_p[]={ - 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, - 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, - 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, - 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, - 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, - 0x47,0x74,0xE8,0x33, - }; -static unsigned char dh512_g[]={ - 0x02, - }; +static unsigned char dh512_g[] = { + 0x02, +}; -/* And the function that parses the above "standard" parameters, again, straight - * out of s_server. */ +/* + * And the function that parses the above "standard" parameters, again, + * straight out of s_server. + */ static DH *get_dh512(void) - { - DH *dh=NULL; +{ + DH *dh = NULL; - if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); - dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); - if ((dh->p == NULL) || (dh->g == NULL)) - return(NULL); - return(dh); - } + if ((dh = DH_new()) == NULL) + return (NULL); + dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL); + dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL); + if ((dh->p == NULL) || (dh->g == NULL)) + return (NULL); + return (dh); +} /* Various help/error messages used by main() */ static int usage(const char *errstr, int isunknownarg) { - if(isunknownarg) - fprintf(stderr, "Error: unknown argument '%s'\n", errstr); - else - fprintf(stderr, "Error: %s\n", errstr); - fprintf(stderr, "%s\n", helpstring); - return 1; + if (isunknownarg) + fprintf(stderr, "Error: unknown argument '%s'\n", errstr); + else + fprintf(stderr, "Error: %s\n", errstr); + fprintf(stderr, "%s\n", helpstring); + return 1; } static int err_str0(const char *str0) { - fprintf(stderr, "%s\n", str0); - return 1; + fprintf(stderr, "%s\n", str0); + return 1; } static int err_str1(const char *fmt, const char *str1) { - fprintf(stderr, fmt, str1); - fprintf(stderr, "\n"); - return 1; + fprintf(stderr, fmt, str1); + fprintf(stderr, "\n"); + return 1; } static int parse_max_tunnels(const char *s, unsigned int *maxtunnels) { - unsigned long l; - if(!int_strtoul(s, &l) || (l < 1) || (l > 1024)) { - fprintf(stderr, "Error, '%s' is an invalid value for " - "maxtunnels\n", s); - return 0; - } - *maxtunnels = (unsigned int)l; - return 1; + unsigned long l; + if (!int_strtoul(s, &l) || (l < 1) || (l > 1024)) { + fprintf(stderr, "Error, '%s' is an invalid value for " + "maxtunnels\n", s); + return 0; + } + *maxtunnels = (unsigned int)l; + return 1; } static int parse_server_mode(const char *s, int *servermode) { - unsigned long l; - if(!int_strtoul(s, &l) || (l > 1)) { - fprintf(stderr, "Error, '%s' is an invalid value for the " - "server mode\n", s); - return 0; - } - *servermode = (int)l; - return 1; + unsigned long l; + if (!int_strtoul(s, &l) || (l > 1)) { + fprintf(stderr, "Error, '%s' is an invalid value for the " + "server mode\n", s); + return 0; + } + *servermode = (int)l; + return 1; } static int parse_dh_special(const char *s, const char **dh_special) { - if((strcmp(s, "NULL") == 0) || (strcmp(s, "generate") == 0) || - (strcmp(s, "standard") == 0)) { - *dh_special = s; - return 1; - } - fprintf(stderr, "Error, '%s' is an invalid value for 'dh_special'\n", s); - return 0; + if ((strcmp(s, "NULL") == 0) || (strcmp(s, "generate") == 0) || + (strcmp(s, "standard") == 0)) { + *dh_special = s; + return 1; + } + fprintf(stderr, "Error, '%s' is an invalid value for 'dh_special'\n", s); + return 0; } static int parse_verify_level(const char *s, unsigned int *verify_level) { - unsigned long l; - if(!int_strtoul(s, &l) || (l > 3)) { - fprintf(stderr, "Error, '%s' is an invalid value for " - "out_verify\n", s); - return 0; - } - *verify_level = (unsigned int)l; - return 1; + unsigned long l; + if (!int_strtoul(s, &l) || (l > 3)) { + fprintf(stderr, "Error, '%s' is an invalid value for " + "out_verify\n", s); + return 0; + } + *verify_level = (unsigned int)l; + return 1; } static int parse_verify_depth(const char *s, unsigned int *verify_depth) { - unsigned long l; - if(!int_strtoul(s, &l) || (l < 1) || (l > 50)) { - fprintf(stderr, "Error, '%s' is an invalid value for " - "verify_depth\n", s); - return 0; - } - *verify_depth = (unsigned int)l; - return 1; + unsigned long l; + if (!int_strtoul(s, &l) || (l < 1) || (l > 50)) { + fprintf(stderr, "Error, '%s' is an invalid value for " + "verify_depth\n", s); + return 0; + } + *verify_depth = (unsigned int)l; + return 1; } /* Some fprintf format strings used when tunnels close */ static const char *io_stats_dirty = -" SSL traffic; %8lu bytes in, %8lu bytes out\n"; + " SSL traffic; %8lu bytes in, %8lu bytes out\n"; static const char *io_stats_clean = -" clear traffic; %8lu bytes in, %8lu bytes out\n"; + " clear traffic; %8lu bytes in, %8lu bytes out\n"; int main(int argc, char *argv[]) { - unsigned int loop; - int newfd; - tunala_world_t world; - tunala_item_t *t_item; - const char *proxy_ip; - unsigned short proxy_port; - /* Overridables */ - const char *proxyhost = def_proxyhost; - const char *listenhost = def_listenhost; - unsigned int max_tunnels = def_max_tunnels; - const char *cacert = def_cacert; - const char *cert = def_cert; - const char *key = def_key; - const char *dcert = def_dcert; - const char *dkey = def_dkey; - const char *engine_id = def_engine_id; - int server_mode = def_server_mode; - int flipped = def_flipped; - const char *cipher_list = def_cipher_list; - const char *dh_file = def_dh_file; - const char *dh_special = def_dh_special; - int tmp_rsa = def_tmp_rsa; - int ctx_options = def_ctx_options; - int verify_mode = def_verify_mode; - unsigned int verify_depth = def_verify_depth; - int out_state = def_out_state; - unsigned int out_verify = def_out_verify; - int out_totals = def_out_totals; - int out_conns = def_out_conns; + unsigned int loop; + int newfd; + tunala_world_t world; + tunala_item_t *t_item; + const char *proxy_ip; + unsigned short proxy_port; + /* Overridables */ + const char *proxyhost = def_proxyhost; + const char *listenhost = def_listenhost; + unsigned int max_tunnels = def_max_tunnels; + const char *cacert = def_cacert; + const char *cert = def_cert; + const char *key = def_key; + const char *dcert = def_dcert; + const char *dkey = def_dkey; + const char *engine_id = def_engine_id; + int server_mode = def_server_mode; + int flipped = def_flipped; + const char *cipher_list = def_cipher_list; + const char *dh_file = def_dh_file; + const char *dh_special = def_dh_special; + int tmp_rsa = def_tmp_rsa; + int ctx_options = def_ctx_options; + int verify_mode = def_verify_mode; + unsigned int verify_depth = def_verify_depth; + int out_state = def_out_state; + unsigned int out_verify = def_out_verify; + int out_totals = def_out_totals; + int out_conns = def_out_conns; /* Parse command-line arguments */ -next_arg: - argc--; argv++; - if(argc > 0) { - if(strcmp(*argv, "-listen") == 0) { - if(argc < 2) - return usage("-listen requires an argument", 0); - argc--; argv++; - listenhost = *argv; - goto next_arg; - } else if(strcmp(*argv, "-proxy") == 0) { - if(argc < 2) - return usage("-proxy requires an argument", 0); - argc--; argv++; - proxyhost = *argv; - goto next_arg; - } else if(strcmp(*argv, "-maxtunnels") == 0) { - if(argc < 2) - return usage("-maxtunnels requires an argument", 0); - argc--; argv++; - if(!parse_max_tunnels(*argv, &max_tunnels)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-cacert") == 0) { - if(argc < 2) - return usage("-cacert requires an argument", 0); - argc--; argv++; - if(strcmp(*argv, "NULL") == 0) - cacert = NULL; - else - cacert = *argv; - goto next_arg; - } else if(strcmp(*argv, "-cert") == 0) { - if(argc < 2) - return usage("-cert requires an argument", 0); - argc--; argv++; - if(strcmp(*argv, "NULL") == 0) - cert = NULL; - else - cert = *argv; - goto next_arg; - } else if(strcmp(*argv, "-key") == 0) { - if(argc < 2) - return usage("-key requires an argument", 0); - argc--; argv++; - if(strcmp(*argv, "NULL") == 0) - key = NULL; - else - key = *argv; - goto next_arg; - } else if(strcmp(*argv, "-dcert") == 0) { - if(argc < 2) - return usage("-dcert requires an argument", 0); - argc--; argv++; - if(strcmp(*argv, "NULL") == 0) - dcert = NULL; - else - dcert = *argv; - goto next_arg; - } else if(strcmp(*argv, "-dkey") == 0) { - if(argc < 2) - return usage("-dkey requires an argument", 0); - argc--; argv++; - if(strcmp(*argv, "NULL") == 0) - dkey = NULL; - else - dkey = *argv; - goto next_arg; - } else if(strcmp(*argv, "-engine") == 0) { - if(argc < 2) - return usage("-engine requires an argument", 0); - argc--; argv++; - engine_id = *argv; - goto next_arg; - } else if(strcmp(*argv, "-server") == 0) { - if(argc < 2) - return usage("-server requires an argument", 0); - argc--; argv++; - if(!parse_server_mode(*argv, &server_mode)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-flipped") == 0) { - if(argc < 2) - return usage("-flipped requires an argument", 0); - argc--; argv++; - if(!parse_server_mode(*argv, &flipped)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-cipher") == 0) { - if(argc < 2) - return usage("-cipher requires an argument", 0); - argc--; argv++; - cipher_list = *argv; - goto next_arg; - } else if(strcmp(*argv, "-dh_file") == 0) { - if(argc < 2) - return usage("-dh_file requires an argument", 0); - if(dh_special) - return usage("cannot mix -dh_file with " - "-dh_special", 0); - argc--; argv++; - dh_file = *argv; - goto next_arg; - } else if(strcmp(*argv, "-dh_special") == 0) { - if(argc < 2) - return usage("-dh_special requires an argument", 0); - if(dh_file) - return usage("cannot mix -dh_file with " - "-dh_special", 0); - argc--; argv++; - if(!parse_dh_special(*argv, &dh_special)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-no_tmp_rsa") == 0) { - tmp_rsa = 0; - goto next_arg; - } else if(strcmp(*argv, "-no_ssl2") == 0) { - ctx_options |= SSL_OP_NO_SSLv2; - goto next_arg; - } else if(strcmp(*argv, "-no_ssl3") == 0) { - ctx_options |= SSL_OP_NO_SSLv3; - goto next_arg; - } else if(strcmp(*argv, "-no_tls1") == 0) { - ctx_options |= SSL_OP_NO_TLSv1; - goto next_arg; - } else if(strcmp(*argv, "-v_peer") == 0) { - verify_mode |= SSL_VERIFY_PEER; - goto next_arg; - } else if(strcmp(*argv, "-v_strict") == 0) { - verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - goto next_arg; - } else if(strcmp(*argv, "-v_once") == 0) { - verify_mode |= SSL_VERIFY_CLIENT_ONCE; - goto next_arg; - } else if(strcmp(*argv, "-v_depth") == 0) { - if(argc < 2) - return usage("-v_depth requires an argument", 0); - argc--; argv++; - if(!parse_verify_depth(*argv, &verify_depth)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-out_state") == 0) { - out_state = 1; - goto next_arg; - } else if(strcmp(*argv, "-out_verify") == 0) { - if(argc < 2) - return usage("-out_verify requires an argument", 0); - argc--; argv++; - if(!parse_verify_level(*argv, &out_verify)) - return 1; - goto next_arg; - } else if(strcmp(*argv, "-out_totals") == 0) { - out_totals = 1; - goto next_arg; - } else if(strcmp(*argv, "-out_conns") == 0) { - out_conns = 1; - goto next_arg; - } else if((strcmp(*argv, "-h") == 0) || - (strcmp(*argv, "-help") == 0) || - (strcmp(*argv, "-?") == 0)) { - fprintf(stderr, "%s\n", helpstring); - return 0; - } else - return usage(*argv, 1); - } - /* Run any sanity checks we want here */ - if(!cert && !dcert && server_mode) - fprintf(stderr, "WARNING: you are running an SSL server without " - "a certificate - this may not work!\n"); + next_arg: + argc--; + argv++; + if (argc > 0) { + if (strcmp(*argv, "-listen") == 0) { + if (argc < 2) + return usage("-listen requires an argument", 0); + argc--; + argv++; + listenhost = *argv; + goto next_arg; + } else if (strcmp(*argv, "-proxy") == 0) { + if (argc < 2) + return usage("-proxy requires an argument", 0); + argc--; + argv++; + proxyhost = *argv; + goto next_arg; + } else if (strcmp(*argv, "-maxtunnels") == 0) { + if (argc < 2) + return usage("-maxtunnels requires an argument", 0); + argc--; + argv++; + if (!parse_max_tunnels(*argv, &max_tunnels)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-cacert") == 0) { + if (argc < 2) + return usage("-cacert requires an argument", 0); + argc--; + argv++; + if (strcmp(*argv, "NULL") == 0) + cacert = NULL; + else + cacert = *argv; + goto next_arg; + } else if (strcmp(*argv, "-cert") == 0) { + if (argc < 2) + return usage("-cert requires an argument", 0); + argc--; + argv++; + if (strcmp(*argv, "NULL") == 0) + cert = NULL; + else + cert = *argv; + goto next_arg; + } else if (strcmp(*argv, "-key") == 0) { + if (argc < 2) + return usage("-key requires an argument", 0); + argc--; + argv++; + if (strcmp(*argv, "NULL") == 0) + key = NULL; + else + key = *argv; + goto next_arg; + } else if (strcmp(*argv, "-dcert") == 0) { + if (argc < 2) + return usage("-dcert requires an argument", 0); + argc--; + argv++; + if (strcmp(*argv, "NULL") == 0) + dcert = NULL; + else + dcert = *argv; + goto next_arg; + } else if (strcmp(*argv, "-dkey") == 0) { + if (argc < 2) + return usage("-dkey requires an argument", 0); + argc--; + argv++; + if (strcmp(*argv, "NULL") == 0) + dkey = NULL; + else + dkey = *argv; + goto next_arg; + } else if (strcmp(*argv, "-engine") == 0) { + if (argc < 2) + return usage("-engine requires an argument", 0); + argc--; + argv++; + engine_id = *argv; + goto next_arg; + } else if (strcmp(*argv, "-server") == 0) { + if (argc < 2) + return usage("-server requires an argument", 0); + argc--; + argv++; + if (!parse_server_mode(*argv, &server_mode)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-flipped") == 0) { + if (argc < 2) + return usage("-flipped requires an argument", 0); + argc--; + argv++; + if (!parse_server_mode(*argv, &flipped)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-cipher") == 0) { + if (argc < 2) + return usage("-cipher requires an argument", 0); + argc--; + argv++; + cipher_list = *argv; + goto next_arg; + } else if (strcmp(*argv, "-dh_file") == 0) { + if (argc < 2) + return usage("-dh_file requires an argument", 0); + if (dh_special) + return usage("cannot mix -dh_file with " "-dh_special", 0); + argc--; + argv++; + dh_file = *argv; + goto next_arg; + } else if (strcmp(*argv, "-dh_special") == 0) { + if (argc < 2) + return usage("-dh_special requires an argument", 0); + if (dh_file) + return usage("cannot mix -dh_file with " "-dh_special", 0); + argc--; + argv++; + if (!parse_dh_special(*argv, &dh_special)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-no_tmp_rsa") == 0) { + tmp_rsa = 0; + goto next_arg; + } else if (strcmp(*argv, "-no_ssl2") == 0) { + ctx_options |= SSL_OP_NO_SSLv2; + goto next_arg; + } else if (strcmp(*argv, "-no_ssl3") == 0) { + ctx_options |= SSL_OP_NO_SSLv3; + goto next_arg; + } else if (strcmp(*argv, "-no_tls1") == 0) { + ctx_options |= SSL_OP_NO_TLSv1; + goto next_arg; + } else if (strcmp(*argv, "-v_peer") == 0) { + verify_mode |= SSL_VERIFY_PEER; + goto next_arg; + } else if (strcmp(*argv, "-v_strict") == 0) { + verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + goto next_arg; + } else if (strcmp(*argv, "-v_once") == 0) { + verify_mode |= SSL_VERIFY_CLIENT_ONCE; + goto next_arg; + } else if (strcmp(*argv, "-v_depth") == 0) { + if (argc < 2) + return usage("-v_depth requires an argument", 0); + argc--; + argv++; + if (!parse_verify_depth(*argv, &verify_depth)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-out_state") == 0) { + out_state = 1; + goto next_arg; + } else if (strcmp(*argv, "-out_verify") == 0) { + if (argc < 2) + return usage("-out_verify requires an argument", 0); + argc--; + argv++; + if (!parse_verify_level(*argv, &out_verify)) + return 1; + goto next_arg; + } else if (strcmp(*argv, "-out_totals") == 0) { + out_totals = 1; + goto next_arg; + } else if (strcmp(*argv, "-out_conns") == 0) { + out_conns = 1; + goto next_arg; + } else if ((strcmp(*argv, "-h") == 0) || + (strcmp(*argv, "-help") == 0) || + (strcmp(*argv, "-?") == 0)) { + fprintf(stderr, "%s\n", helpstring); + return 0; + } else + return usage(*argv, 1); + } + /* Run any sanity checks we want here */ + if (!cert && !dcert && server_mode) + fprintf(stderr, "WARNING: you are running an SSL server without " + "a certificate - this may not work!\n"); - /* Initialise network stuff */ - if(!ip_initialise()) - return err_str0("ip_initialise failed"); - /* Create the SSL_CTX */ - if((world.ssl_ctx = initialise_ssl_ctx(server_mode, engine_id, - cacert, cert, key, dcert, dkey, cipher_list, dh_file, - dh_special, tmp_rsa, ctx_options, out_state, out_verify, - verify_mode, verify_depth)) == NULL) - return err_str1("initialise_ssl_ctx(engine_id=%s) failed", - (engine_id == NULL) ? "NULL" : engine_id); - if(engine_id) - fprintf(stderr, "Info, engine '%s' initialised\n", engine_id); - /* Create the listener */ - if((world.listen_fd = ip_create_listener(listenhost)) == -1) - return err_str1("ip_create_listener(%s) failed", listenhost); - fprintf(stderr, "Info, listening on '%s'\n", listenhost); - if(!ip_parse_address(proxyhost, &proxy_ip, &proxy_port, 0)) - return err_str1("ip_parse_address(%s) failed", proxyhost); - fprintf(stderr, "Info, proxying to '%s' (%d.%d.%d.%d:%d)\n", proxyhost, - (int)proxy_ip[0], (int)proxy_ip[1], - (int)proxy_ip[2], (int)proxy_ip[3], (int)proxy_port); - fprintf(stderr, "Info, set maxtunnels to %d\n", (int)max_tunnels); - fprintf(stderr, "Info, set to operate as an SSL %s\n", - (server_mode ? "server" : "client")); - /* Initialise the rest of the stuff */ - world.tunnels_used = world.tunnels_size = 0; - world.tunnels = NULL; - world.server_mode = server_mode; - selector_init(&world.selector); + /* Initialise network stuff */ + if (!ip_initialise()) + return err_str0("ip_initialise failed"); + /* Create the SSL_CTX */ + if ((world.ssl_ctx = initialise_ssl_ctx(server_mode, engine_id, + cacert, cert, key, dcert, dkey, |