Added new tests for SSL

* tests/SSLServer.pm: New file
* tests/SSLTest.pm: New file
* tests/Test-https-pfs.px: New file
* tests/Test-https-selfsigned.px: New file
* tests/Test-https-tlsv1.px: New file
* tests/Test-https-tlsv1x.px: New file
* tests/certs/server.crt: New file
* tests/certs/server.key: New file
* tests/certs/test-ca-cert.pem: New file

Added 4 new test scripts all for SSL.
Added base pm for SSL testing.
Added SSL tests for TLSv1, TLSv1_1 and PFS.
Added test for self signed cert : check that it fails without
--no-check-certificate and passes with that flag.
This commit is contained in:
Vijo Cherian 2017-03-15 00:09:46 -07:00 committed by Tim Rühsen
parent 56c78c4b09
commit ac519c041e
9 changed files with 612 additions and 0 deletions

225
tests/SSLServer.pm Normal file
View File

@ -0,0 +1,225 @@
package SSLServer;
# This is only HTTPS server for now.
# But it is named SSLServer to easily distinguish from HTTPServer
use strict;
use warnings;
use lib '.';
use HTTP::Daemon;
use HTTP::Status;
use HTTP::Headers;
use HTTP::Response;
use IO::Socket::SSL; # 'debug4';
use HTTPServer;
our @ISA = qw(IO::Socket::SSL HTTP::Daemon::ClientConn HTTP::Daemon HTTPServer);
my $VERSION = 0.01;
my $CRLF = "\015\012"; # "\r\n" is not portable
# Config options for server
my $log = undef;
my $DEBUG = undef;
my %ssl_params;
my $sslsock;
my $plaincon;
my %args;
$HTTP::Daemon::DEBUG=5;
#*DEBUG = \$HTTP::Daemon::DEBUG;
$args{SSL_error_trap} ||= \&ssl_error;
my $class = shift;
my $self = {};
$self = bless $self, $class;
sub init
{
my $self = shift;
my %sargs = @_;
%ssl_params = %sargs;
unless (exists($ssl_params{'lhostname'}) &&
exists($ssl_params{'ciphers'}) &&
exists($ssl_params{'cafile'}) &&
exists($ssl_params{'certfile'}) &&
exists($ssl_params{'keyfile'})) {
die "Required parameters for SSL tests are missing";
}
}
sub ssl_setup_conn
{
$sslsock = IO::Socket::SSL->new(LocalAddr => $ssl_params{'lhostname'},
LocalPort => 55443,
Listen => 10,
Timeout => 30,
ReuseAddr => 1,
SSL_cipher_list => $ssl_params{'ciphers'},
SSL_verify_mode => 0x00,
SSL_ca_file => $ssl_params{'cafile'},
SSL_cert_file => $ssl_params{'certfile'},
SSL_key_file => $ssl_params{'keyfile'});
$sslsock || warn $IO::Socket::SSL::ERROR;
return $sslsock;
}
sub fileno
{
my $self = shift;
my $fn = ${*$self}{'_SSL_fileno'};
return defined($fn) ? $fn : $self->SUPER::fileno();
}
sub accept
{
my $self = shift;
my $pkg = shift || "SSLServer";
my ($sock, $peer) = $sslsock->accept($pkg);
if ($sock) {
${*$sock}{'httpd_daemon'} = $self;
${*$self}{'httpd_daemon'} = $sock;
my $fileno = ${*$self}{'_SSL_fileno'} = fileno($self);
my $f = $sock->fileno;
return wantarray ? ($sock, $peer) : $sock;
}
else {
print STDERR "Failed to get socket from SSL\n" if $DEBUG;
return;
}
}
sub _default_port { 443; }
sub _default_scheme { "https"; }
sub url
{
my $self = shift;
my $url = $self->SUPER::url;
return $url if ($self->can("HTTP::Daemon::_default_port"));
# Workaround for old versions of HTTP::Daemon
$url =~ s!^http:!https:!;
$url =~ s!/$!:80/! unless ($url =~ m!:(?:\d+)/$!);
$url =~ s!:443/$!/!;
return $url;
}
sub _need_more
{
my $self = shift;
if ($_[1]) {
my($timeout, $fdset) = @_[1,2];
print STDERR "select(,,,$timeout)\n" if $DEBUG;
my $n = select($fdset,undef,undef,$timeout);
unless ($n) {
$self->reason(defined($n) ? "Timeout" : "select: $!");
return;
}
}
my $total = 0;
while (1){
print STDERR sprintf("sysread() already %d\n",$total) if $DEBUG;
my $n = sysread(${*$self}{'httpd_daemon'}, $_[0], 2048, length($_[0]));
print STDERR sprintf("sysread() just \$n=%s\n",(defined $n?$n:'undef')) if $DEBUG;
$total += $n if defined $n;
last if $! =~ 'Resource temporarily unavailable';
#SSL_Error because of aggressive reading
$self->reason(defined($n) ? "Client closed" : "sysread: $!") unless $n;
last unless $n;
last unless $n == 2048;
}
$total;
}
sub daemon
{
my $self = shift;
${*$self}{'httpd_daemon'};
}
sub conn
{
my $self = shift;
${*$self}{'sslcon'};
}
sub run
{
my ($self, $urls, $synch_callback) = @_;
my $initialized = 0;
while (1)
{
if (!$initialized)
{
$initialized = 1;
open (LOGFILE, '>', "/tmp/wgetserver.log");
LOGFILE->autoflush(1);
print LOGFILE "Starting logging";
}
my $sslsock = $self->ssl_setup_conn();
$sslsock || warn "Failed to get ssl sock";
$synch_callback->() if $synch_callback;
my $con = $self->accept();
${*$self}{'sslcon'} = $con;
while (my $req = $self->get_request)
{
#my $url_path = $req->url->path;
my $url_path = $req->url->as_string;
if ($url_path =~ m{/$})
{ # append 'index.html'
$url_path .= 'index.html';
}
#if ($url_path =~ m{^/}) { # remove trailing '/'
# $url_path = substr ($url_path, 1);
#}
if ($log)
{
print LOGFILE "Method: ", $req->method, "\n";
print LOGFILE "Path: ", $url_path, "\n";
print LOGFILE "Available URLs: ", "\n";
foreach my $key (keys %$urls)
{
print LOGFILE $key, "\n";
}
}
if (exists($urls->{$url_path}))
{
print LOGFILE "Serving requested URL: ", $url_path, "\n" if $log;
next unless ($req->method eq "HEAD" || $req->method eq "GET");
my $url_rec = $urls->{$url_path};
HTTPServer::send_response($self, $req, $url_rec, $con);
last;
}
else
{
print LOGFILE "Requested wrong URL: ", $url_path, "\n" if $log;
$con->send_error($HTTP::Status::RC_FORBIDDEN);
last;
}
last;
}
print LOGFILE "Closing connection\n" if $log;
close(LOGFILE);
$con->close();
last;
}
}
1;
# vim: et ts=4 sw=4

65
tests/SSLTest.pm Normal file
View File

@ -0,0 +1,65 @@
package SSLTest;
use strict;
use warnings;
use SSLServer;
use WgetTests;
use HTTPTest;
our @ISA = qw(WgetTest HTTPTest);
my $VERSION = 0.01;
my %ssl_defaults = (
_certfile => "certs/server.crt",
_keyfile => "certs/server.key",
_cafile => "certs/test-ca-cert.pem",
_ciphers => 'ALL',
_lhostname => 'wgettestingserver',
);
{
my %_attr_data = %ssl_defaults;
sub _default_for
{
my ($self, $attr) = @_;
return $_attr_data{$attr} if exists $_attr_data{$attr};
return $self->SUPER::_default_for($attr);
}
sub _standard_keys
{
my ($self) = @_;
($self->SUPER::_standard_keys(), keys %_attr_data);
}
}
sub _setup_server
{
my $self = shift;
my %ssl_config = %ssl_defaults;
$self->{_server} = SSLServer->new()
or die "Cannot create SSL server!!!";
for my $attrname ($self->_standard_keys())
{
my ($argname) = ($attrname =~ m/^_(.*)/msx);
$ssl_config{$argname} = $self->{$attrname};
}
for my $attrname (keys %ssl_config)
{
if ($attrname =~ m/file$/)
{
my $cwd = $self->SUPER::_default_for('_workdir');
my $cfile = $ssl_config{$attrname};
$ssl_config{$attrname} = "$cwd/$cfile";
}
}
$self->{_server}->init(%ssl_config);
}
1;
# vim: et ts=4 sw=4

50
tests/Test-https-pfs.px Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env perl
use strict;
use warnings;
use SSLTest;
###############################################################################
# code, msg, headers, content
my %urls = (
'/somefile.txt' => {
code => "200",
msg => "Dontcare",
headers => {
"Content-type" => "text/plain",
},
content => "blabla",
},
);
my $cdir = $ENV{'PWD'};
# HOSTALIASES env variable allows us to create hosts file alias.
my $testhostname = "WgetTestingServer";
my $testhostfile = "$cdir/wgethosts";
open(my $fh, '>', $testhostfile);
print $fh "$testhostname 127.0.0.1\n";
close $fh;
$ENV{'HOSTALIASES'} = "$cdir/wgethosts";
my $cmdline = $WgetTest::WGETPATH . " --secure-protocol=PFS --ca-certificate=$cdir/certs/test-ca-cert.pem https://$testhostname:55443/somefile.txt";
my $expected_error_code = 0;
my %existing_files = (
);
my %expected_downloaded_files = (
'somefile.txt' => {
content => "blabla",
},
);
my $sslsock = SSLTest->new(cmdline => $cmdline,
input => \%urls,
errcode => $expected_error_code,
existing => \%existing_files,
output => \%expected_downloaded_files);
$sslsock->run();
# vim: et ts=4 sw=4

82
tests/Test-https-selfsigned.px Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env perl
use strict;
use warnings;
use SSLTest;
###############################################################################
# code, msg, headers, content
my %urls = (
'/somefile.txt' => {
code => "200",
msg => "Dontcare",
headers => {
"Content-type" => "text/plain",
},
content => "blabla",
},
);
my $cdir = $ENV{'PWD'};
# HOSTALIASES env variable allows us to create hosts file alias.
my $testhostname = "wgettesterr";
my $testhostfile = "$cdir/wgethosts";
open(my $fh, '>', $testhostfile);
print $fh "$testhostname 127.0.0.1\n";
close $fh;
$ENV{'HOSTALIASES'} = "$cdir/wgethosts";
# Prepare self-signed certifcates
my $certfile="tmpsscert.pem";
my $keyfile="tmpsskey.pem";
my $certsubj="/C=US/ST=CA/L=Mystery Spot/O=Dis/CN=$testhostname/emailAddress=tester";
my $sscertcmd="openssl req -x509 -nodes -newkey rsa:4096 -keyout $keyfile -out $certfile -days 365 -subj \"$certsubj\"";
system($sscertcmd);
my $sscheck=`(openssl x509 -noout -modulus -in $certfile | openssl md5 ; openssl rsa -noout -modulus -in $keyfile | openssl md5) | uniq|wc -l`;
# Check if Self signed certificate and key are made correctly.
unless(-e $certfile && -e $keyfile && $sscheck == 1) {
exit 77; # skip
}
# Try Wget using SSL first without --no-check-certificate. expect error
my $cmdline = $WgetTest::WGETPATH . " --ca-certificate=$cdir/certs/test-ca-cert.pem https://$testhostname:55443/somefile.txt";
my $expected_error_code = 5;
my %existing_files = (
);
my %expected_downloaded_files = (
'somefile.txt' => {
content => "blabla",
},
);
my $sslsock = SSLTest->new(cmdline => $cmdline,
input => \%urls,
errcode => $expected_error_code,
existing => \%existing_files,
output => \%expected_downloaded_files,
certfile => $certfile,
keyfile => $keyfile,
lhostname => $testhostname);
$sslsock->run();
# Retry the test with --no-check-certificate. expect success
$cmdline = $WgetTest::WGETPATH . " --no-check-certificate --ca-certificate=$cdir/certs/test-ca-cert.pem https://$testhostname:55443/somefile.txt";
$expected_error_code = 0;
my $retryssl = SSLTest->new(cmdline => $cmdline,
input => \%urls,
errcode => $expected_error_code,
existing => \%existing_files,
output => \%expected_downloaded_files,
certfile => $certfile,
keyfile => $keyfile,
lhostname => $testhostname);
$retryssl->run();
# vim: et ts=4 sw=4

50
tests/Test-https-tlsv1.px Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env perl
use strict;
use warnings;
use SSLTest;
###############################################################################
# code, msg, headers, content
my %urls = (
'/somefile.txt' => {
code => "200",
msg => "Dontcare",
headers => {
"Content-type" => "text/plain",
},
content => "blabla",
},
);
my $cdir = $ENV{'PWD'};
# HOSTALIASES env variable allows us to create hosts file alias.
my $testhostname = "WgetTestingServer";
my $testhostfile = "$cdir/wgethosts";
open(my $fh, '>', $testhostfile);
print $fh "$testhostname 127.0.0.1\n";
close $fh;
$ENV{'HOSTALIASES'} = "$cdir/wgethosts";
my $cmdline = $WgetTest::WGETPATH . " --secure-protocol=TLSv1 --ca-certificate=$cdir/certs/test-ca-cert.pem https://$testhostname:55443/somefile.txt";
my $expected_error_code = 0;
my %existing_files = (
);
my %expected_downloaded_files = (
'somefile.txt' => {
content => "blabla",
},
);
my $sslsock = SSLTest->new(cmdline => $cmdline,
input => \%urls,
errcode => $expected_error_code,
existing => \%existing_files,
output => \%expected_downloaded_files);
$sslsock->run();
# vim: et ts=4 sw=4

50
tests/Test-https-tlsv1x.px Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env perl
use strict;
use warnings;
use SSLTest;
###############################################################################
# code, msg, headers, content
my %urls = (
'/somefile.txt' => {
code => "200",
msg => "Dontcare",
headers => {
"Content-type" => "text/plain",
},
content => "blabla",
},
);
my $cdir = $ENV{'PWD'};
# HOSTALIASES env variable allows us to create hosts file alias.
my $testhostname = "WgetTestingServer";
my $testhostfile = "$cdir/wgethosts";
open(my $fh, '>', $testhostfile);
print $fh "$testhostname 127.0.0.1\n";
close $fh;
$ENV{'HOSTALIASES'} = "$cdir/wgethosts";
my $cmdline = $WgetTest::WGETPATH . " --secure-protocol=TLSv1_1 --ca-certificate=$cdir/certs/test-ca-cert.pem https://$testhostname:55443/somefile.txt";
my $expected_error_code = 0;
my %existing_files = (
);
my %expected_downloaded_files = (
'somefile.txt' => {
content => "blabla",
},
);
my $sslsock = SSLTest->new(cmdline => $cmdline,
input => \%urls,
errcode => $expected_error_code,
existing => \%existing_files,
output => \%expected_downloaded_files);
$sslsock->run();
# vim: et ts=4 sw=4

28
tests/certs/server.crt Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIEsTCCApkCCQCFKV9Q4gGmRjANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMC
VVMxCzAJBgNVBAgMAkNBMREwDwYDVQQHDAhTYW4gSm9zZTEgMB4GA1UECgwXV2dl
dCBUZXN0aW5nIERlcGFydG1lbnQxEDAOBgNVBAsMB1Rlc3RpbmcxFDASBgNVBAMM
C1dnZXRUZXN0aW5nMSAwHgYJKoZIhvcNAQkBFhFidWdzLXdnZXRAZ251Lm9yZzAe
Fw0xNzA0MDYyMTMxMTNaFw0xODA4MTkyMTMxMTNaMIGaMQswCQYDVQQGEwJVUzEL
MAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMRwwGgYDVQQKDBNXZ2V0IFRl
c3RpbmcgU2VydmVyMQ8wDQYDVQQLDAZTZXJ2ZXIxGjAYBgNVBAMMEVdnZXRUZXN0
aW5nU2VydmVyMSAwHgYJKoZIhvcNAQkBFhFidWdzLXdnZXRAZ251Lm9yZzCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANXGNSzoaeTX3B34xqiKuVXc2YzL
/QQFexj+dyJ5XwwDF420gEv+zFjy8Y9wiGZ4rgHzF2TviNCoAy7ntlltA9Ab41jk
CikwbZ9R81qsvmxc4HXRNgiKadNIb7BYNh6HljJjOSclkbF/LypJtdF5g7b6Qron
ME/UuDIYLQV765emZh+2h/BJLtTXU+8n985gC+/9dw68WjLnWk9REzHYZPFU4UGK
bCx+h7M/cVE5uIWjDC3Uq93jCweZJ8UFbmAnwlER8fXSEzy2SK5yqlRu+st8ae5w
ZQAgXSeHF0jZ/lUgZBlq2QnqfzVlDd26CXMa/2OLZo9qUIoS/c0y5qLghTUCAwEA
ATANBgkqhkiG9w0BAQsFAAOCAgEACWiOsXM9Mu+mg0+eGAlhuHP4/nOR8nFrZ0A/
RaBwsW6yBSZ6NAHLQKhApm3TOgxrMFM82hB+L9AW05p6dz6fHm25ajJKmefsbAGi
gqhBdEI9GJJKj6Wm5od7MT9jZ0z5edcPFXqnyapLXYJHps+Sm7ZJ81Mt/sTDjQCb
6I/Y5yQW6KomjtqfMIw6miOqXnabRDFN8CQ6nKzFBMviQVBn04G+pQRCJ5//4bSc
33erZb56C36xTnTXiIXKo6LkVhH+TG28dTxRh8d+xBYbqe8ZR9aCoCVVn7ca3UZZ
iQBOTfVKMRVUthHo2ntRs/jE5qhPYXA1km5rvUE2+sSIUdoqol4JTshK6bzt6VN9
1bDKkmJa5IqcXEjcXADEJA62Zcr+I/8D1KxVf/CAPvtT1z4EqCWOeKk1uMjURZVR
BbFmjJ76LZ65YFTAJBm0EdVG917Yd9jsC8zCT/Lb+LFLuecXpBBp9tCcdp9z1MX+
Pw4Co54keMBWXQeOnrtg8haGTXSwTOOp0F5wmWdUKjiwjhxanTgJZMZTjfcMLcNS
1GIhFt7sIEnc/PkX6vBOIeyFBppw9So+YYJE2MOsKaUvi+IX5XJXZf8R73k1+e0d
V8sKjQoYVDwavJSeOx19nJVKQa8fEvv5t5tPES3UlZ1FWAdKVEpDECiEKyQEfkmK
jQ9qZJU=
-----END CERTIFICATE-----

27
tests/certs/server.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA1cY1LOhp5NfcHfjGqIq5VdzZjMv9BAV7GP53InlfDAMXjbSA
S/7MWPLxj3CIZniuAfMXZO+I0KgDLue2WW0D0BvjWOQKKTBtn1HzWqy+bFzgddE2
CIpp00hvsFg2HoeWMmM5JyWRsX8vKkm10XmDtvpCuicwT9S4MhgtBXvrl6ZmH7aH
8Eku1NdT7yf3zmAL7/13DrxaMudaT1ETMdhk8VThQYpsLH6Hsz9xUTm4haMMLdSr
3eMLB5knxQVuYCfCURHx9dITPLZIrnKqVG76y3xp7nBlACBdJ4cXSNn+VSBkGWrZ
Cep/NWUN3boJcxr/Y4tmj2pQihL9zTLmouCFNQIDAQABAoIBAEXCOlP/O58Lua6m
Id2Z90THns5NOrF3QGY1k5bSWGvJDoSVZFBoQzK7hIw0Qq59rvq/4uBzMgg062UB
BAZGhroAf73gHFi4ju0whuMN/83IuQ55SNKcqE/kEV5QSsjHogGrU1ks71AmmrOH
/ibvKkYpgGDSrPdACSN/tCFYANcpQtzbhkFXRqZ5JSIQyVCE+XLrZinxI6D23XVe
5qMpfBH1gnKfBPf86UCI+iVTdNIC9sLp+C5MoSKCWMvYzKlQqbxVgulEdcOq01U7
Sq7ZU6/f8QuTjd3d+WGTp2ZxFf2H+2XuKNVl9akp2exap+/JEj9Et0jMIN5Z9zHa
6bTDMPkCgYEA8uO+VAAq4R1WJCTFpYy4/gzJPbQtxVxOMGBnxgAW+4G0jv+BiqiU
WrQ6Rtcyfx8LFB/z1tExfDSJSpTw8wd3j19a/sMqACwCgkudmi8dzKbH2Y9U9DCz
IB++zaQVKgJNE1VEsuySpf9HzQKBJGhO4fNMzol6YhlQT4ex7gSrFyMCgYEA4VAl
p0A6798a9rmUGhNSzn5IcO2unpS7IYDTqKv46oIQ1rKKEiawugni+F1gL9StK90g
NvDREiaM0eKo9QlhUzqBBSsNBVh4UVadbOpBOqyM6CUE94I4H199SwfzPuCILYa4
01syaosJ2SRUr8S101x7U0VQ2SCYq38as27FY8cCgYB67dr5RrBtCNz9JANIW2WR
ZsU/Tn7P4XzNLS24X3lCR44rxZM5q0KSeZ75FZdAEWUZBWby9SN3elt1/NXKGqBf
VuKGCB6swZlvenfEfk41sr95E/rqL++otYhrKb1waoO54jEH4YYDL6WWU8sqswQh
hXL9IUVoeulTpxjdn008QwKBgCxCnELwoSNBxoA1EFzW8utRb1WPuz+3o9L/BZUa
wzj99+TVCb5rD0hcbNOxNBXxR1tYgt2IDOnt3LfWOK55+z5oPbQQMuyb5nbD9wTQ
N6QZBU0NCJ6+W9v93BUDKMtvPBEFaAVM4uh/C542PtSQZc9xWWCQO0OL3bHCtDIP
ToM9AoGADJ+6tYMTBEHhJyZxqD6oZgHTAqfA6HqKP5UUCpQ8G4IEedEq+cpQSFM9
Wez+ChUdeDCaFSOeh+8o/u4w3x44g7GyFdOL6lGV6YjzGk4WkbRwqJWW/AKV0htl
Fby2y2PzLnbLGKnt7nGTxag9l28NwbGppy7Kex8jVYcQP15djCg=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGBzCCA++gAwIBAgIJAJlGYwAp0+gKMA0GCSqGSIb3DQEBCwUAMIGZMQswCQYD
VQQGEwJVUzELMAkGA1UECAwCQ0ExETAPBgNVBAcMCFNhbiBKb3NlMSAwHgYDVQQK
DBdXZ2V0IFRlc3RpbmcgRGVwYXJ0bWVudDEQMA4GA1UECwwHVGVzdGluZzEUMBIG
A1UEAwwLV2dldFRlc3RpbmcxIDAeBgkqhkiG9w0BCQEWEWJ1Z3Mtd2dldEBnbnUu
b3JnMB4XDTE3MDQwNjIxMDEyOFoXDTE4MDQwNjIxMDEyOFowgZkxCzAJBgNVBAYT
AlVTMQswCQYDVQQIDAJDQTERMA8GA1UEBwwIU2FuIEpvc2UxIDAeBgNVBAoMF1dn
ZXQgVGVzdGluZyBEZXBhcnRtZW50MRAwDgYDVQQLDAdUZXN0aW5nMRQwEgYDVQQD
DAtXZ2V0VGVzdGluZzEgMB4GCSqGSIb3DQEJARYRYnVncy13Z2V0QGdudS5vcmcw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvHmnQlY58T/PcZeR3ntBp
6YYELxmYTjrdiHLpa1HvDDkwYyVCaWxhi8R5mP/cUt7aZ0BrNMCVTy5/cEzl/w9R
VqERKDB68ZU0ku2A4YmDFenlyyUuVZhn5reovUUlhWo8p+Ir+1vwGyDPM/IQKaUJ
6tfDWVD7fgVzfpvDm8XDqKB6BvzLPk3n3K9mndv2KihTUnnJFMZOkSYaFStQ11Rz
YwR7ZvAuISB99WZf2hzaYiovB9G0WMky81vpmvjbKWVYLlpV5Inzq2QiG4tFBEP+
ebLc1H9PGd7vrgGE2cn78g1XXpR8nPUDYF4UGFs90ftPqNDHcHFENB7DrpB7wRIa
5ZrpKyNbCGIKX+UnVR5Ra32mMM2pPiR95ZDNkqdsygLuHAsyaaj1+wvrmM81H2Jy
V/kVcFqnf3+C1aX2+hu5OL7rIskEYG8HgWwWxE0NW7Q8zTrBR7D932hM/7f8Yojx
SeqJP7vpGULeVzJF0CTksoWh+D1s+Q2b93DpoMW18VMTig2NFetQr3DdJmySed7a
g694qgY5iDv1P/CWBSj75TDBrw3Ji6PJxWES+ox29frxrCWtAjEwVI5zJ5qIZW5n
+BYir/tVloMkYSmeby9eSmTLGENZrepBwuocpvJ1yQRosdzYG42MjfI2JhlTFWvw
wdGCsFqsRcsfPTJqu801QQIDAQABo1AwTjAdBgNVHQ4EFgQUF+2TQ4+npgB11Oi2
gg2IN37AbQgwHwYDVR0jBBgwFoAUF+2TQ4+npgB11Oi2gg2IN37AbQgwDAYDVR0T
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAewaQ/hmPbjNI7FFNM63M1qnWHK+t
Zsm5qHWMk5WkcdavsqpexGDc3VxBYFzqqEjlCTseMgsNZ76FENZeNGNFtKScUHuR
J6Fp+pqEZJ9AoQy8WbkDuFjsKs+En3cMvqy4QUqVOFrKg1PKJEWlqvonMs+apzvJ
0bjj5Aj2w906XvpKYTnfR6QHJC5ZP5xTorJWLvAwWl0ZuqxQKT0fXKcPeAlE0c4b
3eJ5jFXPIFkYt0fJcUnZp6QJv608/METl9x+rTYfRsD6kQGC+281C19PxBacTzxH
fAjsesvP7t7pPlh+Chdd7w1QqFg4UUH9NfIkiq06UtIUoQHfCgT1FvXoFoPiRR5f
5m67jGE8Sn04nnGhvHnN03kOuwK/VIniLuHdWw0nwLBWIEpzZPbIQQSezoJd7ViY
2zBJQCtp1ewEDOXecBL+8CNIUXTiFoOxP/YMuLruoYB5dkLpIFbscHp3dZJMScoz
XJQHh68KH0oRm+/FnK3MLxn56nbwoV4uhdIr5FgLglh7PUfUa2wavFjhi3MY50qD
SsvoCmBny/N2KJK2tEBIGWbdYy1XBF/l8xaORdT/M4ILYV52Wf2AYy9NTYJxiB0V
LwVGbG5plMbJiBFDOZcram4pQrG6k21t2Xv2lkVf1AvOlx4qKfUN04TGWXwu5dAP
pnv5yEwOelBLq7Q=
-----END CERTIFICATE-----