File Coverage

blib/lib/Metabrik/Client/Ssl.pm
Criterion Covered Total %
statement 12 198 6.0
branch 0 66 0.0
condition 0 14 0.0
subroutine 4 10 40.0
pod 1 6 16.6
total 17 294 5.7


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # client::ssl Brik
5             #
6             package Metabrik::Client::Ssl;
7 1     1   746 use strict;
  1         2  
  1         29  
8 1     1   6 use warnings;
  1         2  
  1         27  
9              
10 1     1   5 use base qw(Metabrik);
  1         2  
  1         2740  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable tls) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             uri => [ qw(uri) ],
20             },
21             commands => {
22             install => [ ], # Inherited
23             verify_server => [ qw(uri|OPTIONAL) ],
24             getcertificate => [ qw(uri|OPTIONAL) ],
25             getcertificate2 => [ qw(host port) ],
26             },
27             require_modules => {
28             'Data::Dumper' => [ ],
29             'IO::Socket::SSL' => [ ],
30             'LWP::UserAgent' => [ ],
31             'LWP::ConnCache' => [ ],
32             'URI' => [ ],
33             'Net::SSLeay' => [ ],
34             'Metabrik::String::Uri' => [ ],
35             },
36             need_packages => {
37             ubuntu => [ qw(libssl-dev) ],
38             debian => [ qw(libssl-dev) ],
39             kali => [ qw(libssl-dev) ],
40             centos => [ qw(openssl-devel) ],
41             redhat => [ qw(openssl-devel) ],
42             },
43             };
44             }
45              
46             sub verify_server {
47 0     0 0   my $self = shift;
48 0           my ($uri) = @_;
49              
50 0   0       $uri ||= $self->uri;
51 0 0         $self->brik_help_run_undef_arg('verify_server', $uri) or return;
52              
53 0 0         my $su = Metabrik::String::Uri->new_from_brik_init($self) or return;
54 0 0         my $parsed = $su->parse($uri) or return;
55              
56 0           my $host = $parsed->{host};
57 0           my $port = $parsed->{port};
58              
59             $self->log->debug("verify_server: trying host [".$parsed->{host}."] ".
60 0           "with port [".$parsed->{port}."]");
61              
62             my $client = IO::Socket::SSL->new(
63             PeerHost => $parsed->{host},
64             PeerPort => $parsed->{port},
65             SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(),
66             SSL_verifycn_name => $parsed->{host},
67 0           SSL_verifycn_scheme => 'http',
68             );
69 0 0 0       if (! defined($client) && ! length($!)) {
    0          
70 0           $self->log->verbose("verify_server: not verified: [".
71             $IO::Socket::SSL::SSL_ERROR."]");
72 0           return 0;
73             }
74             elsif (! defined($client)) {
75 0           return $self->log->error("verify_server: connection failed with ".
76             "error: [$!]");
77             }
78              
79 0           $self->log->verbose("verify_server: verified");
80              
81 0           return 1;
82             }
83              
84             #
85             # Note: works only with IO::Socket::SSL, not with Net::SSL (using Crypt::SSLeay)
86             #
87             sub getcertificate {
88 0     0 0   my $self = shift;
89 0           my ($uri) = @_;
90              
91 0   0       $uri ||= $self->uri;
92 0 0         $self->brik_help_run_undef_arg('getcertificate', $uri) or return;
93              
94 0 0         if ($uri !~ /^https:\/\//) {
95 0           return $self->log->error("must use https to get a certificate");
96             }
97              
98 0           my $ua = LWP::UserAgent->new(
99             #ssl_opts => { verify_hostname => 0 }, # will do manual check
100             ssl_opts => { SSL_verify_mode => 'SSL_VERIFY_NONE'},
101             );
102 0   0       $ua->timeout(defined($self->global) && $self->global->rtimeout || 3);
103 0           $ua->max_redirect(0);
104 0           $ua->env_proxy;
105              
106 0           my $cache = LWP::ConnCache->new;
107 0           $ua->conn_cache($cache);
108              
109 0           my $response = $ua->get($uri);
110             # XXX: we ignore response?
111              
112 0           my $cc = $ua->conn_cache->{cc_conns};
113 0 0         if (! defined($cc)) {
114 0           return $self->log->error("unable to retrieve connection cache");
115             }
116              
117 0 0         if (scalar(@$cc) == 0) {
118 0           return $self->log->error("getcertificate: no connection cached");
119             }
120              
121 0           my $sock = $cc->[0][0];
122              
123 0           my %info = ();
124             # peer_certificate from IO::Socket::SSL/Crypt::SSLeay
125 0 0         if ($sock->can('peer_certificate')) {
126 0           my $authority = $sock->peer_certificate('authority'); # issuer
127 0           my $owner = $sock->peer_certificate('owner'); # subject
128 0           my $commonName = $sock->peer_certificate('commonName'); # cn
129 0           my $subjectAltNames = $sock->peer_certificate('subjectAltNames');
130 0           my $sslversion = $sock->get_sslversion;
131 0           my $cipher = $sock->get_cipher;
132 0           my $servername = $sock->get_servername; # Only when SNI is used
133             #my $verify_hostname = $sock->verify_hostname('hostname', 'http');
134              
135 0           $info{authority} = $authority;
136 0           $info{owner} = $owner;
137 0           $info{commonName} = $commonName;
138 0           $info{subjectAltNames} = $subjectAltNames;
139 0           $info{sslversion} = $sslversion;
140 0           $info{cipher} = $cipher;
141 0           $info{servername} = $servername;
142             #$info{verify_hostname} = $verify_hostname;
143              
144 0           print Data::Dumper::Dumper(\%info)."\n";
145             }
146             else {
147 0           return $self->log->error("socket [$sock] cannot do 'peer_certificate'");
148             }
149              
150             #$sock->stop_SSL;
151              
152 0           return $sock;
153             }
154              
155 1     1   704 eval("use Net::SSLeay qw/XN_FLAG_RFC2253 ASN1_STRFLGS_ESC_MSB/;");
  1         11783  
  1         444  
156              
157             # Taken from http://cpansearch.perl.org/src/MIKEM/Net-SSLeay-1.57/examples/x509_cert_details.pl
158             sub get_cert_details {
159 0     0 0   my $x509 = shift;
160 0           my $rv = {};
161 0           my $flag_rfc22536_utf8 = (Net::SSLeay::XN_FLAG_RFC2253()) & (~ Net::SSLeay::ASN1_STRFLGS_ESC_MSB());
162              
163 0 0         die 'ERROR: $x509 is NULL, gonna quit' unless $x509;
164              
165             #warn "Info: dumping subject\n";
166 0           my $subj_name = Net::SSLeay::X509_get_subject_name($x509);
167 0           my $subj_count = Net::SSLeay::X509_NAME_entry_count($subj_name);
168 0           $rv->{subject}->{count} = $subj_count;
169 0           $rv->{subject}->{oneline} = Net::SSLeay::X509_NAME_oneline($subj_name);
170 0           $rv->{subject}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($subj_name);
171 0           $rv->{subject}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8);
172 0           $rv->{subject}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($subj_name, $flag_rfc22536_utf8, 1);
173 0           for my $i (0..$subj_count-1) {
174 0           my $entry = Net::SSLeay::X509_NAME_get_entry($subj_name, $i);
175 0           my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry);
176 0           my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry);
177 0           my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
178 0 0         $rv->{subject}->{entries}->[$i] = {
    0          
    0          
179             oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
180             data => Net::SSLeay::P_ASN1_STRING_get($asn1_string),
181             data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1),
182             nid => ($nid>0) ? $nid : undef,
183             ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
184             sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
185             };
186             }
187              
188             #warn "Info: dumping issuer\n";
189 0           my $issuer_name = Net::SSLeay::X509_get_issuer_name($x509);
190 0           my $issuer_count = Net::SSLeay::X509_NAME_entry_count($issuer_name);
191 0           $rv->{issuer}->{count} = $issuer_count;
192 0           $rv->{issuer}->{oneline} = Net::SSLeay::X509_NAME_oneline($issuer_name);
193 0           $rv->{issuer}->{print_rfc2253} = Net::SSLeay::X509_NAME_print_ex($issuer_name);
194 0           $rv->{issuer}->{print_rfc2253_utf8} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8);
195 0           $rv->{issuer}->{print_rfc2253_utf8_decoded} = Net::SSLeay::X509_NAME_print_ex($issuer_name, $flag_rfc22536_utf8, 1);
196 0           for my $i (0..$issuer_count-1) {
197 0           my $entry = Net::SSLeay::X509_NAME_get_entry($issuer_name, $i);
198 0           my $asn1_string = Net::SSLeay::X509_NAME_ENTRY_get_data($entry);
199 0           my $asn1_object = Net::SSLeay::X509_NAME_ENTRY_get_object($entry);
200 0           my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
201 0 0         $rv->{issuer}->{entries}->[$i] = {
    0          
    0          
202             oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
203             data => Net::SSLeay::P_ASN1_STRING_get($asn1_string),
204             data_utf8_decoded => Net::SSLeay::P_ASN1_STRING_get($asn1_string, 1),
205             nid => ($nid>0) ? $nid : undef,
206             ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
207             sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
208             };
209             }
210              
211             #warn "Info: dumping alternative names\n";
212 0           $rv->{subject}->{altnames} = [ Net::SSLeay::X509_get_subjectAltNames($x509) ];
213             #XXX-TODO maybe add a function for dumping issuerAltNames
214             #$rv->{issuer}->{altnames} = [ Net::SSLeay::X509_get_issuerAltNames($x509) ];
215              
216             #warn "Info: dumping hashes/fingerprints\n";
217 0           $rv->{hash}->{subject} = { dec=>Net::SSLeay::X509_subject_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_subject_name_hash($x509)) };
218 0           $rv->{hash}->{issuer} = { dec=>Net::SSLeay::X509_issuer_name_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_name_hash($x509)) };
219 0           $rv->{hash}->{issuer_and_serial} = { dec=>Net::SSLeay::X509_issuer_and_serial_hash($x509), hex=>sprintf("%X",Net::SSLeay::X509_issuer_and_serial_hash($x509)) };
220 0           $rv->{fingerprint}->{md5} = Net::SSLeay::X509_get_fingerprint($x509, "md5");
221 0           $rv->{fingerprint}->{sha1} = Net::SSLeay::X509_get_fingerprint($x509, "sha1");
222 0           my $sha1_digest = Net::SSLeay::EVP_get_digestbyname("sha1");
223 0           $rv->{digest_sha1}->{pubkey} = Net::SSLeay::X509_pubkey_digest($x509, $sha1_digest);
224 0           $rv->{digest_sha1}->{x509} = Net::SSLeay::X509_digest($x509, $sha1_digest);
225              
226             #warn "Info: dumping expiration\n";
227 0           $rv->{not_before} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($x509));
228 0           $rv->{not_after} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509));
229              
230             #warn "Info: dumping serial number\n";
231 0           my $ai = Net::SSLeay::X509_get_serialNumber($x509);
232             $rv->{serial} = {
233 0           hex => Net::SSLeay::P_ASN1_INTEGER_get_hex($ai),
234             dec => Net::SSLeay::P_ASN1_INTEGER_get_dec($ai),
235             long => Net::SSLeay::ASN1_INTEGER_get($ai),
236             };
237 0           $rv->{version} = Net::SSLeay::X509_get_version($x509);
238              
239             #warn "Info: dumping extensions\n";
240 0           my $ext_count = Net::SSLeay::X509_get_ext_count($x509);
241 0           $rv->{extensions}->{count} = $ext_count;
242 0           for my $i (0..$ext_count-1) {
243 0           my $ext = Net::SSLeay::X509_get_ext($x509,$i);
244 0           my $asn1_string = Net::SSLeay::X509_EXTENSION_get_data($ext);
245 0           my $asn1_object = Net::SSLeay::X509_EXTENSION_get_object($ext);
246 0           my $nid = Net::SSLeay::OBJ_obj2nid($asn1_object);
247 0 0         $rv->{extensions}->{entries}->[$i] = {
    0          
    0          
248             critical => Net::SSLeay::X509_EXTENSION_get_critical($ext),
249             oid => Net::SSLeay::OBJ_obj2txt($asn1_object,1),
250             nid => ($nid>0) ? $nid : undef,
251             ln => ($nid>0) ? Net::SSLeay::OBJ_nid2ln($nid) : undef,
252             sn => ($nid>0) ? Net::SSLeay::OBJ_nid2sn($nid) : undef,
253             data => Net::SSLeay::X509V3_EXT_print($ext),
254             };
255             }
256              
257             #warn "Info: dumping CDP\n";
258 0           $rv->{cdp} = [ Net::SSLeay::P_X509_get_crl_distribution_points($x509) ];
259             #warn "Info: dumping extended key usage\n";
260             $rv->{extkeyusage} = {
261 0           oid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,0) ],
262             nid => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,1) ],
263             sn => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,2) ],
264             ln => [ Net::SSLeay::P_X509_get_ext_key_usage($x509,3) ],
265             };
266             #warn "Info: dumping key usage\n";
267 0           $rv->{keyusage} = [ Net::SSLeay::P_X509_get_key_usage($x509) ];
268             #warn "Info: dumping netscape cert type\n";
269 0           $rv->{ns_cert_type} = [ Net::SSLeay::P_X509_get_netscape_cert_type($x509) ];
270              
271             #warn "Info: dumping other info\n";
272 0           $rv->{certificate_type} = Net::SSLeay::X509_certificate_type($x509);
273 0           $rv->{signature_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_signature_alg($x509));
274 0           $rv->{pubkey_alg} = Net::SSLeay::OBJ_obj2txt(Net::SSLeay::P_X509_get_pubkey_alg($x509));
275 0           $rv->{pubkey_size} = Net::SSLeay::EVP_PKEY_size(Net::SSLeay::X509_get_pubkey($x509));
276 0           $rv->{pubkey_bits} = Net::SSLeay::EVP_PKEY_bits(Net::SSLeay::X509_get_pubkey($x509));
277 0           $rv->{pubkey_id} = Net::SSLeay::EVP_PKEY_id(Net::SSLeay::X509_get_pubkey($x509));
278              
279 0           return $rv;
280             }
281              
282             # This routine will only check the certificate chain, not the actual contact
283             # of the certificate. You still have to check for CN validity and expiration date.
284             sub verify {
285 0     0 0   my ($ok, $x509_store_ctx) = @_;
286              
287 0           print "**** Verify called ($ok)\n";
288              
289 0           my $x = Net::SSLeay::X509_STORE_CTX_get_current_cert($x509_store_ctx);
290 0 0         if ($x) {
291 0           print "Certificate:\n";
292 0           print " Subject Name: "
293             . Net::SSLeay::X509_NAME_oneline(
294             Net::SSLeay::X509_get_subject_name($x))
295             . "\n";
296 0           print " Issuer Name: "
297             . Net::SSLeay::X509_NAME_oneline(
298             Net::SSLeay::X509_get_issuer_name($x))
299             . "\n";
300             }
301              
302 0           return $ok;
303             }
304              
305             sub getcertificate2 {
306 0     0 0   my $self = shift;
307 0           my ($host, $port) = @_;
308              
309 0 0         $self->brik_help_run_undef_arg('getcertificate2', $host) or return;
310 0 0         $self->brik_help_run_undef_arg('getcertificate2', $port) or return;
311              
312 0           eval("use Net::SSLeay qw(print_errs set_fd);");
313              
314 0 0         if (defined($ENV{HTTPS_PROXY})) {
315 0           my $proxy = URI->new($ENV{HTTPS_PROXY});
316 0           my $user = '';
317 0           my $pass = '';
318 0           my $userinfo = $proxy->userinfo;
319 0 0         if (defined($userinfo)) {
320 0           ($user, $pass) = split(':', $userinfo);
321             }
322 0           my $host = $proxy->host;
323 0           my $port = $proxy->port;
324 0           Net::SSLeay::set_proxy($host, $port, $user, $pass);
325             }
326              
327             # Taken from Net::SSLeay source code: sslcat()
328 0           my ($got, $errs) = Net::SSLeay::open_proxy_tcp_connection($host, $port);
329 0 0         if (! $got) {
330 0           return $self->log->error("Net::SSLeay::open_proxy_tcp_connection: $errs");
331             }
332              
333 0           Net::SSLeay::initialize();
334              
335 0           my $ctx = Net::SSLeay::new_x_ctx();
336 0 0 0       if ($errs = print_errs('Net::SSLeay::new_x_ctx') || ! $ctx) {
337 0           return $self->log->error($errs);
338             }
339              
340 0           Net::SSLeay::CTX_set_options($ctx, &Net::SSLeay::OP_ALL);
341 0 0         if ($errs = print_errs('Net::SSLeay::CTX_set_options')) {
342 0           return $self->log->error($errs);
343             }
344              
345             # Certificate chain verification routines
346 0           Net::SSLeay::CTX_set_default_verify_paths($ctx);
347 0           my $cert_dir = '/etc/ssl/certs';
348 0 0         Net::SSLeay::CTX_load_verify_locations($ctx, '', $cert_dir)
349             or return $self->log->error("CTX load verify loc=`$cert_dir' $!");
350 0           Net::SSLeay::CTX_set_verify($ctx, 0, \&verify);
351             #die_if_ssl_error('callback: ctx set verify');
352              
353             # XXX: skipped client certs part from sslcat()
354              
355 0           my $ssl = Net::SSLeay::new($ctx);
356 0 0         if ($errs = print_errs('Net::SSLeay::new')) {
357 0           return $self->log->error($errs);
358             }
359              
360 0           set_fd($ssl, fileno(Net::SSLeay::SSLCAT_S()));
361 0 0         if ($errs = print_errs('fileno')) {
362 0           return $self->log->error($errs);
363             }
364              
365             # Gather cipher list
366 0           my $i = 0;
367 0           my @cipher_list = ();
368 0           my $cont = 1;
369 0           while ($cont) {
370 0           my $cipher = Net::SSLeay::get_cipher_list($ssl, $i);
371 0 0         if (! $cipher) {
372             #print "DEBUG last cipher\n";
373 0           $cont = 0;
374 0           last;
375             }
376             #print "cipher [$cipher]\n";
377 0           push @cipher_list, $cipher;
378 0           $i++;
379             }
380              
381 0           $got = Net::SSLeay::connect($ssl);
382 0 0         if (! $got) {
383 0           $errs = print_errs('Net::SSLeay::connect');
384 0           return $self->log->error($errs);
385             }
386              
387 0           my $cipher = Net::SSLeay::get_cipher($ssl);
388 0           print "Using cipher [$cipher]\n";
389              
390 0           print Net::SSLeay::dump_peer_certificate($ssl);
391              
392 0           my $server_cert = Net::SSLeay::get_peer_certificate($ssl);
393             #print "get_peer_certificate: ".Data::Dumper::Dumper($server_cert)."\n";
394              
395 0           my $cert_details = get_cert_details($server_cert);
396             #print Data::Dumper::Dumper($cert_details)."\n";
397              
398 0           my @rv = Net::SSLeay::get_peer_cert_chain($ssl);
399             #print "get_peer_cert_chain: ".Data::Dumper::Dumper(\@rv)."\n";
400              
401 0           my $rv = Net::SSLeay::get_verify_result($ssl);
402 0           print "get_verify_result: ".Data::Dumper::Dumper($rv)."\n";
403              
404             #print 'Subject Name: '.Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($server_cert)).
405             #"\n".'Issuer Name: '.Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert))."\n";
406              
407 0           my $subj_name = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($server_cert));
408 0           print "$subj_name\n";
409              
410             #my $pem = Net::SSLeay::PEM_get_string_X509_CRL($server_cert);
411              
412              
413              
414             #
415             # X509 certificate details
416             #
417              
418             # # X509 version
419             # my $version = Net::SSLeay::X509_get_version($server_cert);
420             # print "version: $version\n";
421             #
422             # # Number of extension used
423             # my $ext_count = Net::SSLeay::X509_get_ext_count($server_cert);
424             # print "ext_count: $ext_count\n";
425             #
426             # # Extensions
427             # # X509_get_ext
428             # for my $index (0..$ext_count-1) {
429             # my $ext = Net::SSLeay::X509_get_ext($server_cert, $index);
430             # #my $data = Net::SSLeay::X509_EXTENSION_get_data($ext);
431             # #my $string = Net::SSLeay::P_ASN1_STRING_get($data);
432             # #print Data::Dumper::Dumper($string)."\n";
433             #
434             # print "EXT: ".Net::SSLeay::X509V3_EXT_print($ext)."\n";
435             # }
436             #
437             # # Fingerprint
438             # my $fingerprint = Net::SSLeay::X509_get_fingerprint($server_cert, "md5");
439             # print "MD5 fingerprint: $fingerprint\n";
440             # $fingerprint = Net::SSLeay::X509_get_fingerprint($server_cert, "sha1");
441             # print "SHA-1 fingerprint: $fingerprint\n";
442             # $fingerprint = Net::SSLeay::X509_get_fingerprint($server_cert, "sha256");
443             # print "SHA-256 fingerprint: $fingerprint\n";
444             # $fingerprint = Net::SSLeay::X509_get_fingerprint($server_cert, "ripemd160");
445             # print "RIPEMD160 fingerprint: $fingerprint\n";
446             #
447             # # Issuer name
448             # my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert));
449             # print "issuer: $issuer\n";
450             #
451             # # Not after
452             # my $time = Net::SSLeay::X509_get_notAfter($server_cert);
453             # my $not_after = Net::SSLeay::P_ASN1_TIME_get_isotime($time);
454             # print "not after: $not_after\n";
455             #
456             # # Not before
457             # $time = Net::SSLeay::X509_get_notBefore($server_cert);
458             # my $not_before = Net::SSLeay::P_ASN1_TIME_get_isotime($time);
459             # print "not before: $not_before\n";
460             #
461             # # What kind of encryption is using the public key
462             # my $pubkey = Net::SSLeay::X509_get_pubkey($server_cert);
463             # my $type = Net::SSLeay::EVP_PKEY_id($pubkey);
464             # my $encryption_type = Net::SSLeay::OBJ_nid2sn($type);
465             # print "pubkey: $encryption_type\n";
466             #
467             # #
468             # @rv = Net::SSLeay::X509_get_subjectAltNames($server_cert);
469             # print Data::Dumper::Dumper(\@rv)."\n";
470             #
471             # # Serial number
472             # my $serial_number = Net::SSLeay::X509_get_serialNumber($server_cert);
473             # print "serial_number: $serial_number\n";
474              
475 0           return $server_cert;
476             }
477              
478             1;
479              
480             __END__