Guzzle curl error 60 ssl certificate problem unable to get local issuer certificate

Hi, I am getting the SSL exception while uploading file to S3 , Strange thing is i have specified the certificate in the config/filesystems.php in s3 block but it still gives this error. I tried up...

Hi, I am getting the SSL exception while uploading file to S3 , Strange thing is i have specified the certificate in the config/filesystems.php in s3 block but it still gives this error.
I tried uploading file to s3 using Curl command line it works fine with the cacerts which i am providing in the filesystem.

Any help will be greatly appreciated, I am not able to pin point the issue as curl command line able to upload file to s3.

Below is Stack Trace

GuzzleHttpExceptionRequestException: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:187
Stack trace:
#0 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(150): GuzzleHttpHandlerCurlFactory::createRejection(Object(GuzzleHttpHandlerEasyHandle), Array)
#1 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(103): GuzzleHttpHandlerCurlFactory::finishError(Object(GuzzleHttpHandlerCurlMultiHandler), Object(GuzzleHttpHandlerEasyHandle), Object(GuzzleHttpHandlerCurlFactory))
#2 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(179): GuzzleHttpHandlerCurlFactory::finish(Object(GuzzleHttpHandlerCurlMultiHandler), Object(GuzzleHttpHandlerEasyHandle), Object(GuzzleHttpHandlerCurlFactory))
#3 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(108): GuzzleHttpHandlerCurlMultiHandler->processMessages()
#4 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(123): GuzzleHttpHandlerCurlMultiHandler->tick()
#5 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(246): GuzzleHttpHandlerCurlMultiHandler->execute(true)
#6 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(223): GuzzleHttpPromisePromise->invokeWaitFn()
#7 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(267): GuzzleHttpPromisePromise->waitIfPending()
#8 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(225): GuzzleHttpPromisePromise->invokeWaitList()
#9 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(267): GuzzleHttpPromisePromise->waitIfPending()
#10 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(225): GuzzleHttpPromisePromise->invokeWaitList()
#11 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttpPromisePromise->waitIfPending()
#12 /var/www/laravel/vendor/aws/aws-sdk-php/src/S3/S3ClientTrait.php(33): GuzzleHttpPromisePromise->wait()
#13 /var/www/laravel/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(583): AwsS3S3Client->upload(‘elevatecds’, ‘4/mampleInitial…’, Resource id #8, ‘private’, Array)
#14 /var/www/laravel/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(368): LeagueFlysystemAwsS3v3AwsS3Adapter->upload(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#15 /var/www/laravel/vendor/league/flysystem/src/Filesystem.php(122): LeagueFlysystemAwsS3v3AwsS3Adapter->writeStream(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#16 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(132): LeagueFlysystemFilesystem->putStream(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#17 /var/www/laravel/app/Http/Controllers/WorkspacesController.php(621): IlluminateFilesystemFilesystemAdapter->put(‘4/mampleInitial…’, Resource id #8, Array)
#18 [internal function]: AppHttpControllersWorkspacesController->uploadFile(Object(IlluminateHttpRequest))
#19 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(55): call_user_func_array(Array, Array)
#20 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(44): IlluminateRoutingController->callAction(‘uploadFile’, Array)
#21 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Route.php(203): IlluminateRoutingControllerDispatcher->dispatch(Object(IlluminateRoutingRoute), Object(AppHttpControllersWorkspacesController), ‘uploadFile’)
#22 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Route.php(160): IlluminateRoutingRoute->runController()
#23 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(572): IlluminateRoutingRoute->run()
#24 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): IlluminateRoutingRouter->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#25 /var/www/laravel/app/Http/Middleware/Authenticate.php(27): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#26 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): AppHttpMiddlewareAuthenticate->handle(Object(IlluminateHttpRequest), Object(Closure))
#27 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#28 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(65): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#29 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateFoundationHttpMiddlewareVerifyCsrfToken->handle(Object(IlluminateHttpRequest), Object(Closure))
#30 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#31 /var/www/laravel/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#32 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateViewMiddlewareShareErrorsFromSession->handle(Object(IlluminateHttpRequest), Object(Closure))
#33 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#34 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#35 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateSessionMiddlewareStartSession->handle(Object(IlluminateHttpRequest), Object(Closure))
#36 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#37 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#38 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateCookieMiddlewareAddQueuedCookiesToResponse->handle(Object(IlluminateHttpRequest), Object(Closure))
#39 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#40 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(59): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#41 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateCookieMiddlewareEncryptCookies->handle(Object(IlluminateHttpRequest), Object(Closure))
#42 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#43 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#44 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(574): IlluminatePipelinePipeline->then(Object(Closure))
#45 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(533): IlluminateRoutingRouter->runRouteWithinStack(Object(IlluminateRoutingRoute), Object(IlluminateHttpRequest))
#46 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(511): IlluminateRoutingRouter->dispatchToRoute(Object(IlluminateHttpRequest))
#47 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): IlluminateRoutingRouter->dispatch(Object(IlluminateHttpRequest))
#48 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): IlluminateFoundationHttpKernel->IlluminateFoundationHttp{closure}(Object(IlluminateHttpRequest))
#49 /var/www/laravel/vendor/barryvdh/laravel-debugbar/src/Middleware/Debugbar.php(51): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#50 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): BarryvdhDebugbarMiddlewareDebugbar->handle(Object(IlluminateHttpRequest), Object(Closure))
#51 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#52 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(46): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#53 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode->handle(Object(IlluminateHttpRequest), Object(Closure))
#54 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#55 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#56 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): IlluminatePipelinePipeline->then(Object(Closure))
#57 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): IlluminateFoundationHttpKernel->sendRequestThroughRouter(Object(IlluminateHttpRequest))
#58 /var/www/laravel/public/index.php(53): IlluminateFoundationHttpKernel->handle(Object(IlluminateHttpRequest))
#59 {main}

753 votes

22 answers

Get the solution ↓↓↓

I am trying to send an API request using Stripe but get the error message:

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

This is the code I am running:

public function chargeStripe()
{
    $stripe = new Stripe;
    $stripe = Stripe::make(env('STRIPE_PUBLIC_KEY'));

    $charge = $stripe->charges()->create([
        'amount'   => 2900,
        'customer' => Input::get('stripeEmail'),
        'currency' => 'EUR',
    ]);

    return Redirect::route('step1');
}

I searched a lot on Google and lots of people are suggesting that I download this file: cacert.pem, put it somewhere and reference it in my php.ini. This is the part in my php.ini:

curl.cainfo = "C:Windowscacert.pem"

Yet, even after restarting my server several times and changing the path, I get the same error message.

I have the ssl_module enabled in Apache, and I have php_curl enabled in myphp.ini.

I have also tried this fix: How to fix PHP CURL Error 60 SSL

Which suggests that I add these lines to my cURL options:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, true);

Where do I add options to my cURL? Apparently not through the command line, since my CLI doesn’t find the command «curl_setopt»

2022-03-27

Write your answer


247

votes


430

votes


672

votes

Answer

Solution:

If you are using PHP 5.6 with Guzzle, Guzzle has switched to using the PHP libraries autodetect for certificates rather than it’s process (ref). PHP outlines the changes here.

Finding out Where PHP/Guzzle is Looking for Certificates

You can dump where PHP is looking using the following PHP command:

 var_dump(openssl_get_cert_locations());

Getting a Certificate Bundle

For OS X testing, you can use homebrew to install opensslbrew install openssl and then useopenssl.cafile=/usr/local/etc/openssl/cert.pem in your php.ini or Zend Server settings (under OpenSSL).

A certificate bundle is also available from curl/Mozilla on the curl website: https://curl.haxx.se/docs/caextract.html

Telling PHP Where the Certificates Are

Once you have a bundle, either place it where PHP is already looking (which you found out above) or updateopenssl.cafile in php.ini. (Generally,/etc/php.ini or/etc/php/7.0/cli/php.ini or/etc/php/php.ini on Unix.)


630

votes

Answer

Solution:

Guzzle, which is used by cartalyst/stripe, will do the following to find a proper certificate archive to check a server certificate against:

  1. Check ifopenssl.cafile is set in your php.ini file.
  2. Check ifcurl.cainfo is set in your php.ini file.
  3. Check if/etc/pki/tls/certs/ca-bundle.crt exists (Red Hat, CentOS, Fedora; provided by the ca-certificates package)
  4. Check if/etc/ssl/certs/ca-certificates.crt exists (Ubuntu, Debian; provided by the ca-certificates package)
  5. Check if/usr/local/share/certs/ca-root-nss.crt exists (FreeBSD; provided by the ca_root_nss package)
  6. Check if/usr/local/etc/openssl/cert.pem (OS X; provided by homebrew)
  7. Check ifC:windowssystem32curl-ca-bundle.crt exists (Windows)
  8. Check ifC:windowscurl-ca-bundle.crt exists (Windows)

You will want to make sure that the values for the first two settings are properly defined by doing a simple test:

echo "openssl.cafile: ", ini_get('openssl.cafile'), "n";
echo "curl.cainfo: ", ini_get('curl.cainfo'), "n";

Alternatively, try to write the file into the locations indicated by #7 or #8.


113

votes

Answer

Solution:

If you’re unable to change php.ini you could also point to the cacert.pem file from code like this:

$http = new GuzzleHttpClient(['verify' => '/path/to/cacert.pem']);
$client = new Google_Client();
$client->setHttpClient($http);


617

votes

Answer

Solution:

What i did was usevar_dump(openssl_get_cert_locations()); die; in any php script, which gave me the information about defaults that my local php was using:

array (size=8)
  'default_cert_file' => string 'c:/openssl-1.0.1c/ssl/cert.pem' (length=30)
  'default_cert_file_env' => string 'SSL_CERT_FILE' (length=13)
  'default_cert_dir' => string 'c:/openssl-1.0.1c/ssl/certs' (length=27)
  'default_cert_dir_env' => string 'SSL_CERT_DIR' (length=12)
  'default_private_dir' => string 'c:/openssl-1.0.1c/ssl/private' (length=29)
  'default_default_cert_area' => string 'c:/openssl-1.0.1c/ssl' (length=21)
  'ini_cafile' => string 'E:xamppphpextrassslcacert.pem' (length=34)
  'ini_capath' => string '' (length=0)

As you can notice, i have set the ini_cafile or the ini option curl.cainfo. But in my case, curl would try to use the «default_cert_file» which did not exist.

I copied the file from https://curl.haxx.se/ca/cacert.pem into the location for «default_cert_file» (c:/openssl-1.0.1c/ssl/cert.pem) and i was able to get it to work.

This was the only solution for me.


368

votes

Answer

Solution:

I had this problem appear out-of-the-blue one day, when a Guzzle(5) script was attempting to connect to a host over SSL. Sure, I could disable the VERIFY option in Guzzle/Curl, but that’s clearly not the correct way to go.

I tried everything listed here and in similar threads, then eventually went to terminal with openssl to test against the domain with which I was trying to connect:

openssl s_client -connect example.com:443 

… and received first few lines indicating:

CONNECTED(00000003)
depth=0 CN = example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = example.com
verify error:num=21:unable to verify the first certificate
verify return:1 

… while everything worked fine when trying other destinations (ie: google.com, etc)

This prompted me to contact the domain I had been trying to connect to, and indeed, they had a problem on THEIR END that had crept up. It was resolved and my script went back to working.

So… if you’re pulling your hair out, give openssl a shot and see if there’s anything up with the response from the location you are attempting to connect. Maybe the issue isn’t so ‘local’ after all sometimes.


905

votes

Answer

Solution:

I found a solution that worked for me. I downgraded from the latest guzzle to version ~4.0 and it worked.

In composer.json add «guzzlehttp/guzzle»: «~4.0»

Hope it helps someone


418

votes

Answer

Solution:

Be sure that you open thephp.ini file directly by your Window Explorer. (in my case:C:DevProgramswamp64binphpphp5.6.25).

Don’t use the shortcut tophp.ini in the Wamp/Xamp icon’s menu in the System Tray. This shortcut doesn’t work in this case.

Then edit thatphp.ini :

curl.cainfo ="C:/DevPrograms/wamp64/bin/php/cacert.pem" 

and

openssl.cafile="C:/DevPrograms/wamp64/bin/php/cacert.pem"

After savingphp.ini you don’t need to «Restart All Services» in Wamp icon or close/re-open CMD.


711

votes

Answer

Solution:

Have you tried..

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

If you are consuming a trusted source you can skip the verify.


667

votes

Answer

Solution:

For WAMP, this is what finally worked for me.
While it is similar to others, the solutions mentioned on this page, and other locations on the web did not work. Some «minor» detail differed.
Either the location to save the PEM file mattered, but was not specified clearly enough.
Or WHICHphp.ini file to be edited was incorrect. Or both.
I’m running a 2020 installation of WAMP 3.2.0 on a Windows 10 machine.

Link to get the pem file:

http://curl.haxx.se/ca/cacert.pem
Copy the entire page and save it as:cacert.pem, in the location mentioned below.

Save the PEM file in this location

<wamp install directory>binphpphp<version>extrasssl
eg saved file and path: «T:wamp64binphpphp7.3.12extrassslcacert.pem»

*(I had originally saved it elsewhere (and indicated the saved location in the php.ini file, but that did not work).
There might, or might not be, other locations also work. This was the recommended location — I do not know why.)

WHERE
<wamp install directory> = path to your WAMP installation.
eg:T:wamp64

<php version> of php that WAMP is running: (to find out, goto:WAMP icon tray -> PHP <version number>
if the version number shown is 7.3.12, then the directory would be: php7.3.12)
eg:php7.3.12

Which php.ini file to edit

To open the properphp.ini file for editing, goto:WAMP icon tray -> PHP -> php.ini.
eg:T:wamp64binapacheapache2.4.41binphp.ini
NOTE: it is NOT the file in the php directory!

Update:
While it looked like I was editing the file:T:wamp64binapacheapache2.4.41binphp.ini,
it was actually editing that file’s symlink target:T:/wamp64/bin/php/php7.3.12/phpForApache.ini.

Note that if you follow the above directions, you are NOT editing aphp.ini file directly. You are actually editing aphpForApache.ini file. (a post with info about symlinks)

If you read the comments at the top of some of thephp.ini files in various WAMP directories, it specifically states to NOT EDIT that particular file.
Make sure that the file you do open for editing does not include this warning.

Installing the extension Link Shell Extension allowed me to see the target of the symlink in the file Properites window, via an added tab. here is an SO answer of mine with more info about this extension.

If you run various versions of php at various times, you may need to save the PEM file in each relevant php directory.

The edits to make in your php.ini file:

Paste the path to your PEM file in the following locations.

  • uncomment;curl.cainfo = and paste in the path to your PEM file.
    eg:curl.cainfo = "T:wamp64binphpphp7.3.12extrassslcacert.pem"

  • uncomment;openssl.cafile= and paste in the path to your PEM file.
    eg:openssl.cafile="T:wamp64binphpphp7.3.12extrassslcacert.pem"

Credits:

While not an official resource, here is a link back to the YouTube video that got the last of the details straightened out for me: https://www.youtube.com/watch?v=Fn1V4yQNgLs.


36

votes

Answer

Solution:

All of the answers are correct ; but the most important thing is You have to find the right php.ini file.
check this command in cmd » php —ini » is not the right answer for finding the right php.ini file.

if you edit

curl.cainfo ="PATH/cacert.pem"

and check

var_dump(openssl_get_cert_locations()); 

then curl.cainfo should have a value. if not then that’s not right php.ini file;

*I recommend you to search *.ini in wamp/bin or xxamp/bin or any server you use and change them one by one and check it. *


370

votes

Answer

Solution:

I just experienced this same problem with the Laravel 4 php framework which uses theguzzlehttp/guzzle composer package. For some reason, the SSL certificate for mailgun stopped validating suddenly and I got that same «error 60» message.

If, like me, you are on a shared hosting without access tophp.ini, the other solutions are not possible. In any case, Guzzle has this client initializing code that would most likely nullify thephp.ini effects:

// vendor/guzzlehttp/guzzle/src/Client.php
    $settings = [
        'allow_redirects' => true,
        'exceptions'      => true,
        'decode_content'  => true,
        'verify'          => __DIR__ . '/cacert.pem'
    ];

Here Guzzle forces usage of its own internal cacert.pem file, which is probably now out of date, instead of using the one provided by cURL’s environment. Changing this line (on Linux at least) configures Guzzle to use cURL’s default SSL verification logic and fixed my problem:

        'verify'          => true

You can also set this tofalse if you don’t care about the security of your SSL connection, but that’s not a good solution.

Since the files invendor are not meant to be tampered with, a better solution would be to configure the Guzzle client on usage, but this was just too difficult to do in Laravel 4.

Hope this saves someone else a couple hours of debugging…


438

votes


314

votes

Answer

Solution:

This might be an edge case, but in my case the problem was not the client conf (I already had curl.cainfo configured in php.ini), but rather the remote server not being configured properly:

It did not send any intermediate certs in the chain. There was no error browsing the site using Chrome, but with PHP I got following error.

cURL error 60

After including the Intermediate Certs in the remote webserver configuration it worked.

You can use this site to check the SSL configuration of your server:

https://whatsmychaincert.com/


235

votes

Answer

Solution:

when I run'var_dump(php_ini_loaded_file());'
I get this output on my page'C:Developmentbinapacheapache2.4.33binphp.ini' (length=50)'

and to get php to load my cert file I had to edit the php.ini in this path'C:Developmentbinapacheapache2.4.33binphp.ini'
and addopenssl.cafile="C:/Development/bin/php/php7.2.4/extras/ssl/cacert.pem" where I had downloaded and place my cert file from https://curl.haxx.se/docs/caextract.html

am on windows 10, using drupal 8, wamp and php7.2.4


964

votes

Answer

Solution:

I’m using Centos 7 with the free version of virtualmin. With Virtualmin you can create a wordpress website. There is functionality that will automatically update your ssl certificate for you. I noticed that /etc/httpd/conf/httpd.conf did not contain an entry for SSLCertificateChainFile. Which should be set to something like /home/websitename/ssl.combined. Updating that file accordingly and restarting apache fix this problem for me. I discovered my issue trying to install a jetpack plugin for wordpress. A search on the internet led me to realize that I didn’t have SSL Configured. I followed Redhat’s instructions on how to install a certificate. I hope this was useful to someone.


626

votes

Answer

Solution:

Guzzle Version 5

This default config is working good for mine. It will disable https required.

  $options = [
    'defaults' => ['verify' => false],
  ];
  new GuzzleClient($options);

In other case, you want to set path of ca, change to:

['verify' => '/path/to/cacert.pem']


814

votes

Answer

Solution:

For those of you who are trying to use WordPress’s application password functionality on your local machine. You need to update thewp-includescertificatesca-bundle.crt

Open this file in a text editor and append your server’s certificate.

  1. Open your self-signed certificate(.crt) file and

  2. Copy all between and including

—-BEGIN CERTIFICATE——

——END CERTIFICATE——

  1. Paste at the end of thewp-includescertificatesca-bundle.crt


771

votes

Answer

Solution:

I have a proper solution of this problem, lets try and understand the root cause of this issue. This issue comes when remote servers ssl cannot be verified using root certificates in your system’s certificate store or remote ssl is not installed along with chain certificates. If you have a linux system with root ssh access, then in this case you can try updating your certificate store with below command:

update-ca-certificates

If still, it doesn’t work then you need to add root and interim certificate of remote server in your cert store. You can download root and intermediate certs and add them in /usr/local/share/ca-certificates directory and then run command update-ca-certificates. This should do the trick. Similarly for windows you can search how to add root and intermediate cert.

The other way you can solve this problem is by asking remote server team to add ssl certificate as a bundle of domain root cert, intermediate cert and root cert.


606

votes

Answer

Solution:

As you are using Windows, I think your path separator is » (and ‘/’ on Linux).
Try using the constantDIRECTORY_SEPARATOR. Your code will be more portable.

Try:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem');

EDIT: and write the full path. I had some issues with relative paths (perhaps curl is executed from another base directory?)


532

votes

Answer

Solution:

if you use WAMP you should also add the certificate line in php.ini for Apache (besides the default php.ini file):

[curl]
curl.cainfo = C:your_locationcacert.pem

works for php5.3+


Share solution ↓

Additional Information:

Date the issue was resolved:

2022-03-27

Link To Source

Link To Answer
People are also looking for solutions of the problem: an exception occurred in the driver: could not find driver

Didn’t find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.


Similar questions

Find the answer in similar questions on our website.

If you are using PHP’s cURL functions to connect to an HTTPS URL, then you might come across the following error:

SSL certificate problem: unable to get local issuer certificate.  (cURL error code 60)

This is a common error that occurs whenever you attempt to use cURL functions to connect to an HTTPS website.

In plain English, it means that you have not configured cURL to connect to SSL-enabled websites.

The quick fix.

If you do not care about security and are looking for a quick fix, then you can simply disable the following cURL options:

  • CURLOPT_SSL_VERIFYHOST: This option tells cURL that it must verify the host name in the server cert.
  • CURLOPT_SSL_VERIFYPEER: This option tells cURL to verify the authenticity of the SSL cert on the server.

Disabling these two options disables SSL verification.

To disable these two options, you can use the curl_setopt function like so:

//The URL we are connecting to.
$url = 'https://google.com';

//Initiate cURL.
$ch = curl_init($url);

//Disable CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER by
//setting them to false.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

//Execute the request.
curl_exec($ch);

//Check for errors.
if(curl_errno($ch)){
    throw new Exception(curl_error($ch));
}

The PHP code above essentially tells cURL that we don’t care if the server has a valid SSL cert or not. We want to connect to it anyway.

The problem with this method is that it is insecure and it leaves you open to man-in-the-middle attacks. Simply put, this means that an attacker could potentially intercept the data that you are sending in your cURL requests.

Using a cert with PHP’s cURL functions.

To use a certificate with PHP’s cURL functions, you can download the cacert.pem certificate bundle from the official cURL website.

Once you have downloaded the cacert.pem file, you should move it to whatever directory makes the most sense for you and your setup.

For example, on Windows, I moved my bundle to C:wampcacert.pem

Then, you can simply tell cURL where your certificate bundle is located by using the curl_setopt function:

//Tell cURL where our certificate bundle is located.
$certificate = "C:wampcacert.pem";
curl_setopt($ch, CURLOPT_CAINFO, $certificate);
curl_setopt($ch, CURLOPT_CAPATH, $certificate);

This allows us to make a secure request to the server and prevent any man-in-the-middle attacks.

Adding the cert to your php.ini file.

If you don’t like the thought of having to specify the location of the certificate bundle in your PHP code, then you can add its path information to your php.ini file like so:

curl.cainfo="C:wampcacert.pem" 
openssl.cafile="C:wampcacert.pem"

Once you add the above lines to your php.ini file, make sure that you reload the web server / PHP process so that the changes take effect.

Enabling mod_ssl and php_openssl.dll.

If you are using Apache and PHP on Windows, then you might need to enable both mod_ssl and php_openssl.dll.

To enable mod_ssl, you can add the following to your Apache configuration file:

LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so

The configuration line above presumes that a file called mod_ssl.so exists in a Linux directory called “/usr/lib/httpd/modules/”.

On Windows, this directory might be something like “C:wampbinapacheapache2.4.9modules“.

You will need to change this line to match your own Apache setup.

To enable php_openssl.dll, you will need to uncomment the following line in your php.ini file:

extension=php_openssl.dll

As always, you should test your configurations and then reload your server for any changes to take effect.

‘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»;

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Guzzle curl error 60 ssl certificate problem certificate has expired
  • Guzzle curl error 52 empty reply from server
  • Guzzle client error
  • Guvcview error no video device found
  • Gutrend style 220 ошибки

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии