Skip Menu |

This queue is for tickets about the IO-Async-SSL CPAN distribution.

Report information
The Basics
Id: 96474
Status: resolved
Priority: 0/
Queue: IO-Async-SSL

People
Owner: leonerd-cpan [...] leonerd.org.uk
Requestors: DAKKAR [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.14
Fixed in: 0.15



Subject: SSL parameters auto-detection has problems
On some systems, F</etc/ssl/certs> is not the best place to get certificates from (CentOS 6.4 is an example, where we should be looking at C</etc/pki/tls/certs>). L<IO::Socket::SSL> provides a function, C<default_ca()>, that returns the best path to use. It is also the default path used if no options are passed in. So, on my machine, my $client = IO::Socket::SSL->new( PeerHost => 'wwwcie.ups.com', PeerPort => 'https', ) or die "failed connect or ssl handshake: $!,$SSL_ERROR"; works, but my $client = IO::Socket::SSL->new( PeerHost => 'wwwcie.ups.com', PeerPort => 'https', SSL_ca_path => '/etc/ssl/certs', ) or die "failed connect or ssl handshake: $!,$SSL_ERROR"; fails. The main reason seems to be that the CA bundle is called F</etc/ssl/certs/ca-bundle.crt>, but something is looking for a file called F<cert.pem> (there's a symlink from F</etc/pki/tls/cert.pem> to F</etc/ssl/certs/ca-bundle.crt>) In addition, looking at C<default_ca()> at https://metacpan.org/source/SULLR/IO-Socket-SSL-1.993/lib/IO/Socket/SSL.pm#L308 we see that it already delegates to L<Mozilla::CA>. Given all this, the logic in L<IO::Async::SSL> could be simplified to: %SSL_ca_args = IO::Socket::SSL::default_ca(); unless (%SSL_ca_args) { carp "Unable to set SSL_VERIFY_PEER because Mozilla::CA is unavailable and your SSL configuration is wonky"; $SSL_ca_args{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_NONE(); } I have not actually tested this code, but I have verified that if I pass C<< SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(), >> explicitly (thus disabling the auto-detect code in L<IO::Async::SSL>), server verification works. Hope this helps.
Patched -- Paul Evans
Subject: rt96474.patch
=== modified file 'Build.PL' --- Build.PL 2013-10-15 00:17:01 +0000 +++ Build.PL 2015-04-04 13:31:09 +0000 @@ -12,9 +12,6 @@ 'IO::Async::Stream' => '0.59', 'IO::Socket::SSL' => 0, }, - recommends => { - 'Mozilla::CA' => 0, - }, build_requires => { 'IO::Async::OS' => 0, 'Test::More' => '0.88', # done_testing === modified file 'lib/IO/Async/SSL.pm' --- lib/IO/Async/SSL.pm 2015-01-14 17:53:09 +0000 +++ lib/IO/Async/SSL.pm 2015-04-04 13:31:09 +0000 @@ -65,17 +65,13 @@ connection to use SSL. As an additional convenience, if the C<SSL_verify_mode> and C<SSL_ca_*> -options are omitted, the module will attempt to provide them. If the -F</etc/ssl/certs> directory exists, it will be used. Failing that, if -L<Mozilla::CA> can be loaded, that will be used. Otherwise, the module will -print a warning and set C<SSL_VERIFY_NONE> instead. +options are omitted, the module will attempt to provide them by quering the +result of L<IO::Socket::SSL>'s C<default_ca> function. Otherwise, the module +will print a warning and set C<SSL_VERIFY_NONE> instead. =cut -# Linux etc.. often stores SSL certs here -# TODO: Make this a property of IO::Async::OS -my $SSL_ca_path = "/etc/ssl/certs"; -my %SSL_ca_args; +my %SSL_ca_args = IO::Socket::SSL::default_ca(); sub _SSL_args { @@ -84,21 +80,9 @@ # SSL clients (i.e. non-server) require a verify mode if( !$args{SSL_server} and !defined $args{SSL_verify_mode} and !defined $args{SSL_ca_file} and !defined $args{SSL_ca_path} ) { - # Try to load Mozilla::CA; but if it fails remember that so we don't - # reload it repeatedly unless( %SSL_ca_args ) { - if( -d $SSL_ca_path ) { - $SSL_ca_args{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_PEER(); - $SSL_ca_args{SSL_ca_path} = $SSL_ca_path; - } - elsif( eval { require Mozilla::CA } ) { - $SSL_ca_args{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_PEER(); - $SSL_ca_args{SSL_ca_file} = Mozilla::CA::SSL_ca_file(); - } - else { - carp "Unable to set SSL_VERIFY_PEER because Mozilla::CA is unavailable"; - $SSL_ca_args{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_NONE(); - } + carp "Unable to set SSL_VERIFY_PEER because IO::Socket::SSL::default_ca() gives nothing"; + $SSL_ca_args{SSL_verify_mode} = IO::Socket::SSL::SSL_VERIFY_NONE(); } %args = ( %SSL_ca_args, %args );