Soap perl and ssl certificate changed - perl

I have a perl code that sends SOAP request through SOAP::Lite like this:
eval
{
$sresp = SOAP::Lite
->uri('http://machine/key')
->proxy('https://usr:pwd#website.com/addr/addr/remotescript.pl')
->remotescript_pl_function(#parms, $gmtime);
};
if ($#)
{
print $#;
}
After existing certificate for *.website.com has been replaced I am not getting valid responses anymore, I am getting
500 Can\'t connect to website.com:443 at localscript.pl line 123.
If I enable
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
everything works. But I would like to verify the SSL hostname, how can I do that, or track down the problem? (I am a little lost in this proxying).
I have c++ code with libcurl that goes along the same lines and works well. Entering https://website.com into browser works fine. Entering http://machine (machine is on local network) works.
edit 1:
Both perl -MIO::Socket::SSL=debug4 yourscript.pl and analyze-ssl.pl from p5-ssl-tools show error message 1416F086 which lead me to information that SSL certificate has "Chain issues" that have to be fixed in certificate installation.
edit 2:
After fix of the certificate is the error gone! Perfect, solved!

Here is solution mentioned in comments by Corion and Steffen Ullrich:
Running either:
https://github.com/noxxi/p5-ssl-tools script analyze-ssl.pl
perl -MIO::Socket::SSL=debug4 yourscript.pl
displayed same error: SSL connect attempt failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed. This pointed me to: telegram bot SSL error: SSL error {error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed} where I found that I too have "Chain issues Incomplete".
After fixing certificate the error is gone.

Related

Does perl-5.16.0-LWP-Protocol-Connect-6.09.tgz supports TLS 1.2?

I am kind of new to perl world but my script fails when loaded via SFTP with below error ,
IN SUBROUTINE: CSRF TOKEN DECODED CONTENT:
error while setting up ssl connection (SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure) at /home/rcc/perl5/lib/perl5/LWP/Protocol/https/connect/Socket.pm line 23.
Looping through csrf response array, param = [error while setting up ssl connection (SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure) at /home/rcc/perl5/lib/perl5/LWP/Protocol/https/connect/Socket.pm line 23.
]
Under the assumption its because of TLS depreciation , we upgraded SSL version but still doesn't work, can someone help us understand how to fix the issue ?
Or is there a latest version of perl LWP which by upgrade can fix the issue ? repacking the current package seems to be complex.
Thanks in advance.
The SSL handling is not done directly by LWP::Protocol::connect. Instead it uses IO::Socket::SSL which then uses Net::SSLeay which then uses the linked in OpenSSL library which is not necessarily the one used by the openssl binary. The general capability to use TLS 1.2 depends on the version of OpenSSL which should be at least 1.0.1.
To get the versions of the various parts use the following code
use strict;
use IO::Socket::SSL;
printf "IO::Socket::SSL %s\n", $IO::Socket::SSL::VERSION;
printf "Net::SSLeay %s\n", $Net::SSLeay::VERSION;
printf "OpenSSL compiled %x\n", Net::SSLeay::OPENSSL_VERSION_NUMBER();
printf "OpenSSL linked %x - %s\n", Net::SSLeay::SSLeay(),
Net::SSLeay::SSLeay_version(0);
... SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
Note that a TLS handshake problem can have lots of different reasons and an unsupported TLS protocol version is just one of many. No shared ciphers is another common problem at this stage of the connection.

My sendmail log get TLS setup failed

I setup my nagios in docker container,and It working.and sendmail can send mail to me.
I find it can't send message to me one day,and I see the Log of sendmail,I get this error
nagios sendEmail.pl[15471]: ERROR => TLS setup failed: SSL connect attempt failed because of handshake problems error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
during this time,I just stop and restart my nagios container
the packages of libio-socket-ssl-perl and libnet-ssleay-perl perl also have installed.
How can I slove this problem??
Thanks very much
If you mean with sendEmail.pl this script with the last update from 2009 then you are using unsupported and broken software. It might work if you change the following line in the script:
- if (! IO::Socket::SSL->start_SSL($SERVER, SSL_version => 'SSLv3 TLSv1')) {
+ if (! IO::Socket::SSL->start_SSL($SERVER)) {
Reason for this change is that the setting of SSL_version in the code was wrong from the beginning, only that 7 years ago IO::Socket::SSL did not complain about it but simply used the first setting SSLv3. But since 4 years IO::Socket::SSL is stricter and complains about the wrong usage. Apart from that SSLv3 would not work in many cases anyway today because the protocol is disabled for security reasons.

Unable to connect to JIRA over HTTPS server using the Perl JIRA::Client::Automated

I do not use a proxy.
Here is my code:
use JIRA::Client::Automated;
my $jira = JIRA::Client::Automated->new(https://myserver.com, "user", "password");
And the error response is:
Unable to GET /jira/rest/api/latest/issue/DCS-51191: 500 Can't connect
to myserver.com:443 Can't connect to myserver.com:443
Bad file descriptor at
C:/Users/Fred/applis_portables/Strawberry_Perl/perl/vendor/lib/LWP/Protocol/http.pm
line 47.
at createPage2.pl line 16.
Thank you for your help.
It seems that there is a self signed certificate on JIRA server. To bypass, I added following code:
my $jira_ua = $jira->ua();
$jira_ua->ssl_opts( verify_hostname => 0 );
The error doesn't look like a JIRA::Client::Automated error. It's generated by LWP::UserAgent and usually means exactly what is shown.
Do you have a self signed certificate on your server?
Did you try to open that URL in in your browser? https://myserver.com:443 (exactly as you provide it to the module).
Try using curl from your webserver:
curl -vvv https://myserver.com/jira/rest/api/latest/issue/DCS-51191
Maybe it's just a missing www. prefix in your server URL?

PerL SSL connect attempt failed because of handshake problems

I'm hoping someone can help, I'm using the nagios plugin check_ilo2_health, the plugin works fine on our OpenSuSE systems but the new Ubuntu 14.04 system has issues, removing the nagios stuff and running perl, is basically this:
perl -e 'use IO::Socket::SSL qw(debug3);IO::Socket::SSL->new(SSL_hostname => "", PeerAddr=>"10.0.0.1:443", Proto=>"tcp",SSL_verify_mode => SSL_VERIFY_NONE)or die $!'
I'm connecting to an HP ILO2 with a self signed certificate and get a reply:
DEBUG: .../IO/Socket/SSL.pm:2503: new ctx 19182624
DEBUG: .../IO/Socket/SSL.pm:526: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:528: socket connected
DEBUG: .../IO/Socket/SSL.pm:550: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:586: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:647: Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:695: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:1757: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:2537: free ctx 19182624 open=19182624
DEBUG: .../IO/Socket/SSL.pm:2549: OK free ctx 19182624
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
If I run it in curl:
curl "https://10.0.0.1" --insecure
It works returning the page from the ILO.
I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
Any ideas of what can be done?
Versions:
Perl Version: This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
Crypt::SSLeay 0.72
IO::Socket::SSL 1.997
Net::SSLeay 1.66
Thanks in advance
I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
You are doing it correctly, that is by using SSL_verify_mode of SSL_VERIFY_NONE.
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
Strange, but I've seen other reports with "HP ILO2" and bad_record_mac.
Try to reduce the version to SSL 3.0, e.g. SSL_version => "SSLv3".
But because SSL 3.0 would not be a satisfactory solution because of POODLE I would be interested to have a look at the working SSL handshake from curl (upload to cloudshark.org).
The same error happens with Net::LDAP (which also uses IO::Socket::SSL) when connecting to a server that only supports SSLv2.
IO::Socket::SSL "auto-negotiates between SSLv2 and SSLv3" by default according to man page, so omitting SSL_version allows scripts to work with older servers.
Or, more optimistically, the script will still work when the administrator gets around to upgrading the server!

How can I get LWP to validate SSL server certificates?

How can I get LWP to verify that the certificate of the server I'm connecting to is signed by a trusted authority and issued to the correct host? As far as I can tell, it doesn't even check that the certificate claims to be for the hostname I'm connecting to. That seems like a major security hole (especially with the recent DNS vulnerabilities).
Update: It turns out what I really wanted was HTTPS_CA_DIR, because I don't have a ca-bundle.crt. But HTTPS_CA_DIR=/usr/share/ca-certificates/ did the trick. I'm marking the answer as accepted anyway, because it was close enough.
Update 2: It turns out that HTTPS_CA_DIR and HTTPS_CA_FILE only apply if you're using Net::SSL as the underlying SSL library. But LWP also works with IO::Socket::SSL, which will ignore those environment variables and happily talk to any server, no matter what certificate it presents. Is there a more general solution?
Update 3: Unfortunately, the solution still isn't complete. Neither Net::SSL nor IO::Socket::SSL is checking the host name against the certificate. This means that someone can get a legitimate certificate for some domain, and then impersonate any other domain without LWP complaining.
Update 4: LWP 6.00 finally solves the problem. See my answer for details.
This long-standing security hole has finally been fixed in version 6.00 of libwww-perl. Starting with that version, by default LWP::UserAgent verifies that HTTPS servers present a valid certificate matching the expected hostname (unless $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} is set to a false value or, for backwards compatibility if that variable is not set at all, either $ENV{HTTPS_CA_FILE} or $ENV{HTTPS_CA_DIR} is set).
This can be controlled by the new ssl_opts option of LWP::UserAgent. See that link for details on how the Certificate Authority certificates are located. But be careful, the way LWP::UserAgent used to work, if you provide a ssl_opts hash to the constructor, then verify_hostname defaulted to 0 instead of 1. (This bug was fixed in LWP 6.03.) To be safe, always specify verify_hostname => 1 in your ssl_opts.
So use LWP::UserAgent 6; should be sufficient to have server certificates validated.
There are two means of doing this depending on which SSL module you have installed. The LWP docs recommend installing Crypt::SSLeay. If that's what you've done, setting the HTTPS_CA_FILE environment variable to point to your ca-bundle.crt should do the trick. (the Crypt::SSLeay docs mentions this but is a bit light on details). Also, depending on your setup, you may need to set the HTTPS_CA_DIR environment variable instead.
Example for Crypt::SSLeay:
use LWP::Simple qw(get);
$ENV{HTTPS_CA_FILE} = "/path/to/your/ca/file/ca-bundle";
$ENV{HTTPS_DEBUG} = 1;
print get("https://some-server-with-bad-certificate.com");
__END__
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:unknown CA
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:bad certificate
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv2 write client hello A
SSL_connect:error in SSLv2 read server hello B
Note that get doesn't die, but it does return an undef.
Alternatively, you can use the IO::Socket::SSL module (also available from the CPAN). To make this verify the server certificate you need to modify the SSL context defaults:
use IO::Socket::SSL qw(debug3);
use Net::SSLeay;
BEGIN {
IO::Socket::SSL::set_ctx_defaults(
verify_mode => Net::SSLeay->VERIFY_PEER(),
ca_file => "/path/to/ca-bundle.crt",
# ca_path => "/alternate/path/to/cert/authority/directory"
);
}
use LWP::Simple qw(get);
warn get("https:://some-server-with-bad-certificate.com");
This version also causes get() to return undef but prints a warning to STDERR when you execute it (as well as a bunch of debugging if you import the debug* symbols from IO::Socket::SSL):
% perl ssl_test.pl
DEBUG: .../IO/Socket/SSL.pm:1387: new ctx 139403496
DEBUG: .../IO/Socket/SSL.pm:269: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:271: socket connected
DEBUG: .../IO/Socket/SSL.pm:284: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:327: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1135: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:333: fatal SSL error: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1422: free ctx 139403496 open=139403496
DEBUG: .../IO/Socket/SSL.pm:1425: OK free ctx 139403496
DEBUG: .../IO/Socket/SSL.pm:1135: IO::Socket::INET configuration failederror:00000000:lib(0):func(0):reason(0)
500 Can't connect to some-server-with-bad-certificate.com:443 (SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed)
I landed on this page looking for a way to bypass SSL validation but all answers were still very helpful. Here are my findings. For those looking to bypass SSL validation (not recommended but there may be cases where you will absolutely have to), I'm on lwp 6.05 and this worked for me:
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common qw(GET);
use Net::SSL;
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );
my $req = GET 'https://github.com';
my $res = $ua->request($req);
if ($res->is_success) {
print $res->content;
} else {
print $res->status_line . "\n";
}
I also tested on a page with POST and it also worked. The key is to use Net::SSL along with verify_hostname = 0.
If you use LWP::UserAgent directly (not via LWP::Simple) you can validate the hostname in the certificate by adding the "If-SSL-Cert-Subject" header to your HTTP::Request object. The value of the header is treated as a regular expression to be applied on the certificate subject, and if it does not match, the request fails. For example:
#!/usr/bin/perl
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => 'https://yourdomain.tld/whatever');
$req->header('If-SSL-Cert-Subject' => '/CN=make-it-fail.tld');
my $res = $ua->request( $req );
print "Status: " . $res->status_line . "\n"
will print
Status: 500 Bad SSL certificate subject: '/C=CA/ST=Ontario/L=Ottawa/O=Your Org/CN=yourdomain.tld' !~ //CN=make-it-fail.tld/
All the solutions presented here contain a major security flaw in that they only verify the validity of the certificate's trust chain, but don't compare the certificate's Common Name to the hostname you're connecting to. Thus, a man in the middle may present an arbitrary certificate to you and LWP will happily accept it as long as it's signed by a CA you trust. The bogus certificate's Common Name is irrelevant because it's never checked by LWP.
If you're using IO::Socket::SSL as LWP's backend, you can enable verification of the Common Name by setting the verifycn_scheme parameter like this:
use IO::Socket::SSL;
use Net::SSLeay;
BEGIN {
IO::Socket::SSL::set_ctx_defaults(
verify_mode => Net::SSLeay->VERIFY_PEER(),
verifycn_scheme => 'http',
ca_path => "/etc/ssl/certs"
);
}
You may also consider Net::SSLGlue ( http://search.cpan.org/dist/Net-SSLGlue/lib/Net/SSLGlue.pm ) But, take care, it depends on recent IO::Socket::SSL and Net::SSLeay versions.
You are right to be concerned about this. Unfortunately, I don't think it's possible to do it 100% securely under any of the low-level SSL/TLS bindings I looked at for Perl.
Essentially you need to pass in the hostname of the server you want to connect to the SSL library before the handshaking gets underway. Alternatively, you could arrange for a callback to occur at the right moment and abort the handshake from inside the callback if it doesn't check out. People writing Perl bindings to OpenSSL seemed to have troubles making the callback interface consistently.
The method to check the hostname against the server's cert is dependent on the protocol, too. So that would have to be a parameter to any perfect function.
You might want to see if there are any bindings to the Netscape/Mozilla NSS library. It seemed pretty good at doing this when I looked at it.
Just perform execute the following command in Terminal:
sudo cpan install Mozilla::CA
It should solve it.