Url error 60 ssl certificate problem certificate has expired

We running 2 application on amazon EC2 (backend.example.com & frontend.example.com). For that application, we used a paid SSL Certificate. That certificate expiration date at 2021 June. But tod...

We running 2 application on amazon EC2 (backend.example.com & frontend.example.com). For that application, we used a paid SSL Certificate. That certificate expiration date at 2021 June. But today, we got an error —

cURL error 60: SSL certificate problem: certificate has expired (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

We check certificate expiration date, but there was no problem (2021 June). Then we follow this thread — curl: (60) SSL certificate problem: unable to get local issuer certificate (@Dahomz answer)

After that, when we curl example.com by — curl -v --url https://backend.example.com --cacert /etc/ssl/ssl.cert/cacert.pem, It working fine. Response like —

* Rebuilt URL to: https://backend.example.com/
*   Trying 127.0.0.1...
* Connected to backend.example.com (127.0.0.1) port 443 (#0)
* found 139 certificates in /etc/ssl/ssl.cert/cacert.pem
* found 600 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ******_RSA_***_***_GCM_*****
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: *.example.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: OU=Domain Control Validated,OU=PositiveSSL Wildcard,CN=*.example.xyz
*    start date: Mon, 04 May 2019 00:00:00 GMT
*    expire date: Wed, 07 June 2021 23:59:59 GMT
*    issuer: C=GB,ST=Greater Manchester,L=Salford,O=Sectigo Limited,CN=Sectigo RSA Domain Validation Secure Server CA
*    compression: NULL
* ALPN, server accepted to use http/1.1

But when we hit from frontend.example.com to backend.example.com by curl, it throws this error —

* Rebuilt URL to: https://backend.example.com/
*   Trying 127.0.0.1...
* Connected to backend.example.com (127.0.0.1) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/ssl.cert/cacert.pem
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / *****-RSA-*****-GCM-******
* ALPN, server accepted to use http/1.1
* Server certificate:
*    subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.example.com
*    start date: Mar  4 00:00:00 2019 GMT
*    expire date: Apr  7 23:59:59 2021 GMT
*    issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*    SSL certificate verify result: certificate has expired (10), continuing anyway.

My curl code —

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://backend.example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, fopen(public_path("c.log"), 'w'));
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$output = curl_exec($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);

We running 2 application on amazon EC2 (backend.example.com & frontend.example.com). For that application, we used a paid SSL Certificate. That certificate expiration date at 2021 June. But today, we got an error —

cURL error 60: SSL certificate problem: certificate has expired (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

We check certificate expiration date, but there was no problem (2021 June). Then we follow this thread — curl: (60) SSL certificate problem: unable to get local issuer certificate (@Dahomz answer)

After that, when we curl example.com by — curl -v --url https://backend.example.com --cacert /etc/ssl/ssl.cert/cacert.pem, It working fine. Response like —

* Rebuilt URL to: https://backend.example.com/
*   Trying 127.0.0.1...
* Connected to backend.example.com (127.0.0.1) port 443 (#0)
* found 139 certificates in /etc/ssl/ssl.cert/cacert.pem
* found 600 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ******_RSA_***_***_GCM_*****
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: *.example.com (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: OU=Domain Control Validated,OU=PositiveSSL Wildcard,CN=*.example.xyz
*    start date: Mon, 04 May 2019 00:00:00 GMT
*    expire date: Wed, 07 June 2021 23:59:59 GMT
*    issuer: C=GB,ST=Greater Manchester,L=Salford,O=Sectigo Limited,CN=Sectigo RSA Domain Validation Secure Server CA
*    compression: NULL
* ALPN, server accepted to use http/1.1

But when we hit from frontend.example.com to backend.example.com by curl, it throws this error —

* Rebuilt URL to: https://backend.example.com/
*   Trying 127.0.0.1...
* Connected to backend.example.com (127.0.0.1) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/ssl.cert/cacert.pem
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / *****-RSA-*****-GCM-******
* ALPN, server accepted to use http/1.1
* Server certificate:
*    subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.example.com
*    start date: Mar  4 00:00:00 2019 GMT
*    expire date: Apr  7 23:59:59 2021 GMT
*    issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*    SSL certificate verify result: certificate has expired (10), continuing anyway.

My curl code —

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://backend.example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, fopen(public_path("c.log"), 'w'));
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
$output = curl_exec($ch);
$error = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);

C 30 сентября 2021 года на сайтах WordPress, для которых был установлен сертификат Let’s Encrypt, могут перестать работать HTTP API запросы.

Например такой запрос будет выдавать ошибку:

$res = wp_remote_get( 'https://wp-kama.ru/' );

if( is_wp_error( $res ) ){
	echo $res->get_error_message();
}

Получим:

cURL error 60: SSL certificate problem: certificate has expired

Такую ошибку можно будет увидеть где угодно, например:

  • в админке при проверке обновлений WordPress
  • при проверке обновлений плагинов
  • при обращении к апи любого сервиса. Например, перестанет работать плагин TinyPNG — JPEG, PNG & WebP image compression и куча других, которые используют какие бы то ни было запросы.

Почему мы видим ошибку certificate has expired?

Почему так происходит подробно расписано на хабре.

Если коротко, то в ядре WP есть файл корневых сертификатов /wp-includes/certificates/ca-bundle.crt который используется для проверки SSL всех запросов созданных через HTTP API. В этом файле просрочен один из корневых сертификатов на основе которого был создан сертификат для вашего сайта. Поэтому запрос не может пройти проверку и выдается такая ошибка.

С очередными обновлениями WP эта ошибка должна пропасть, но вот что делать если решение нужно уже сегодня, или если вы не планируете обновлять WordPress, а рабочие HTTP запросы нужны.

Решение ошибки: cURL error 60: SSL certificate has expired

Вариант 1

Нужно обновить контент файла /wp-includes/certificates/ca-bundle.crt изменить его на контент этого файла https://curl.haxx.se/ca/cacert.pem.

Изменять в данном случае файл ядра допустимо, потому что при следующем обновлении WP проблема исчезнет. См. соответствующий коммит на GitHub.

Это можно сделать вручную:

  1. Скачайте файл по ссылке https://curl.haxx.se/ca/cacert.pem.
  2. Обновите контент /wp-includes/certificates/ca-bundle.crt контентом из скаченного файла.

Или используйте следующий код

Использовать код удобно, когда у вас есть возможность запустить код из админки или как-то еще, например через плагин Code Snippets.

Добавьте следующий код куда угодно и перейдите на страницу http://ВАШСАЙТ.com/?update-wp-ca-bundle.

/**
 * Goto http://yoursite.com/?update-wp-ca-bundle
 */
if( isset( $_GET['update-wp-ca-bundle'] ) ){

	$crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt';
	$new_crt_url = 'https://curl.haxx.se/ca/cacert.pem';

	if( is_writable( $crt_file ) ){
		$new_str = file_get_contents( $new_crt_url );

		if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){
			$up = file_put_contents( $crt_file, $new_str );

			echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt';
		}
		else {
			echo 'ERROR: cant download https://curl.haxx.se/ca/cacert.pem';
		}
	}
	else {
		echo 'ERROR: ca-bundle.crt not writable';
	}

	exit;
}

После использования, код нужно удалить.

Вариант 2

Решить проблему можно через хук http_request_args. Этот хук нужно использовать в MU плагине.

  1. Создайте файл loader.php в папке wp-content/mu-plugins (если такой папки у вас нет, создайте её).

  2. Добавьте следующий код в этот файл:

    <?php
    
    require_once __DIR__ .'/fix-wp-ca-bundle/main.php';
  3. Создайте папку wp-content/mu-plugins/fix-wp-ca-bundle.

  4. Создайте файлы: main.php и ca-bundle.crt в папке fix-wp-ca-bundle.

    Добавьте следующий код в эти файлы.

    Код файла main.php:

    <?php
    
    defined( 'ABSPATH' ) || exit;
    
    /**
     * Update the path to the WordPress trusted root certificates.
     *
     * Actual certificates can be downloaded at this link: http://curl.haxx.se/ca/cacert.pem
     */
    add_filter( 'http_request_args', 'http_request_change_sslsertificates' );
    
    function http_request_change_sslsertificates( $parsed_args ){
    
    	$parsed_args[ 'sslcertificates' ] = __DIR__ . '/ca-bundle.crt';
    
    	return $parsed_args;
    }

    Контент файла ca-bundle.crt:

    Скопируйте контент этого файла http://curl.haxx.se/ca/cacert.pem

Должна получится такая структура:

Готово! Теперь все должно работать как и прежде.

‘cURL error 60 SSL certificate problem’ occurs when we make a cURL call to third party services.

Here at Bobcares, we have seen several such cURL command related errors as part of our Server Management Services for web hosts and online service providers.

Today we’ll take a look at the causes for this error and see the fix.

What causes ‘cURL error 60 SSL certificate problem’ error to occur

Digital certificates are mainly used in transferring sensitive content. These digital certificates are issued by certificate authorities or CA.

When a cURL receives a server CA that is not signed by one of the trusted certificates in the installed CA certificate store, then it will lead to an error: “failed to verify the legitimacy of the server” during the SSL handshake. As a result, SSL will then refuse the communication with the server leading to an SSL error.

In short, this error occurs because cURL makes sure to verify and make a secure connection request using a self-signed certificate. But when it doesn’t find any valid certificate then it throws this error message.

How we fix the error ‘cURL error 60 SSL certificate problem’

Now let’s see how our Support Engineers resolve this error message.

1. Re-download the cURL CA-Bundle from the cURL site to fix this error. Here are the steps for it.

  • First, download the “cacert.pem” from the link: http://curl.haxx.se/docs/caextract.html
  • Next copy the complete page and save it as “cacert.pem
  • Now, open the php.ini file and add the following line in it.
    curl.cainfo = “[pathtofile]cacert.pem”
    In, case, if the php.ini file doesn’t have the curl.cainfo line, then just add it to the end of the file. Then add the file path where cacert.pem file is saved.
  • Finally, restart the web server or on Windows, restart the application pool and try the request again.

2. If the insecure certificate is a self-signed, known-trusted certificate, then load the certificate to your local trusted certificate location for your OS.

[Need any further assistance in fixing curl errors? – We are here to help you.]

Conclusion

In short, this error occurs when cURL doesn’t find any valid certificate to communicate over https. Today, we saw how our Support Engineers fix this error.

PREVENT YOUR SERVER FROM CRASHING!

Never again lose customers to poor server speed! Let us help you.

Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.

GET STARTED

var google_conversion_label = «owonCMyG5nEQ0aD71QM»;

From September 30, 2021, HTTP API requests may stop working on WordPress sites that have a Let’s Encrypt certificate installed.

For example, a request like this will result in an error:

$res = wp_remote_get( 'https://wp-kama.com/' );

if( is_wp_error( $res ) ){
	echo $res->get_error_message();
}

We get it:

cURL error 60: SSL certificate problem: certificate has expired

Such an error can be seen anywhere, for example:

  • In the admin panel when checking for WordPress updates.
  • When checking for plugin updates.
  • When accessing the api of any service. For example, will stop working plugin TinyPNG — JPEG, PNG & WebP image compression and a bunch of others that use any kind of requests.

Why do we see the error certificate has expired?

In brief, WP core has a file of root certificates /wp-includes/certificates/ca-bundle.crt which is used to check SSL of all requests created through HTTP API. In this file one of the root certificates has expired which was used to create a certificate for your site. Therefore, the request can not pass verification and generates this error.

More detailed explanation:

Without going into too much detail, a couple of words for non-specialists as to why the expiration of a DST Root CA X3 certificate will affect certificates issued by Let’s Encrypt. Each system that validates a certificate has its own repository of trusted root certificates. The system will trust certificates that are signed using the private key of one of these root certificates during validation. Root certificates themselves normally have long expiration dates, are seldom changed and are not used when generating end subject certificates (in this case domain name certificates), instead a public key infrastructure implies using chains of trust — root certificates are used to sign intermediate certificates and already using them to sign end subject certificates (domain certificates). Furthermore, in order for a system to trust an end subject certificate, it must be able to trace the full chain from this certificate to one of the root certificates it trusts.

When Let’s Encrypt appeared, its ISRG Root X1 root certificate (like any new root certificate) could not quickly find its way into the trusted certificate stores of a significant number of systems. At the same time, for the successful functioning of the project the issued certificates from the very beginning had to be trusted by the maximum number of systems «out of the box» (without any additional actions from the users of these systems). In this regard, for certificates Let’s Encrypt began to use the chain of trust leading to the root certificate DST Root CA X3, which is recognized by most systems.

With the next WP update this error disappear, but here’s what to do if you need the solution today, or if you do not plan to update WordPress, but need working HTTP requests.

Solution: cURL error 60: SSL certificate has expired

You need to update the content of /wp-includes/certificates/ca-bundle.crt file. You need to change it to the content of the https://curl.se/ca/cacert.pem file.

Changing the core file in this case is acceptable, because the next time you update WP, the problem will go away. See corresponding commit on GitHub.

It can be done manually

  1. Download this file https://curl.se/ca/cacert.pem.

  2. Update content of /wp-includes/certificates/ca-bundle.crt with content from the downloaded file.

  3. DONE! Everything should now work as before.

Or use the following code to perform this operation programmatically

Using the code is handy when you have the ability to run the code from the admin panel, for example using Code Snippets plugin.

  1. Add the following code into the themes functions.php file (or in Code Snippets plugin):

    /**
     * Goto http://yoursite.com/?update-wp-ca-bundle
     */
    if( isset( $_GET['update-wp-ca-bundle'] ) ){
    
    	$crt_file = ABSPATH . WPINC . '/certificates/ca-bundle.crt';
    	$new_crt_url = 'http://curl.haxx.se/ca/cacert.pem';
    
    	if( is_writable( $crt_file ) ){
    		$new_str = file_get_contents( $new_crt_url );
    
    		if( $new_str && strpos( $new_str, 'Bundle of CA Root Certificates' ) ){
    			$up = file_put_contents( $crt_file, $new_str );
    
    			echo $up ? 'OK: ca-bundle.crt updated' : 'ERROR: can`t put data to ca-bundle.crt';
    		}
    		else {
    			echo 'ERROR: can't download curl.haxx.se/ca/cacert.pem';
    		}
    	}
    	else {
    		echo 'ERROR: ca-bundle.crt not writable';
    	}
    
    	exit;
    }

    After use, delete this code.

  2. Visit http://YOURSITE.com/?update-wp-ca-bundle the page.

    Replace YOURSITE.com to your domain…

  3. DONE! Everything should now work as before.

Today out of a sudden all HTTPS requests, that my Ubuntu 14 server sends to websites with SSL certificates issued by Let’s Encrypt, started to fail. The error produced by cURL is:

curl: (60) SSL certificate problem: certificate has expired

When I inspect the website certificates with this command:

echo -n | openssl s_client -showcerts -connect website.com:443 -servername website.com

I see that all the certificate chain is up to date.

So why do I get the expiration error? How to fix it?

asked Oct 1, 2021 at 5:00

Finesse's user avatar

The reason is that the «DST Root CA X3» certificate has expired yesterday.

To fix it, just disable the certificate on your server. Run:

sudo dpkg-reconfigure ca-certificates

On the first screen that prompts «Trust new certificates from certificate authorities?» choose «yes». On the next screen press the down arrow key on your keyboard until you find mozilla/DST_Root_CA_X3.crt, press the space bar to deselect it (the [*] should turn into [ ]) and press Enter.

answered Oct 1, 2021 at 5:00

Finesse's user avatar

FinesseFinesse

1,0611 gold badge8 silver badges9 bronze badges

5

Edit the file /etc/ca-certificates.conf

Find and comment with ! the line like this

!mozilla/DST_Root_CA_X3.crt

Save the file and update certificates with command

sudo update-ca-certificates

answered Oct 1, 2021 at 19:08

mikep's user avatar

mikepmikep

4393 silver badges5 bronze badges

4

FYI on CentOS like (RPM Based) systems, use:

yum reinstall ca-certificates

answered Oct 1, 2021 at 19:19

Marc Pope's user avatar

4

So why do I get the expiration error?

Android made a design decision to ignore the expiry on root certificates (it’s arguable that expiry on root certificates doesn’t make much sense in the first place).

«lets encrypt» is a relatively new CA and to support existing systems their root was «cross-signed»* by DST. The DST root certificate has now expired but because of the aforementioned android behavior a cross signature is still useful for supporting clients running old versions of andriod.

When such a chain is used on a system with a modern root certificate list the cross signature should be ignored and the IRSG (lets encrypt) root should be used. Unfortunately openssl 1.0.x does not handle this scenario correctly.

This issue can be worked around by removing the old DST root certificate. When this is done the chain will correctly be built to the IRSG root.

* My understanding is that technically the «cross signature» consists of an «intermediate certificate» with the same content and key as Lets Encrypt’s root certificate.

answered Oct 4, 2021 at 4:58

plugwash's user avatar

plugwashplugwash

5,7452 gold badges18 silver badges25 bronze badges

1

Home » cURL error 60: SSL certificate problem: unable to get local issuer certificate

Last updated on June 17, 2022 by

Often, cURL error 60: SSL certificate problem: unable to get local issuer certificate error occurs when we try to call the API with the secure https:// protocol in the request URL. In this article, we will discuss why does this error occur? how to resolve: unable to get local issuer certificate error occurs? Let’s jump into it.

Why Does This Error Occur?

Just go to your API call code and try to run the request URL with only http:// protocol. You can’t see the error anymore because secure API calls require an SSL certificate.

This error occurs because the API call makes a secure connection request using the self-signed certificate. When it does not find a valid certificate, it throws an error.

It has a very very simple solution. We just need to download the certificate and set the path. Are you ready? Then let’s set up an SSL certificate step by step as below:

How To Resolve: unable to get local issuer certificate error?

  1. Download the “cacert.pem” free certificate file from the official website here: http://curl.haxx.se/docs/caextract.html
  2. Move the cacert.pem file in a reachable destination for the PHP. It is advisable to move the file for the WAMP user to C:wamp64binphpcacert.pem, for XAMPP user to C:xamppphpextrassslcacert.pem, for the AMPPS user to C:Program Files (x86)Amppsphpextrassslcacert.pem
  3. Now, open your php.ini file and find the “curl.cainfo” option. You will see something like the following:
  1. After that, we need to add the path of the certificate to “curl.cainfo” and remove semicolon(;) as follow:
curl.cainfo = "C:wamp64binphpcacert.pem"
  1. The very very most important step is to save and close your php.ini. Restart your web server and try your request again. If you do not set the right path, then you will experience a CURL 77 error.

Hurray! we have completed all steps to solve unable to get local issuer certificate error.

Additionally, read our guide:

  1. Specified Key Was Too Long Error In Laravel
  2. Run PHP Artisan Commands On Shared Hosting Servers
  3. How To Calculate Age From Birthdate
  4. Active Directory Using LDAP in PHP or Laravel
  5. How To Use The Laravel Soft Delete
  6. How To Add Laravel Next Prev Pagination
  7. Best Way to Remove Public from URL in Laravel
  8. Difference Between Factory And Seeders In Laravel
  9. Difference Between Events and Observers In Laravel
  10. Session Not Working In Laravel
  11. How To Install Vue In Laravel 8 Step By Step
  12. How To Handle Failed Jobs In Laravel
  13. Best Ways To Define Global Variable In Laravel
  14. How To Get Latest Records In Laravel
  15. Laravel Twilio Send SMS Tutorial With Example
  16. How To Pass Laravel URL Parameter
  17. Laravel 9 Resource Controller And Route With Example
  18. Laravel 9 File Upload Tutorial With Example
  19. How To Schedule Tasks In Laravel With Example
  20. Laravel Collection Push() And Put() With Example

That’s it from our end. We hope this article helped you to resolve cURL error 60: SSL certificate problem: unable to get local issuer certificate error.

Please let us know in the comments if everything worked as expected, your issues, or any questions. If you think this article saved your time & money, please do comment, share, like & subscribe. Thank you for reading this post. 🙂 Keep Smiling! Happy Coding!

Понравилась статья? Поделить с друзьями:
  • Urban vpn ошибка установки
  • Urban vpn setup ended prematurely because of an error
  • Urban vpn connection error
  • Uptool error 0074
  • Uptool error 0071