Merge pull request #3060 from mpg/skip-close-notify-2.16

[backport 2.16] Fix possible close_notify/ClientHello confusion
This commit is contained in:
Manuel Pégourié-Gonnard 2020-03-03 12:11:56 +01:00 committed by GitHub
commit d7c2737f40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 21 deletions

View file

@ -115,6 +115,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"
@ -278,6 +279,7 @@ int main( void )
" options: 1 (level-triggered, implies nbio=1),\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" \
@ -376,6 +378,7 @@ struct options
int dgram_packing; /* allow/forbid datagram packing */
int extended_ms; /* negotiate extended master secret? */
int etm; /* negotiate encrypt then mac? */
int skip_close_notify; /* skip sending the close_notify alert */
} opt;
int query_config( const char *config );
@ -653,6 +656,7 @@ int main( int argc, char *argv[] )
opt.extended_ms = DFL_EXTENDED_MS;
opt.etm = DFL_ETM;
opt.dgram_packing = DFL_DGRAM_PACKING;
opt.skip_close_notify = DFL_SKIP_CLOSE_NOTIFY;
for( i = 1; i < argc; i++ )
{
@ -993,6 +997,12 @@ int main( int argc, char *argv[] )
{
return query_config( q );
}
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;
}
@ -2032,10 +2042,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" );

View file

@ -1575,7 +1575,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" \
@ -1589,7 +1589,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" \
@ -1603,7 +1603,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" \
@ -1735,7 +1735,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" \
@ -1749,7 +1749,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" \
@ -1763,7 +1763,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" \
@ -1772,7 +1772,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" \
@ -1781,7 +1781,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" \
@ -1790,7 +1790,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" \
@ -1799,7 +1799,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" \
@ -3348,19 +3348,19 @@ run_test "Event-driven I/O, DTLS: ticket + client auth" \
run_test "Event-driven I/O, DTLS: ticket + client auth + resume" \
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1 skip_close_notify=1" \
0 \
-c "Read from server: .* bytes read"
run_test "Event-driven I/O, DTLS: ticket + resume" \
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1 skip_close_notify=1" \
0 \
-c "Read from server: .* bytes read"
run_test "Event-driven I/O, DTLS: session-id resume" \
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=none" \
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1 skip_close_notify=1" \
0 \
-c "Read from server: .* bytes read"
@ -3372,7 +3372,7 @@ run_test "Event-driven I/O, DTLS: session-id resume" \
run_test "Event-driven I/O, DTLS: session-id resume, UDP packing" \
-p "$P_PXY pack=50" \
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=required" \
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1 skip_close_notify=1" \
0 \
-c "Read from server: .* bytes read"
@ -6378,7 +6378,7 @@ run_test "DTLS fragmenting: proxy MTU, resumed handshake" \
key_file=data_files/server8.key \
hs_timeout=10000-60000 \
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \
mtu=1450 reconnect=1 reco_delay=1" \
mtu=1450 reconnect=1 skip_close_notify=1 reco_delay=1" \
0 \
-S "autoreduction" \
-s "found fragmented DTLS handshake message" \
@ -7225,7 +7225,7 @@ run_test "DTLS proxy: 3d, min handshake, resumption" \
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
psk=abc123 debug_level=3" \
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \
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" \
@ -7239,7 +7239,7 @@ run_test "DTLS proxy: 3d, min handshake, resumption, nbio" \
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
psk=abc123 debug_level=3 nbio=2" \
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
debug_level=3 reconnect=1 read_timeout=1000 max_resend=10 \
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" \