Skip Menu |

This queue is for tickets about the IO-Socket-SSL CPAN distribution.

Report information
The Basics
Id: 130276
Status: rejected
Priority: 0/
Queue: IO-Socket-SSL

People
Owner: Nobody in particular
Requestors: jonny [...] sevenmail.net
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Bad arg length for Socket::sockaddr_family
Date: Thu, 8 Aug 2019 13:42:01 +0200
To: bug-IO-Socket-SSL [...] rt.cpan.org
From: Jonny Schulz <jonny [...] sevenmail.net>
Hello together, the IO::Socket::SSL module in Debian Buster has the issue, that peeraddr/peerhost is empty or throwing an error if the client closing the connection after accept(). That happends not if I use IO::Socket::INET. Here is the example code: --- #!/usr/bin/perl use strict; use warnings; use IO::Socket::SSL; use IO::Socket::INET; my $sock = IO::Socket::SSL->new( Listen => 5, LocalAddr => "127.0.0.1", Proto => 'tcp', SSL_cert_file => 'server.cert', SSL_key_file => 'server.key', ) or die $!; my $port = $sock->sockport; my $pid = fork; if ($pid) { my $client = $sock->accept; sleep 1; # socket will be closed in this time print "peerhost = ", $client->peerhost, "\n"; print "peeraddr = ", $client->peeraddr, "\n"; } else { my $sock = IO::Socket::SSL->new( PeerAddr => "127.0.0.1", PeerPort => $port, Proto => 'tcp', SSL_verify_mode => SSL_VERIFY_NONE ) or die $!; $sock->close(); } --- Output: Use of uninitialized value in print at test-ssl.pl line 21. peerhost = Use of uninitialized value in subroutine entry at /usr/share/perl/5.28/IO/Socket/IP.pm line 541. Bad arg length for Socket::sockaddr_family, length is 0, should be at least 2 at /usr/share/perl/5.28/IO/Socket/IP.pm line 541. Regards Jonny
This seems to be an issue which is new with TLS 1.3. With TLS 1.2 and lower the handshake is done from the view of the client when it receives the Finished message from the server. The handshake is done from the view of the server when it sends this Finished message. This means that the server is done earlier with the handshake than the client. With TLS 1.3 the handshake is done from the view of the client after sending the Finished message. The handshake is done from the view of the server after receiving the clients Finished message. This means that the server is later than the client with the handshake. On top of that the server sends session tickets to the client after the handshake is finished. In your code the client closes the connection immediately after establishing it. This means that the connection is closed on the client before the SSL handshake is finished by the server. The handshake on the server will be completed though since the FIN from the client (shutdown of the TCP connection) will be processed only after the Finished from the client is read. The server will thus attempt to send the session tickets to the client. But this will result in a Connection Reset from the client since the socket is already closed on the client side. This will close the underlying socket on the server so that the following getpeername will fail since the socket is no longer connected. Unfortunately there is no way to transparently handle the case from within IO::Socket::SSL since there is a race condition. It might well be that the write of the session tickets was successful from the view of the server since the FIN was not received yet. But once the client gets these data on the closed socket it will respond with a RST, which then disconnects the socket inside the servers kernel. This can happen after the SSL_accept returned, i.e. somewhere between your sleep 1 started and ended. In other words: you have to deal with the case that a socket might disconnect yourself in your code. This is actually the same with plain TCP, altough here it is more clear from the view of an application when data are written and thus when such errors might occure.