Permalink
Browse files

MDL-35332 lib: Improve security of hashed passwords

  • Loading branch information...
1 parent 6319737 commit ec2d8ceb885754140b940ed100a78f9c1f35ff49 @simoncoggins simoncoggins committed Sep 30, 2012
@@ -618,14 +618,16 @@
// Do not mess with passwords of remote users.
} else if (!$isinternalauth) {
- $existinguser->password = 'not cached';
+ $existinguser->password = AUTH_PASSWORD_NOT_CACHED;
$upt->track('password', '-', 'normal', false);
// clean up prefs
unset_user_preference('create_password', $existinguser);
unset_user_preference('auth_forcepasswordchange', $existinguser);
} else if (!empty($user->password)) {
if ($updatepasswords) {
+ // Check for passwords that we want to force users to reset next
+ // time they log in.
$errmsg = null;
$weak = !check_password_policy($user->password, $errmsg);
if ($resetpasswords == UU_PWRESET_ALL or ($resetpasswords == UU_PWRESET_WEAK and $weak)) {
@@ -638,7 +640,12 @@
unset_user_preference('auth_forcepasswordchange', $existinguser);
}
unset_user_preference('create_password', $existinguser); // no need to create password any more
- $existinguser->password = hash_internal_user_password($user->password);
+
+ // Use a low cost factor when generating bcrypt hash otherwise
+ // hashing would be slow when uploading lots of users. Hashes
+ // will be automatically updated to a higher cost factor the first
+ // time the user logs in.
+ $existinguser->password = hash_internal_user_password($user->password, true);
$upt->track('password', $user->password, 'normal', false);
} else {
// do not print password when not changed
@@ -771,10 +778,14 @@
}
$forcechangepassword = true;
}
- $user->password = hash_internal_user_password($user->password);
+ // Use a low cost factor when generating bcrypt hash otherwise
+ // hashing would be slow when uploading lots of users. Hashes
+ // will be automatically updated to a higher cost factor the first
+ // time the user logs in.
+ $user->password = hash_internal_user_password($user->password, true);
}
} else {
- $user->password = 'not cached';
+ $user->password = AUTH_PASSWORD_NOT_CACHED;
$upt->track('password', '-', 'normal', false);
}
View
@@ -221,6 +221,9 @@ function user_update_password($user, $newpassword) {
if ($this->is_internal()) {
$puser = $DB->get_record('user', array('id'=>$user->id), '*', MUST_EXIST);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
if (update_internal_user_password($puser, $newpassword)) {
$user->password = $puser->password;
return true;
View
@@ -59,6 +59,9 @@ function user_login ($username, $password) {
*/
function user_update_password($user, $newpassword) {
$user = get_complete_user_data('id', $user->id);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
return update_internal_user_password($user, $newpassword);
}
View
@@ -529,6 +529,9 @@ function user_signup($user, $notify=true) {
profile_save_data($user);
$this->update_user_record($user->username);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
update_internal_user_password($user, $plainslashedpassword);
$user = $DB->get_record('user', array('id'=>$user->id));
View
@@ -82,6 +82,9 @@ function user_login($username, $password) {
*/
function user_update_password($user, $newpassword) {
$user = get_complete_user_data('id', $user->id);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
return update_internal_user_password($user, $newpassword);
}
View
@@ -59,6 +59,9 @@ function user_login ($username, $password) {
*/
function user_update_password($user, $newpassword) {
$user = get_complete_user_data('id', $user->id);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
return update_internal_user_password($user, $newpassword);
}
View
@@ -85,6 +85,9 @@ function user_login_webservice($username, $password) {
*/
function user_update_password($user, $newpassword) {
$user = get_complete_user_data('id', $user->id);
+ // This will also update the stored hash to the latest algorithm
+ // if the existing hash is using an out-of-date algorithm (or the
+ // legacy md5 algorithm).
return update_internal_user_password($user, $newpassword);
}
@@ -1052,7 +1052,7 @@ public static function create_included_users($basepath, $restoreid, $userid) {
// Most external plugins do not store passwords locally
if (!empty($userauth->preventpassindb)) {
- $user->password = 'not cached';
+ $user->password = AUTH_PASSWORD_NOT_CACHED;
// If Moodle is responsible for storing/validating pwd and reset functionality is available, mark
} else if ($userauth->isinternal and $userauth->canresetpwd) {
View
@@ -63,28 +63,7 @@
//=========================================================================
-// 2. SECRET PASSWORD SALT
-//=========================================================================
-// User password salt is very important security feature, it is created
-// automatically in installer, you have to uncomment and modify value
-// on the next line if you are creating config.php manually.
-//
-// $CFG->passwordsaltmain = 'a_very_long_random_string_of_characters#@6&*1';
-//
-// After changing the main salt you have to copy old value into one
-// of the following settings - this allows migration to the new salt
-// during the next login of each user.
-//
-// $CFG->passwordsaltalt1 = '';
-// $CFG->passwordsaltalt2 = '';
-// $CFG->passwordsaltalt3 = '';
-// ....
-// $CFG->passwordsaltalt19 = '';
-// $CFG->passwordsaltalt20 = '';
-
-
-//=========================================================================
-// 3. WEB SITE LOCATION
+// 2. WEB SITE LOCATION
//=========================================================================
// Now you need to tell Moodle where it is located. Specify the full
// web address to where moodle has been installed. If your web site
@@ -98,7 +77,7 @@
//=========================================================================
-// 4. DATA FILES LOCATION
+// 3. DATA FILES LOCATION
//=========================================================================
// Now you need a place where Moodle can save uploaded files. This
// directory should be readable AND WRITEABLE by the web server user
@@ -114,7 +93,7 @@
//=========================================================================
-// 5. DATA FILES PERMISSIONS
+// 4. DATA FILES PERMISSIONS
//=========================================================================
// The following parameter sets the permissions of new directories
// created by Moodle within the data directory. The format is in
@@ -128,7 +107,7 @@
//=========================================================================
-// 6. DIRECTORY LOCATION (most people can just ignore this setting)
+// 5. DIRECTORY LOCATION (most people can just ignore this setting)
//=========================================================================
// A very few webhosts use /admin as a special URL for you to access a
// control panel or something. Unfortunately this conflicts with the
@@ -140,7 +119,7 @@
//=========================================================================
-// 7. OTHER MISCELLANEOUS SETTINGS (ignore these for new installations)
+// 6. OTHER MISCELLANEOUS SETTINGS (ignore these for new installations)
//=========================================================================
//
// These are additional tweaks for which no GUI exists in Moodle yet.
@@ -471,7 +450,7 @@
// $CFG->svgicons = false;
//
//=========================================================================
-// 8. SETTINGS FOR DEVELOPMENT SERVERS - not intended for production use!!!
+// 7. SETTINGS FOR DEVELOPMENT SERVERS - not intended for production use!!!
//=========================================================================
//
// Force a debugging mode regardless the settings in the site administration
@@ -512,7 +491,7 @@
// $CFG->showcrondebugging = true;
//
//=========================================================================
-// 9. FORCED SETTINGS
+// 8. FORCED SETTINGS
//=========================================================================
// It is possible to specify normal admin settings here, the point is that
// they can not be changed through the standard admin settings pages any more.
@@ -527,12 +506,35 @@
// 'otherplugin' => array('mysetting' => 'myvalue', 'thesetting' => 'thevalue'));
//
//=========================================================================
-// 10. PHPUNIT SUPPORT
+// 9. PHPUNIT SUPPORT
//=========================================================================
// $CFG->phpunit_prefix = 'phpu_';
// $CFG->phpunit_dataroot = '/home/example/phpu_moodledata';
// $CFG->phpunit_directorypermissions = 02777; // optional
//
+//
+//=========================================================================
+// 10. SECRET PASSWORD SALT
+//=========================================================================
+// A single site-wide password salt is no longer required *unless* you are
+// upgrading an older version of Moodle (prior to 2.5), or if you are using
+// a PHP version below 5.3.7. If upgrading, keep any values from your old
+// config.php file. If you are using PHP < 5.3.7 set to a long random string
+// below:
+//
+// $CFG->passwordsaltmain = 'a_very_long_random_string_of_characters#@6&*1';
+//
+// You may also have some alternative salts to allow migration from previously
+// used salts.
+//
+// $CFG->passwordsaltalt1 = '';
+// $CFG->passwordsaltalt2 = '';
+// $CFG->passwordsaltalt3 = '';
+// ....
+// $CFG->passwordsaltalt19 = '';
+// $CFG->passwordsaltalt20 = '';
+//
+//
//=========================================================================
// 11. BEHAT SUPPORT
//=========================================================================
View
@@ -216,7 +216,11 @@ function cron_run() {
// note: we can not send emails to suspended accounts
foreach ($newusers as $newuser) {
- if (setnew_password_and_mail($newuser)) {
+ // Use a low cost factor when generating bcrypt hash otherwise
+ // hashing would be slow when emailing lots of users. Hashes
+ // will be automatically updated to a higher cost factor the first
+ // time the user logs in.
+ if (setnew_password_and_mail($newuser, true)) {
unset_user_preference('create_password', $newuser);
set_user_preference('auth_forcepasswordchange', 1, $newuser);
} else {
View
@@ -753,7 +753,7 @@
<FIELD NAME="suspended" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="suspended flag prevents users to log in"/>
<FIELD NAME="mnethostid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="username" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
- <FIELD NAME="password" TYPE="char" LENGTH="32" NOTNULL="true" SEQUENCE="false"/>
+ <FIELD NAME="password" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="idnumber" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="firstname" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="lastname" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
View
@@ -1564,6 +1564,18 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2012120300.07);
}
+ if ($oldversion < 2013020900.00) {
+
+ // Changing precision of field password on table user to (255).
+ $table = new xmldb_table('user');
+ $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'username');
+
+ // Launch change of precision for field password.
+ $dbman->change_field_precision($table, $field);
+
+ // Main savepoint reached.
+ upgrade_main_savepoint(true, 2013020900.00);
+ }
return true;
}
View
@@ -233,7 +233,10 @@ function install_generate_configphp($database, $cfg) {
}
$configphp .= '$CFG->directorypermissions = ' . $chmod . ';' . PHP_EOL . PHP_EOL;
- $configphp .= '$CFG->passwordsaltmain = '.var_export(complex_random_string(), true) . ';' . PHP_EOL . PHP_EOL;
+ // A site-wide salt is only needed if bcrypt is not properly supported by the current version of PHP.
+ if (password_compat_not_supported()) {
+ $configphp .= '$CFG->passwordsaltmain = '.var_export(complex_random_string(), true) . ';' . PHP_EOL . PHP_EOL;
+ }
$configphp .= 'require_once(dirname(__FILE__) . \'/lib/setup.php\');' . PHP_EOL . PHP_EOL;
$configphp .= '// There is no php closing tag in this file,' . PHP_EOL;
Oops, something went wrong.

0 comments on commit ec2d8ce

Please sign in to comment.