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;
}
Example #4
0
/**
 * 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;
}