From 01ea77836356405885f436f26c93c96fc0edf16a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 17 Aug 2018 13:33:41 +0100 Subject: [PATCH] UDP proxy: Add option to delay specific handshake messages --- programs/test/udp_proxy.c | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c index 55e0f249ce..2986ee30a7 100644 --- a/programs/test/udp_proxy.c +++ b/programs/test/udp_proxy.c @@ -40,6 +40,8 @@ #define mbedtls_time time #define mbedtls_time_t time_t #define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif /* MBEDTLS_PLATFORM_C */ @@ -106,6 +108,21 @@ int main( void ) " delay=%%d default: 0 (no delayed packets)\n" \ " delay about 1:N packets randomly\n" \ " delay_ccs=0/1 default: 0 (don't delay ChangeCipherSpec)\n" \ + " delay_cli=%%s Handshake message from client that should be\n"\ + " delayed. Possible values are 'ClientHello',\n" \ + " 'Certificate', 'CertificateVerify', and\n" \ + " 'ClientKeyExchange'.\n" \ + " May be used multiple times, even for the same\n"\ + " message, in which case the respective message\n"\ + " gets delayed multiple times.\n" \ + " delay_srv=%%s Handshake message from server that should be\n"\ + " delayed. Possible values are 'HelloRequest',\n"\ + " 'ServerHello', 'ServerHelloDone', 'Certificate'\n"\ + " 'ServerKeyExchange', 'NewSessionTicket',\n"\ + " 'HelloVerifyRequest' and ''CertificateRequest'.\n"\ + " May be used multiple times, even for the same\n"\ + " message, in which case the respective message\n"\ + " gets delayed multiple times.\n" \ " drop=%%d default: 0 (no dropped packets)\n" \ " drop about 1:N packets randomly\n" \ " mtu=%%d default: 0 (unlimited)\n" \ @@ -121,6 +138,9 @@ int main( void ) /* * global options */ + +#define MAX_DELAYED_HS 10 + static struct options { const char *server_addr; /* address to forward packets to */ @@ -131,6 +151,12 @@ static struct options int duplicate; /* duplicate 1 in N packets (none if 0) */ int delay; /* delay 1 packet in N (none if 0) */ int delay_ccs; /* delay ChangeCipherSpec */ + char* delay_cli[MAX_DELAYED_HS]; /* handshake types of messages from + * client that should be delayed. */ + uint8_t delay_cli_cnt; /* Number of entries in delay_cli. */ + char* delay_srv[MAX_DELAYED_HS]; /* handshake types of messages from + * server that should be delayed. */ + uint8_t delay_srv_cnt; /* Number of entries in delay_srv. */ int drop; /* drop 1 packet in N (none if 0) */ int mtu; /* drop packets larger than this */ int bad_ad; /* inject corrupted ApplicationData record */ @@ -164,6 +190,11 @@ static void get_options( int argc, char *argv[] ) opt.pack = DFL_PACK; /* Other members default to 0 */ + opt.delay_cli_cnt = 0; + opt.delay_srv_cnt = 0; + memset( opt.delay_cli, 0, sizeof( opt.delay_cli ) ); + memset( opt.delay_srv, 0, sizeof( opt.delay_srv ) ); + for( i = 1; i < argc; i++ ) { p = argv[i]; @@ -197,6 +228,43 @@ static void get_options( int argc, char *argv[] ) if( opt.delay_ccs < 0 || opt.delay_ccs > 1 ) exit_usage( p, q ); } + else if( strcmp( p, "delay_cli" ) == 0 || + strcmp( p, "delay_srv" ) == 0 ) + { + uint8_t *delay_cnt; + char **delay_list; + size_t len; + char *buf; + + if( strcmp( p, "delay_cli" ) == 0 ) + { + delay_cnt = &opt.delay_cli_cnt; + delay_list = opt.delay_cli; + } + else + { + delay_cnt = &opt.delay_srv_cnt; + delay_list = opt.delay_srv; + } + + if( *delay_cnt == MAX_DELAYED_HS ) + { + mbedtls_printf( " maximally %d uses of delay_cli argument allows\n", + MAX_DELAYED_HS ); + exit_usage( p, NULL ); + } + + len = strlen( q ); + buf = mbedtls_calloc( 1, len + 1 ); + if( buf == NULL ) + { + mbedtls_printf( " Allocation failure\n" ); + exit( 1 ); + } + memcpy( buf, q, len + 1 ); + + delay_list[ (*delay_cnt)++ ] = buf; + } else if( strcmp( p, "drop" ) == 0 ) { opt.drop = atoi( q ); @@ -540,6 +608,10 @@ int handle_message( const char *way, packet cur; size_t id; + uint8_t delay_idx; + char ** delay_list; + uint8_t delay_list_len; + /* receive packet */ if( ( ret = mbedtls_net_recv( src, cur.buf, sizeof( cur.buf ) ) ) <= 0 ) { @@ -555,6 +627,36 @@ int handle_message( const char *way, id = cur.len % sizeof( dropped ); + if( strcmp( way, "S <- C" ) == 0 ) + { + delay_list = opt.delay_cli; + delay_list_len = opt.delay_cli_cnt; + } + else + { + delay_list = opt.delay_srv; + delay_list_len = opt.delay_srv_cnt; + } + /* Check if message type is in the list of messages + * that should be delayed */ + for( delay_idx = 0; delay_idx < delay_list_len; delay_idx++ ) + { + if( delay_list[ delay_idx ] == NULL ) + continue; + + if( strcmp( delay_list[ delay_idx ], cur.type ) == 0 ) + { + /* Delay message */ + memcpy( &prev, &cur, sizeof( packet ) ); + + /* Remove entry from list */ + mbedtls_free( delay_list[delay_idx] ); + delay_list[delay_idx] = NULL; + + return( 0 ); + } + } + /* do we want to drop, delay, or forward it? */ if( ( opt.mtu != 0 && cur.len > (unsigned) opt.mtu ) || @@ -604,6 +706,7 @@ int main( int argc, char *argv[] ) { int ret = 1; int exit_code = MBEDTLS_EXIT_FAILURE; + uint8_t delay_idx; mbedtls_net_context listen_fd, client_fd, server_fd; @@ -798,6 +901,12 @@ exit: } #endif + for( delay_idx = 0; delay_idx < MAX_DELAYED_HS; delay_idx++ ) + { + mbedtls_free( opt.delay_cli + delay_idx ); + mbedtls_free( opt.delay_srv + delay_idx ); + } + mbedtls_net_free( &client_fd ); mbedtls_net_free( &server_fd ); mbedtls_net_free( &listen_fd );