diff --git a/lib/filelib.php b/lib/filelib.php index 7553ff6cc41..b101a40bbf5 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3166,14 +3166,6 @@ class curl { * @return resource The curl handle */ private function apply_opt($curl, $options) { - // Some more security first. - if (defined('CURLOPT_PROTOCOLS')) { - $this->options['CURLOPT_PROTOCOLS'] = (CURLPROTO_HTTP | CURLPROTO_HTTPS); - } - if (defined('CURLOPT_REDIR_PROTOCOLS')) { - $this->options['CURLOPT_REDIR_PROTOCOLS'] = (CURLPROTO_HTTP | CURLPROTO_HTTPS); - } - // Clean up $this->cleanopt(); // set cookie @@ -3235,12 +3227,14 @@ class curl { $this->options['CURLOPT_FOLLOWLOCATION'] = 0; } + // Limit the protocols to HTTP and HTTPS. + if (defined('CURLOPT_PROTOCOLS')) { + $this->options['CURLOPT_PROTOCOLS'] = (CURLPROTO_HTTP | CURLPROTO_HTTPS); + $this->options['CURLOPT_REDIR_PROTOCOLS'] = (CURLPROTO_HTTP | CURLPROTO_HTTPS); + } + // Set options. foreach($this->options as $name => $val) { - if ($name === 'CURLOPT_PROTOCOLS' or $name === 'CURLOPT_REDIR_PROTOCOLS') { - // These can not be changed, sorry. - continue; - } if ($name === 'CURLOPT_FOLLOWLOCATION' and $this->emulateredirects) { // The redirects are emulated elsewhere. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0); diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 004dc8b49e8..180c9d86a0c 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -504,6 +504,45 @@ class core_filelib_testcase extends advanced_testcase { $this->assertSame('OK', $contents); } + public function test_curl_protocols() { + + // HTTP and HTTPS requests were verified in previous requests. Now check + // that we can selectively disable some protocols. + $curl = new curl(); + + // Other protocols than HTTP(S) are disabled by default. + $testurl = 'file:///'; + $curl->get($testurl); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + + $testurl = 'ftp://nowhere'; + $curl->get($testurl); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + + $testurl = 'telnet://somewhere'; + $curl->get($testurl); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + + // Protocols are also disabled during redirections. + $testurl = $this->getExternalTestFileUrl('/test_redir_proto.php'); + $curl->get($testurl, array('proto' => 'file')); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + + $testurl = $this->getExternalTestFileUrl('/test_redir_proto.php'); + $curl->get($testurl, array('proto' => 'ftp')); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + + $testurl = $this->getExternalTestFileUrl('/test_redir_proto.php'); + $curl->get($testurl, array('proto' => 'telnet')); + $this->assertNotEmpty($curl->error); + $this->assertEquals(CURLE_UNSUPPORTED_PROTOCOL, $curl->errno); + } + /** * Testing prepare draft area *