I have a PHP site that queries several APIs via HTTPS. All work, except for reCAPTCHA. This produces the following error:
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
A common solution to this problem is to download a .pem file from the curl site and add it to the PHP.ini file, which I did:
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo="/var/www/cacert.pem"
[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile="/var/www/cacert.pem"
The error still happens. If I check phpinfo() the curl property is not set, but the openssl property is:
I have restarted php-fpm and hard rebooted the server to no avail. There are no relevant errors in the startup log.
I am using PHP Version 7.2.4-1+ubuntu14.04.1+deb.sury.org+1
This issue was solved by upgrading OpenSSL to the latest version, OpenSSL 1.1.0h 27 Mar 2018.
Related
When using curl on my server to access my other servers, I get this response:
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
Using curl from my local machine or opening the same URL in the browser displays the certificate as valid. The problem seems to be due to letsencrypt shutting down support for an older root certificate. But I am just not able to update the trusted root certificates of the server.
I tried update-ca-certificates -f -v and manually downloading the updated root certificates via wget https://curl.se/ca/cacert.pem -O /etc/ssl/certs/cacert.pem but nothing works.
Any ideas?
As the information is not enough, I cannot confirm the cause, but you may try the following steps to remove the old Let'sEncrypt CA:
Check DST Root is in /etc/pki/tls/certs/ca-bundle.crt, and ISRG Root
X1 is in ISRG Root X1.
Copy the "# DST Root CA X3" section into /etc/pki/ca-trust/source/blacklist directory as pem file
run update-ca-trust
Check DST Root is no longer in
/etc/pki/tls/certs/ca-bundle.crt, and ISRG Root X1 is in ISRG Root
X1.
This may be late.
But recently I faced this issue
In my case, the system time was set to 2012 for somereason!!
I just fixed it by synchronizing the time:
timedatectl set-ntp true
Suddenly, curl works.
In fact I wasn't trying curl itself, I was trying to install composer on centos 7 when this error appeared, but now everything is great.
Stupid error took me a whole day to fix!
I am using Firebase php SDK link and working with laravel latest version on XAMMP server on windows 10 but when i try to use Firebase APi using above php SDK i get this error.i download .pem certificate manually but still not working
Error
Kreait \ Firebase \ Exception \ ApiException
cURL error 77: error setting certificate verify locations: CAfile: C:\xampp\apache\bin\curl-ca-bundle.crt CApath: none (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
Previous exceptions
cURL error 77: error setting certificate verify locations: CAfile: C:\xampp\apache\bin\curl-ca-bundle.crt CApath: none (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) (0)
In your case, simply do this
Open your php.ini file and update this
;openssl.cafile=
with
openssl.cafile="C:\xampp\apache\bin\curl-ca-bundle.crt"
For others who might face this error, follow this:
It has to do with your cURL certification. Take these steps:
Head over to http://curl.haxx.se/ca/cacert.pem. This link gets you (downloads) the latest cacert.pem file.
Use this command on your terminal on the application you are currently working on so that you would know the exact PHP used in cases of multiple installations of PHP on your computer, php -i | grep 'Configuration File'. This shows you the exact location of the php.ini file for the current application you are running. For instance, mine is C:\php-7.4.11\php.ini. Note this location as we will use it soon.
Go into this location C:\php-7.4.11 ie. the folder containing the php.ini file in my case, open "extras", open "ssl" (for clarity sake, mine looks like this C:\php-7.4.11\extras\ssl). In this folder, paste in the newly downloaded cacert.pem file from Step 1 above.
Right-click on the cacert.pem file and unblock it from "Properties" as it could complain of coming from another computer. Still on this Properties section pop-up, copy the new file location link from the "Security" section (mine is C:\php-7.4.11\extras\ssl\cacert.pem ensure to copy yours). You can also copy this from the file browser header.
Go to this location C:\php-7.4.11\php.ini (this is my php.ini location. Go to yours) and update the following 2 fields on your php.ini file.
;curl.cainfo =
;openssl.cafile=
with
curl.cainfo ="C:\php-7.4.11\extras\ssl\cacert.pem"
openssl.cafile="C:\php-7.4.11\extras\ssl\cacert.pem"
Restart your xampp/wamp server. In my case, I also restart every other server running.
NB: You get cURL 60 error if curl.cainfo is not updated. And cURL 77 if openssl.cafile is not updated.
Also, do not forget to uncomment the ; before curl.cainfo and openssl.cafile.
Hope this helps someone.
In my case using MAMP PRO I had this error :
CURL error: error setting certificate verify locations:
CAfile: /Applications/MAMP/Library/OpenSSL/cert.pem
CApath: none
The file /Applications/MAMP/Library/OpenSSL/cert.pem was a symlink to /Applications/MAMP/Library/OpenSSL/certs/cacert.pem
it appeared that the file was here but seems to be corrupted or out of date.
I downloaded the new one from here and replaced it. Then it worked again.
I have l5.2 and I followed this steps in hooking sparkpost and laravel and I reverted my services and mail.php to its original configuration:
https://medium.com/#petehouston/send-mail-with-sparkpost-in-laravel-b5e30a941ebf#.s2hebpwb6
But I get this error:
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
This is a problem with your local cacert and usually occurs when using xampp, wamp or similar related software because when making default curl requests there is no certificate in place.
My suggestion would be to download a cacert from here: http://curl.haxx.se/ca/cacert.pem
Copy the cert to C:\Xampp\certs
Update your PHP.ini file with:
curl.cainfo="C:/xampp/certs/ca-bundle.crt"
openssl.cafile="C:/xampp/certs/ca-bundle.crt"
Restart your web server and you should be good to go.
I am trying to debug a problem with ssl certificate verification and have determined that openssl get cert locations with returning incorrect paths. (See below)
How do I figure out how to set this? I looked in the php.ini file and couldn't find this reference anywhere.
cmuench-air:bin cmuench$ ./php -r "print_r(openssl_get_cert_locations());"
Array
(
[default_cert_file] => /bitnami/mampstack56Dev-osx-x64/output/common/openssl/cert.pem
[default_cert_file_env] => SSL_CERT_FILE
[default_cert_dir] => /bitnami/mampstack56Dev-osx-x64/output/common/openssl/certs
[default_cert_dir_env] => SSL_CERT_DIR
[default_private_dir] => /bitnami/mampstack56Dev-osx-x64/output/common/openssl/private
[default_default_cert_area] => /bitnami/mampstack56Dev-osx-x64/output/common/openssl
[ini_cafile] =>
[ini_capath] =>
)
php.ini (relevant parts)...I don't see bitnami/mampstack56Dev anywhere...
[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
;openssl.cafile=
; If openssl.cafile is not specified or if the CA file is not found, the
; directory pointed to by openssl.capath is searched for a suitable
; certificate. This value must be a correctly hashed certificate directory.
; Most users should not specify a value for this directive as PHP will
; attempt to use the OS-managed cert stores in its absence. If specified,
; this value may still be overridden on a per-stream basis via the "capath"
; SSL stream context option.
;openssl.capath=
;Curl ca bundle certificate
curl.cainfo="/Applications/phppos/common/openssl/certs/curl-ca-bundle.crt"
EDIT:
I know this is dumb but there are times where the ssl certificate will be self signed. Is there an ini setting I can modify to disable checking all certificates? or do I have to do this in code for sockets and curl?
If you check the PHP source for the openssl_get_cert_locations() function, it is getting those locations by calling various OpenSSL functions such as X509_get_default_cert_file and looking at php.ini values openssl.cafile and openssl.capath described here.
What certificates/paths are you looking for exactly? If you are trying to get a CA bundle file you could set the above referenced php.ini values so they are returned by openssl_get_cert_locations.
The default php.ini file for PHP 5.6 has no default settings for those OpenSSL ini settings as they need to be defined manually. This configuration is located near the end of php.ini
[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
;openssl.cafile=
; If openssl.cafile is not specified or if the CA file is not found, the
; directory pointed to by openssl.capath is searched for a suitable
; certificate. This value must be a correctly hashed certificate directory.
; Most users should not specify a value for this directive as PHP will
; attempt to use the OS-managed cert stores in its absence. If specified,
; this value may still be overridden on a per-stream basis via the "capath"
; SSL stream context option.
;openssl.capath=
When using cURL, you can use the option CURLOPT_CAINFO to provide the full path to the file holding one or more certificates to verify the peer with by using curl_setopt():
curl_setopt($ch, CURLOPT_CAINFO, "/path/to/ca/bundle");
This can also be set in php.ini:
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
;curl.cainfo =
I'm getting:
Warning: ldap_start_tls()
[function.ldap-start-tls]: Unable to
start TLS: Connect error in
/var/www/X.php on line Y
/etc/ldap/ldap.conf:
TLS_CACERT /etc/ssl/certs/ca.crt
ca.crt is the CA which signed the LDAP server certificate. The certificate on the LDAP server is expired and I can't change it.
You can ignore the validity in windows by issuing
putenv('LDAPTLS_REQCERT=never');
in your php code. In *nix you need to edit your /etc/ldap.conf to contain
TLS_REQCERT never
Another thing to be aware of is that it requires version 3 (version 2 is php default):
//$hostnameSSL example would be "ldaps://just.example.com:636" , just make sure it has ldaps://
$con = ldap_connect($hostnameSSL);
ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
To get a better idea of what's going on, you can enable debug logging by:
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
This can be done before the ldap_connect takes place.
The specific scenario presented in the question--with an expired certificate that can't be changed--does appear to require disabling certificate validation on the LDAP client.
However, I suspect a lot of people, like me, reach this page for other root causes of receiving opaque LDAP TLS errors, where disabling validation of TLS certificates is not an appropriate answer.
In my case--using the LDAP Authentication extension for Mediawiki on an Ubuntu 18.04 LTS server, and authenticating against Active Directory on a Windows Server 2012 server--authentication stopped working in January/February 2020. The server certificate and the CA certificate were still both valid, and openssl s_client -verify 2 -connect <AD server>:636 from the Mediawiki server passed just fine.
Eventually I noticed that the signature algorithm in the SSL certificate served by AD/LDAP was SHA1, which I remembered recently suffered from the first known chosen-prefix collision exploit. This led me to investigate the changelog for packages that had recently been updated on the system, which turned up "Mark SHA1 as insecure for certificate signing" in the gnutls28 changelog circa January 8th, 2020. (The chain of dependencies from the php-ldap package in Ubuntu 18.04 goes to php7.2-ldap -> libldap-2.4-2 -> libgnutls30, whose source package is gnutls28.)
I followed some instructions to update the Windows CA to use SHA256 and then selectively followed instructions to renew the AD/LDAP cert, installed the new CA cert on my Mediawiki server, and the problem was solved! Briefly, these steps included:
In an Admin PowerShell on the AD server, run certutil -setreg ca\csp\CNGHashAlgorithm SHA256
In the Certification Authority MMC, right click on the CA -> All Tasks -> Renew CA Certificate
In a blank MMC, add snap-in for Certificates; select Local Computer
Under Personal -> Certificates, find the current entry used by LDAPS (Kerberos Authentication template type) -> All Tasks -> Advanced Options -> Renew This Certificate with the Same Key
In the same window, open the new CA certificate -> Details -> Copy to file -> no private key -> base64-encoded X.509
Copy the resulting file to /usr/share/ca-certificates/ on the Mediawiki server, then run sudo dpkg-reconfigure ca-certificates and select the new CA cert for inclusion.
P.S. For SEO purposes, depending on the mode I was using, error messages included:
ldap_start_tls(): Unable to start TLS: Connect error in /var/www/mediawiki/extensions/LdapAuthentication/LdapAuthenticationPlugin.php in the HTTP error log
ldap_start_tls(): Unable to start TLS: Can't contact LDAP server in [...]
Failed to start TLS. in the Mediawiki debug log (when using wgLDAPEncryptionType = ssl, i.e. encrypted LDAP port, 636)
Failed to bind as CN=foobar,CN=Users,DC=myOrgName,DC=local in the Mediwiki debug log (when using wgLDAPEncryptionType = tls, i.e. STARTTLS on the unencrypted LDAP port, 389)
My solution/workaround is to use
/etc/ldap/ldap.conf:
#TLS_CACERT /etc/ssl/certs/ca.crt
TLS_REQCERT never
If you have any better idea, please post another answer.
The path for ldap.conf in Windows is fixed:
c:\openldap\sysconf\ldap.conf
A restart of the web server may be required to apply changes.
In debian based systems:
Install the package: ldap-utils and in the file
/etc/ldap/ldap.conf, edit the line:
TLS_CACERT /etc/ldap/cacerts/cacert.asc
Create the directory /etc/ldap/cacerts and copy the cacert to
/etc/ldap/cacerts/cacert.asc
Restart apache.
In redhat based systems:
Install the package: openldap-clients and in the file
/etc/openldap/ldap.conf edit the line:
TLS_CACERT /etc/openldap/cacerts/cacert.asc
Create the directory /etc/openldap/cacerts and copy the cacert to
/etc/openldap/cacerts/cacert.asc
Restart httpd
I was able to get this working properly with openldap on Amazon Linux (Elastic Beanstalk PHP 7.0) with MacOS Server 5 LDAP, with TLS set to demand.
in /etc/openldap/ldap.conf:
TLS_REQCERT demand
TLS_CACERT /etc/openldap/certs/yourcacert.pem
(note that if you are not using openldap, the path will be /etc/ldap/certs/yourcacert.pem). This setup did not work until I placed the certificate inside the certs folder; it did not work from any other path.
The certificate to be placed in that path is NOT the TLS certificate of the server. It is the CA (Certificate Authority) certificate of the authority whom issued the server/domain specific TLS certificate. Only the CA certificate placed in that path will allow TLS to work before attempting an LDAP bind in php. Get the CA certificate from your server or download it from the authority's site, they are freely available.
To test if LDAP bind is even working without TLS, set TLS_REQCERT never temporarily (may need to comment # out TLS_CACERT). If you get "Can't connect to LDAP" it is not a TLS error; it simply cannot connect to the server and you likely need to open port 389 (not 636 for TLS).
Remember to restart your Apache server every time you make a change to the config file or certificate.
Some additional help for others, the certificate solution here solved my ldapsearch command line issue, but still PHP complained **Can't contact LDAP server**
Turned out to be SELinux on RHEL7 ( CentOS7 ) blocks HTTPD from using LDAP ports 389 and 636 by default, you can unblock with:
setsebool -P httpd_can_network_connect 1
Check your SELinux audit log file for things being blocked.