diff --git a/admin/report/security/lib.php b/admin/report/security/lib.php index c79bbb610cd..0c9433c9531 100644 --- a/admin/report/security/lib.php +++ b/admin/report/security/lib.php @@ -42,6 +42,7 @@ function report_security_get_issue_list() { 'report_security_check_mediafilterswf', 'report_security_check_openprofiles', 'report_security_check_google', + 'report_security_check_passwordsaltmain', 'report_security_check_configrw', 'report_security_check_defaultuserrole', 'report_security_check_guestrole', @@ -740,3 +741,38 @@ function report_security_check_courserole($detailed=false) { return $result; } +/** + * Checks to see whether a password salt has been defined + * + * @param bool $detailed + * @return object result + */ +function report_security_check_passwordsaltmain($detailed=false) { + global $CFG; + + $result = new object(); + $result->issue = 'report_security_check_passwordsaltmain'; + $result->name = get_string('check_passwordsaltmain_name', 'report_security'); + $result->info = null; + $result->details = null; + $result->status = null; + $result->link = null; + + if (empty($CFG->passwordsaltmain)) { + $result->status = REPORT_SECURITY_WARNING; + $result->info = get_string('check_passwordsaltmain_warning', 'report_security'); + } else if ($CFG->passwordsaltmain === 'a_very_long_random_string_of_characters#@6&*1' + || trim($CFG->passwordsaltmain) === '' || preg_match('/^([\w]+|[\d]+)$/i', $CFG->passwordsaltmain)) { + $result->status = REPORT_SECURITY_WARNING; + $result->info = get_string('check_passwordsaltmain_weak', 'report_security'); + } else { + $result->status = REPORT_SECURITY_OK; + $result->info = get_string('check_passwordsaltmain_ok', 'report_security'); + } + + if ($detailed) { + $result->details = get_string('check_passwordsaltmain_details', 'report_security'); + } + + return $result; +} \ No newline at end of file diff --git a/install.php b/install.php index 895d448090e..00f34d2d474 100644 --- a/install.php +++ b/install.php @@ -532,6 +532,9 @@ if ($nextstage == SAVE) { $str .= '$CFG->directorypermissions = 00777; // try 02777 on a server in Safe Mode'."\r\n"; $str .= "\r\n"; + $str .= '$CFG->passwordsaltmain = \''.addsingleslashes(complex_random_string()).'\';'."\r\n"; + $str .= "\r\n"; + $str .= 'require_once("$CFG->dirroot/lib/setup.php");'."\r\n"; $str .= '// MAKE SURE WHEN YOU EDIT THIS FILE THAT THERE ARE NO SPACES, BLANK LINES,'."\r\n"; $str .= '// RETURNS, OR ANYTHING ELSE AFTER THE TWO CHARACTERS ON THE NEXT LINE.'."\r\n"; @@ -1278,4 +1281,13 @@ function toggledbinfo() { diff --git a/lang/en_utf8/admin.php b/lang/en_utf8/admin.php index 38fb45ead01..9cd32e230ec 100644 --- a/lang/en_utf8/admin.php +++ b/lang/en_utf8/admin.php @@ -587,6 +587,12 @@ $string['upgradesure'] = 'Your Moodle files have been changed, and you are about Once you do this you can not go back again.

Please note that this process can take a long time.

Are you sure you want to upgrade this server to this version?'; +$string['upgrade1811notice'] = '

Moodle 1.8.11 contains a number of security fixes to user passwords and backups to protect the user information on your site.
+As a result some of your settings and permissions relating to backups may have changed.
+Please see the Moodle 1.8.11 release notes for full details.

'; +$string['upgrade1811noticesubject'] = 'Moodle 1.8.11 upgrade security notices'; +$string['upgrade1811salt'] = 'It is also now strongly recommended that you set a password salt to greatly reduce the risk of password theft.
+Please refer to the Moodle security report for more information on this topic. The security report can be accessed by logging into your site as an administrator and go to Site Administration - Security - Site policies'; $string['upgradingdata'] = 'Upgrading data'; $string['upgradinglogs'] = 'Upgrading logs'; $string['upwards'] = 'upwards'; diff --git a/lang/en_utf8/report_security.php b/lang/en_utf8/report_security.php index 455a0209369..5acd90fbf62 100644 --- a/lang/en_utf8/report_security.php +++ b/lang/en_utf8/report_security.php @@ -119,6 +119,14 @@ $string['check_passwordpolicy_error'] = 'Password policy not set.'; $string['check_passwordpolicy_name'] = 'Password policy'; $string['check_passwordpolicy_ok'] = 'Password policy enabled.'; +$string['check_passwordsaltmain_name'] = 'Password salt'; +$string['check_passwordsaltmain_warning'] = 'No password salt has been set'; +$string['check_passwordsaltmain_ok'] = 'Password salt is OK'; +$string['check_passwordsaltmain_weak'] = 'Password salt is weak'; +$string['check_passwordsaltmain_details'] = '

It is strongly recommended that a password salt is set as it greatly reduces the risk of password theft.
To set a password salt add the following to your config.php file.

\$CFG->passwordsaltmain = \'a_very_long_random_string_of_characters#@6&*1\'; +

The random string of characters should be a mix of letters, numbers and other characters.

+

When changing main salt make sure that you include the old value in config.php, there may be 20 alternative salts. Without the old value in alternative salts list users will not be able to login and will have to use password reset.
\$CFG->passwordsaltalt1 = \'previous_main_salt\';

'; + $string['check_riskadmin_detailsok'] = '

Please verify the following list of system administrators:

$a'; $string['check_riskadmin_detailswarning'] = '

Please verify the following list of system administrators:

$a->admins

It is recommended to assign administrator role in system context only. Following users have unsupported admin role assignments:

$a->unsupported'; diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 0955386a731..e3393166d0e 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -780,6 +780,55 @@ function xmldb_main_upgrade($oldversion=0) { filter_tex_updatedcallback(null); } + if ($result && $oldversion < 2007021599.11) { + $messagesubject = get_string('upgrade1811noticesubject', 'admin'); + $message = addslashes(get_string('upgrade1811notice', 'admin')); + if (empty($CFG->passwordmainsalt)) { + $message .= "\n".get_string('upgrade1811salt', 'admin'); + } + + notify($message, 'notifysuccess'); + + $systemcontext = get_context_instance(CONTEXT_SYSTEM); + // Force administrators to change password on next login + $sql = "SELECT DISTINCT u.id, u.firstname, u.lastname, u.picture, u.imagealt, u.email, u.password + FROM {$CFG->prefix}role_capabilities rc + JOIN {$CFG->prefix}role_assignments ra ON (ra.contextid = rc.contextid AND ra.roleid = rc.roleid) + JOIN {$CFG->prefix}user u ON u.id = ra.userid + WHERE rc.capability = 'moodle/site:doanything' + AND rc.permission = ".CAP_ALLOW." + AND u.deleted = 0 + AND rc.contextid = ".$systemcontext->id.""; + + $adminusers = get_records_sql($sql); + foreach ($adminusers as $adminuser) { + if ($adminuser->password === 'not cached') { + // no need to change password if stored only outside of moodle - most probably ldap auth + continue; + } + if ($preference = get_record('user_preferences', 'userid', $adminuser->id, 'name', 'auth_forcepasswordchange')) { + if ($preference->value == '1') { + continue; + } + set_field('user_preferences', 'value', '1', 'id', $preference->id); + } else { + $preference = new stdClass; + $preference->userid = $adminuser->id; + $preference->name = 'auth_forcepasswordchange'; + $preference->value = '1'; + insert_record('user_preferences', $preference); + } + + // Message them with the notice about upgrading + email_to_user($adminuser, $adminuser, $messagesubject, $message); + } + + unset($adminusers); + unset($preference); + unset($message); + unset($messagesubject); + } + return $result; } diff --git a/version.php b/version.php index 5ddc6f9cd8d..a32706b02c1 100644 --- a/version.php +++ b/version.php @@ -6,10 +6,12 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2007021599.100; // YYYYMMDD = date of the 1.8 branch (don't change) + $version = 2007021599.11; // YYYYMMDD = date of the 1.8 branch (don't change) // 99 = we reached a .10 release! (don't change) // .XX = release number 1.8.[10,11,12,..] - // Y = micro-increments between releases + + // Do not use more than two decimal points as we have + // hit the float limit $release = '1.8.10+ (Build: 20091117)'; // Human-friendly version name