Skip to content

Commit ac18ec5

Browse files
committed
Add trusted certificate check
1 parent cb5eb3c commit ac18ec5

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
lines changed

.github/workflows/linux.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
curl -sL https://cpanmin.us/ | perl - -nq --with-develop --installdeps .
3131
- name: Build Module
3232
run: |
33-
apt-get install make gcc libssl-dev;
33+
apt-get install make gcc libssl-dev openssl;
3434
perl Makefile.PL;
3535
make
3636
- name: Run Tests

META.yml

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ build_requires:
88
File::Slurp: '0'
99
Test::Exception: '0'
1010
Test::More: '0.88'
11+
IO::Socket::SSL: '2.068'
12+
Net::SSLeay: '1.88'
1113
configure_requires:
1214
ExtUtils::MakeMaker: '0'
1315
dynamic_config: 0

Makefile.PL

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ author_requires 'Test::Pod::Coverage' => '1.04';
6767
test_requires 'Test::More' => '0.88';
6868
test_requires 'File::Slurp';
6969
test_requires 'Test::Exception';
70+
test_requires 'IO::Socket::SSL' => '2.068';
71+
test_requires 'Net::SSLeay' => '1.88';
7072

7173
resources
7274
license => "http://dev.perl.org/licenses",

t/07-verify-trusted-cert.t

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
use strict;
2+
use warnings;
3+
use Crypt::OpenSSL::Verify;
4+
use Crypt::OpenSSL::X509;
5+
use IO::Socket::SSL;
6+
use Net::SSLeay;
7+
use Data::Dumper;
8+
use File::Slurp qw{ write_file };
9+
use Test::More;
10+
11+
my $openssl_version = `openssl version`;
12+
$openssl_version =~ /OpenSSL ([\d\.]+)/;
13+
$openssl_version = $1;
14+
15+
my %chain = ();
16+
my $inter_cnt = 1;
17+
18+
my $server_name = 'www.google.com';
19+
20+
sub verify_callback {
21+
my $cert = $_[4];
22+
my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert));
23+
my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert));
24+
25+
$subject =~ /CN=(.*$)/;
26+
$subject = $1;
27+
$issuer =~ /CN=(.*$)/;
28+
$issuer = $1;
29+
if ( $subject eq $server_name ) {
30+
$chain{'server'} = { name => $subject, x509 => Net::SSLeay::PEM_get_string_X509($cert), };
31+
} elsif ( $subject ne $issuer ) {
32+
my $int = 'intermediate' . $inter_cnt;
33+
$chain{'intermediates'} = $inter_cnt;
34+
$chain{$int} = { 'name' => $subject, 'x509' => Net::SSLeay::PEM_get_string_X509($cert), };
35+
$inter_cnt++;
36+
} elsif ( $subject eq $issuer ) {
37+
$chain{'root'} = { 'name' => $subject, 'x509' => Net::SSLeay::PEM_get_string_X509($cert), };
38+
}
39+
return 1;
40+
}
41+
42+
sub get_cert_chain {
43+
my $peer = shift;
44+
IO::Socket::SSL->new(
45+
PeerHost => $peer . ":443",
46+
SSL_verify_callback => \&verify_callback
47+
) or die $SSL_ERROR||$!;
48+
}
49+
50+
get_cert_chain($server_name);
51+
52+
my $cert = $chain{'server'}{'x509'};
53+
54+
my $intermediate = '';
55+
for ( my $i = 1; $i <= $chain{intermediates}; $i++ ) {
56+
$intermediate = $intermediate . $chain{"intermediate$i"}{'x509'} ."\n";
57+
}
58+
59+
write_file('intermediate.pem', $intermediate);
60+
write_file('cert.pem', $cert);
61+
62+
my $ret;
63+
64+
SKIP: {
65+
skip "openSSL not installed", 1 unless `which openssl`;
66+
67+
#say 'OpenSSL verification:';
68+
eval {
69+
$ret = `openssl verify -CAfile intermediate.pem cert.pem`;
70+
};
71+
like($ret, qr/OK/, "OpenSSL verification - OK");
72+
}
73+
74+
#say 'Crypt::OpenSSL::Verify verification:';
75+
my $verifier = Crypt::OpenSSL::Verify->new('intermediate.pem',{strict_certs=>0});
76+
my $cert_object = Crypt::OpenSSL::X509->new_from_string($cert);
77+
my $verify = $verifier->verify($cert_object);
78+
ok($verify, "Crypt::OpenSSL::Verify verification - OK");
79+
80+
$verifier = Crypt::OpenSSL::Verify->new('intermediate.pem',{strict_certs=>1});
81+
$cert_object = Crypt::OpenSSL::X509->new_from_string($cert);
82+
$verify = $verifier->verify($cert_object);
83+
ok($verify, "Crypt::OpenSSL::Verify strict verification - OK");
84+
85+
SKIP: {
86+
skip "Incorrect/missing version of openSSL", 2 unless (($openssl_version ge '1.1.1') and (`which openssl`));
87+
#say 'OpenSSL verification - noCApath:';
88+
eval {
89+
$ret = `openssl verify -no-CApath -CAfile intermediate.pem cert.pem 2>&1`;
90+
};
91+
like ($ret, qr/error 2 at 1 depth lookup: .* issuer certificate/s, "OpenSSL verification no-CApath - OK");
92+
93+
$verifier = Crypt::OpenSSL::Verify->new('intermediate.pem', {noCApath =>1, strict_certs=>1});
94+
$cert_object = Crypt::OpenSSL::X509->new_from_string($cert);
95+
eval {
96+
$ret = $verifier->verify($cert_object);
97+
};
98+
like($ret, qr/error 2 at 1 depth lookup: .* issuer certificate/s, "Crypt::OpenSSL::Verify - noCApath failed to find root - OK");
99+
}
100+
101+
SKIP: {
102+
skip "Incorrect/missing version of openSSL", 2 unless (($openssl_version ge '1.1.1') and (`which openssl`));;
103+
#say 'OpenSSL verification intermediate:';
104+
eval {
105+
$ret = `openssl verify intermediate.pem`;
106+
};
107+
like ($ret, qr/intermediate.pem: OK/s, "OpenSSL verification intermediate - OK");
108+
}
109+
110+
$verifier = Crypt::OpenSSL::Verify->new('', { strict_certs=>1});
111+
$cert_object = Crypt::OpenSSL::X509->new_from_string($intermediate);
112+
eval {
113+
$ret = $verifier->verify($cert_object);
114+
};
115+
ok($ret, "Crypt::OpenSSL::Verify intermediate - OK");
116+
117+
SKIP: {
118+
skip "Incorrect/missing version of openSSL", 2 unless (($openssl_version ge '1.1.1') and (`which openssl`));;
119+
#say 'OpenSSL verification intermediate - noCAfile & noCApath:';
120+
eval {
121+
$ret = `openssl verify -no-CApath -no-CAfile intermediate.pem 2>&1`;
122+
};
123+
like ($ret, qr/error 20 at 0 depth lookup: unable to get local issuer certificate/s, "OpenSSL verification intermediate no-CAfile & no-CApath - OK");
124+
125+
$verifier = Crypt::OpenSSL::Verify->new('', {noCAfile =>1, noCApath =>1, strict_certs=>1});
126+
$cert_object = Crypt::OpenSSL::X509->new_from_string($intermediate);
127+
eval {
128+
$ret = $verifier->verify($cert_object);
129+
};
130+
like($ret, qr/error 20 at 0 depth lookup: unable to get local issuer certificate/s, "Crypt::OpenSSL::Verify intermediate - noCAfile & noCApath failed to find root - OK");
131+
}
132+
133+
done_testing;

0 commit comments

Comments
 (0)