protected function setUp() { if (password_compat_not_supported()) { // Skip test if password_compat is not supported. $this->markTestSkipped('password_compat not supported'); } }
/** * Test function update_internal_user_password(). */ public function test_update_internal_user_password() { global $DB; $this->resetAfterTest(); $passwords = array('password', '1234', 'changeme', '****'); foreach ($passwords as $password) { $user = $this->getDataGenerator()->create_user(array('auth' => 'manual')); update_internal_user_password($user, $password); // The user object should have been updated. $this->assertTrue(validate_internal_user_password($user, $password)); // The database field for the user should also have been updated to the // same value. $this->assertSame($user->password, $DB->get_field('user', 'password', array('id' => $user->id))); } $user = $this->getDataGenerator()->create_user(array('auth' => 'manual')); // Manually set the user's password to the md5 of the string 'password'. $DB->set_field('user', 'password', '5f4dcc3b5aa765d61d8327deb882cf99', array('id' => $user->id)); // Update the password. update_internal_user_password($user, 'password'); if (password_compat_not_supported()) { // If bcrypt not properly supported the password should remain as an md5 hash. $expected_hash = hash_internal_user_password('password', true); $this->assertSame($user->password, $expected_hash); $this->assertTrue(password_is_legacy_hash($user->password)); } else { // Otherwise password should have been updated to a bcrypt hash. $this->assertFalse(password_is_legacy_hash($user->password)); } }
/** * Update password hash in user object (if necessary). * * The password is updated if: * 1. The password has changed (the hash of $user->password is different * to the hash of $password). * 2. The existing hash is using an out-of-date algorithm (or the legacy * md5 algorithm). * * Updating the password will modify the $user object and the database * record to use the current hashing algorithm. * * @param stdClass $user User object (password property may be updated). * @param string $password Plain text password. * @return bool Always returns true. */ function update_internal_user_password($user, $password) { global $CFG, $DB; require_once $CFG->libdir . '/password_compat/lib/password.php'; // Use the legacy hashing algorithm (md5) if PHP doesn't support bcrypt properly. $legacyhash = password_compat_not_supported(); // Figure out what the hashed password should be. $authplugin = get_auth_plugin($user->auth); if ($authplugin->prevent_local_passwords()) { $hashedpassword = AUTH_PASSWORD_NOT_CACHED; } else { $hashedpassword = hash_internal_user_password($password); } if ($legacyhash) { $passwordchanged = $user->password !== $hashedpassword; $algorithmchanged = false; } else { // If verification fails then it means the password has changed. $passwordchanged = !password_verify($password, $user->password); $algorithmchanged = password_needs_rehash($user->password, PASSWORD_DEFAULT); } if ($passwordchanged || $algorithmchanged) { $DB->set_field('user', 'password', $hashedpassword, array('id' => $user->id)); $user->password = $hashedpassword; // Trigger event. $event = \core\event\user_updated::create(array('objectid' => $user->id, 'context' => context_user::instance($user->id))); $event->add_record_snapshot('user', $user); $event->trigger(); } return true; }
/** * Returns content of config.php file. * * Uses PHP_EOL for generating proper end of lines for the given platform. * * @param moodle_database $database database instance * @param object $cfg copy of $CFG * @return string */ function install_generate_configphp($database, $cfg) { $configphp = '<?php // Moodle configuration file' . PHP_EOL . PHP_EOL; $configphp .= 'unset($CFG);' . PHP_EOL; $configphp .= 'global $CFG;' . PHP_EOL; $configphp .= '$CFG = new stdClass();' . PHP_EOL . PHP_EOL; // prevent PHP5 strict warnings $dbconfig = $database->export_dbconfig(); foreach ($dbconfig as $key => $value) { $key = str_pad($key, 9); $configphp .= '$CFG->' . $key . ' = ' . var_export($value, true) . ';' . PHP_EOL; } $configphp .= PHP_EOL; $configphp .= '$CFG->wwwroot = ' . var_export($cfg->wwwroot, true) . ';' . PHP_EOL; $configphp .= '$CFG->dataroot = ' . var_export($cfg->dataroot, true) . ';' . PHP_EOL; $configphp .= '$CFG->admin = ' . var_export($cfg->admin, true) . ';' . PHP_EOL . PHP_EOL; if (empty($cfg->directorypermissions)) { $chmod = '02777'; } else { $chmod = '0' . decoct($cfg->directorypermissions); } $configphp .= '$CFG->directorypermissions = ' . $chmod . ';' . 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; $configphp .= '// it is intentional because it prevents trailing whitespace problems!' . PHP_EOL; return $configphp; }