diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index c63c4f75a1..08b6c8ea31 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -108,6 +108,7 @@ int main( void ) #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_SKIP_CLOSE_NOTIFY 0 #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " #define GET_REQUEST_END "\r\n\r\n" @@ -256,6 +257,7 @@ int main( void ) " options: 1 (non-blocking), 2 (added delays)\n" \ " read_timeout=%%d default: 0 ms (no timeout)\n" \ " max_resend=%%d default: 0 (no resend on timeout)\n" \ + " skip_close_notify=%%d default: 0 (send close_notify)\n" \ "\n" \ USAGE_DTLS \ "\n" \ @@ -344,6 +346,7 @@ struct options int fallback; /* is this a fallback connection? */ int extended_ms; /* negotiate extended master secret? */ int etm; /* negotiate encrypt then mac? */ + int skip_close_notify; /* skip sending the close_notify alert */ } opt; static void my_debug( void *ctx, int level, @@ -562,6 +565,7 @@ int main( int argc, char *argv[] ) opt.fallback = DFL_FALLBACK; opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; + opt.skip_close_notify = DFL_SKIP_CLOSE_NOTIFY; for( i = 1; i < argc; i++ ) { @@ -864,6 +868,12 @@ int main( int argc, char *argv[] ) if( opt.dhmlen < 0 ) goto usage; } + else if( strcmp( p, "skip_close_notify" ) == 0 ) + { + opt.skip_close_notify = atoi( q ); + if( opt.skip_close_notify < 0 || opt.skip_close_notify > 1 ) + goto usage; + } else goto usage; } @@ -1733,10 +1743,25 @@ close_notify: mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); - /* No error checking, the connection might be closed already */ - do ret = mbedtls_ssl_close_notify( &ssl ); - while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); - ret = 0; + /* + * Most of the time sending a close_notify before closing is the right + * thing to do. However, when the server already knows how many messages + * are expected and closes the connection by itself, this alert becomes + * redundant. Sometimes with DTLS this redundancy becomes a problem by + * leading to a race condition where the server might close the connection + * before seeing the alert, and since UDP is connection-less when the + * alert arrives it will be seen as a new connection, which will fail as + * the alert is clearly not a valid ClientHello. This may cause spurious + * failures in tests that use DTLS and resumption with ssl_server2 in + * ssl-opt.sh, avoided by enabling skip_close_notify client-side. + */ + if( opt.skip_close_notify == 0 ) + { + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + } mbedtls_printf( " done\n" ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 26ea124307..9bb5bd8859 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1394,7 +1394,7 @@ run_test "Session resume using tickets: openssl client" \ run_test "Session resume using tickets, DTLS: basic" \ "$P_SRV debug_level=3 dtls=1 tickets=1" \ - "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \ + "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1" \ 0 \ -c "client hello, adding session ticket extension" \ -s "found session ticket extension" \ @@ -1408,7 +1408,7 @@ run_test "Session resume using tickets, DTLS: basic" \ run_test "Session resume using tickets, DTLS: cache disabled" \ "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \ - "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1" \ + "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1" \ 0 \ -c "client hello, adding session ticket extension" \ -s "found session ticket extension" \ @@ -1422,7 +1422,7 @@ run_test "Session resume using tickets, DTLS: cache disabled" \ run_test "Session resume using tickets, DTLS: timeout" \ "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0 ticket_timeout=1" \ - "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 reco_delay=2" \ + "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1 reco_delay=2" \ 0 \ -c "client hello, adding session ticket extension" \ -s "found session ticket extension" \ @@ -1554,7 +1554,7 @@ run_test "Session resume using cache: openssl server" \ run_test "Session resume using cache, DTLS: tickets enabled on client" \ "$P_SRV dtls=1 debug_level=3 tickets=0" \ - "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \ + "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1 skip_close_notify=1" \ 0 \ -c "client hello, adding session ticket extension" \ -s "found session ticket extension" \ @@ -1568,7 +1568,7 @@ run_test "Session resume using cache, DTLS: tickets enabled on client" \ run_test "Session resume using cache, DTLS: tickets enabled on server" \ "$P_SRV dtls=1 debug_level=3 tickets=1" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1" \ 0 \ -C "client hello, adding session ticket extension" \ -S "found session ticket extension" \ @@ -1582,7 +1582,7 @@ run_test "Session resume using cache, DTLS: tickets enabled on server" \ run_test "Session resume using cache, DTLS: cache_max=0" \ "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=0" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1" \ 0 \ -S "session successfully restored from cache" \ -S "session successfully restored from ticket" \ @@ -1591,7 +1591,7 @@ run_test "Session resume using cache, DTLS: cache_max=0" \ run_test "Session resume using cache, DTLS: cache_max=1" \ "$P_SRV dtls=1 debug_level=3 tickets=0 cache_max=1" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1" \ 0 \ -s "session successfully restored from cache" \ -S "session successfully restored from ticket" \ @@ -1600,7 +1600,7 @@ run_test "Session resume using cache, DTLS: cache_max=1" \ run_test "Session resume using cache, DTLS: timeout > delay" \ "$P_SRV dtls=1 debug_level=3 tickets=0" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=0" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1 reco_delay=0" \ 0 \ -s "session successfully restored from cache" \ -S "session successfully restored from ticket" \ @@ -1609,7 +1609,7 @@ run_test "Session resume using cache, DTLS: timeout > delay" \ run_test "Session resume using cache, DTLS: timeout < delay" \ "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=1" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1 reco_delay=2" \ 0 \ -S "session successfully restored from cache" \ -S "session successfully restored from ticket" \ @@ -1618,7 +1618,7 @@ run_test "Session resume using cache, DTLS: timeout < delay" \ run_test "Session resume using cache, DTLS: no timeout" \ "$P_SRV dtls=1 debug_level=3 tickets=0 cache_timeout=0" \ - "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_delay=2" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1 reco_delay=2" \ 0 \ -s "session successfully restored from cache" \ -S "session successfully restored from ticket" \ @@ -5239,9 +5239,9 @@ run_test "DTLS proxy: delay ChangeCipherSpec" \ client_needs_more_time 2 run_test "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ -s "Extra-header:" \ @@ -5250,8 +5250,8 @@ run_test "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, \"short\" RSA handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none" \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 \ force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ 0 \ -s "Extra-header:" \ @@ -5260,8 +5260,8 @@ run_test "DTLS proxy: 3d, \"short\" RSA handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, \"short\" (no ticket, no cli_auth) FS handshake" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none" \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5269,8 +5269,8 @@ run_test "DTLS proxy: 3d, \"short\" (no ticket, no cli_auth) FS handshake" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, FS, client auth" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0" \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=required" \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5278,8 +5278,8 @@ run_test "DTLS proxy: 3d, FS, client auth" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, FS, ticket" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=none" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=1 auth_mode=none" \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5287,8 +5287,8 @@ run_test "DTLS proxy: 3d, FS, ticket" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=1 auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=1" \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=1 auth_mode=required" \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5296,9 +5296,9 @@ run_test "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \ client_needs_more_time 2 run_test "DTLS proxy: 3d, max handshake, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 nbio=2 tickets=1 \ + "$P_SRV dtls=1 hs_timeout=500-10000 nbio=2 tickets=1 \ auth_mode=required" \ - "$P_CLI dtls=1 hs_timeout=250-10000 nbio=2 tickets=1" \ + "$P_CLI dtls=1 hs_timeout=500-10000 nbio=2 tickets=1" \ 0 \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" @@ -5306,10 +5306,10 @@ run_test "DTLS proxy: 3d, max handshake, nbio" \ client_needs_more_time 4 run_test "DTLS proxy: 3d, min handshake, resumption" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 debug_level=3" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ - debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ + debug_level=3 reconnect=1 skip_close_notify=1 read_timeout=1000 max_resend=10 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ -s "a session has been resumed" \ @@ -5320,10 +5320,10 @@ run_test "DTLS proxy: 3d, min handshake, resumption" \ client_needs_more_time 4 run_test "DTLS proxy: 3d, min handshake, resumption, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 debug_level=3 nbio=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ - debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ + debug_level=3 reconnect=1 skip_close_notify=1 read_timeout=1000 max_resend=10 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 nbio=2" \ 0 \ -s "a session has been resumed" \ @@ -5335,9 +5335,9 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, client-initiated renego" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiation=1 debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ renegotiate=1 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5350,9 +5350,9 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, client-initiated renego, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiation=1 debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ renegotiate=1 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5365,10 +5365,10 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, server-initiated renego" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \ debug_level=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ renegotiation=1 exchanges=4 debug_level=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5381,10 +5381,10 @@ client_needs_more_time 4 requires_config_enabled MBEDTLS_SSL_RENEGOTIATION run_test "DTLS proxy: 3d, min handshake, server-initiated renego, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ - "$P_SRV dtls=1 hs_timeout=250-10000 tickets=0 auth_mode=none \ + "$P_SRV dtls=1 hs_timeout=500-10000 tickets=0 auth_mode=none \ psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \ debug_level=2 nbio=2" \ - "$P_CLI dtls=1 hs_timeout=250-10000 tickets=0 psk=abc123 \ + "$P_CLI dtls=1 hs_timeout=500-10000 tickets=0 psk=abc123 \ renegotiation=1 exchanges=4 debug_level=2 nbio=2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \ 0 \ @@ -5398,7 +5398,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 2048" \ - "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \ + "$P_CLI dtls=1 hs_timeout=500-60000 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5407,7 +5407,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 768" \ - "$P_CLI dtls=1 hs_timeout=250-60000 tickets=0" \ + "$P_CLI dtls=1 hs_timeout=500-60000 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5416,7 +5416,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, openssl server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5 protect_hvr=1" \ "$O_SRV -dtls1 -mtu 768" \ - "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2 tickets=0" \ + "$P_CLI dtls=1 hs_timeout=500-60000 nbio=2 tickets=0" \ 0 \ -c "HTTP/1.0 200 OK" @@ -5426,7 +5426,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 2048 -a" \ - "$P_CLI dtls=1 hs_timeout=250-60000" \ + "$P_CLI dtls=1 hs_timeout=500-60000" \ 0 \ -s "Extra-header:" \ -c "Extra-header:" @@ -5437,7 +5437,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server, fragmentation" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 512" \ - "$P_CLI dtls=1 hs_timeout=250-60000" \ + "$P_CLI dtls=1 hs_timeout=500-60000" \ 0 \ -s "Extra-header:" \ -c "Extra-header:" @@ -5448,7 +5448,7 @@ not_with_valgrind # risk of non-mbedtls peer timing out run_test "DTLS proxy: 3d, gnutls server, fragmentation, nbio" \ -p "$P_PXY drop=5 delay=5 duplicate=5" \ "$G_SRV -u --mtu 512" \ - "$P_CLI dtls=1 hs_timeout=250-60000 nbio=2" \ + "$P_CLI dtls=1 hs_timeout=500-60000 nbio=2" \ 0 \ -s "Extra-header:" \ -c "Extra-header:"