Ticket #238: sni_tests.diff

File sni_tests.diff, 4.8 KB (added by vl, 14 years ago)
  • lib/Test/Nginx.pm

    # HG changeset patch
    # User Valentin Bartenev <ne@vbart.ru>
    # Date 1347892340 -14400
    # Node ID 21c20b866f5a40417d22d8adf7929df8faa63fb2
    # Parent  62114a0c13896f1bb83410fb9544bcf5488d0706
    Tests: https sni tests.
    
    diff -r 62114a0c1389 -r 21c20b866f5a lib/Test/Nginx.pm
    a b sub has_module($) {  
    6969
    7070        my %regex = (
    7171                mail    => '--with-mail(?!\S)',
     72                ssl     => '--with-http_ssl_module',
     73                sni     => 'TLS SNI support enabled',
    7274                flv     => '--with-http_flv_module',
    7375                perl    => '--with-http_perl_module',
    7476                charset => '(?s)^(?!.*--without-http_charset_module)',
    … … sub http($;%) {  
    387389                local $SIG{ALRM} = sub { die "timeout\n" };
    388390                local $SIG{PIPE} = sub { die "sigpipe\n" };
    389391                alarm(2);
    390                 my $s = IO::Socket::INET->new(
     392                my $s = $extra{socket} || IO::Socket::INET->new(
    391393                        Proto => 'tcp',
    392394                        PeerAddr => '127.0.0.1:8080'
    393395                );
  • new file ssl_sni.t

    diff -r 62114a0c1389 -r 21c20b866f5a ssl_sni.t
    - +  
     1#!/usr/bin/perl
     2
     3# (C) Maxim Dounin
     4# (C) Valentin Bartenev
     5
     6# Tests for Server Name Indication (SNI) TLS extension
     7
     8###############################################################################
     9
     10use warnings;
     11use strict;
     12
     13use Test::More;
     14
     15BEGIN { use FindBin; chdir($FindBin::Bin); }
     16
     17use lib 'lib';
     18use Test::Nginx;
     19
     20###############################################################################
     21
     22select STDERR; $| = 1;
     23select STDOUT; $| = 1;
     24
     25eval "use IO::Socket::SSL 1.56";
     26Test::More::plan(skip_all => "IO::Socket::SSL >= 1.56 not found") if $@;
     27
     28my $t = Test::Nginx->new()->has(qw/http ssl sni rewrite/)
     29        ->has_daemon('openssl')->plan(6)
     30        ->write_file_expand('nginx.conf', <<'EOF');
     31
     32%%TEST_GLOBALS%%
     33
     34daemon         off;
     35
     36events {
     37}
     38
     39http {
     40    %%TEST_GLOBALS_HTTP%%
     41
     42    ssl_certificate_key test.key;
     43
     44    server {
     45        listen       127.0.0.1:4433 ssl;
     46        server_name  localhost;
     47
     48        ssl_certificate localhost.crt;
     49
     50        underscores_in_headers off;
     51
     52        location / {
     53            return 200 $server_name;
     54        }
     55    }
     56
     57    server {
     58        listen       127.0.0.1:4433;
     59        server_name  example.com;
     60
     61        ssl_certificate example.com.crt;
     62
     63        underscores_in_headers on;
     64
     65        location / {
     66            return 200 $server_name;
     67        }
     68
     69        location /header {
     70            return 200 $http_special_header;
     71        }
     72    }
     73}
     74
     75EOF
     76
     77my $d = $t->testdir();
     78
     79system('openssl', 'genrsa', '-out', "$d/test.key", '2048') == 0
     80        or die "system() failed: $?\n";
     81
     82foreach my $crt ('localhost', 'example.com'){
     83        system('openssl', 'req', '-new',
     84                '-subj', '/C=RU/ST=Moscow/L=Moscow/O=test/OU=none'
     85                . "/CN=$crt/emailAddress=test\@$crt/",
     86                '-key', "$d/test.key", '-out', "$d/$crt.csr") == 0
     87                or die "system() failed: $?\n";
     88
     89        system('openssl', 'x509', '-req', '-days', '7', '-in', "$d/$crt.csr",
     90                '-signkey', "$d/test.key", '-out', "$d/$crt.crt") == 0
     91                or die "system() failed: $?\n";
     92}
     93
     94$t->run();
     95
     96###############################################################################
     97
     98is(get_cert_cn(), 'localhost', 'default cert');
     99is(get_cert_cn('example.com'), 'example.com', 'sni cert');
     100
     101like(https_get_host('example.com'), qr!example.com!,
     102        'host exists, sni exists, and host is equal sni');
     103
     104like(https_get_host('example.com', 'example.org'), qr!example.com!,
     105        'host exists, sni not found');
     106
     107TODO: {
     108local $TODO = 'sni restrictions';
     109
     110like(https_get_host('example.com', 'localhost'), qr!400 Bad Request!,
     111        'host exists, sni exists, and host is not equal sni');
     112
     113like(https_get_host('example.org', 'example.com'), qr!400 Bad Request!,
     114        'host not found, sni exists');
     115
     116}
     117
     118###############################################################################
     119
     120sub get_ssl_socket {
     121        my $s = eval {
     122                local $SIG{ALRM} = sub { die "timeout\n" };
     123                local $SIG{PIPE} = sub { die "sigpipe\n" };
     124                my ($host) = @_;
     125                alarm(2);
     126                return IO::Socket::SSL->new(
     127                        Proto => 'tcp',
     128                        PeerAddr => '127.0.0.1:4433',
     129                        SSL_hostname => $host,
     130                        SSL_error_trap => sub { die $_[1] }
     131                );
     132        };
     133        alarm(0);
     134        if ($@) {
     135                log_in("died: $@");
     136                return undef;
     137        }
     138        return $s;
     139}
     140
     141sub get_cert_cn {
     142        my ($host) = @_;
     143        my $s = get_ssl_socket($host) or return undef;
     144        $s->dump_peer_certificate() =~ qr!/CN=([^/]+)/!;
     145        return $1;
     146}
     147
     148sub https_get_host {
     149        my ($host, $sni) = @_;
     150        my $s = get_ssl_socket($sni ? $sni : $host) or return undef;
     151        return http(<<EOF, socket => $s);
     152GET / HTTP/1.0
     153Host: $host
     154
     155EOF
     156}
     157
     158###############################################################################