Bug#914034: Bug#911938: libhttp-daemon-ssl-perl FTBFS: tests fail: Connection refused

Steffen Ullrich coyote.frank at gmx.net
Sat May 11 20:56:01 BST 2019


I think the issue is a  bit different than what was analyzed so far.
As far as I can see it has nothing to do with SSL_MODE_AUTO_RETRY but
instead is caused by expectations on the behavior of select which are wrong
with TLS 1.3.

I've added some more debugging to IO::Socket::SSL and what I saw was:

- With TLS 1.2 LWP did first a write to send the request and then a read to
  read the response - that's expected.
- With TLS 1.3 LWP first tried to read the response and then hang there,
  i.e. no request was even send to the server. This is obviously not what is
  expected.

The reason for this is that LWP::protocol::http::request does not actually
try to write the request first. Instead it creates a select-loop to wait for
both read and write events on the socket and then acts based on what event
select returns.

The obvious expectation is, that there is nothing to read first but that
it will be able to write the request. After the request is sent it will
disable selecting for write-events and only care about reads.

Only, with TLS 1.3 this expectation is wrong.
Up to TLS 1.2 issuing session tickets by the server were part of the TLS
handshake. With TLS 1.3 this is no longer the case and these are send after
the TLS handshake is done. This means that the initial select will actually
trigger a read-event since there are actual data to read on the underlying
socket: the session tickets send by the server.
Only, these are no application data. But sysread on a blocking socket is
supposed to only return if there was at least 1 byte read or if the peer
closed the connection or if a permanent error occured. And since no
application data were send it just hangs.

I don't see how this can be fixed in IO::Socket::SSL only since the real
problem is that sysread is called at this stage (i.e. no request sent yet)
in the first place. Instead the code which is making the wrong assumptions
about select need to be fixed, so that sysread either not get called at this
stage or at least not get called with blocking.

The following small patch for LWP::protocol::http seems to fix the
problem for me:

--- /usr/share/perl5/LWP/Protocol/http.pm       2019-05-11 19:05:21.488561325 +0000
+++ lib/LWP/Protocol/http.pm   2019-05-11 19:40:49.332810627 +0000
@@ -374,7 +374,9 @@
            if (defined($rbits) && $rbits =~ /[^\0]/) {
                # readable
                my $buf = $socket->_rbuf;
+               my $was_blocking = $socket->blocking(0);
                my $n = $socket->sysread($buf, 1024, length($buf));
+               $socket->blocking(1) if $was_blocking;
                 unless (defined $n) {
                     die "read failed: $!" unless  $!{EINTR} || $!{EWOULDBLOCK} || $!{EAGAIN};
                     # if we get here the rest of the block will do nothing


Regards,
Steffen



More information about the pkg-perl-maintainers mailing list