[PATCH 03 of 11] Tests: added has_feature() tests for IO::Socket::SSL

Sergey Kandaurov pluknet at nginx.com
Wed May 3 16:20:02 UTC 2023


> On 17 Apr 2023, at 07:31, Maxim Dounin <mdounin at mdounin.ru> wrote:
> 
> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1681702252 -10800
> #      Mon Apr 17 06:30:52 2023 +0300
> # Node ID f704912ed09f3494a815709710c3744b0adca50b
> # Parent  6f0148ef1991d92a003c8529c8cce9a8dd49e706
> Tests: added has_feature() tests for IO::Socket::SSL.
> 
> The following distinct features supported:
> 
> - "socket_ssl", which requires IO::Socket::SSL and also implies
>  existance of the IO::Socket::SSL::SSL_VERIFY_NONE() symbol.
>  It is used by most of the tests.
> 

SSL_VERIFY_NONE was added in IO::Socket::SSL 1.31 (2009.09.25).
The check was added primarily for then supported CentOS 5.
Now CentOS 5 is long obsolete, SSL_VERIFY_NONE can be dropped.

Most popular modern distributions have something of IO::Socket::SSL 2.0xx,
the oldest still supported CentOS 7 has IO::Socket::SSL 1.94.

> - "socket_ssl_sni", which requires IO::Socket::SSL with the can_client_sni()
>  function (1.84), and SNI support available in Net::SSLeay and the OpenSSL
>  library being used.  Used by ssl_sni.t, ssl_sni_sessions.t,
>  stream_ssl_preread.t.  Additional Net::SSLeay testing is believed to be
>  unneeded and was removed.
> 

I agree that Net::SSLeay is believed to be redundant: properly implemented
IO::Socket::SSL should detect Net::SSLeay is too old and behave accordingly.

Note that you removed can_client_sni() from h2_ssl_verify_client.t.
In fact, it is replaced with "socket_ssl_alpn".  ALPN support was added
to IO::Socket::SSL after SNI, so it should work in practice, although not
evident.  Formally, the "socket_ssl_sni" prerequisite needs to be added.

On the other way, can_client_sni() was added in 1.83, while SNI support
factually was added noticeably earlier - in version 1.56, via SSL_hostname.
Using IO::Socket::SSL 1.82 allowed me to run the following tests
that would be otherwise skipped due to socket_ssl_sni:

ssl_sni.t - replacing with "socket_ssl" is enough
stream_ssl_preread.t - replacing with "socket_ssl" is enough
ssl_sni_sessions.t - also needs SSL_VERIFY_NONE in get_ssl_socket()
to stop whining on old IO::Socket::SSL that presumably doesn't get it
from $ctx.  It won't run anyway though due to IO::Socket::SSL version
is too old to support TLSv1.3 sessions.

If we tend to drop anything older than 1.94 (CentOS 7), then we can freely
drop "socket_ssl_sni" from the patch.  SSL_hostname is already there.

diff --git a/lib/Test/Nginx.pm b/lib/Test/Nginx.pm
--- a/lib/Test/Nginx.pm
+++ b/lib/Test/Nginx.pm
@@ -244,15 +244,9 @@ sub has_feature($) {
 	if ($feature =~ /^socket_ssl/) {
 		eval { require IO::Socket::SSL; };
 		return 0 if $@;
-		eval { IO::Socket::SSL::SSL_VERIFY_NONE(); };
-		return 0 if $@;
 		if ($feature eq 'socket_ssl') {
 			return 1;
 		}
-		if ($feature eq 'socket_ssl_sni') {
-			eval { IO::Socket::SSL->can_client_sni() or die; };
-			return !$@;
-		}
 		if ($feature eq 'socket_ssl_alpn') {
 			eval { IO::Socket::SSL->can_alpn() or die; };
 			return !$@;
diff --git a/ssl_sni.t b/ssl_sni.t
--- a/ssl_sni.t
+++ b/ssl_sni.t
@@ -22,7 +22,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http http_ssl sni rewrite socket_ssl_sni/)
+my $t = Test::Nginx->new()->has(qw/http http_ssl sni rewrite socket_ssl/)
 	->has_daemon('openssl')->plan(8)
 	->write_file_expand('nginx.conf', <<'EOF');
 
diff --git a/ssl_sni_sessions.t b/ssl_sni_sessions.t
--- a/ssl_sni_sessions.t
+++ b/ssl_sni_sessions.t
@@ -21,7 +21,7 @@ use Test::Nginx;
 select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
-my $t = Test::Nginx->new()->has(qw/http http_ssl sni rewrite socket_ssl_sni/)
+my $t = Test::Nginx->new()->has(qw/http http_ssl sni rewrite socket_ssl/)
 	->has_daemon('openssl')
 	->write_file_expand('nginx.conf', <<'EOF');
 
@@ -177,6 +177,7 @@ sub get_ssl_socket {
 			PeerPort => $port,
 			SSL_hostname => $host,
 			SSL_reuse_ctx => $ctx,
+			SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(),
 			SSL_error_trap => sub { die $_[1] }
 		);
 		alarm(0);
diff --git a/stream_ssl_preread.t b/stream_ssl_preread.t
--- a/stream_ssl_preread.t
+++ b/stream_ssl_preread.t
@@ -24,7 +24,7 @@ select STDERR; $| = 1;
 select STDOUT; $| = 1;
 
 my $t = Test::Nginx->new()->has(qw/stream stream_map stream_ssl_preread/)
-	->has(qw/stream_ssl stream_return socket_ssl_sni/)
+	->has(qw/stream_ssl stream_return socket_ssl/)
 	->has_daemon('openssl')->plan(13)
 	->write_file_expand('nginx.conf', <<'EOF');
 

> - "socket_ssl_alpn", which requires IO::Socket::SSL with ALPN support (2.009),
>  and ALPN support in Net::SSLeay and the OpenSSL library being used.
>  Used by h2_ssl.t, h2_ssl_verify_client.t, stream_ssl_alpn.t,
>  stream_ssl_preread_alpn.t.
> 
> - "socket_ssl_sslversion", which requires IO::Socket::SSL with
>  the get_sslversion() and get_sslversion_int() methods (1.964).
>  Used by mail_imap_ssl.t.

I don't like that the whole mail_imap_ssl.t is skipped on < 1.964
(even though it is not quite new and most distributions have it now),
because of a minor optional feature that could not be tested.
In principle, we can rewrite the test similar to $ssl_protocol
to avoid dependency on 1.964:

diff --git a/mail_imap_ssl.t b/mail_imap_ssl.t
--- a/mail_imap_ssl.t
+++ b/mail_imap_ssl.t
@@ -29,7 +29,7 @@ select STDOUT; $| = 1;
 local $SIG{PIPE} = 'IGNORE';
 
 my $t = Test::Nginx->new()
-	->has(qw/mail mail_ssl imap http rewrite socket_ssl_sslversion/)
+	->has(qw/mail mail_ssl imap http rewrite socket_ssl/)
 	->has_daemon('openssl')->plan(13)
 	->write_file_expand('nginx.conf', <<'EOF');
 
@@ -209,12 +209,9 @@ my $s = Test::Nginx::IMAP->new(PeerAddr 
 
 # Auth-SSL-Protocol and Auth-SSL-Cipher headers
 
-my ($cipher, $sslversion);
+$s = get_ssl_socket(8143);
 
-$s = get_ssl_socket(8143);
-$cipher = $s->get_cipher();
-$sslversion = $s->get_sslversion();
-$sslversion =~ s/_/./;
+my $cipher = $s->get_cipher();
 
 undef $s;
 
@@ -237,7 +234,7 @@ TODO: {
 local $TODO = 'not yet' unless $t->has_version('1.21.2');
 
 $f = $t->read_file('auth2.log');
-like($f, qr|^$cipher:$sslversion$|m, 'log - cipher sslversion');
+like($f, qr/^$cipher:(TLS|SSL)v(\d|\.)+$/m, 'log - cipher sslversion');
 
 }
 

> 
> - "socket_ssl_reused", which requires IO::Socket::SSL with
>  the get_session_reused() method (2.057).  To be used in the following
>  patches.
> 
> This makes it possible to simplify and unify various SSL tests.

[..]

-- 
Sergey Kandaurov


More information about the nginx-devel mailing list