comparison h3_ssl_reject_handshake.t @ 1887:1023354f3a41

Tests: ssl_reject_handshake tests with HTTP/3. Notably, LibreSSL fails to properly implement QUIC send_alert callback. It uses to return send_alert result as the result of TLS handshake.
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 23 Feb 2023 17:25:57 +0400
parents
children 8b74936ff2ac
comparison
equal deleted inserted replaced
1886:90a310f3cee6 1887:1023354f3a41
1 #!/usr/bin/perl
2
3 # (C) Sergey Kandaurov
4 # (C) Nginx, Inc.
5
6 # Tests for HTTP/3 protocol, ssl_reject_handshake.
7
8 ###############################################################################
9
10 use warnings;
11 use strict;
12
13 use Test::More;
14
15 BEGIN { use FindBin; chdir($FindBin::Bin); }
16
17 use lib 'lib';
18 use Test::Nginx;
19 use Test::Nginx::HTTP3;
20
21 ###############################################################################
22
23 select STDERR; $| = 1;
24 select STDOUT; $| = 1;
25
26 eval { require Crypt::Misc; die if $Crypt::Misc::VERSION < 0.067; };
27 plan(skip_all => 'CryptX version >= 0.067 required') if $@;
28
29 my $t = Test::Nginx->new()->has(qw/http http_v3/)
30 ->has_daemon('openssl')->plan(7)
31 ->write_file_expand('nginx.conf', <<'EOF');
32
33 %%TEST_GLOBALS%%
34
35 daemon off;
36
37 events {
38 }
39
40 http {
41 %%TEST_GLOBALS_HTTP%%
42
43 add_header X-Name $ssl_server_name;
44
45 server {
46 listen 127.0.0.1:%%PORT_8980_UDP%% quic;
47 server_name localhost;
48
49 ssl_reject_handshake on;
50 }
51
52 server {
53 listen 127.0.0.1:%%PORT_8980_UDP%% quic;
54 server_name virtual;
55
56 ssl_certificate localhost.crt;
57 ssl_certificate_key localhost.key;
58 }
59
60 server {
61 listen 127.0.0.1:%%PORT_8982_UDP%% quic;
62 server_name localhost;
63
64 ssl_certificate localhost.crt;
65 ssl_certificate_key localhost.key;
66 }
67
68 server {
69 listen 127.0.0.1:%%PORT_8982_UDP%% quic;
70 server_name virtual1;
71 }
72
73 server {
74 listen 127.0.0.1:%%PORT_8982_UDP%% quic;
75 server_name virtual2;
76
77 ssl_reject_handshake on;
78 }
79 }
80
81 EOF
82
83 $t->write_file('openssl.conf', <<EOF);
84 [ req ]
85 default_bits = 2048
86 encrypt_key = no
87 distinguished_name = req_distinguished_name
88 [ req_distinguished_name ]
89 EOF
90
91 my $d = $t->testdir();
92
93 foreach my $name ('localhost') {
94 system('openssl req -x509 -new '
95 . "-config $d/openssl.conf -subj /CN=$name/ "
96 . "-out $d/$name.crt -keyout $d/$name.key "
97 . ">>$d/openssl.out 2>&1") == 0
98 or die "Can't create certificate for $name: $!\n";
99 }
100
101 $t->write_file('index.html', '');
102
103 $t->run();
104
105 ###############################################################################
106
107 my $alert = 0x100 + 112; # "unrecognized_name"
108
109 SKIP: {
110 # OpenSSL < 1.1.1j requires TLSv1.3-capable certificates in the default server
111 # See commit "Modify is_tls13_capable() to take account of the servername cb"
112 # Additionally, it was seen with OpenSSL 1.1.1k FIPS as found on RHEL 8.1
113
114 my $got = bad('default', 8980);
115 skip "OpenSSL too old", 3 if $got && $got == 0x100 + 70; # "protocol_version"
116
117 # default virtual server rejected
118
119 TODO: {
120 local $TODO = 'broken send_alert in LibreSSL' if $t->has_module('LibreSSL');
121
122 is(bad('default', 8980), $alert, 'default rejected');
123 is(bad(undef, 8980), $alert, 'absent sni rejected');
124
125 }
126
127 like(get('virtual', 8980), qr/virtual/, 'virtual accepted');
128
129 }
130
131 # non-default server "virtual2" rejected
132
133 like(get('default', 8982), qr/default/, 'default accepted');
134 like(get(undef, 8982), qr/200/, 'absent sni accepted');
135 like(get('virtual1', 8982), qr/virtual1/, 'virtual 1 accepted');
136
137 TODO: {
138 local $TODO = 'broken send_alert in LibreSSL' if $t->has_module('LibreSSL');
139
140 is(bad('virtual2', 8982), $alert, 'virtual 2 rejected');
141
142 }
143
144 ###############################################################################
145
146 sub get {
147 my ($sni, $port) = @_;
148 my $s = Test::Nginx::HTTP3->new($port, sni => $sni);
149 my $sid = $s->new_stream({ host => $sni });
150 my $frames = $s->read(all => [{ sid => $sid, fin => 1 }]);
151
152 my ($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
153 return $frame->{headers}->{':status'}
154 . ($frame->{headers}->{'x-name'} || '');
155 }
156
157 sub bad {
158 my ($sni, $port) = @_;
159 my $s = Test::Nginx::HTTP3->new($port, sni => $sni, probe => 1);
160 my $frames = $s->read(all => [{ type => "CONNECTION_CLOSE" }]);
161
162 my ($frame) = grep { $_->{type} eq "CONNECTION_CLOSE" } @$frames;
163 return $frame->{error};
164 }
165
166 ###############################################################################