comparison ssl_session_ticket_key.t @ 1865:0e1865aa9b33

Tests: reworked http SSL tests to use IO::Socket::SSL. Relevant infrastructure is provided in Test::Nginx http() functions. This also ensures that SSL handshake and various read and write operations are guarded with timeouts. The ssl_sni_reneg.t test uses IO::Socket::SSL::_get_ssl_object() to access the Net::SSLeay object directly and trigger renegotation. While not exactly correct, this seems to be good enough for tests. Similarly, IO::Socket::SSL::_get_ssl_object() is used in ssl_stapling.t, since SSL_ocsp_staple_callback is called with the socket instead of the Net::SSLeay object. Similarly, IO::Socket::SSL::_get_ssl_object() is used in ssl_verify_client.t, since there seems to be no way to obtain CA list with IO::Socket::SSL. Notable change to http() request interface is that http_end() now closes the socket. This is to make sure that SSL connections are properly closed and SSL sessions are not removed from the IO::Socket::SSL session cache. This affected access_log.t, which was modified accordingly.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 18 May 2023 18:07:17 +0300
parents 0381a0a212e1
children 5c50786e5da9
comparison
equal deleted inserted replaced
1864:46351d990aee 1865:0e1865aa9b33
13 use Test::More; 13 use Test::More;
14 14
15 BEGIN { use FindBin; chdir($FindBin::Bin); } 15 BEGIN { use FindBin; chdir($FindBin::Bin); }
16 16
17 use lib 'lib'; 17 use lib 'lib';
18 use Test::Nginx; 18 use Test::Nginx qw/ :DEFAULT http_end /;
19 19
20 ############################################################################### 20 ###############################################################################
21 21
22 select STDERR; $| = 1; 22 select STDERR; $| = 1;
23 select STDOUT; $| = 1; 23 select STDOUT; $| = 1;
24 24
25 eval { 25 eval { require Net::SSLeay; die if $Net::SSLeay::VERSION < 1.86; };
26 require Net::SSLeay; die if $Net::SSLeay::VERSION < 1.86;
27 Net::SSLeay::load_error_strings();
28 Net::SSLeay::SSLeay_add_ssl_algorithms();
29 Net::SSLeay::randomize();
30 };
31 plan(skip_all => 'Net::SSLeay version => 1.86 required') if $@; 26 plan(skip_all => 'Net::SSLeay version => 1.86 required') if $@;
32 27
33 my $t = Test::Nginx->new()->has(qw/http http_ssl/)->has_daemon('openssl') 28 my $t = Test::Nginx->new()->has(qw/http http_ssl socket_ssl/)
34 ->plan(2)->write_file_expand('nginx.conf', <<'EOF'); 29 ->has_daemon('openssl')->plan(2)
30 ->write_file_expand('nginx.conf', <<'EOF');
35 31
36 %%TEST_GLOBALS%% 32 %%TEST_GLOBALS%%
37 33
38 daemon off; 34 daemon off;
39 worker_processes 2; 35 worker_processes 2;
45 %%TEST_GLOBALS_HTTP%% 41 %%TEST_GLOBALS_HTTP%%
46 42
47 ssl_certificate_key localhost.key; 43 ssl_certificate_key localhost.key;
48 ssl_certificate localhost.crt; 44 ssl_certificate localhost.crt;
49 45
46 add_header X-SSL-Protocol $ssl_protocol;
47
50 server { 48 server {
51 listen 127.0.0.1:8080 ssl; 49 listen 127.0.0.1:8443 ssl;
52 server_name localhost; 50 server_name localhost;
53 51
54 ssl_session_cache shared:SSL:1m; 52 ssl_session_cache shared:SSL:1m;
55 ssl_session_timeout 2; 53 ssl_session_timeout 2;
56 } 54 }
73 . "-config $d/openssl.conf -subj /CN=$name/ " 71 . "-config $d/openssl.conf -subj /CN=$name/ "
74 . "-out $d/$name.crt -keyout $d/$name.key " 72 . "-out $d/$name.crt -keyout $d/$name.key "
75 . ">>$d/openssl.out 2>&1") == 0 73 . ">>$d/openssl.out 2>&1") == 0
76 or die "Can't create certificate for $name: $!\n"; 74 or die "Can't create certificate for $name: $!\n";
77 } 75 }
76
77 $t->write_file('index.html', '');
78 78
79 $t->run(); 79 $t->run();
80 80
81 ############################################################################### 81 ###############################################################################
82 82
103 cmp_ok(get_ticket_key_name(), 'ne', $key, 'ticket key next'); 103 cmp_ok(get_ticket_key_name(), 'ne', $key, 'ticket key next');
104 104
105 ############################################################################### 105 ###############################################################################
106 106
107 sub get_ticket_key_name { 107 sub get_ticket_key_name {
108 my $ses = get_ssl_session(); 108 my $asn = get_ssl_session();
109 my $asn = Net::SSLeay::i2d_SSL_SESSION($ses);
110 my $any = qr/[\x00-\xff]/; 109 my $any = qr/[\x00-\xff]/;
111 next: 110 next:
112 # tag(10) | len{2} | OCTETSTRING(4) | len{2} | ticket(key_name|..) 111 # tag(10) | len{2} | OCTETSTRING(4) | len{2} | ticket(key_name|..)
113 $asn =~ /\xaa\x81($any)\x04\x81($any)($any{16})/g; 112 $asn =~ /\xaa\x81($any)\x04\x81($any)($any{16})/g;
114 return '' if !defined $3; 113 return '' if !defined $3;
117 Test::Nginx::log_core('||', "ticket key: $key"); 116 Test::Nginx::log_core('||', "ticket key: $key");
118 return $key; 117 return $key;
119 } 118 }
120 119
121 sub get_ssl_session { 120 sub get_ssl_session {
122 my ($s, $ssl) = get_ssl_socket(); 121 my $cache = IO::Socket::SSL::Session_Cache->new(100);
123 122
124 Net::SSLeay::write($ssl, <<EOF); 123 my $s = http_get(
125 GET / HTTP/1.0 124 '/', start => 1,
126 Host: localhost 125 SSL => 1,
126 SSL_session_cache => $cache,
127 SSL_session_key => 1
128 );
127 129
128 EOF 130 return unless $s;
129 Net::SSLeay::read($ssl); 131 http_end($s);
130 Net::SSLeay::get_session($ssl); 132
133 my $sess = $cache->get_session(1);
134 return '' unless defined $sess;
135 return Net::SSLeay::i2d_SSL_SESSION($sess);
131 } 136 }
132 137
133 sub test_tls13 { 138 sub test_tls13 {
134 my ($s, $ssl) = get_ssl_socket(); 139 return http_get('/', SSL => 1) =~ /TLSv1.3/;
135 return (Net::SSLeay::version($ssl) > 0x303);
136 }
137
138 sub get_ssl_socket {
139 my $s = IO::Socket::INET->new('127.0.0.1:' . port(8080));
140 my $ctx = Net::SSLeay::CTX_new() or die("Failed to create SSL_CTX $!");
141 my $ssl = Net::SSLeay::new($ctx) or die("Failed to create SSL $!");
142 Net::SSLeay::set_fd($ssl, fileno($s));
143 Net::SSLeay::connect($ssl) or die("ssl connect");
144 return ($s, $ssl);
145 } 140 }
146 141
147 ############################################################################### 142 ###############################################################################