Skip to content

Commit 8826e9e

Browse files
committed
Add trusted certificate check
1 parent cb5eb3c commit 8826e9e

File tree

4 files changed

+132
-1
lines changed

4 files changed

+132
-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

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

0 commit comments

Comments
 (0)