Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LWP with SSL and client certificates

I'm porting an application from PHP/cURL to Perl and LWP::UserAgent. I need to do a POST request to a web server and provide a client certificate and key file. The PHP code I'm trying to replicate is this:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSLCERT, "/path/to/certificate.pem"); 
curl_setopt($ch, CURLOPT_SSLKEY, "/path/to/private.key"); 
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, "secretpassword");

And here's my Perl code:

my $ua = LWP::UserAgent->new();
$ua->ssl_opts(
   SSL_verify_mode => 0,
   SSL_cert_file   => '/path/to/certificate.pem',
   SSL_key_file    => "/path/to/private.key",
   SSL_passwd_cb   => sub { return "secretpassword"; }  
);

The PHP code successfully connects to the server but the Perl code fails with:

SSL read error error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure

I can't figure out what I'm missing.

like image 691
kent Avatar asked Oct 02 '12 20:10

kent


3 Answers

sub send_command(){
        my $command = shift;
        my $parser = XML::LibXML->new('1.0','utf-8');

        print color ("on_yellow"), "SEND: ", $command, color ("reset"), "\n";

        # Create a request
        my $req = HTTP::Request->new( GET => $Gateway.$command );

        # Pass request to the user agent and get a response back
        my $res;
        eval {
                 my $ua;
                 local $SIG{'__DIE__'};
                 $ua = LWP::UserAgent->new(); #  или 
                 $ua->ssl_opts( #$key => $value 
                    SSL_version         => 'SSLv3',
                    SSL_ca_file         => '/ca.pem',
                    #SSL_passwd_cb       => sub { return "xxxxx\n"; },
                    SSL_cert_file       => '/test_test_cert.pem',
                    SSL_key_file        => '/test_privkey_nopassword.pem',
                ); # ssl_opts => { verify_hostname => 0 }
                 $ua->agent("xxxxxx xxxx_tester.pl/0.1 ");
                 $res = $ua->request($req);

        };  
        warn $@ if $@;
        # Check the outcome of the response
        if ( $res->is_success ) {
                open  xxxLOG, ">> $dir/XXXX_tester.log";
                my $without_lf = $res->content;
                $without_lf =~ s/(\r|\n)//gm;
                print PAYLOG $without_lf,"\n";
                close PAYLOG;
        }
        else {
                 return $res->status_line;
        }       
        print  color ("on_blue"), "RESPONSE: ", color ("reset"), respcode_color($res->content), color ("reset"),"\n\n";
        return $res->content;
} 
like image 160
nexoma Avatar answered Nov 02 '22 03:11

nexoma


The answer from emazep above solved my problem. I'm using the sample Perl code from UPS to connect to their Rate service via XML. From my tests, this will work any time LWP::UserAgent is being called without arguments that you can control directly, which makes it handy if you're using some other module which makes calls to LWP for you. Just use Net::SSL (in addition to whatever packages have already used LWP) and set a few environment variables:

...
use Net::SSL;
$ENV{HTTPS_VERSION} = 3;
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
my $browser = LWP::UserAgent->new();
...

That's it! You shouldn't even need to specify the path to your server's root certificate with $ENV{PERL_LWP_SSL_CA_FILE}.

like image 25
goddogsrunning Avatar answered Nov 02 '22 03:11

goddogsrunning


Indeed this is a messy bit. Depending on your setup LWP::UserAgent may use one of (at least) two SSL modules to handle the SSL connection.

  • IO::Socket::SSL
  • Net::SSL

The first one should be the default for newer versions of LWP::UserAgent. You can test which of these are installed by running the standard command in a terminal for each module:

perl -e 'use <module>;'

IO::socket::SSL requires the SSL configuration with the ssl_opts as in your example.

Net::SSL requires the SSL configuration in environment variables as in goddogsrunnings answer.

Personally I fall in the second category and had good inspiration from the Crypt::SSLeay page. Particularly the section named "CLIENT CERTIFICATE SUPPORT ".

like image 1
Phluks Avatar answered Nov 02 '22 03:11

Phluks