Skip to content

Commit

Permalink
MDL-39356 add ca certificate bundles for cURL
Browse files Browse the repository at this point in the history
This is necessary because PHP in Windows does not have any certificates and some *nix systems have outdated or missing ca bundles too.

The order is:
1/ dataroot/moodleorgca.crt always wins - needs to be added manually by admin
2/ php.ini setting "curl.cainfo" is next
3/ on Windows libdir/cacert.pem is used because it does not have any default cert bundles
4/ system default is the last - the previous value, ok for properly configured *nix systems
  • Loading branch information
skodak committed Apr 28, 2013
1 parent cf5a329 commit c2140b5
Show file tree
Hide file tree
Showing 7 changed files with 3,982 additions and 31 deletions.
7 changes: 0 additions & 7 deletions admin/tool/installaddon/classes/installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,13 +366,6 @@ public function download_file($source, $target) {
'ssl_verifyhost' => 2,
);

$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
if (is_readable($cacertfile)) {
// Do not use CA certs provided by the operating system. Instead,
// use this CA cert to verify the ZIP provider.
$options['cainfo'] = $cacertfile;
}

$curl = new curl(array('proxy' => true));

$result = $curl->download_one($source, null, $options);
Expand Down
7 changes: 0 additions & 7 deletions admin/tool/installaddon/classes/pluginfo_client.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,6 @@ protected function service_request_options() {
'CURLOPT_SSL_VERIFYPEER' => true,
);

$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
if (is_readable($cacertfile)) {
// Do not use CA certs provided by the operating system. Instead,
// use this CA cert to verify the updates provider.
$options['CURLOPT_CAINFO'] = $cacertfile;
}

return $options;
}

Expand Down
3,895 changes: 3,895 additions & 0 deletions lib/cacert.pem

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions lib/cacert.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CA Certificates for cURL library
================================

The file cacert.pem can be downloaded from http://curl.haxx.se/docs/caextract.html
or created directly from http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt
using mk-ca-bundle conversion tool.

The file is licensed under the same licenses as the Mozilla source file:
MPL 1.1, GPL v2.0 or LGPL 2.1

This file is by default used in all Windows installations that do not have
any "curl.cainfo =" specified in php.ini

It is also possible to force using of arbitrary CA bundle by putting it
into $CFG->dataroot/moodleorgca.crt, this may be useful especially on
non-windows servers with outdated system certificates.

More information at http://docs.moodle.org/en/SSL_certificate_for_moodle.org

Petr Skoda (skodak)
37 changes: 37 additions & 0 deletions lib/filelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,10 @@ function download_file_content($url, $headers=null, $postdata=null, $fullrespons
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connecttimeout);

if ($cacert = curl::get_cacert()) {
curl_setopt($ch, CURLOPT_CAINFO, $cacert);
}

if (!ini_get('open_basedir') and !ini_get('safe_mode')) {
// TODO: add version test for '7.10.5'
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
Expand Down Expand Up @@ -2930,6 +2934,39 @@ public function resetopt(){
$this->options['CURLOPT_SSL_VERIFYPEER'] = 0;
$this->options['CURLOPT_SSL_VERIFYHOST'] = 2;
$this->options['CURLOPT_CONNECTTIMEOUT'] = 30;

if ($cacert = self::get_cacert()) {
$this->options['CURLOPT_CAINFO'] = $cacert;
}
}

/**
* Get the location of ca certificates.
* @return string absolute file path or empty if default used
*/
public static function get_cacert() {
global $CFG;

// Bundle in dataroot always wins.
if (is_readable("$CFG->dataroot/moodleorgca.crt")) {
return realpath("$CFG->dataroot/moodleorgca.crt");
}

// Next comes the default from php.ini
$cacert = ini_get('curl.cainfo');
if (!empty($cacert) and is_readable($cacert)) {
return realpath($cacert);
}

// Windows PHP does not have any certs, we need to use something.
if ($CFG->ostype === 'WINDOWS') {
if (is_readable("$CFG->libdir/cacert.pem")) {
return realpath("$CFG->libdir/cacert.pem");
}
}

// Use default, this should work fine on all properly configured *nix systems.
return null;
}

/**
Expand Down
14 changes: 0 additions & 14 deletions lib/pluginlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1429,13 +1429,6 @@ protected function prepare_request_options() {
'CURLOPT_SSL_VERIFYPEER' => true,
);

$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
if (is_readable($cacertfile)) {
// Do not use CA certs provided by the operating system. Instead,
// use this CA cert to verify the updates provider.
$options['CURLOPT_CAINFO'] = $cacertfile;
}

return $options;
}

Expand Down Expand Up @@ -2318,13 +2311,6 @@ protected function update_downloadable($downloadurl) {
'CURLOPT_SSL_VERIFYPEER' => true,
);

$cacertfile = $CFG->dataroot.'/moodleorgca.crt';
if (is_readable($cacertfile)) {
// Do not use CA certs provided by the operating system. Instead,
// use this CA cert to verify the updates provider.
$curloptions['CURLOPT_CAINFO'] = $cacertfile;
}

$curl = new curl(array('proxy' => true));
$result = $curl->head($downloadurl, $curloptions);
$errno = $curl->get_errno();
Expand Down
33 changes: 30 additions & 3 deletions mdeploy.php
Original file line number Diff line number Diff line change
Expand Up @@ -1054,9 +1054,7 @@ protected function download_file($source, $target) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20); // nah, moodle.org is never unavailable! :-p
curl_setopt($ch, CURLOPT_URL, $source);

$dataroot = $this->input->get_option('dataroot');
$cacertfile = $dataroot.'/moodleorgca.crt';
if (is_readable($cacertfile)) {
if ($cacertfile = $this->get_cacert()) {
// Do not use CA certs provided by the operating system. Instead,
// use this CA cert to verify the ZIP provider.
$this->log('Using custom CA certificate '.$cacertfile);
Expand Down Expand Up @@ -1116,6 +1114,35 @@ protected function download_file($source, $target) {
return true;
}

/**
* Get the location of ca certificates.
* @return string absolute file path or empty if default used
*/
protected function get_cacert() {
$dataroot = $this->input->get_option('dataroot');

// Bundle in dataroot always wins.
if (is_readable($dataroot.'/moodleorgca.crt')) {
return realpath($dataroot.'/moodleorgca.crt');
}

// Next comes the default from php.ini
$cacert = ini_get('curl.cainfo');
if (!empty($cacert) and is_readable($cacert)) {
return realpath($cacert);
}

// Windows PHP does not have any certs, we need to use something.
if (stristr(PHP_OS, 'win') && !stristr(PHP_OS, 'darwin')) {
if (is_readable(__DIR__.'/lib/cacert.pem')) {
return realpath(__DIR__.'/lib/cacert.pem');
}
}

// Use default, this should work fine on all properly configured *nix systems.
return null;
}

/**
* Log a message
*
Expand Down

0 comments on commit c2140b5

Please sign in to comment.