Perl: Cannot Access Web Service with SSL

11,382

Solution 1

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.

Solution 2

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

Solution 3

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!

Solution 4

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;

Solution 5

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\""});
Share:
11,382
capdragon
Author by

capdragon

Updated on June 23, 2022

Comments

  • capdragon
    capdragon almost 2 years

    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
    
  • Drav Sloan
    Drav Sloan about 10 years
    The $soap->ssl_opts( verify_hostname => 0 ); call didn't work for me, but the above did. So a +1 here.