Bug 1355802

Summary: perl-libwww-perl-5.833-3.el6 SSLv3 handshake error
Product: Red Hat Enterprise Linux 6 Reporter: Konrad Mosoń <mosonkonrad>
Component: perl-libwww-perlAssignee: perl-maint-list
Status: CLOSED INSUFFICIENT_DATA QA Contact: BaseOS QE - Apps <qe-baseos-apps>
Severity: high Docs Contact:
Priority: unspecified    
Version: 6.1CC: ankush819, djez, mosonkonrad, ppisar, psabata
Target Milestone: rc   
Target Release: ---   
Hardware: noarch   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-03-24 06:31:57 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Konrad Mosoń 2016-07-12 14:48:24 UTC
Updating from 0:5.833-2.el6 to this version (0:5.833-3.el6) causes software to misbehave and causes SSL errors.

500 Can't connect to example.com:443 (SSL connect attempt failed because of handshake problemserror:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure).

This patch[1] changes a lot more than just adding "ssl_opts". It puts the opposite order of loading SSL perl libs.

Trying to use ssl_opts => { SSL_version => "TLSv1" } doesn't works.

[1] See external bug for details about patch.

Comment 1 Petr Pisar 2016-07-12 15:50:35 UTC
Yes, because otherwise PERL_LWP_SSL_VERIFY_HOSTNAME environment variable would not work because Net::SSLeay would be always used and Net::SSLeay does not support host name verification at all.

If you cannot connect with IO::Socket::SSL your server, then it's an independent bug in the IO::Socket::SSL.

Please provide more details. What Net::SSLeay or IO::Socket::SSL module you use, how do you invoke the LWP::UserAgent, how the server is configured and SSL protocol trace (e.g. a pcap dump).

Comment 3 Konrad Mosoń 2016-07-12 16:13:21 UTC
Hostname verification is not a problem here, cause I'm using correct certificate which works in Firefox, Chrome and cURL.

I have those SSL-related packages installed (latest available in CentOS at the time of writing this; removed):

openssl-1.0.1e-48.el6_8.1.x86_64
perl-Crypt-SSLeay-0.57-17.el6.x86_64
perl-IO-Socket-SSL-1.31-3.el6.noarch
perl-Net-SSLeay-1.35-10.el6.x86_64

I've tried all combinations, and only updating perl-libwww-perl causes connection problem.

Code I use is quite standard.

---
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(timeout => 600);
my $req = HTTP::Request->new(POST => $url);
$req->content_type('application/json');
$req->content_encoding('gzip');
$req->content($postdata);
my $res = $ua->request($req);
---

There, $res->content results in message posted above.


Server I'm connecting to has disabled SSLv3, what I've tested using openssl s_client. Works only with TLS1/1.1/1.2.

Comment 4 Petr Pisar 2016-07-26 10:51:35 UTC
I'm sorry for the delay. I tried to reproduce it, but I was not able.

I have the same versions:

# rpm -q openssl perl-Crypt-SSLeay perl-IO-Socket-SSL perl-Net-SSLeay
openssl-1.0.1e-48.el6_8.1.x86_64
perl-Crypt-SSLeay-0.57-17.el6.x86_64
perl-IO-Socket-SSL-1.31-3.el6_6.noarch
perl-Net-SSLeay-1.35-10.el6.x86_64

I generated a key and a certificate and started a TLS server with disabled SSL and TLSv1:

$ printf 'HTTP/1.0 200 Ok\r\n\r\n' | openssl s_server -accept 2000 -cert cert -key key -no_ssl2 -no_ssl3 -no_tls1
Using default temp DH parameters
Using default temp ECDH parameters
ACCEPT

Then I used your client code:

$ cat test
#!/usr/bin/perl
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(timeout => 600);
my $req = HTTP::Request->new(POST => $ARGV[0]);
$req->content_type('application/json');
$req->content_encoding('gzip');
$req->content('');
my $res = $ua->request($req);
print $res->status_line, "\n";

And executed it without any problems:

$ ./test https://localhost:2000/
200 Ok

I have no LWP environment variable set:

$ set | grep PERL

It looks like there is another hidden factor. Could you please divulge the HTTPS server you connect to or provide the PCAP dump of the misbehaving connection?

Comment 6 Petr Pisar 2016-09-09 14:02:48 UTC
Konrad, do you know any other details? Maybe you experienced issues with client SSL authentication (bug #1365490) that changed behavior with the updated perl-libwww-perl and should be restored in next release.

Comment 7 Konrad Mosoń 2016-10-07 09:38:11 UTC
Patch proposed in #1365490 didn't worked. I'm still getting:

500 Can't connect to example.com:443 (SSL connect attempt failed because of handshake problemserror:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure)
500 Can't connect to example.com:443 (SSL connect attempt failed because of handshake problemserror:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure)

Comment 8 Petr Pisar 2016-10-07 09:47:28 UTC
Well, without pcap dump of a failed and successed connection or access to your server logs I cannot do anything because I cannot know what's wrong within the SSL handshake. The SSL protocol is built in a way that is does not reveal reason of a failure.

You have to catch the SSL session and compare difference in client requests.

Comment 9 Ankush S 2016-10-13 09:42:51 UTC
+1 

I am having the same problem and I believe my updated libwww-perl + openssl combination is causing this problem. 

We changed our machine and the libwww-perl version got bumped from 5.834 to 6.05-2 and openssl changed from 0.9.8 to 1.0.1f. Our script is failing with handshake problems after this.

Comment 10 Petr Pisar 2016-10-13 11:03:50 UTC
Could you compare the two handshakes on the SSL level? You can use ssltap tool that comes with nss-tools package. E.g.:

(1) Execute in on terminal ssltap to listen on TCP port 2000 and to forward requests to bugzilla.redhat.com:443:

$ ssltap -sx -p 2000 bugzilla.redhat.com:443
Looking up "bugzilla.redhat.com"...
Proxy socket ready and listening

(2) In another terminal point your client to the port 2000:

$ lwp-request -m HEAD https://127.0.0.1:2000/

then the ssltap will display the SSL protocol dump like this:

Looking up "bugzilla.redhat.com"...
Proxy socket ready and listening
Connected to bugzilla.redhat.com:443
--> [
(247 bytes of 242)
SSLRecord { [Thu Oct 13 13:01:10 2016]
   0: 16 03 01 00  f2                                     | .....
   type    = 22 (handshake)
   version = { 3,1 }
   length  = 242 (0xf2)
   handshake {
   0: 01 00 00 ee                                         | ....
      type = 1 (client_hello)
      length = 238 (0x0000ee)
         ClientHelloV3 {
            client_version = {3, 3}
            random = {...}
   0: 57 ff 69 76  2d 6b 7c 88  25 52 11 1e  1b 95 1a ee  | W.iv-k|.%R......
  10: f5 2d e9 e8  73 d9 94 72  08 fd 52 73  ec 61 74 41  | .-..s..r..Rs.atA
            session ID = {
                length = 0
                contents = {...}
            }   
            cipher_suites[66] = {
                (0xc030) ????/????????/?????????/???
                (0xc02c) TLS/ECDHE-ECDSA/AES256-GCM/SHA384
                (0xc028) TLS/ECDHE-RSA/AES256-CBC/SHA384
                (0xc024) TLS/ECDHE-ECDSA/AES256-CBC/SHA384
[...]

If repeat it on the old machine, you could spot a difference in the client request.