Net::LDAPS throws unknown error during SSL connect - perl

I am trying to connect to an LDAP server using the Net::LDAPS module. I am passing the right username, password and capath to it. The same code with all the modules in the same version works on one of my other machines. But on this particular machine I see this error.
The sample code I am working with :
my $ad_host = 'XYZ';
my $ad_port = 636;
my $ad_user = 'ABC';
my $ad_pass = '****';
my $ca_path = '<path to ca cert>';
my $ldap = Net::LDAPS->new(
$ad_host,
port => $ad_port,
verify => 'require',
capath => $ca_path
);
Is it a known bug in the LDAPS module? Or am I missing out something apparent.
The debug logs:
DEBUG: .../IO/Socket/SSL.pm:179: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1427: new ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:309: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:311: socket connected
DEBUG: .../IO/Socket/SSL.pm:324: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:354: set socket to non-blocking to enforce timeout=120
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1175: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:373: fatal SSL error: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1462: free ctx 21295632 open=21295632
DEBUG: .../IO/Socket/SSL.pm:1465: OK free ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:1175: IO::Socket::INET6 configuration failederror:00000000:lib(0):func(0):reason(0)
Versions of the modules I am using :
...:~/test_perl$ perlmodver Net::LDAPS
0.05
...:~/test_perl$ perlmodver Net::LDAP
0.39
...:~/test_perl$ perlmodver IO::Socket::SSL
1.18

If you look at the error you can see that certificate verification failed.
SSL connect attempt failed with unknown error..error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
You can either correct the certificate or ignore certificate verification by passing
verify => 'none'
On a sidenote, you can also use Net::LDAP if you pass ldaps:// as a prefix to $ad_host.
$ldaps = Net::LDAP->new('ldaps://myhost.example.com:10000',
verify => 'require',
capath => $ca_path);
Oops just noticed that you said
The same code with all the modules in the same version works on one of
my other machines. But on this particular machine I see this error.
Then this looks like a configuration issue. Can you connect to your server using ldapsearch?

This issue is resolved.
There are 2 ways to solve this :
Bypass the verification (Not recommended)
If you are using the "verify" attribute like the one in my code, you just have to comment it out. It will bypass the cert verification.
Add a soft link to the certificates
Maybe it is a behavior specific to trusty, because on lucid it was working fine. So, you need to create a soft link to all your pem files and place it in the CA Path. You can do this by running
ln -s cacert.pem `openssl x509 -hash -noout < cacert.pem`.0

Related

How to verify self-signed certificate?

I use Net::Jabber::Client to send messages via XMPP.
The server I am connecting to uses self-signed certificate:
DEBUG: .../IO/Socket/SSL.pm:2853: new ctx 45728400
DEBUG: .../IO/Socket/SSL.pm:1540: start handshake
DEBUG: .../IO/Socket/SSL.pm:717: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:750: using SNI with hostname my.host.name
DEBUG: .../IO/Socket/SSL.pm:785: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:806: set socket to non-blocking to enforce timeout=10
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:832: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:842: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:862: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:819: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2754: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2707: ok=0 [0] /CN=my.host.name/CN=my.host.name
DEBUG: .../IO/Socket/SSL.pm:822: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:825: SSL connect attempt failed
DEBUG: .../IO/Socket/SSL.pm:825: local error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:828: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1963: downgrading SSL only, not closing socket
DEBUG: .../IO/Socket/SSL.pm:2875: free ctx 45728400 open=
DEBUG: .../IO/Socket/SSL.pm:2879: free ctx 45728400 callback
DEBUG: .../IO/Socket/SSL.pm:2886: OK free ctx 45728400
I have found that I can pass SSL_fingerprint and/or SSL_verifycn_name to pass verification of self-signed certificate.
To make it just work I hack this
my %ssl_params = (
SSL_verify_mode => $self->{SIDS}->{newconnection}->{ssl_verify},
SSL_hostname => 'my.host.name',
SSL_verifycn_name => 'my.host.name',
);
without success =(
I try to use ->get_fingerprint to obtain finger print and pass it to SSL_fingerprint parameter, but:
IO::Socket::SSL->start_SSL(
$self->{SIDS}->{$sid}->{sock},
$self->{SIDS}->{$sid}->{ssl_params}
) or die "$IO::Socket::SSL::SSL_ERROR";
fail with error:
SSL connect attempt failed error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed at
Which option to pass to IO::Socket::SSL to verify self-signed certificate?
Using the fingerprint is probably the easiest way to verify a self-signed certificate which is in your own control. When using SSL_fingerprint it will not care about any other kind of validations, i.e. not check the name, revocation, expiration etc anymore - so if you want to have checks for this too you should not use SSL_fingerprint.
Getting the fingerprint of a site can be done by connecting to the site once without validation (since you have no trust in the certificate yet) and getting the fingerprint or by getting the fingerprint from the certificate directly.
To get the fingerprint by asking the server, assuming that the connection is not intercepted so that you get the correct fingerprint:
use IO::Socket::SSL;
print IO::Socket::SSL->new(
PeerHost => 'example.com:443',
# switch off validation since the certificate is not trusted yet
SSL_verify_mode => SSL_VERIFY_NONE,
)->get_fingerprint,"\n";
This currently gives sha256$642de54d84c30494157f53f657bf9f89b4ea6c8b16351fd7ec258d556f821040 which can be directly used as argument for SSL_fingerprint.
If you have instead the certificate for the site already you can compute the fingerprint directly on it:
# get the certificate
$ openssl s_client -connect example.com:443 -servername example.com
...
-----BEGIN CERTIFICATE-----
MIIF8jCCBNqgAwIBAgIQDmTF+8I2reFLFyrrQceMsDANBgkqhkiG9w0BAQsFADBw
...
-----END CERTIFICATE-----
# take this PEM certificate and get fingerprint
$ openssl x509 -fingerprint -sha256 -noout -in cert.pem
SHA256 Fingerprint=64:2D:E5:4D:84:C3:04:94:15:7F:53:F6:57:BF:9F:89:B4:EA:6C:8B:16:35:1F:D7:EC:25:8D:55:6F:82:10:40
The shown fingerprint is practically the same as before, only written in a different way. By removing all ':' (which are only there for readability) one gets 642DE5....1040 and by prefixing it with the used hash algorithm sha256 one gets something to be usable in SSL_fingerprint: sha256$642DE5...1040.
To use the fingerprint then to connect to the site:
my $cl = IO::Socket::SSL->new(
PeerHost => 'example.com:443',
SSL_fingerprint => 'sha256$642DE5...1040'
);
IO::Socket::SSL can verify self signed certificate only if it trusts the certificate authority file that you use to self sign the certificate.
I think you need to pass proper SSL_ca_file or SSL_ca_path to IO::Socket::SSL so that certificate authority file is accessible to it. This is the first thing mentioned in common usage errors section of IO::Socket::SSL docs.
Typically this occurs when encrypting via localhost, where a certificate per se hardly plays a role.
Modules that involve IO::Socket::SSL can be used with an additional parameter to prevent crashing with "certificate verify failed".
To solve that issue in the long-term, at the top, add this line:
use IO::Socket::SSL qw(SSL_VERIFY_NONE);
$smtp = Net::SMTPS->new('localhost',
doSSL => 'starttls',
Port => 587,
SSL_verify_mode => SSL_VERIFY_NONE
);

No suitable servers found (`serverSelectionTryOnce` set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate

i`m trying to connect mongodb to php application from compose to local,but get this error.
but i can remote using mongo chef
No suitable servers found (serverSelectionTryOnce set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed calling ismaster
I think you have 3 options to solve this problem.
1. Disable SSL on your server
Find mongod.conf, if you're using linux, then normally it should locate at /etc/mongod.conf, use # to comment these lines under net. Finally, you need to restart mongodb for making change works.
net:
ssl:
mode: requireSSL
PEMKeyFile: ./mongodb.pem
...
2. Use the option called weak_cert_validation on your client
This is not a safety solution, but this is definitely one of the simplest one.
For example, if the mongoDB server has enable SSL but without (or did't) offering CA certificate(means self-signed certificate), then set weak_cert_validation as true in the client side, a example for C client:
mongoc_ssl_opt_t ssl_opts = {0};
ssl_opts.weak_cert_validation = true;
mongoc_client_set_ssl_opts(client, &ssl_opts);
3. Follow configure-ssl to create a certificate and get it signed for your program.
Here some provider: https://en.wikipedia.org/wiki/Certificate_authority#Providers

Override DNS For Specific Domains Like A Hosts File, But Without Using Hosts file

I need to issue a series of parallelized web requests from the same server to a specific domain, but control what IP address these requests actually go to. Originally, I came up with a scheme where I would request the IP I wanted specifically, and then manually set the Host: www.example.com header on the request, and use a series of handlers to make sure that redirects issued followed the same pattern.
This seemed to work for some time, but lately I've been having trouble with redirects to HTTPS. The handshake will fail, and the request in turn. I have tried disabling SSL verification in a variety of ways, including:
local $ENV{ PERL_LWP_SSL_VERIFY_HOSTNAME } = 0;
local $ENV{ HTTPS_DEBUG } = 1;
$ua->ssl_opts(
SSL_ca_file => Mozilla::CA::SSL_ca_file(),
verify_hostname => 0,
SSL_verify_mode => 0x00,
);
IO::Socket::SSL::set_ctx_defaults(
SSL_verifycn_scheme => 'www',
SSL_verify_mode => 0,
);
I have also tried using LWP::UserAgent::DNS::Hosts to solve the problem, but it persists.
<edit>I should note that the reason why turning off peer validation for SSL is not solving the problem is likely because for some reason requesting this way is actually causing the handshake to fail, not failing on a validation point.</edit>
One thing that works is making an entry in /etc/hosts to point the domain at the appropriate IP, however this is not practical, because I may need to run tens, or hundreds, of tests, in parallel, on the same domain.
Is there a way to emulate the functionality of adding an entry to /etc/hosts that does not involve requesting the IP specifically and overriding the Host: ... HTTP header?
EDIT: SSL Debug Info
DEBUG: .../IO/Socket/SSL.pm:1914: new ctx 140288835318480
DEBUG: .../IO/Socket/SSL.pm:402: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:404: socket connected
DEBUG: .../IO/Socket/SSL.pm:422: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:455: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:478: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:491: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:501: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:511: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:531: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:491: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1388: SSL connect attempt failed with unknown error
DEBUG: .../IO/Socket/SSL.pm:497: fatal SSL error: SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: .../IO/Socket/SSL.pm:1948: free ctx 140288835318480 open=140288835318480
DEBUG: .../IO/Socket/SSL.pm:1953: free ctx 140288835318480 callback
DEBUG: .../IO/Socket/SSL.pm:1956: OK free ctx 140288835318480
And in the response I get:
Can't connect to redacted.org:443
SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure at /System/Library/Perl/Extras/5.18/LWP/Protocol/http.pm line 51.
It fails equally well on our server (using an older legacy version of Perl, which I will not disclose here as it seems irrelevant).
The server initially responds to a non-HTTPS request with a 301 redirect to the HTTPS site. Then the failure occurs. I will post reproducing code with the specific details of my request removed, but any site which redirects non-HTTPS traffic to HTTPS should suffice.
use IO::Socket::SSL qw/ debug4 /;
use LWP::UserAgent;
use LWP::UserAgent::DNS::Hosts;
use HTTP::Request;
use Mozilla::CA;
use Data::Dumper;
LWP::UserAgent::DNS::Hosts->register_hosts(
'recacted.org' => '127.0.0.1', # no I am not redirecting to loopback in reality, this is anonymized
'www.redacted.org' => '127.0.0.1',
);
LWP::UserAgent::DNS::Hosts->enable_override;
my $ua = LWP::UserAgent->new;
$ua->ssl_opts( SSL_ca_file => Mozilla::CA::SSL_ca_file() );
my $request = HTTP::Request->new(GET => 'http://redacted.org/');
my $response = $ua->request($request);
print $response->content; #Dumper ( $response->is_success ? $response->headers : $response );
Again, that is not the production code, just enough code to reproduce the issue. It doesn't seem to have anything to do with SSL verification, but moreover an inability to negotiate the request, presumably because LWP::UserAgent::DNS::Hosts is doing exactly what I was doing: changing the request target to the desired IP, and then writing the Host: ... header manually. Why this causes the SSL handshake to fail, I do not know.
On my local machine debugging
openssl version -a: 1.0.2j 26 Sep 2016
IO::Socket::SSL->VERSION == 1.966
Net::SSLeay->VERSION == 1.72
On a server of ours
openssl version -a: 1.0.1t 3 May 2016
IO::Socket::SSL->VERSION == 1.76
Net::SSLeay->VERSION == 1.48
Given that it works with an explicit /etc/hosts file but not with just replacing PeerAddr or using LWP::UserAgent::DNS::Hosts this looks like a problem with the SNI extension. This TLS extension is used to provide the TLS server with the requested hostname (similar to the HTTP Host header) so that it can choose the appropriate certificate. If this SNI extension is missing some servers return a default certificate while others throw an error, like in this case.
The fix is to provide the hostname using SSL_hostname in ssl_opts. Such fix could probably also help with LWP::UserAgent::DNS::Hosts, i.e in LWP/Protocol/https/hosts.pm:
12 if (my $peer_addr = LWP::UserAgent::DNS::Hosts->_registered_peer_addr($host)) {
13 push #opts, (
14 PeerAddr => $peer_addr,
15 Host => $host,
16 SSL_verifycn_name => $host,
NEW SSL_hostname => $host, # for SNI
17 );
18 }

Error: 500 Can't connect to foo.com:443 ( unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3)

I am using LWP::UserAgent version 6.03 to fetch the status of website.
my $ua = LWP::UserAgent->new(ssl_opts => {verify_hostname => 0},);
$ua->cookie_jar({});
$ua->agent('Mozilla/5.0');
push #{$ua->requests_redirectable}, 'POST';
push #{$ua->requests_redirectable}, 'GET';
my $url = 'https://foo.com'
$page = $ua->get($url);
print "Error ".$page->status_line."\n";
When I am running this code on my unix machine it giving the following status and the error message for LWP module.
#status
500 Can't connect to foo.com:443
#error
LWP::Protocol::https::Socket: SSL connect attempt failed with unknown
errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert
unexpected message at /usr/local/lib/perl5/site_perl/5.8.9/LWP/Protocol/http.pm line 51.
I tried to make use of answer given to similar question but it did not worked out. Need your valuable advice.
ran the debug
DEBUG: .../IO/Socket/SSL.pm:193: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1545: new ctx 74489552
DEBUG: .../IO/Socket/SSL.pm:334: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:336: socket connected
DEBUG: .../IO/Socket/SSL.pm:349: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:379: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:392: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:402: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:412: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:432: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:392: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1276: SSL connect attempt failed with unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message
DEBUG: .../IO/Socket/SSL.pm:398: fatal SSL error: SSL connect attempt failed with unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message
DEBUG: .../IO/Socket/SSL.pm:1276: IO::Socket::INET6 configuration failederror:00000000:lib(0):func(0):reason(0)
DEBUG: .../IO/Socket/SSL.pm:1582: free ctx 74489552 open=74489552
DEBUG: .../IO/Socket/SSL.pm:1590: OK free ctx 74489552`
Yeah... This sort of thing happens when some services account for the Poodle vulnerability. I haven't done the research to find the exact cause. It just appears the in some cases the client and server don't properly negotiate the protocol. We've gotten around it by adding 'SSL_version' => 'tlsv1' to the "ssl_opts". I don't really like it though since next protocol upgrade it will need fixing again. I'd far rather let the libraries do the negotiation on their own.

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!