Skip to content

Commit

Permalink
usable_ca.t: update for current fingerprints (changed after heartblee…
Browse files Browse the repository at this point in the history
…d), check that we have a usable CA for host in CA store

allow PEM in CA store to contain "X509 CERTIFICATE" or "TRUSTED CERTIFICATE" too
  • Loading branch information
noxxi committed Apr 27, 2014
1 parent 6f4638c commit bee7322
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 34 deletions.
4 changes: 2 additions & 2 deletions Makefile.PL
Expand Up @@ -91,7 +91,7 @@ my %usable_ca;
FILES: for my $f ( grep { m{^[a-f\d]{8}(\.\d+)?$} } readdir($dh) ) {
open( my $fh,'<',"$dir/$f") or next;
while (<$fh>) {
m{^-+BEGIN CERTIFICATE-} or next;
m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
$usable_ca{SSL_ca_path} = $dir;
last FILES;
}
Expand All @@ -101,7 +101,7 @@ my %usable_ca;
|| ( $^O =~m{vms}i ? "SSLCERTS:cert.pem":"$openssldir/cert.pem" );
if ( open(my $fh,'<',$file)) {
while (<$fh>) {
m{^-+BEGIN CERTIFICATE-} or next;
m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
$usable_ca{SSL_ca_file} = $file;
last;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/IO/Socket/SSL.pm
Expand Up @@ -311,7 +311,7 @@ BEGIN {
FILES: for my $f ( grep { m{^[a-f\d]{8}(\.\d+)?$} } readdir($dh) ) {
open( my $fh,'<',"$dir/$f") or next;
while (my $line = <$fh>) {
$line =~m{^-+BEGIN CERTIFICATE-} or next;
$line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
$default_ca{SSL_ca_path} = $dir;
last FILES;
}
Expand All @@ -321,7 +321,7 @@ BEGIN {
|| ( $^O =~m{vms}i ? "SSLCERTS:cert.pem":"$openssldir/cert.pem" );
if ( open(my $fh,'<',$file)) {
while (my $line = <$fh>) {
$line =~m{^-+BEGIN CERTIFICATE-} or next;
$line =~m{^-+BEGIN (X509 |TRUSTED |)CERTIFICATE-} or next;
$default_ca{SSL_ca_file} = $file;
last;
}
Expand Down
87 changes: 57 additions & 30 deletions t/external/usable_ca.t
Expand Up @@ -2,6 +2,7 @@ use strict;
use warnings;
use Test::More;
use IO::Socket::SSL;
use IO::Socket::SSL::Utils;

my $ipclass = 'IO::Socket::INET';
for( qw( IO::Socket::IP IO::Socket::INET6 )) {
Expand All @@ -10,61 +11,96 @@ for( qw( IO::Socket::IP IO::Socket::INET6 )) {
last;
}

my %hosts = qw(
www.google.com sha1$baa77df4ce1d50df3466f9258b2394f4c6c6c5b9
www.yahoo.com sha1$764a19e1eb26917ef298cf785ad77bafcebee445
www.comdirect.de sha1$0d9626705b9984b19bca19f8ceb18885b103d0e9
meine.deutsche-bank.de sha1$ba54c47dd5493db54cd0f76a120cac11cdfb76f8
www.twitter.com sha1$256e402523c3418e1e9a0185448458af96c4a1be
www.facebook.com sha1$13d0376c2ab2143640a62d08bb71f5e9ef571361
www.live.com sha1$10c56ee9e2acaf2e77caeb7072bf6522dd7422b8
# host:port fingerprint_cert subject_hash_ca
my @tests = qw(
www.google.com:443 sha1$c0019e434cc04dc9086a6e63c8ecf74781e4f4a0 578d5c04
www.yahoo.com:443 sha1$6b52651caf7b1f306050179d27570d4d5c5bfd24 415660c1
www.comdirect.de:443 sha1$0d9626705b9984b19bca19f8ceb18885b103d0e9 415660c1
meine.deutsche-bank.de:443 sha1$ba54c47dd5493db54cd0f76a120cac11cdfb76f8 415660c1
www.twitter.com:443 sha1$813fd89d264cc9a5bb650d0b2d2bb0d63259bcaa b204d74a
www.facebook.com:443 sha1$bd012a89b2cc9e49f81f47bfbd52de48a04ed3ab 244b5494
www.live.com:443 sha1$10c56ee9e2acaf2e77caeb7072bf6522dd7422b8 415660c1
);


my %ca = IO::Socket::SSL::default_ca();
plan skip_all => "no default CA store found" if ! %ca;

my %have_ca;
for my $f (
( $ca{SSL_ca_file} ? ($ca{SSL_ca_file}) : ()),
( $ca{SSL_ca_path} ? glob("$ca{SSL_ca_path}/*") :()),
) {
open( my $fh,'<',$f ) or next;
my $pem;
while (<$fh>) {
if ( m{^--+END} ) {
my $cert = PEM_string2cert($pem.$_);
$pem = undef;
$cert or next;
my $hash = Net::SSLeay::X509_subject_name_hash($cert);
$have_ca{sprintf("%08x",$hash)} = 1;
} elsif ( m{^--+BEGIN (TRUSTED |X509 |)CERTIFICATE-+} ) {
$pem = $_;
} elsif ( $pem ) {
$pem .= $_;
}
}
}
diag( "found ".(0+keys %have_ca)." CA certs");
plan skip_all => "no CA certs found" if ! %have_ca;

my $proxy = ( $ENV{https_proxy} || $ENV{http_proxy} || '' )
=~m{^(?:\w+://)?([\w\-.:\[\]]+:\d+)/?$} && $1;

my @cap = ('SSL_verifycn_name');
push @cap, 'SSL_hostname' if IO::Socket::SSL->can_client_sni();
plan tests => 1 + (1+@cap)*keys(%hosts);
plan tests => (1+@cap)*(@tests/3);

my $builtin_ca_ok = 0;
my $builtin_ca_fail = 0;
while ( my ($host,$fp) = each %hosts ) {
while ( @tests ) {
my ($host,$fp,$ca_hash) = splice(@tests,0,3);
my $port = $host =~s{:(\d+)$}{} && $1;
SKIP: {
# first check if we can connect at all
# first check if we have the CA in store
skip "no root CA $ca_hash for $host in store",1+@cap
if ! $have_ca{$ca_hash};
diag("have root CA for $host in store");
# then build inet connections for later SSL upgrades
my @cl;
for my $cap ('fp','nocn',@cap,'noca') {
my $cl;
if ( ! $proxy ) {
# direct connection
$cl = $ipclass->new(
PeerAddr => $host,
PeerPort => 443,
PeerPort => $port,
Timeout => 15,
)
} elsif ( $cl = $ipclass->new(
PeerAddr => $proxy,
Timeout => 15
} elsif ( $cl = $ipclass->new(
PeerAddr => $proxy,
Timeout => 15
)) {
# try to establish tunnel via proxy with CONNECT
my $reply = '';
if ( eval {
local $SIG{ALRM} = sub { die "timed out" };
alarm(15);
print $cl "CONNECT $host:443 HTTP/1.0\r\n\r\n";
while (<$cl>) {
while (<$cl>) {
$reply .= $_;
last if m{\A\r?\n\Z};
}
$reply =~m{\AHTTP/1\.[01] 200\b} or
$reply =~m{\AHTTP/1\.[01] 200\b} or
die "unexpected response from proxy: $reply";
}) {
} else {
$cl = undef
}
}
skip "cannot connect to $host:443 with $ipclass: $!",1+@cap
skip "cannot connect to $host:443 with $ipclass: $!",1+@cap
if ! $cl;
push @cl,$cl;
}
Expand All @@ -82,11 +118,9 @@ while ( my ($host,$fp) = each %hosts ) {
# check if it can verify against builtin CA store
$cl = shift(@cl);
if ( ! IO::Socket::SSL->start_SSL($cl)) {
$builtin_ca_fail++;
skip "ssl upgrade failed with builtin CA store",1+@cap;
}
diag("check $host against builtin CA store ok");
$builtin_ca_ok++;
for my $cap (@cap) {
my $cl = shift(@cl);
Expand Down Expand Up @@ -116,10 +150,3 @@ while ( my ($host,$fp) = each %hosts ) {
}
}
}

if ( $builtin_ca_ok + $builtin_ca_fail == 0 ) {
pass("no successful connects, not checking CA usage");
} else {
ok( $builtin_ca_ok,
"verification against builtin CA store: $builtin_ca_ok/".(0+keys %hosts));
}

0 comments on commit bee7322

Please sign in to comment.