From 282d8b1c385aad08969a307950350574c66a3ec2 Mon Sep 17 00:00:00 2001 From: Geoff Thorpe Date: Mon, 12 Feb 2001 02:28:29 +0000 Subject: [PATCH] This change was a quick experiment that I'd wanted to try that works quite well (and is a good demonstration of how encapsulating the SSL in a memory-based state machine can make it easier to apply to different situations). The change implements a new command-line switch "-flipped <0|1>" which, if set to 1, reverses the usual interpretation of a client and server for SSL tunneling. Normally, an ssl client (ie. "-server 0") accepts "cleartext" connections and conducts SSL/TLS over a proxied connection acting as an SSL client. Likewise, an ssl server (ie. "-server 1") accepts connections and conducts SSL/TLS (as an SSL server) over them and passes "cleartext" over the proxied connection. With "-flipped 1", an SSL client (specified with "-server 0") in fact accepts SSL connections and proxies clear, whereas an SSL server ("-server 1") accepts clear and proxies SSL. NB: most of this diff is command-line handling, the actual meat of the change is simply the line or two that plugs "clean" and "dirty" file descriptors into the item that holds the state-machine - reverse them and you get the desired behaviour. This allows a network server to be an SSL client, and a network client to be an SSL server. Apart from curiosity value, there's a couple of possibly interesting applications - SSL/TLS is inherently vulnerable to trivial DoS attacks, because the SSL server usually has to perform a private key operation first, even if the client is authenticated. With this scenario, the network client is the SSL server and performs the first private key operation, whereas the network server serves as the SSL client. Another possible application is when client-only authentication is required (ie. the underlying protocol handles (or doesn't care about) authenticating the server). Eg. an SSL/TLS version of 'ssh' could be concocted where the client's signed certificate is used to validate login to a server system - whether or not the client needs to validate who the server is can be configured at the client end rather than at the server end (ie. a complete inversion of what happens in normal SSL/TLS). NB: This is just an experiment/play-thing, using "-flipped 1" probably creates something that is interoperable with exactly nothing. :-) --- demos/tunala/tunala.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/demos/tunala/tunala.c b/demos/tunala/tunala.c index 9c3ff5978b..dbf155c67a 100644 --- a/demos/tunala/tunala.c +++ b/demos/tunala/tunala.c @@ -80,7 +80,7 @@ static int selector_select(tunala_selector_t *selector); * 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 unsigned char *ip, unsigned short port); + const unsigned 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); @@ -98,6 +98,7 @@ static const char *def_dcert = NULL; static const char *def_dkey = NULL; static const char *def_engine_id = NULL; static int def_server_mode = 0; +static int def_flipped = 0; static const char *def_cipher_list = NULL; static const char *def_dh_file = NULL; static const char *def_dh_special = NULL; @@ -121,6 +122,7 @@ static const char *helpstring = " -dkey (usually for DSA, default = whatever '-dcert' is)\n" " -engine (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 (specifies cipher list to use)\n" " -dh_file (a PEM file containing DH parameters to use)\n" " -dh_special (see below: def=NULL)\n" @@ -143,7 +145,24 @@ static const char *helpstring = " 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"; +" 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. */ @@ -293,6 +312,7 @@ int main(int argc, char *argv[]) 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; @@ -384,6 +404,13 @@ next_arg: 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); @@ -512,8 +539,8 @@ main_loop: &world.selector, world.listen_fd, &newfd) == 1)) { /* We have a new connection */ - if(!tunala_world_new_item(&world, newfd, - proxy_ip, proxy_port)) + if(!tunala_world_new_item(&world, newfd, proxy_ip, + proxy_port, flipped)) fprintf(stderr, "tunala_world_new_item failed\n"); else fprintf(stderr, "Info, new tunnel opened, now up to " @@ -908,7 +935,7 @@ static int tunala_world_make_room(tunala_world_t *world) } static int tunala_world_new_item(tunala_world_t *world, int fd, - const unsigned char *ip, unsigned short port) + const unsigned char *ip, unsigned short port, int flipped) { tunala_item_t *item; int newfd; @@ -929,8 +956,10 @@ static int tunala_world_new_item(tunala_world_t *world, int fd, goto err; /* Which way round? If we're a server, "fd" is the dirty side and the * connection we open is the clean one. For a client, it's the other way - * around. */ - if(world->server_mode) { + * around. Unless, of course, we're "flipped" in which case everything + * gets reversed. :-) */ + if((world->server_mode && !flipped) || + (!world->server_mode && flipped)) { item->dirty_read = item->dirty_send = fd; item->clean_read = item->clean_send = newfd; } else { -- 2.25.1