Subject: | t/connect_hook_nodata.t fails with OpenSSL 1.1.1 |
OpenSSL released 1.1.1 prerelease that implements TLSv1.3 and enables it by default. TLSv1.3 differs from TLSv1.2 and patched Net-SSLeay (CPAN RT#125218) is needed. With these a POE-Component-SSLify-1.012 test still fails:
$ perl -Ilib t/connect_hook_nodata.t
ok 1 - SERVER: SSLify_Options
ok 2 - SERVER: Server_SSLify
ok 3 - SERVER: SSLify_GetStatus is pending
ok 4 - SERVER: accepted
ok 5 - CLIENT: Client_SSLify
ok 6 - CLIENT: SSLify_GetStatus is pending
ok 7 - CLIENT: connected
ok 8 - CLIENT: Got callback hook
ok 9 - CLIENT: Status received from callback is OK
ok 10 - CLIENT: SSLify_GetCipher: TLS_AES_256_GCM_SHA384
ok 11 - CLIENT: SSLify_GetStatus is done
ok 12 - SERVER: Got callback hook
not ok 13 - SERVER: Status received from callback is OK
# Failed test 'SERVER: Status received from callback is OK'
# at t/connect_hook_nodata.t line 57.
# got: '0'
# expected: '1'
ok 14 - SERVER: SSLify_GetCipher: TLS_AES_256_GCM_SHA384
not ok 15 - SERVER: SSLify_GetStatus is done
# Failed test 'SERVER: SSLify_GetStatus is done'
# at t/connect_hook_nodata.t line 62.
ok 16 - SERVER: client disconnected
1..16
# Looks like you failed 2 tests of 16.
There are other differences in TLS resulting in SIGPIPE OpenSSL issue <https://github.com/openssl/openssl/issues/6904#issuecomment-411811600> being more prominent. (In short, if a client closes TCP connection to fast, TLS server will fail in SSL_accept() on EPIPE error from writing to the server socket descriptor). And this cannot be masked by Net-SSLeay because Net-SSLeay is a low-level wrapper exposing bare OpenSSL API.
After adding some debugging to ServerHandle::_check_status() one can see it's because the of the same SIGIPE issue:
$ perl -Ilib t/connect_hook_nodata.t
ok 1 - SERVER: SSLify_Options
ok 2 - SERVER: Server_SSLify
ok 3 - SERVER: SSLify_GetStatus is pending
ok 4 - SERVER: accepted
ok 5 - CLIENT: Client_SSLify
ok 6 - CLIENT: SSLify_GetStatus is pending
ok 7 - CLIENT: connected
not ok 8 - Test::FailWarnings should catch no warnings
# Failed test 'Test::FailWarnings should catch no warnings'
# at lib/POE/Component/SSLify/ServerHandle.pm line 74.
# Warning was '_check_status(): status=-1, errval=2, errno=Resource temporarily unavailable at lib/POE/Component/SSLify/ServerHandle.pm line 74.'
ok 9 - CLIENT: Got callback hook
ok 10 - CLIENT: Status received from callback is OK
ok 11 - CLIENT: SSLify_GetCipher: TLS_AES_256_GCM_SHA384
ok 12 - CLIENT: SSLify_GetStatus is done
not ok 13 - Test::FailWarnings should catch no warnings
# Failed test 'Test::FailWarnings should catch no warnings'
# at lib/POE/Component/SSLify/ServerHandle.pm line 74.
# Warning was '_check_status(): status=-1, errval=5, errno=Broken pipe at lib/POE/Component/SSLify/ServerHandle.pm line 74.'
ok 14 - SERVER: Got callback hook
not ok 15 - SERVER: Status received from callback is OK
# Failed test 'SERVER: Status received from callback is OK'
# at t/connect_hook_nodata.t line 57.
# got: '0'
# expected: '1'
ok 16 - SERVER: SSLify_GetCipher: TLS_AES_256_GCM_SHA384
not ok 17 - SERVER: SSLify_GetStatus is done
# Failed test 'SERVER: SSLify_GetStatus is done'
# at t/connect_hook_nodata.t line 62.
ok 18 - SERVER: client disconnected
1..18
# Looks like you failed 4 tests of 18.
As POE-Component-SSLify is a high-level abstraction, I believe this is the right place for handling the SIGPIPE issue. I believe it can be fixed by properly shutting down the TLS connection. Although this will not help if a foreign TLS client does not perform proper TLS shutdown. But there is not much to do except from pressing OpenSSL developers to resolve the SIGPIPE issue internally.