diff --git a/admin/index.php b/admin/index.php index 785f3e59b6c5b..513b17903a166 100644 --- a/admin/index.php +++ b/admin/index.php @@ -368,6 +368,10 @@ } +if (empty($CFG->passwordsaltmain)) { + print_box(get_string('upgrade197notice', 'admin')."\n".get_string('upgrade197salt', 'admin')); +} + if (defined('WARN_DISPLAY_ERRORS_ENABLED')) { echo $OUTPUT->box(get_string('displayerrorswarning', 'admin'), 'generalbox adminwarning'); } diff --git a/admin/report/security/lib.php b/admin/report/security/lib.php index a4e1928eae417..e20c7e812912a 100644 --- a/admin/report/security/lib.php +++ b/admin/report/security/lib.php @@ -49,6 +49,7 @@ function report_security_get_issue_list() { 'report_security_check_openprofiles', 'report_security_check_google', 'report_security_check_passwordpolicy', + 'report_security_check_passwordsaltmain', 'report_security_check_emailchangeconfirmation', 'report_security_check_cookiesecure', 'report_security_check_configrw', @@ -473,6 +474,35 @@ function report_security_check_configrw($detailed=false) { return $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 (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; +} + /** * Lists all users with XSS risk, it would be great to combine this with risk trusts in user table, * unfortunately nobody implemented user trust UI yet :-( diff --git a/admin/settings/security.php b/admin/settings/security.php index e9e97c4244418..2e74e5a6ad11f 100644 --- a/admin/settings/security.php +++ b/admin/settings/security.php @@ -47,7 +47,7 @@ $temp->add(new admin_setting_configcheckbox('cronclionly', get_string('cronclionly', 'admin'), get_string('configcronclionly', 'admin'), 0)); $temp->add(new admin_setting_configpasswordunmask('cronremotepassword', get_string('cronremotepassword', 'admin'), get_string('configcronremotepassword', 'admin'), '')); - $temp->add(new admin_setting_configcheckbox('passwordpolicy', get_string('passwordpolicy', 'admin'), get_string('configpasswordpolicy', 'admin'), 0)); + $temp->add(new admin_setting_configcheckbox('passwordpolicy', get_string('passwordpolicy', 'admin'), get_string('configpasswordpolicy', 'admin'), 1)); $temp->add(new admin_setting_configtext('minpasswordlength', get_string('minpasswordlength', 'admin'), get_string('configminpasswordlength', 'admin'), 8, PARAM_INT)); $temp->add(new admin_setting_configtext('minpassworddigits', get_string('minpassworddigits', 'admin'), get_string('configminpassworddigits', 'admin'), 1, PARAM_INT)); $temp->add(new admin_setting_configtext('minpasswordlower', get_string('minpasswordlower', 'admin'), get_string('configminpasswordlower', 'admin'), 1, PARAM_INT)); diff --git a/lang/en_utf8/admin.php b/lang/en_utf8/admin.php index fa092b8ed7c9a..b21b2fbe3590c 100644 --- a/lang/en_utf8/admin.php +++ b/lang/en_utf8/admin.php @@ -882,6 +882,12 @@ $string['uploadpicture_userupdated'] = 'Picture updated for user $a.'; $string['uploadpicture_cannotsave'] = 'Cannot save picture for user $a. Check original picture file.'; $string['updatetimezones'] = 'Update timezones'; +$string['upgrade197notice'] = '
Moodle 1.9.7 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.9.7 release notes for full 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 = \'arandomstringofcharacters\';
The random string of characters should be a mix of letters, numbers and other characters.
'; + $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->adminsIt is recommended to assign administrator role in system context only. Following users have unsupported admin role assignments:
$a->unsupported'; diff --git a/lib/installlib.php b/lib/installlib.php index c36bb51acb968..5af8c22bc9cf5 100644 --- a/lib/installlib.php +++ b/lib/installlib.php @@ -203,6 +203,9 @@ function install_generate_configphp($database, $cfg, $userealpath=false) { $configphp .= '$CFG->directorypermissions = 00777; // try 02777 on a server in Safe Mode'."\r\n"; $configphp .= "\r\n"; + $configphp .= '$CFG->passwordsaltmain = '.var_export(complex_random_string(), true).";\r\n"; + $configphp .= "\r\n"; + $configphp .= 'require_once("$CFG->dirroot/lib/setup.php");'."\r\n\r\n"; $configphp .= '// There is no php closing tag in this file,'."\r\n"; $configphp .= '// it is intentional because it prevents trailing whitespace problems!'."\r\n"; diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 64a8ad3472e19..f0b43b7d82fc1 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7553,6 +7553,30 @@ function random_string ($length=15) { return $string; } +/** + * Generate a complex random string (usefull for md5 salts) + * + * This function is based on the above {@link random_string()} however it uses a + * larger pool of characters and generates a string between 24 and 32 characters + * + * @param int $length Optional if set generates a string to exactly this length + * @return string + */ +function complex_random_string($length=null) { + $pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + $pool .= '`~!@#%^&*()_+-=[];,./<>?:{} '; + $poollen = strlen($pool); + mt_srand ((double) microtime() * 1000000); + if ($length===null) { + $length = floor(rand(24,32)); + } + $string = ''; + for ($i = 0; $i < $length; $i++) { + $string .= $pool[(mt_rand()%$poollen)]; + } + return $string; +} + /** * Given some text (which may contain HTML) and an ideal length, * this function truncates the text neatly on a word boundary if possible @@ -7564,7 +7588,6 @@ function random_string ($length=15) { * @param string $ending The string to append if the passed string is truncated * @return string $truncate - shortened string */ - function shorten_text($text, $ideal=30, $exact = false, $ending='...') { global $CFG;