MoodleRest icon indicating copy to clipboard operation
MoodleRest copied to clipboard

file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

Open aortizsm opened this issue 3 years ago • 1 comments

Hi my man! after all, thank you for this lib, it's very useful, btw, I found this error:


A PHP Error was encountered

Severity: Warning

Message: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

Filename: moodlerest/MoodleRest.php

Line Number: 437

Backtrace:

File: /var/www/html/moogesdev/vendor/llagerlof/moodlerest/MoodleRest.php
Line: 437
Function: file_get_contents 

I'd fix it with the following code:

if ($this->getMethod() != self::METHOD_POST) {
            // GET
            //$moodle_request = file_get_contents($this->getUrl(false));
            $arrContextOptions=array(
                "ssl"=>array(
                    "verify_peer"=>false,
                    "verify_peer_name"=>false,
                ),
            );  
          $moodle_request = file_get_contents($this->getUrl(false), false, stream_context_create($arrContextOptions));

aortizsm avatar Oct 28 '21 14:10 aortizsm

I'm going to verify the security issues involved in the problem and it's solution. Thank you.

llagerlof avatar Oct 28 '21 15:10 llagerlof

Forgot to answer this issue, sorry. This happens when the user doesn't have a certificate configured when making requests to https.

llagerlof avatar Aug 07 '23 15:08 llagerlof

SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in Command line code on line 1

mahtias avatar Aug 08 '23 06:08 mahtias

I hit this randomly today too. I wrapped my call in a try / catch and added retry in the catch and that randomly fixed it. It would be good if we could specify additional options like in the constructor function so that it doesn't ignore cert validation by default, but can if the user chooses to.

mpchadwick avatar Aug 29 '23 12:08 mpchadwick

@mpchadwick

I hit this randomly today too.

What do you mean "randomly"?

  • Do requests with the same payload to the same Moodle webservice function throw an error sometimes?
  • Do requests with the different payload to the same Moodle webservice function throw an error sometimes?
  • Do requests with the different payload to different Moodle webservice function throw an error sometimes?
  • ...

I wrapped my call in a try / catch and added retry in the catch and that randomly fixed it.

Probably not randomly. The class sends a GET or a POST request to the Moodle webservice. If the request fails for any reason then an exception is raised. Many reasons can cause a request to fail, like:

  • URL not found
  • Network issues (timeout, connection refused, etc.)
  • HTTP status code errors (404 Not Found, 503 Service Unavailable, etc.)
  • SSL certificate issues (like the original reason this issue exists)
  • Insufficient permissions
  • PHP configuration issues (like allow_url_fopen being disabled)

file_get_contents used internally by the MoodleRest class doesn't return an error, just false in case of any http error, so I suggest you to debug the requested URL manually doing the request using curl, wget or any http client. I use httpie. To print the URL and query string built by the class, just call setDebug() before calling request().

Just an info that can help: If the request is successful but the Moodle Webservice return an error, the MoodleRest will not raise an exception. In this case you need to check if Moodle returned one of these keys:

exception
errorcode
message
debuginfo (you need to enable the debug mode in Moodle admin for this one)

It would be good if we could specify additional options like in the constructor function so that it doesn't ignore cert validation by default, but can if the user chooses to.

What do you mean "ignore cert validation by default"? The class itself doesn't, neither can, ignore Moodle validations. I am assuming this is a misunderstanding on how this lib works. Can you give more details?

llagerlof avatar Sep 04 '23 13:09 llagerlof

By randomly I mean that I'll send the exact same API request to our Moodle server and I will sometimes get this error

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error in /Users/maxchadwick/moodle-test/vendor/llagerlof/moodlerest/MoodleRest.php on line 437
PHP Warning:  file_get_contents(https://READACTED/webservice/rest/server.php?wstoken=REDACTED&moodlewsrestformat=json&wsfunction=tool_lp_data_for_plans_page&userid=345): Failed to open stream: HTTP request failed! in /Users/maxchadwick/moodle-test/vendor/llagerlof/moodlerest/MoodleRest.php on line 437

Then I retry literally the exact same request and I don't get the error anymore.

The server seems flaky somehow (or it might be something on my laptop, I'm not sure, this is a work laptop and I have to use Zscaler which causes all kinds of weird issues).

I am using Moodle cloud with an XXX.moodle.school url.

My suggestion is that when constructing MoodleRest the user could pass an array of stream_context_create options. For example

// My insecure Moodle
$myMoodle = new MoodleRest('https://moodle.moodle', $token, 'array', [
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => False
    ]
])

Then in the lib you would pass any use any user specified stream options in the file_get_contents request (for POST currently you'd have to merge the arrays).

mpchadwick avatar Sep 05 '23 13:09 mpchadwick

@mpchadwick

...

Then in the lib you would pass any use any user specified stream options in the file_get_contents request

This is a good idea and addresses the issue when the user wants to make insecure connections. I just need to make a decision about how to design the constructor. Given that we already have three optional parameters, I am considering a few options here:

  1. Add a fourth optional parameter and a separate method, similar to the existing ones.
  2. Introduce this configurable option through a separate method, but not in the constructor.
  3. Redesign the constructor to use a single array of options as an argument (simulating named arguments).
  4. Create a separate class just to hold all the options and pass it to the constructor.
  5. Bullets 3 and 4 would break the major version of this library and code hinting in the editor would stop working. Alternatively, to not breaking existing code, I could test if the first argument is an array or an object within the constructor. This approach might seem a bit messy, but it would work.

@aortizsm, since you originally opened this issue, what are your thoughts about all this?

llagerlof avatar Sep 05 '23 15:09 llagerlof