Here's a program that does an HTTPS request, with some code at the start that I'm going to explain below:
use 5.012;
use LWP::UserAgent;
use HTTP::Request::Common;
use Net::SSLeay;
BEGIN {
return unless $^O eq 'MSWin32'; # only needed on Windows
print STDERR "attempting to set HTTPS_CA_FILE to PEM file path\n";
require Mozilla::CA; # load module to determine PEM file path
my $pemfile = do {
my $path = $INC{ 'Mozilla/CA.pm' };
$path =~ s#\.pm$#/cacert.pem#;
$path;
};
if ( -f $pemfile ) {
$ENV{HTTPS_CA_FILE} = $pemfile;
print STDERR "HTTPS_CA_FILE set to $pemfile\n";
}
else {
warn "PEM file $pemfile missing";
}
} # ==========================================================================
$Net::SSLeay::trace = 2;
my $ua = LWP::UserAgent->new;
my $req = GET 'https://client.billsafe.de/';
my $rsp = $ua->request( $req );
say $rsp->is_success ? 'success' : 'failure';
say $rsp->status_line;
say '=================';
say substr $rsp->decoded_content, 0, 200;
say '=================';
# possibly relevant module versions
for ( qw/Net::SSLeay Crypt::SSLeay LWP::Protocol::https Mozilla::CA/ ) {
no strict 'refs';
say $_, "\t", ${"${_}::VERSION"}
}
The code at the beginning sets the environment variable HTTPS_CA_FILE
to the value of the PEM file cacert.pem
from Mozilla::CA
that gets loaded by default (I checked using procmon.exe
, the file is fully read by default).
The reason for doing this apparently nonsensical setting is that we have some Windows machines (Windows Server 2008) where the SSL setup fails with certificate verify failed when the environment variable is not set. It is a mystery to us why this is so. And it works fine on other Windows machines with identical versions for Net::SSLeay
, LWP::Protocol::https
and Mozilla::CA
.
Our module versions are:
- Net::SSLeay 1.36
- Crypt::SSLeay -/-
- LWP::Protocol::https 6.02
- Mozilla::CA 20110409
Now the question: Are there other places, apart from cacert.pem
, that root certificates are loaded from in this constellation (Windows, Perl, Net::SSLeay)? If so, what are they? Where can I read up on it?
Update
The OpenSSL docs do not mention any certificate store other than a plain file and a plain directory:
The Windows C API functions used to open the system certificate store are the following:
I checked out the OpenSSL HEAD from CVS. The CertOpenStore
function is indeed used in engines/e_capi.c
. I haven't investigated further to find out what is used to access a store in the OpenSSL versions on the servers in question.
If you do a web search you'll see that a couple of people have wondered whether OpenSSL can access the Windows certificate store directly, or have proposed to patch OpenSSL accordingly. There's also this recent issue on the TortoiseSVN list (Windows Certificate Store / OpenSSL CAPI). Some more research needed to find out what's the matter here.