I had a problem with PHPMailer suddenly saying my certificate had expired and refusing to connect properly to port 587 with TLS encryption, from Oct 1 2021.
Changing the ssl flags to not verify_peer and not verify_peer_name will temp fix the email issue.
$mail->SMTPOptions = array (
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
));
But its not an ideal solution.
If I go to the same server via port 80 and web there is nothing wrong with the certificate.
If I connect with OpenSSL command line it says the certificate expired on Sep 30 2021.
This problem also appears under the php command file_get_contents.
NOTE: This issue is PHPMailer and email specific and provides good information about PHPMailer, it should not be closed. It has nothing to do with docker or the other question its associated with other than the cause and fix being similar.
The issue here is a real expired authority cert embedded in the LetsEncrypt chain which really DID expire on Sep 30 2021.
From the openssl blog ...
The currently recommended certificate chain as presented to Let’s Encrypt ACME clients when new certificates are issued contains an intermediate certificate (ISRG Root X1) that is signed by an old DST Root CA X3 certificate that expires on 2021-09-30. In some cases the OpenSSL 1.0.2 version will regard the certificates issued by the Let’s Encrypt CA as having an expired trust chain.
Read more here ...
https://www.openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire/
It mainly affects OpenSSL 1.0.2. On my Mac with OpenSSL 1.1.1 I did not have the issue.
CentOS, and I'm sure others have provided fixes to this issue ...
Backup
cp -i /etc/pki/tls/certs/ca-bundle.crt ~/ca-bundle.crt-backup
Add certificate to blacklist directory
trust dump --filter "pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10" | openssl x509 | sudo tee /etc/pki/ca-trust/source/blacklist/DST-Root-CA-X3.pem
Update root store
sudo update-ca-trust extract
Verify removal
diff ~/ca-bundle.crt-backup /etc/pki/tls/certs/ca-bundle.crt
The CentOS specific steps above are from this post ...
https://blog.devgenius.io/rhel-centos-7-fix-for-lets-encrypt-change-8af2de587fe4#:~:text=So%2C%20DST%20Root%20CA%20X3%20needs%20to%20be,The%20manual%20steps%20below%20are%20no%20longer%20necessary.
This is quite a crazy issue that appeared out of nowhere (unless you follow the openSSL blog)
Took me approx 1 day to track down, all the while no emails are being sent and large pieces of the web site not appearing.
Hope this points people in the right direction.
UPDATE: As pointed out by #hakre you may be able to get away with just ...
yum upgrade ca-certificates
Simply edit the fullchain.pem file and remove the last certificate. - if using an OS different to the accepted answer
I have a bunch of PHP scripts that use curl to communicate with various services. Currently, one of those services' SSL certificate got updated and my curl started crying about it when I try to get it from my server's CLI:
~$ curl https://example.com
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
More details here: http://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.
Currently, I hardcoded verify => false to all of my requests in order to keep my scripts operating but that's not something I would like to have laying around.
I got the latest cacert file from mozilla, put it in /etc/ssl/certs/ca-certificates.crt and then ran sudo update-ca-certificates which ran successfully (I suppose..)
~$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
But then again curl is not too happy about it, still can't get my resource without passing the -k flag.
You can use the openssl s_client command to further debug the issue, in order to find out what exactly seems to be the problem with the certificate.
openssl s_client -showcerts -servername myservice.com -connect myservice.com:443
I am getting the following error using curl:
curl: (77) error setting certificate verify locations:
CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
How do I set this certificate verify locations?
I also had the newest version of ca-certificates installed but was still getting the error:
curl: (77) error setting certificate verify locations:
CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
The issue was that curl expected the certificate to be at the path /etc/pki/tls/certs/ca-bundle.crt but could not find it because it was at the path /etc/ssl/certs/ca-certificates.crt.
Copying my certificate to the expected destination by running
sudo cp /etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt
worked for me. You will need to create folders for the target destination if they do not exist by running
sudo mkdir -p /etc/pki/tls/certs
If needed, modify the above command to make the destination file name match the path expected by curl, i.e. replace /etc/pki/tls/certs/ca-bundle.crt with the path following "CAfile:" in your error message.
This error is related to a missing package: ca-certificates. Install it.
In Ubuntu Linux (and similar distro):
# apt-get install ca-certificates
In CygWin via Apt-Cyg
# apt-cyg install ca-certificates
In Arch Linux (Raspberry Pi)
# pacman -S ca-certificates
The documentation tells:
This package includes PEM files of CA certificates to allow SSL-based applications to check for the authenticity of SSL connections.
As seen at: Debian -- Details of package ca-certificates in squeeze
Put this into your .bashrc
# fix CURL certificates path
export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
(see comment from Robert)
Create a file ~/.curlrc with the following content
cacert=/etc/ssl/certs/ca-certificates.crt
as follows
echo "cacert=/etc/ssl/certs/ca-certificates.crt" >> ~/.curlrc
The quickest way to get around the error is add on the -k option somewhere in your curl request. That option "allows connections to SSL cites without certs." (from curl --help)
Be aware that this may mean that you're not talking to the endpoint you think you are, as they are presenting a certificate not signed by a CA you trust.
For example:
$ curl -o /usr/bin/apt-cyg https://raw.github.com/cfg/apt-cyg/master/apt-cyg
gave me the following error response:
curl: (77) error setting certificate verify locations:
CAfile: /usr/ssl/certs/ca-bundle.crt
CApath: none
I added on -k:
curl -o /usr/bin/apt-cyg https://raw.github.com/cfg/apt-cyg/master/apt-cyg -k
and no error message. As a bonus, now I have apt-cyg installed. And ca-certificates.
From $ man curl:
--cert-type <type>
(SSL) Tells curl what certificate type the provided certificate
is in. PEM, DER and ENG are recognized types. If not specified,
PEM is assumed.
If this option is used several times, the last one will be used.
--cacert <CA certificate>
(SSL) Tells curl to use the specified certificate file to verify
the peer. The file may contain multiple CA certificates. The
certificate(s) must be in PEM format. Normally curl is built to
use a default file for this, so this option is typically used to
alter that default file.
#roens is correct. This affects all Anaconda users, with below error
curl: (77) error setting certificate verify locations:
CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
The workaround is to use the default system curl and avoid messing with the prepended Anaconda PATH variable. You can either
Rename the Anaconda curl binary :)
mv /path/to/anaconda/bin/curl /path/to/anaconda/bin/curl_anaconda
OR remove Anaconda curl
conda remove curl
$ which curl
/usr/bin/curl
[0] Anaconda Ubuntu curl Github issue https://github.com/conda/conda-recipes/issues/352
If anyone is still having trouble, try this, it worked for me.
Delete the files in your /etc/ssl/certs/ directory
then reinstall ca-certificates:
sudo apt install ca-certificates --reinstall
Did this when I tried installing Linuxbrew.
Another alternative to fix this problem is to disable the certificate validation:
echo insecure >> ~/.curlrc
For PHP code running on XAMPP on Windows I found I needed to edit php.ini to include the below
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo = curl-ca-bundle.crt
and then copy to a file https://curl.haxx.se/ca/cacert.pem and rename to curl-ca-bundle.crt and place it under \xampp path (I couldn't get curl.capath to work). I also found the CAbundle on the cURL site wasn't enough for the remote site I was connecting to, so used one that is listed with a pre-compiled Windows version of curl 7.47.1 at http://winampplugins.co.uk/curl/
I had the exact same problem. As it turns out, my /etc/ssl/certs/ca-certificates.crt file was malformed. The last entry showed something like this:
-----BEGIN CERTIFICATE-----
MIIEDTCCAvWgAwIBAgIJAN..lots of certificate text....AwIBAgIJAN-----END CERTIFICATE-----
After adding a newline before -----END CERTIFICATE-----, curl was able handle the certificates file.
This was very annoying to find out since my update-ca-certificates command did not give me any warning.
This may or may not be a version specific problem of curl, so here is my version, just for completeness:
curl --version
# curl 7.51.0 (x86_64-alpine-linux-musl) libcurl/7.51.0 OpenSSL/1.0.2j zlib/1.2.8 libssh2/1.7.0
# Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
# Features: IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP UnixSockets
This worked for me
sudo apt-get install ca-certificates
then go into the certificates folder at
sudo cd /etc/ssl/certs
then you copy the ca-certificates.crt file into the /etc/pki/tls/certs
sudo cp ca-certificates.crt /etc/pki/tls/certs
if there is no tls/certs folder: create one and change permissions using chmod 777 -R folderNAME
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). The default
bundle is named curl-ca-bundle.crt; 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.
for example
curl --insecure http://........
It seems your curl points to a non-existing file with CA certs or similar.
For the primary reference on CA certs with curl, see: https://curl.haxx.se/docs/sslcerts.html
Just create the folders, which is missing in your system..
/etc/pki/tls/certs/
and create the file using the following command,
sudo apt-get install ca-certificates
and then copy and paste the certificate to the destination folder, which is showing in your error.. mine was " with message 'error setting certificate verify locations: CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none' in " make sure you paste the file to the exact location mentioned in the error. Use the following command to copy paste..
sudo cp /etc/ssl/certs/ca-certificates.crt
/etc/pki/tls/certs/ca-bundle.crt
Fixed.
I've got the same problem : I'm building a alpine based docker image, and when I want to curl to a website of my organisation, this error appears. To solve it, I have to get the CA cert of my company, then, I have to add it to the CA certs of my image.
Get the CA certificate
Use OpenSSL to get the certificates related to the website :
openssl s_client -showcerts -servername my.company.website.org -connect my.company.website.org:443
This will output something like :
CONNECTED(00000005)
depth=2 CN = UbisoftRootCA
verify error:num=19:self signed certificate in certificate chain
...
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
...
Get the last certificate (the content between the -----BEGIN CERTIFICATE----- and the
-----END CERTIFICATE----- markups included) and save it into a file (mycompanyRootCA.crt for example)
Build your image
Then, when you'll build your docker image from alpine, do the following :
FROM alpine
RUN apk add ca-certificates curl
COPY mycompanyRootCA.crt /usr/local/share/ca-certificates/mycompanyRootCA.crt
RUN update-ca-certificates
Your image will now work properly ! \o/
I came across this curl 77 problem while was trying to access elasticsearch running in docker container on Ubuntu 20.04 localhost. Afrer container was started:
Check curl without ssl: curl --cacert http_ca.crt -u elastic https://localhost:9200 -k lowercase -k for insecure connection.
Check curl configs: curl-config --configure, noticed what is ca-bundle: --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt.
Copy http_ca.crt file from container to:/usr/local/share/ca-certificates/, original command is here.
Run update on ca-certificates: sudo update-ca-certificates.
Run curl: curl -u elastic:<password> https://localhost:9201.
Finally got response with "tagline" : "You Know, for Search".
Change <password> to the one that was generated when Docker Image was run.
Also notice that on my machine elastic was started on port 9201 (don't know why: sudo ss -tlpn | grep 9200 gives me nothing), I have found the port with: sudo netstat -ntlp and Programm name was docker-proxy.
For what it's worth, checking which curl is being run is significant too.
A user on a shared machine I maintain had been getting this error. But the cause turned out to be because they'd installed Anaconda (http://continuum.io). Doing so put Anaconda's binary path before the standard $PATH, and it comes with its own curl binary, which had trouble finding the default certs that were installed on this Ubuntu machine.
Just find this solution works perfectly for me.
echo 'cacert=/etc/ssl/certs/ca-certificates.crt' > ~/.curlrc
I found this solution from here
Run following command in git bash that works fine for me
git config --global http.sslverify "false"
I use MobaXterm which intern uses Cygwin so even after installing ca-certificates using apt-cyg install ca-certificates problem didn't resolve.
I was still getting the following error:
curl: (77) error setting certificate verify locations: CAfile: /etc/ssl/certs/ca-certificates.crt CApath: none
Then I tried listing the file /etc/ssl/certs/ca-certificates.crt and I couldn't find it. However I could find /usr/ssl/certs/ca-bundle.crt with all standard CA certificates so I copied the file /usr/ssl/certs/ca-bundle.crt as /etc/ssl/certs/ca-certificates.crt and problem got resolved.
I had this problem as well. My issue was this file:
/usr/ssl/certs/ca-bundle.crt
is by default just an empty file. So even if it exists, you'll still get the error as it doesn't contain any certificates. You can generate them like this:
p11-kit extract --overwrite --format pem-bundle /usr/ssl/certs/ca-bundle.crt
https://github.com/msys2/MSYS2-packages/blob/master/ca-certificates/ca-certificates.install
For windows :-
Download the certificate from https://curl.se/docs/caextract.html
Rename cacert.pem to curl-ca-bundle.crt
Add the file to any of the below locations
Check this for details https://curl.se/docs/sslcerts.html
Apache/PHP/Symphony is being used in my middle layer for authentication and routing. A request comes through on http then if the request authenticates the person making the request is authorized then makes a call to a backend web service over https. The back end web service is over https with a self signed certificate. I can hit the backend service directly and see my certificate information via chrome inspector. When I make the request directly to the backend via the url, everything works. When I try to go through the middle layer, I get a response back that is a 504:
{"code":504,"message":"A network communication error has occurred","error":{"code":77,"message":"SSL: can\u0027t load CA certificate file \/etc\/pki\/tls\/certs\/ca-bundle.crt"}}
I generated the certificate to:
/usr/local/jboss-eap-6.4/standalone/configuration/.keystore
Using the command:
keytool -genkey -keyalg RSA -alias jboss -keystore .keystore -storepass changeit -validity 9999 -keysize 2048
I also updated my standalone.xml to reference the file via:
<ssl name="ssl" key-alias="jboss" password="changeit" certificate-key-file="/usr/local/jboss-eap-6.4/standalone/configuration/.keystore" protocol="TLSv1" verify-client="false"/>
My dev machine is OSX.
It seems that apache or symfony is looking for the cert in /etc/pki/tls/certs/ca-bundle.cert which is a file that doesn't exist on my system. Searching for "pki" in /etc/apache2/httpd.conf yields no results.
How do I setup apache/symfony2 to trust this cert, or is there a different way to trust this cert more globally?
Create the CA Cert Bundle File
The system is looking for /etc/pki/tls/certs/ca-bundle.cert which is a standard path on linux, but not on osx. We get around this by generating the file.
I generated the .keystore file using keytool and used jboss for my alias. In order to build the ca bundle file, we need it to be in the pem format, so we need to add the -rfc to our export statement. Below are the commands:
cd /usr/local/jboss-eap-6.4/standalone/configuration
keytool -export -alias jboss -file local-sbx.dev.yourcompany.com.crt -keystore .keystore -rfc
After you have the file, you can cat it out and verify that the file has the BEGIN CERTIFICATE and END CERTIFICATE stuff in it. If so, its in the right format.
Lastly, create the directory structure, move the cert to act like the bundle (which is just a bunch of certs appended to each other) and then restart apache:
mkdir -p /etc/pki/tls/certs/
sudo cp local-sbx.dev.yourcompany.com.crt /etc/pki/tls/certs/ca-bundle.crt
sudo apachectl restart
Note: This was a sub problem of SSL: can't load CA certificate file /etc/pki/tls/certs/ca-bundle.crt so if you are still having issues, you might need to update your php setup too... directions are in the link provided.
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.