Dmitry Pismennyy
Dmitry Pismennyy

Reputation: 89

Crypt-SSLeay can't verify hostnames

I am not Perl guy at all. But for circumstances I have to deploy perl script on new gentoo server. Script works nicely on several other servers that were configured by another guy. So new one server I've installed by myself and have different versions for some packages. As result with given perl script I have an issue:

Net::SSL from Crypt-SSLeay can't verify hostnames; either install IO::Socket::SSL or turn off verification by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0

Actually it is installed.

perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"' 2.024

Why it does not see installed module. And what can I do on new server to fix issue without modification script? Is version difference so important? new server Perl version: 5.24.0 old server Perl version: 5.22.1

New server:

perl -v

This is perl 5, version 24, subversion 0 (v5.24.0) built for x86_64-linux

perl -MCrypt::SSLeay -e 'print "$Crypt::SSLeay::VERSION\n"'

0.72

perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"'

2.024

env | grep PERL_LWP_SSL_VERIFY_HOSTNAME

Old server: perl -v

This is perl 5, version 22, subversion 1 (v5.22.1) built for x86_64-linux

network6 ~ # perl -MCrypt::SSLeay -e 'print "$Crypt::SSLeay::VERSION\n"'

0.72

network6 ~ # perl -MIO::Socket::SSL -e 'print "$IO::Socket::SSL::VERSION\n"'

2.012

env | grep PERL_LWP_SSL_VERIFY_HOSTNAME

Upvotes: 3

Views: 5757

Answers (1)

ikegami
ikegami

Reputation: 386371

The choice can be affected by completely unrelated parts of your programs. I recommend adding the following near the top of your program:

use IO::Socket::SSL;

Alternatively, set var PERL_NET_HTTPS_SSL_SOCKET_CLASS to IO::Socket::SSL in the process that launches your program.

export PERL_NET_HTTPS_SSL_SOCKET_CLASS=IO::Socket::SSL
  • If your program now throws an exception, this could be why Net::SSL was being used.

    Solution: Solve that error, or settle for the less secure Net::SSL (which requires setting env var PERL_LWP_SSL_VERIFY_HOSTNAME to 0).

  • If your program now runs perfectly, then Net::SSL is being loaded elsewhere in your program, and this is skewing the decision process.

    Solution: Keep using one of the two solution.


Detailed version

That message comes from Net::HTTPS, which is used by LWP::Protocol::https, which is used by LWP::UserAgent and LWP::Simple (and thus WWW::Mechanize).

The following is the process used by Net::HTTPS to determine which SSL class to use:

package Net::HTTPS;

use vars qw( $SSL_SOCKET_CLASS );

# Figure out which SSL implementation to use
if ($SSL_SOCKET_CLASS) {
    # somebody already set it
}
elsif ($SSL_SOCKET_CLASS = $ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS}) {
    unless ($SSL_SOCKET_CLASS =~ /^(IO::Socket::SSL|Net::SSL)\z/) {
        die "Bad socket class [$SSL_SOCKET_CLASS]";
    }
    eval "require $SSL_SOCKET_CLASS";
    die $@ if $@;
}
elsif ($IO::Socket::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "IO::Socket::SSL"; # it was already loaded
}
elsif ($Net::SSL::VERSION) {
    $SSL_SOCKET_CLASS = "Net::SSL";
}
else {
    eval { require IO::Socket::SSL; };
    if ($@) {
        my $old_errsv = $@;
        eval {
            require Net::SSL;  # from Crypt-SSLeay
        };
        if ($@) {
            $old_errsv =~ s/\s\(\@INC contains:.*\)/)/g;
            die $old_errsv . $@;
        }
        $SSL_SOCKET_CLASS = "Net::SSL";
    }
    else {
        $SSL_SOCKET_CLASS = "IO::Socket::SSL";
    }
}

Generally speaking, Net::HTTPS will use IO::Socket::SSL if installed, and Net::SSL otherwise.

One way in which this could be accidentally overridden is by loading Net::SSL before loading Net::HTTPS (elsif ($Net::SSL::VERSION)).

# Causes the "elsif ($Net::SSL::VERSION)" path to be taken
use Net::SSL;

In other words, the choice can be affected by other parts of your programs.

This can be counteracted by loading IO::Socket::SSL before loading Net::HTTPS, or by setting env var PERL_NET_HTTPS_SSL_SOCKET_CLASS to IO::Socket::SSL in the process that launches your program.

So try adding the folowing to the top of your program:

# Causes the "elsif ($IO::Socket::SSL::VERSION)" path to be taken
use IO::Socket::SSL;

Or try doing the following in the process that launches your program:

# Causes the "elsif ([...]$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS})" path to be taken
export PERL_NET_HTTPS_SSL_SOCKET_CLASS=IO::Socket::SSL

Upvotes: 5

Related Questions