From a8c0a0dbd0111b426b9ea7b695ba221c73afe36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 15 Aug 2014 12:07:38 +0200 Subject: [PATCH] Add "exchanges" option to test server and client Goal is to test renegotiation better: we need more than one exchange for server-initiated renego to work reliably (the previous hack for this wouldn't work with non-blocking I/O and probably not with DTLS either). Also check message termination in a semi-realistic way. --- programs/ssl/ssl_client2.c | 27 ++++++++++++++- programs/ssl/ssl_server2.c | 71 +++++++++++++++++++------------------- tests/ssl-opt.sh | 48 +++++++++++++------------- 3 files changed, 86 insertions(+), 60 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index dda426301..f235b4ca4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -85,6 +85,7 @@ int main( int argc, char *argv[] ) #define DFL_RENEGOTIATION SSL_RENEGOTIATION_DISABLED #define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION #define DFL_RENEGOTIATE 0 +#define DFL_EXCHANGES 1 #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_REQUIRED @@ -120,6 +121,8 @@ struct options int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ int renegotiate; /* attempt renegotiation? */ + int renego_delay; /* delay before enforcing renegotiation */ + int exchanges; /* number of data exchanges */ int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ @@ -303,6 +306,7 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) " renegotiation=%%d default: 1 (enabled)\n" \ " allow_legacy=%%d default: 0 (disabled)\n" \ " renegotiate=%%d default: 0 (disabled)\n" \ + " exchanges=%%d default: 1\n" \ " reconnect=%%d default: 0 (disabled)\n" \ USAGE_TIME \ USAGE_TICKETS \ @@ -399,6 +403,7 @@ int main( int argc, char *argv[] ) opt.renegotiation = DFL_RENEGOTIATION; opt.allow_legacy = DFL_ALLOW_LEGACY; opt.renegotiate = DFL_RENEGOTIATE; + opt.exchanges = DFL_EXCHANGES; opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; @@ -486,6 +491,12 @@ int main( int argc, char *argv[] ) if( opt.renegotiate < 0 || opt.renegotiate > 1 ) goto usage; } + else if( strcmp( p, "exchanges" ) == 0 ) + { + opt.exchanges = atoi( q ); + if( opt.exchanges < 1 ) + goto usage; + } else if( strcmp( p, "reconnect" ) == 0 ) { opt.reconnect = atoi( q ); @@ -1136,11 +1147,25 @@ send_request: len = ret; buf[len] = '\0'; printf( " %d bytes read\n\n%s", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( ret > 0 && buf[len-1] == '\n' ) + { + ret = 0; + break; + } } while( 1 ); /* - * 9. Reconnect? + * 7b. Continue doing data exchanges? + */ + if( --opt.exchanges > 0 ) + goto send_request; + + /* + * 7c. Reconnect? */ reconnect: if( opt.reconnect != 0 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index ae512c0ae..721dab42e 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -587,7 +587,7 @@ void term_handler( int sig ) int main( int argc, char *argv[] ) { - int ret = 0, len, written, frags; + int ret = 0, len, written, frags, exchanges; int client_fd = -1; int version_suites[4][2]; unsigned char buf[IO_BUF_LEN]; @@ -1502,6 +1502,8 @@ reset: } #endif /* POLARSSL_X509_CRT_PARSE_C */ + exchanges = opt.exchanges; +data_exchange: /* * 6. Read the HTTP Request */ @@ -1510,6 +1512,7 @@ reset: do { + int terminated = 0; len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = ssl_read( &ssl, buf, len ); @@ -1534,7 +1537,7 @@ reset: default: printf( " ssl_read returned -0x%x\n", -ret ); - goto close_notify; + goto reset; } } @@ -1543,6 +1546,11 @@ reset: len = ret; buf[len] = '\0'; printf( " %d bytes read\n\n%s\n", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( buf[len - 1] == '\n' ) + terminated = 1; } else { @@ -1578,22 +1586,31 @@ reset: ori_len + extra_len, ori_len, extra_len, (char *) larger_buf ); + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( larger_buf[ori_len + extra_len - 1] == '\n' ) + terminated = 1; + polarssl_free( larger_buf ); } - if( ret > 0 ) + if( terminated ) + { + ret = 0; break; + } } while( 1 ); /* - * 7. Write the 200 Response + * 7a. Request renegotiation while client is waiting for input from us. + * (only if we're going to exhange more data afterwards) */ - if( opt.renegotiate ) + if( opt.renegotiate && exchanges > 1 ) { - /* Request renegotiation while the client is waiting for input */ printf( " . Requestion renegotiation..." ); fflush( stdout ); + while( ( ret = ssl_renegotiate( &ssl ) ) != 0 ) { if( ret != POLARSSL_ERR_NET_WANT_READ && @@ -1603,8 +1620,13 @@ reset: goto reset; } } + + printf( " ok\n" ); } + /* + * 7. Write the 200 Response + */ printf( " > Write to client:" ); fflush( stdout ); @@ -1632,45 +1654,24 @@ reset: buf[written] = '\0'; printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); - if( opt.renegotiate ) - { - /* - * Should be a while loop, not an if, but here we're not actually - * expecting data from the client, and since we're running tests - * locally, we can just hope the handshake will finish the during the - * first call. - */ - if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 ) - { - if( ret != POLARSSL_ERR_NET_WANT_READ && - ret != POLARSSL_ERR_NET_WANT_WRITE ) - { - printf( " failed\n ! ssl_read returned %d\n\n", ret ); - - /* Unexpected message probably means client didn't renegotiate - * as requested */ - if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ) - goto reset; - else - goto exit; - } - } - - printf( " ok\n" ); - } /* - * 8. Close the connection cleanly + * 7b. Continue doing data exchanges? + */ + if( --exchanges > 0 ) + goto data_exchange; + + /* + * 8. Done, cleanly close the connection */ close_notify: printf( " . Closing the connection..." ); while( ( ret = ssl_close_notify( &ssl ) ) < 0 ) { - printf( " ret = %d (-0x%04X)", ret, -ret ); if( ret == POLARSSL_ERR_NET_CONN_RESET ) { - printf( " connection was reset by peer\n" ); + printf( " ok (already closed by peer)\n" ); ret = 0; goto reset; } diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 63258cc60..e05019fa6 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -564,8 +564,8 @@ run_test "Max fragment length #3" \ # Tests for renegotiation run_test "Renegotiation #0 (none)" \ - "$P_SRV debug_level=4" \ - "$P_CLI debug_level=4" \ + "$P_SRV debug_level=4 exchanges=2" \ + "$P_CLI debug_level=4 exchanges=2" \ 0 \ -C "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -577,8 +577,8 @@ run_test "Renegotiation #0 (none)" \ -S "write hello request" run_test "Renegotiation #1 (enabled, client-initiated)" \ - "$P_SRV debug_level=4 renegotiation=1" \ - "$P_CLI debug_level=4 renegotiation=1 renegotiate=1" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ 0 \ -c "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -590,8 +590,8 @@ run_test "Renegotiation #1 (enabled, client-initiated)" \ -S "write hello request" run_test "Renegotiation #2 (enabled, server-initiated)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1" \ - "$P_CLI debug_level=4 renegotiation=1" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=1" \ 0 \ -c "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -603,8 +603,8 @@ run_test "Renegotiation #2 (enabled, server-initiated)" \ -s "write hello request" run_test "Renegotiation #3 (enabled, double)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1" \ - "$P_CLI debug_level=4 renegotiation=1 renegotiate=1" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ 0 \ -c "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -616,8 +616,8 @@ run_test "Renegotiation #3 (enabled, double)" \ -s "write hello request" run_test "Renegotiation #4 (client-initiated, server-rejected)" \ - "$P_SRV debug_level=4 renegotiation=0" \ - "$P_CLI debug_level=4 renegotiation=1 renegotiate=1" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=0" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ 1 \ -c "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -631,8 +631,8 @@ run_test "Renegotiation #4 (client-initiated, server-rejected)" \ -c "failed" run_test "Renegotiation #5 (server-initiated, client-rejected, default)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1" \ - "$P_CLI debug_level=4 renegotiation=0" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=0" \ 0 \ -C "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -646,9 +646,9 @@ run_test "Renegotiation #5 (server-initiated, client-rejected, default)" \ -S "failed" run_test "Renegotiation #6 (server-initiated, client-rejected, not enforced)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1 \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1 \ renego_delay=-1" \ - "$P_CLI debug_level=4 renegotiation=0" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=0" \ 0 \ -C "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -661,10 +661,11 @@ run_test "Renegotiation #6 (server-initiated, client-rejected, not enforced)" -S "SSL - An unexpected message was received from our peer" \ -S "failed" -run_test "Renegotiation #7 (server-initiated, client-rejected, delay 1)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1 \ - renego_delay=1" \ - "$P_CLI debug_level=4 renegotiation=0" \ +# delay 2 for 1 alert record + 1 application data record +run_test "Renegotiation #7 (server-initiated, client-rejected, delay 2)" \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1 \ + renego_delay=2" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=0" \ 0 \ -C "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -678,9 +679,9 @@ run_test "Renegotiation #7 (server-initiated, client-rejected, delay 1)" \ -S "failed" run_test "Renegotiation #8 (server-initiated, client-rejected, delay 0)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1 \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1 \ renego_delay=0" \ - "$P_CLI debug_level=4 renegotiation=0" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=0" \ 0 \ -C "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \ @@ -690,13 +691,12 @@ run_test "Renegotiation #8 (server-initiated, client-rejected, delay 0)" \ -C "=> renegotiate" \ -S "=> renegotiate" \ -s "write hello request" \ - -s "SSL - An unexpected message was received from our peer" \ - -s "failed" + -s "SSL - An unexpected message was received from our peer" run_test "Renegotiation #9 (server-initiated, client-accepted, delay 0)" \ - "$P_SRV debug_level=4 renegotiation=1 renegotiate=1 \ + "$P_SRV debug_level=4 exchanges=2 renegotiation=1 renegotiate=1 \ renego_delay=0" \ - "$P_CLI debug_level=4 renegotiation=1" \ + "$P_CLI debug_level=4 exchanges=2 renegotiation=1" \ 0 \ -c "client hello, adding renegotiation extension" \ -s "received TLS_EMPTY_RENEGOTIATION_INFO" \