Not 100% sure this is a Perl issue, but it seems to be. I have an IPN script that connects with PayPal to verify transactions. It was working fine until yesterday, when I installed LWP::Protocol::https. Since then, it's been failing with the error:
Can't connect to www.paypal.com:443 (certificate verify failed)
LWP::Protocol::https::Socket: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/local/share/perl5/LWP/Protocol/http.pm line 47.
Running GET https://www.paypal.com
from bash (which uses LWP) yields the same error message. OTOH, running GET https://www.gmail.com
is successful. Running openssl s_client -host paypal.com -port 443
returns (among other things) Verify return code: 0 (ok)
. curl "https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate"
successfully receives a response from PayPal. So it does seem to be Perl-specific.
Module versions:
LWP 6.13
LWP::Protocol::https 6.06
IO::Socket::SSL 2.015
Mozilla::CA 20141217 (note: I've tried the script both using Mozilla::CA and without it... results have been the same)
Please let me know if there are other relevant modules. Perl version is 5.10.1. Server OS is RHEL 6.
Mozilla::CA 20141217 (note: I've tried the script both using Mozilla::CA and without it... results have been the same)
In short: I don't know what "without it" means for RHEL6 but please try again with Mozilla::CA 20130114 or with the "older ca-bundle" linked from http://curl.haxx.se/docs/caextract.html.
Details: The certificate chain you get from www.paypal.com
[0] www.paypal.com
[1] Symantec Class 3 EV SSL CA - G2
[2] VeriSign Class 3 Public Primary Certification Authority - G5
The last certificate in the chain is signed by the 1024 certificate
/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
Since 1024 bit certificates where removed by Mozilla end of last year you will not find them in the current Mozilla::CA any longer. But browsers don't need the old certificate because the create the trust chain based on certificates [0] and [1] already because they use a built-in certificate instead of the certificate [2] send by the server.
While this newer built-in certificate is also included in Mozilla::CA it will not be used because of a long-standing bug in how OpenSSL validates certificates: it will always try to validate the longest chain and not check if a shorter chain is possible.
For more details about this problem see
The problem can be resolved by using the flag X509_V_FLAG_TRUSTED_FIRST which was introduced with OpenSSL 1.02 (released 4 month ago and probably not in RHEL yet) or by using an even newer and not yet released version of OpenSSL where they finally fixed the problem (see https://rt.openssl.org/Ticket/Display.html?id=3637&user=guest&pass=guest).
The problem can be worked around by having the older 1024 bit CA certificates still available, i.e either using an older Mozilla::CA or CA bundle or using the system CA store which usually includes these older CA. See also: