capdragon
capdragon

Reputation: 14899

Perl: Cannot Access Web Service with SSL

This is my first Perl script. I have installed SOAP::Lite using CPAN and it seems to have gone okay.

I'm trying to access a simple HelloWorld .NET web service. I'm getting an error that seems to be related to Perl or SOAP::Lite not being able to verify the SSL certificate.

Although it looks like it's returning a code of 500, I created a Java client that was able to call the web method just fine, so I don't think the problem is on the web service end.

Can anyone point me in the right direction as to how I might get this working?

Script:

#!/usr/bin/perl

use SOAP::Lite 'trace', 'debug';

$api_ns = "https://www.mydomain.com/edgedev/";
$api_url = "https://www.mydomain.com/edgedev/ws.asmx";
$action = "HelloWorld";

my $soap = SOAP::Lite
                -> readable(1)
                -> ns($api_ns, 'tns')
                -> proxy($api_url)
                -> on_action(sub { return "\"$action\""});

print $soap->HelloWorld()->result;

Result

<soap:Envelope 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:tns="https://www.mydomain.com/edgedev/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <tns:HelloWorld xsi:nil="true" />
      </soap:Body>
</soap:Envelope>
SOAP::Transport::HTTP::Client::send_receive: 500 Can't connect to www.mydomain.com:443 (certificate verify failed)
Content-Type: text/plain
Client-Date: Tue, 12 Feb 2013 16:40:28 GMT
Client-Warning: Internal response

Can't connect to www.mydomain.com:443 (certificate verify failed)

You can disable hostname check by setting environment variable PERL_LWP_SSL_VERIFY_HOSTNAME=0

LWP::Protocol::https::Socket: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/lib/perl5/vendor_perl/5.10.0/LWP/Protocol/http.pm line 57.
500 Can't connect to www.mydomain.com:443 (certificate verify failed) at ./soaptest.pl line 15

Upvotes: 3

Views: 12422

Answers (8)

user8131845
user8131845

Reputation: 1

Boy did this work for me! I threw this into stubmaker.pl and my script which uses the stubmaker.pl output.

IO::Socket::SSL::set_defaults(SSL_verify_mode => "SSL_VERIFY_NONE");
use SOAP::Lite +trace => qw( debug );

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0; 

Upvotes: 0

jimtut
jimtut

Reputation: 2393

Just found this thread, and everything was very useful to me, thanks!

I wanted to added my "solution", which is a variation on the previous ones, in case it helps someone else.

Adding

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

is definitely key. However, this causes a big warning to come out of IO::Socket::SLL:

*******************************************************************
 Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
 is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
 together with SSL_ca_file|SSL_ca_path for verification.
 If you really don't want to verify the certificate and keep the
 connection open to Man-In-The-Middle attacks please set
 SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************

The way to get rid of that warning was to add these lines:

use IO::Socket::SSL;
IO::Socket::SSL::set_defaults(SSL_verify_mode => "SSL_VERIFY_NONE");

In addition to the original $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}, that should work no matter what client you're using (LWP::UserAgent, RPC::XML::Client, SOAP::Lite, etc.).

Hope that helps someone else!

Upvotes: 2

DimmuR
DimmuR

Reputation: 291

In perl v5.20.2 two things were required for me to disable ssl certificate validation:

Before any SOAP object creation (I've putted it at top)

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

And then modify SOAP proxy:

my $soap = SOAP::Lite
            -> readable(1)
            -> ns($api_ns, 'tns')
            -> proxy($api_url, ssl_opts => [ SSL_verify_mode => 0 ] )
            -> on_action(sub { return "\"$action\""});

Upvotes: 1

Jander
Jander

Reputation: 5637

Here is how to make this work securely, i.e. without disabling SSL hostname checking.

If you're talking to a public system with a CA-signed certificate, you need to point LWP to your distribution's root certificate collection. Under a Debian-based system (Ubuntu, etc.), this is kept under /etc/ssl/certs/.

BEGIN {
    $ENV{HTTPS_CA_DIR} = '/etc/ssl/certs'
}

If you are talking to your own server with a self-signed certificate, you can save a copy of that certificate on the client, and point your script to that particular file.

BEGIN {
    $ENV{HTTPS_CA_FILE} = '/path/to/my/server-certificate.crt'
}

You could instead set these in the environment before running your script (e.g. export them from your shell), or you could apply the settings directly to your UserAgent object. See the LWP::UserAgent documentation for more details; search for ssl_opts.

Upvotes: 7

dimas
dimas

Reputation: 389

Or add in your code before calling SOAP method:

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

Upvotes: 0

Dennis Kaarsemaker
Dennis Kaarsemaker

Reputation: 286

You need to tell LWP to not do hostname checking. For me this only worked using an environment variable, not by setting an option in SOAP::Lite objects:

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;

Upvotes: 1

Erik Kaju
Erik Kaju

Reputation: 3173

$soap->{_transport}->{_proxy}->{ssl_opts}->{verify_hostname} = 0;

Upvotes: 3

alexsergeyev
alexsergeyev

Reputation: 535

As SOAP::Lite repeats LWP calls it should be possible to use

$soap->ssl_opts( verify_hostname => 0 );

Upvotes: 0

Related Questions