Adapt to OpenSSL 1.1.1

This is not a full support. It only makes the tests passing.
Especially it does not document TLSv1.3 support and it does not
support explicit session resumption in TLSv1.3.

To pass the tests with openssl-1.1.1 it requires patched
perl-Net-SSLeay >= 1.85-7.fc29. But it also works with older openssl
regardless of perl-Net-SSLeay. Thus I did not add a dependency on an
explicit perl-Net-SSLeay release.
This commit is contained in:
Petr Písař 2018-08-21 14:23:06 +02:00
parent 14f244955b
commit e2609f60d1
7 changed files with 433 additions and 1 deletions

View File

@ -0,0 +1,142 @@
From d432295468a1efa18e56c1fbb34e3a23bb07d1e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 16 Aug 2018 14:56:23 +0200
Subject: [PATCH] Adapt to OpenSSL 1.1.1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It needs patched Net-SSLeay (CPAN RT#125218).
This patch introduces some TLSv1.3 identifiers but does not document
them. This is to let the IO-Socket-SSL maintainer to define the API.
This is not a final patch. We need to fix failures in:
t/npn.t
t/session_ticket.t
t/sni_verify.t
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
lib/IO/Socket/SSL.pm | 17 +++++++++++++++--
t/ecdhe.t | 16 +++++++++++-----
t/protocol_version.t | 4 ++--
t/session_ticket.t | 2 ++
4 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/lib/IO/Socket/SSL.pm b/lib/IO/Socket/SSL.pm
index 9c81ffc..5b43467 100644
--- a/lib/IO/Socket/SSL.pm
+++ b/lib/IO/Socket/SSL.pm
@@ -211,7 +211,8 @@ BEGIN{
# get constants for SSL_OP_NO_* now, instead calling the related functions
# every time we setup a connection
my %SSL_OP_NO;
-for(qw( SSLv2 SSLv3 TLSv1 TLSv1_1 TLSv11:TLSv1_1 TLSv1_2 TLSv12:TLSv1_2 )) {
+for(qw( SSLv2 SSLv3 TLSv1 TLSv1_1 TLSv11:TLSv1_1 TLSv1_2 TLSv12:TLSv1_2
+ TLSv1_3 TLSv13:TLSv1_3 )) {
my ($k,$op) = m{:} ? split(m{:},$_,2) : ($_,$_);
my $sub = "Net::SSLeay::OP_NO_$op";
local $SIG{__DIE__};
@@ -1836,6 +1837,7 @@ sub get_sslversion {
my $ssl = shift()->_get_ssl_object || return;
my $version = Net::SSLeay::version($ssl) or return;
return
+ $version == 0x0304 ? 'TLSv1_3' :
$version == 0x0303 ? 'TLSv1_2' :
$version == 0x0302 ? 'TLSv1_1' :
$version == 0x0301 ? 'TLSv1' :
@@ -2281,7 +2283,7 @@ sub new {
my $ver = '';
for (split(/\s*:\s*/,$arg_hash->{SSL_version})) {
- m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1(?:_?[12])?))$}i
+ m{^(!?)(?:(SSL(?:v2|v3|v23|v2/3))|(TLSv1(?:_?[123])?))$}i
or croak("invalid SSL_version specified");
my $not = $1;
( my $v = lc($2||$3) ) =~s{^(...)}{\U$1};
@@ -2329,6 +2331,17 @@ sub new {
IO::Socket::SSL->error("SSL Context init failed");
$CTX_CREATED_IN_THIS_THREAD{$ctx} = 1 if $use_threads;
+ # There is no CTX_tlsv1_3_new(). Create TLSv1.3 only context using
+ # a flexible method.
+ if ($ver eq 'TLSv1_3') {
+ if (!Net::SSLeay::CTX_set_min_proto_version($ctx,
+ Net::SSLeay::TLS1_3_VERSION()) or
+ !Net::SSLeay::CTX_set_max_proto_version($ctx,
+ Net::SSLeay::TLS1_3_VERSION())) {
+ IO::Socket::SSL->error("TLSv1_3 context init failed");
+ }
+ }
+
# SSL_OP_CIPHER_SERVER_PREFERENCE
$ssl_op |= 0x00400000 if $arg_hash->{SSL_honor_cipher_order};
diff --git a/t/ecdhe.t b/t/ecdhe.t
index 638d82b..1b229c5 100644
--- a/t/ecdhe.t
+++ b/t/ecdhe.t
@@ -53,12 +53,18 @@ if ( !defined $pid ) {
};
ok( "client connected" );
- my $cipher = $to_server->get_cipher();
- if ( $cipher !~m/^ECDHE-/ ) {
- notok("bad key exchange: $cipher");
- exit;
+ my $protocol = $to_server->get_sslversion;
+ if ($protocol eq 'TLSv1_3') {
+ # <https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/>
+ ok("# SKIP TLSv1.3 doesn't advertize key exchange in a chipher name");
+ } else {
+ my $cipher = $to_server->get_cipher();
+ if ( $cipher !~m/^ECDHE-/ ) {
+ notok("bad key exchange: $cipher");
+ exit;
+ }
+ ok("ecdh key exchange: $cipher");
}
- ok("ecdh key exchange: $cipher");
} else { ###### Server
diff --git a/t/protocol_version.t b/t/protocol_version.t
index e3853d8..3577720 100644
--- a/t/protocol_version.t
+++ b/t/protocol_version.t
@@ -13,7 +13,7 @@ plan skip_all => "Test::More has no done_testing"
$|=1;
my $XDEBUG = 0;
-my @versions = qw(SSLv3 TLSv1 TLSv1_1 TLSv1_2);
+my @versions = qw(SSLv3 TLSv1 TLSv1_1 TLSv1_2 TLSv1_3);
my $server = IO::Socket::SSL->new(
LocalAddr => '127.0.0.1',
@@ -82,7 +82,7 @@ if ($pid == 0) {
die "best protocol version server supports is $ver" if $supported{foo};
# Check if the OpenSSL was compiled without support for specific protocols
- for(qw(SSLv3 TLSv1 TLSv1_1)) {
+ for(qw(SSLv3 TLSv1 TLSv1_1 TLSv1_2 TLSv1_3)) {
if ( ! $check->($_,'')) {
diag("looks like OpenSSL was compiled without $_ support");
delete $supported{$_};
diff --git a/t/session_ticket.t b/t/session_ticket.t
index d3c15d9..bff6a86 100644
--- a/t/session_ticket.t
+++ b/t/session_ticket.t
@@ -73,6 +73,8 @@ my $client = sub {
};
+# FIXME: TLSv1.3 requires to use SSL_CTX_sess_set_new_cb() by clients instead
+# of SSL_get1_session(). Missing from Net::SSLeay.
$client->(0,0,"no initial session -> no reuse");
$client->(0,1,"reuse with the next session and secret[0]");
$client->(1,1,"reuse even though server changed, since they share ticket secret");
--
2.14.4

View File

@ -0,0 +1,65 @@
From 1d19a7d01960fd8dc00bb3929a1ffaee186470fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Tue, 21 Aug 2018 16:02:19 +0200
Subject: [PATCH] Do two-way shutdown in t/sni.t
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
TLSv1.3 performs more reading and writing in SSL_accept(). If a client
disconnects after the handshake but before the server finishes
SSL_accept(), the t/sni.t test would fail because accept() could fail with
ECONNRESET. This happened randomly.
Failed accept() lead to undef->get_servername() call that triggered
a run-time exception and that caused a client being stucked and the
test script never exited.
This fixes both these issues.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
t/sni.t | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/t/sni.t b/t/sni.t
index de0f06e..91206de 100644
--- a/t/sni.t
+++ b/t/sni.t
@@ -68,15 +68,31 @@ if ( $pid == 0 ) {
$client->verify_hostname($host,'http') or print "not ";
print "ok # client verify hostname in cert $host\n";
+ # Shutdown TLS properly. Otherwise TLSv1.3 $server->accept() fails with
+ # ECONNRESET when a client disconnects too early.
+ $client->close('SSL_fast_shutdown' => 0);
}
exit;
}
+# If the server dies, a client can get stuck in read(2) while Perl interpreter
+# is collecting children status in the die handler using wait4(2).
+$SIG{__DIE__} = sub {
+ STDERR->print("Server died. Killing client with $pid PID.\n");
+ kill(9, $pid);
+};
for my $host (@tests) {
- my $csock = $server->accept or print "not ";
- print "ok # server accept\n";
+ my $csock = $server->accept;
+ if (!$csock) {
+ print "not ok # server accept SSL_ERROR='$SSL_ERROR', errno='$!'";
+ } else {
+ print "ok # server accept\n";
+ }
my $name = $csock->get_servername;
print "not " if ! $name or $name ne $host;
print "ok # server got SNI name $host\n";
+ # Shutdown TLS properly. Otherwise TLSv1.3 $server->accept() fails with
+ # ECONNRESET when a client disconnects too early.
+ $csock->close('SSL_fast_shutdown' => 0);
}
wait;
--
2.14.4

View File

@ -0,0 +1,47 @@
From 84a3bc6c273977bcd4b709e0d9a3d9fcdd58e36d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Fri, 17 Aug 2018 14:46:33 +0200
Subject: [PATCH] Do two-way shutdown in t/sni_verify.t
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OpenSSL 1.1.1-pre7 sigipipes TLSv1.3 server if client does not
shutdown TLS properly.
<https://github.com/openssl/openssl/issues/6904>
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
t/sni_verify.t | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/t/sni_verify.t b/t/sni_verify.t
index b3b299b..b5ac4bd 100644
--- a/t/sni_verify.t
+++ b/t/sni_verify.t
@@ -71,6 +71,13 @@ if ( $pid == 0 ) {
$client->verify_hostname($host,'http') or print "not ";
print "ok # client verify hostname in cert $host\n";
+
+ if ($client) {
+ # Shutdown TLS properly. Otherwise TLSv1.3 server will receive SIGPIPE
+ # in SSL_accept() and dies.
+ # <https://github.com/openssl/openssl/issues/6904>.
+ $client->close('SSL_fast_shutdown' => 0);
+ }
}
exit;
}
@@ -81,5 +88,8 @@ for my $host (@tests) {
my $name = $csock->get_servername;
print "not " if ! $name or $name ne $host;
print "ok # server got SNI name $host\n";
+ if ($csock) {
+ $csock->close('SSL_fast_shutdown' => 0);
+ }
}
wait;
--
2.14.4

View File

@ -0,0 +1,59 @@
From c332d19048735e32e2754685fa3c8654ca068b78 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Tue, 21 Aug 2018 12:32:39 +0200
Subject: [PATCH] Exclude TLSv1.3 from t/session_ticket.t
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The test fails with OpenSSL 1.1.1 because SSL_get1_session() is not
reliable with TLSv1.3. A proper resumption support would need
migration to SSL_CTX_sess_set_new_cb() API.
This patch also performs full SSL_shutdown in the test becasue
SSL_get1_session() manual documents that a connection must be properly
SSL_shutdowned, otherwise the session will be removed from the
(internal) session cache.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
t/session_ticket.t | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/t/session_ticket.t b/t/session_ticket.t
index bff6a86..69cbc96 100644
--- a/t/session_ticket.t
+++ b/t/session_ticket.t
@@ -69,7 +69,7 @@ my $client = sub {
diag("connect to $i: ".
($cl ? "success reuse=$reuse" : "error: $!,$SSL_ERROR"));
is($reuse,$expect_reuse,$desc);
- close($cl);
+ $cl->close('SSL_fast_shutdown' => 0);
};
@@ -123,6 +123,11 @@ sub _server {
SSL_verify_mode => SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
SSL_ticket_keycb => $get_ticket_key,
SSL_session_id_context => 'foobar',
+ SSL_version => 'SSLv23:!TLSv1_3', # TLSv1.3 sends session tickes after
+ # a handshake, this SSL_get1_session() is not reliable anymore.
+ # Exclude TLSv1.3 from tests. Proper TLSv1.3 session resumption
+ # will need SSL_CTX_sess_set_new_cb().
+ # <https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/>
) or die "failed to create SSL context: $SSL_ERROR";
}
@@ -158,7 +163,7 @@ sub _server {
print "rotate secrets\n";
push @secrets, shift(@secrets);
}
- close($cl);
+ $cl->close('SSL_fast_shutdown' => 0);
alarm(0);
last;
}
--
2.14.4

View File

@ -0,0 +1,41 @@
From 12ff43c81b10446bd74cc719f0a6913040598c58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Tue, 21 Aug 2018 16:34:39 +0200
Subject: [PATCH] Fix building on systems without TLSv1.3 support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If OpenSSL does not support TLSv1.3, Net::SSLeay does not have
TLS1_3_VERSION() and t/protocol_version.t fails with:
# Failed test 'Your vendor has not defined SSLeay macro TLS1_3_VERSION at /home/test/fedora/perl-IO-Socket-SSL/IO-Socket-SSL-2.059/blib/lib/IO/Socket/SSL.pm line 2337.
# '
# at ./t/testlib.pl line 39.
This patch fixes creating IO::Socket:SSL context for TLSv1.3 by
checking whether it's supported by Net::SSLeay.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
lib/IO/Socket/SSL.pm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/IO/Socket/SSL.pm b/lib/IO/Socket/SSL.pm
index 5b43467..7138ab0 100644
--- a/lib/IO/Socket/SSL.pm
+++ b/lib/IO/Socket/SSL.pm
@@ -2334,6 +2334,10 @@ sub new {
# There is no CTX_tlsv1_3_new(). Create TLSv1.3 only context using
# a flexible method.
if ($ver eq 'TLSv1_3') {
+ if (!eval {Net::SSLeay::TLS1_3_VERSION()}) {
+ return IO::Socket::SSL->_internal_error(
+ "SSL Version $ver not supported",9);
+ }
if (!Net::SSLeay::CTX_set_min_proto_version($ctx,
Net::SSLeay::TLS1_3_VERSION()) or
!Net::SSLeay::CTX_set_max_proto_version($ctx,
--
2.14.4

View File

@ -0,0 +1,49 @@
From 94b0b52f05911bd8cfe579406248c8afe36004d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Fri, 17 Aug 2018 15:14:40 +0200
Subject: [PATCH] NPN is unavailable in TLSv1.3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
TLSv1.3 does not support NPN. Application can use ALPN. This caused
t/npn.t failures when TLSv1.3 was negotiated. This patch disables
TLSv1.3 in the test.
<https://github.com/openssl/openssl/issues/3665>
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
lib/IO/Socket/SSL.pod | 2 +-
t/npn.t | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/IO/Socket/SSL.pod b/lib/IO/Socket/SSL.pod
index 95401aa..363901b 100644
--- a/lib/IO/Socket/SSL.pod
+++ b/lib/IO/Socket/SSL.pod
@@ -1336,7 +1336,7 @@ as an array ref.
See also method C<next_proto_negotiated>.
Next Protocol Negotiation (NPN) is available with Net::SSLeay 1.46+ and
-openssl-1.0.1+.
+openssl-1.0.1+. NPN is unavailable in TLSv1.3 protocol.
To check support you might call C<< IO::Socket::SSL->can_npn() >>.
If you use this option with an unsupported Net::SSLeay/OpenSSL it will
throw an error.
diff --git a/t/npn.t b/t/npn.t
index 8992a77..6ee6ca6 100644
--- a/t/npn.t
+++ b/t/npn.t
@@ -25,6 +25,8 @@ my $addr = '127.0.0.1';
my $server = IO::Socket::SSL->new(
LocalAddr => $addr,
Listen => 2,
+ SSL_version => 'SSLv23:!TLSv1_3', # NPN does not exist in TLSv1.3
+ # https://github.com/openssl/openssl/issues/3665
SSL_cert_file => 'certs/server-cert.pem',
SSL_key_file => 'certs/server-key.pem',
SSL_npn_protocols => [qw(one two)],
--
2.14.4

View File

@ -1,12 +1,30 @@
Name: perl-IO-Socket-SSL
Version: 2.059
Release: 1%{?dist}
Release: 2%{?dist}
Summary: Perl library for transparent SSL
License: GPL+ or Artistic
URL: https://metacpan.org/release/IO-Socket-SSL
Source0: https://cpan.metacpan.org/modules/by-module/IO/IO-Socket-SSL-%{version}.tar.gz
Patch0: IO-Socket-SSL-2.054-use-system-default-cipher-list.patch
Patch1: IO-Socket-SSL-2.059-use-system-default-SSL-version.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch2: IO-Socket-SSL-2.059-Adapt-to-OpenSSL-1.1.1.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch3: IO-Socket-SSL-2.059-Do-two-way-shutdown-in-t-sni_verify.t.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch4: IO-Socket-SSL-2.059-NPN-is-unavailable-in-TLSv1.3.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch5: IO-Socket-SSL-2.059-Exclude-TLSv1.3-from-t-session_ticket.t.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch6: IO-Socket-SSL-2.059-Do-two-way-shutdown-in-t-sni.t.patch
# Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay, bug #1616198,
# CPAN RT#126899
Patch7: IO-Socket-SSL-2.059-Fix-building-on-systems-without-TLSv1.3-support.patch
BuildArch: noarch
# Module Build
BuildRequires: coreutils
@ -86,6 +104,14 @@ mod_perl.
# Use system-default SSL version too
%patch1
# OpensSSL 1.1.1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%build
NO_NETWORK_TESTING=1 perl Makefile.PL INSTALLDIRS=vendor
make %{?_smp_mflags}
@ -111,6 +137,9 @@ make test
%{_mandir}/man3/IO::Socket::SSL::Utils.3*
%changelog
* Tue Aug 21 2018 Petr Pisar <ppisar@redhat.com> - 2.059-2
- Adapt to OpenSSL 1.1.1, it requires patched Net-SSLeay (bug #1616198)
* Thu Aug 16 2018 Paul Howarth <paul@city-fan.org> - 2.059-1
- Update to 2.059
- Fix memory leak when CRLs are used (CPAN RT#125867)