blob: bc24f7e39fc24d1b20fd704bef2bea654d6543d6 [file] [log] [blame]
#! /usr/bin/env perl
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
use File::Temp qw(tempdir);
use Net::EmptyPort qw(check_port empty_port);
use POSIX ":sys_wait_h";
use Scope::Guard qw(scope_guard);
use Test::More;
use Time::HiRes qw(sleep);
$ENV{BINARY_DIR} ||= ".";
my $cli = "$ENV{BINARY_DIR}/cli";
my $port = empty_port();
my $tempdir = tempdir(CLEANUP => 1);
my @cli_opts = ();
if ($ENV{PTLSLOG}) {
push @cli_opts, "-j$ENV{PTLSLOG}";
}
subtest "hello" => sub {
my $guard = spawn_server("rsa", qw(-i t/assets/hello.txt));
subtest "full-handshake" => sub {
my $resp = `$cli @cli_opts 127.0.0.1 $port 2> /dev/null`;
is $resp, "hello";
};
subtest "resumption" => sub {
for (1..10) {
my $resp = `$cli @cli_opts -s $tempdir/session 127.0.0.1 $port 2> /dev/null`;
is $resp, "hello";
}
};
};
unlink "$tempdir/session";
subtest "early-data" => sub {
subtest "success" => sub {
plan skip_all => "faketime not found"
unless system("which faketime > /dev/null 2>&1") == 0;
my $guard = spawn_server("rsa", qw(-i t/assets/hello.txt -l), "$tempdir/events");
my $resp = `$cli @cli_opts -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
$resp = `$cli @cli_opts -e -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
like slurp_file("$tempdir/events"), qr/^CLIENT_EARLY_TRAFFIC_SECRET /m;
$resp = `$cli @cli_opts -e -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
is 2, (() = slurp_file("$tempdir/events") =~ /^CLIENT_EARLY_TRAFFIC_SECRET /mg);
# check +15 seconds jitter
$resp = `faketime -f +15 $cli @cli_opts -e -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
is 2, (() = slurp_file("$tempdir/events") =~ /^CLIENT_EARLY_TRAFFIC_SECRET /mg);
# re-fetch the ticket
unlink "$tempdir/session";
$resp = `$cli @cli_opts -e -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
is 2, (() = slurp_file("$tempdir/events") =~ /^CLIENT_EARLY_TRAFFIC_SECRET /mg);
# check -15 seconds jitter
$resp = `faketime -f -15 $cli @cli_opts -e -s $tempdir/session 127.0.0.1 $port`;
is $resp, "hello";
is 2, (() = slurp_file("$tempdir/events") =~ /^CLIENT_EARLY_TRAFFIC_SECRET /mg);
};
};
subtest "certificate-compression" => sub {
plan skip_all => "feature disabled"
unless system("$cli -b -h > /dev/null 2>&1") == 0;
my $guard = spawn_server("rsa", qw(-i t/assets/hello.txt -b));
my $resp = `$cli @cli_opts 127.0.0.1 $port 2> /dev/null`;
is $resp, "hello";
$resp = `$cli @cli_opts -b 127.0.0.1 $port 2> /dev/null`;
is $resp, "hello";
};
# This test acts as an end-to-end testing of the certificate verifier of the OpenSSL backend.
subtest "raw-public-keys" => sub {
my @key_types = do {
my $help = `$cli -h`;
$help =~ /^Supported signature algorithms:\s*(.*)\s*$/m
or die "failed to extract list of supported signature algorithms from $cli -h";
split /,\s*/, $1;
};
die "unexpected list of supported signature algorithms: @key_types"
unless grep /^rsa$/, @key_types;
for my $key_type (@key_types) {
subtest $key_type => sub {
my $guard = spawn_server($key_type, qw(-r - -i t/assets/hello.txt));
my $resp = `$cli @cli_opts -v -r t/assets/$key_type/pub.pem 127.0.0.1 $port 2> /dev/null`;
is $resp, "hello";
};
}
};
done_testing;
sub spawn_server {
my $key_type = shift;
my $cert_type = grep(/^-r$/, @_) ? "pub" : "cert";
my @cmd = ($cli, @cli_opts, "-k", "t/assets/$key_type/key.pem", "-c", "t/assets/$key_type/$cert_type.pem", @_, "127.0.0.1", $port);
my $pid = fork;
die "fork failed:$!"
unless defined $pid;
if ($pid == 0) {
exec @cmd;
die "failed to exec $cmd[0]:$?";
}
while (!check_port($port)) {
sleep 0.1;
}
return scope_guard(sub {
kill 9, $pid;
while (waitpid($pid, 0) != $pid) {}
});
}
sub slurp_file {
my $fn = shift;
open my $fh, "<", $fn
or die "failed to open file:$fn:$!";
do {
local $/;
<$fh>;
};
}