Пример #1
0
 /**
  * Updates the user's password.
  *
  * called when the user password is updated.
  *
  * @param  object  $user        User table object  (with system magic quotes)
  * @param  string  $newpassword Plaintext password (with system magic quotes)
  * @return boolean result
  *
  */
 public 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);
 }
Пример #2
0
 /**
  * Updates the user's password.
  *
  * called when the user password is updated.
  *
  * @param  object  $user        User table object  (with system magic quotes)
  * @param  string  $newpassword Plaintext password (with system magic quotes)
  * @return boolean result
  *
  */
 function user_update_password($user, $newpassword)
 {
     global $CFG;
     require_once $CFG->dirroot . '/curriculum/config.php';
     require_once CURMAN_DIRLOCATION . '/lib/user.class.php';
     $user = get_complete_user_data('id', $user->id);
     $select = "idnumber = '{$user->idnumber}'";
     $cuser = new user($select);
     if (!empty($cuser->id)) {
         $cuser->change_password($newpassword, true);
     }
     return update_internal_user_password($user, $newpassword);
 }
Пример #3
0
/**
 * Update a user with a user object (will compare against the ID)
 *
 * @param object $user the user to update
 */
function user_update_user($user)
{
    global $DB;
    // set the timecreate field to the current time
    if (!is_object($user)) {
        $user = (object) $user;
    }
    // unset password here, for updating later
    if (isset($user->password)) {
        $passwd = $user->password;
        unset($user->password);
    }
    $user->timemodified = time();
    $DB->update_record('user', $user);
    // trigger user_updated event on the full database user row
    $updateduser = $DB->get_record('user', array('id' => $user->id));
    events_trigger('user_updated', $updateduser);
    // if password was set, then update its hash
    if (isset($passwd)) {
        update_internal_user_password($updateduser, $passwd);
    }
}
Пример #4
0
 /**
  * Test if the user has a password hash, but now their auth method
  * says not to cache it.  Then it should update.
  */
 public function test_update_internal_user_password_update_no_cache()
 {
     $this->resetAfterTest();
     $user = $this->getDataGenerator()->create_user(array('password' => 'test'));
     $this->assertNotEquals(AUTH_PASSWORD_NOT_CACHED, $user->password);
     $user->auth = 'cas';
     // Change to a auth that does not store passwords.
     $sink = $this->redirectEvents();
     update_internal_user_password($user, 'wonkawonka');
     $this->assertGreaterThanOrEqual(1, $sink->count(), 'User updated event should fire');
     $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password);
 }
Пример #5
0
 /**
  * Authentication hook - is called every time user hit the login page
  * The code is run only if the param code is mentionned.
  */
 function loginpage_hook()
 {
     global $USER, $SESSION, $CFG, $DB;
     $username = optional_param('username', '', PARAM_RAW);
     $password = optional_param('password', '', PARAM_RAW);
     if (!$username or !$password) {
         // Don't allow blank usernames or passwords
         return false;
     }
     //check the AD webservice authorization code
     if (!empty($username)) {
         //set the params specific to the authentication provider
         $params = array();
         $ch = curl_init();
         $server = $DB->get_field('config_plugins', 'value', array('name' => 'adwebserviceip'));
         curl_setopt($ch, CURLOPT_URL, "{$server}?userId={$username}&password={$password}&flag=E");
         curl_setopt($ch, CURLOPT_HEADER, false);
         curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
         curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
         //curl_setopt($ch, CURLOPT_POST, true);
         //curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
         if (!($result = curl_exec($ch))) {
             trigger_error(curl_error($ch));
         }
         curl_close($ch);
         if ($result == 'true') {
             $username = $username;
             $password = $password;
             $newuser = new stdClass();
             $user = $DB->get_record('user', array('username' => $username, 'deleted' => 0, 'mnethostid' => $CFG->mnet_localhost_id));
             if ($user) {
                 //$newuser->id = $user->id;
                 $updated = update_internal_user_password($user, $password);
             }
         } else {
             //throw new moodle_exception('wrongusername', 'auth_adwebservice');
             return false;
         }
         $user = $DB->get_record('user', array('username' => $username, 'deleted' => 0, 'mnethostid' => $CFG->mnet_localhost_id));
         //create the user if it doesn't exist
         if (empty($user)) {
             // deny login if setting "Prevent account creation when authenticating" is on
             if ($CFG->authpreventaccountcreation) {
                 throw new moodle_exception("noaccountyet", "auth_adwebservice");
             }
             //retrieve more information from the provider
             //  $newuser = new stdClass();
             //$newuser->email = '*****@*****.**';
             //create_user_record($username, $password, 'adwebservice');
         } else {
             $username = $user->username;
         }
         //authenticate the user
         //TODO: delete this log later
         $userid = empty($user) ? 'new user' : $user->id;
         //   add_to_log(SITEID, 'auth_adwebservice', '', '', $username . '/' . $useremail . '/' . $userid);
         $user = authenticate_user_login($username, $password);
         if ($user) {
             //set a cookie to remember what auth provider was selected
             setcookie('MOODLEADWEBSERVICE_' . $CFG->sessioncookie, $authprovider, time() + DAYSECS * 60, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $CFG->cookiesecure, $CFG->cookiehttponly);
             //prefill more user information if new user
             //                    if (!empty($newuser)) {
             //                        $newuser->id = $user->id;
             //                        $DB->update_record('user', $newuser);
             //                        $user = (object) array_merge((array) $user, (array) $newuser);
             //                    }
             complete_user_login($user);
             // Redirection
             if (user_not_fully_set_up($USER)) {
                 $urltogo = $CFG->wwwroot . '/user/edit.php';
                 // We don't delete $SESSION->wantsurl yet, so we get there later
             } else {
                 if (isset($SESSION->wantsurl) and strpos($SESSION->wantsurl, $CFG->wwwroot) === 0) {
                     $urltogo = $SESSION->wantsurl;
                     // Because it's an address in this site
                     unset($SESSION->wantsurl);
                 } else {
                     // No wantsurl stored or external - go to homepage
                     $urltogo = $CFG->wwwroot . '/';
                     unset($SESSION->wantsurl);
                 }
             }
             redirect($urltogo);
         }
     }
 }
Пример #6
0
/**
 * Sets specified user's password and send the new password to the user via email.
 *
 * @param stdClass $user A {@link $USER} object
 * @param bool $fasthash If true, use a low cost factor when generating the hash for speed.
 * @return bool|string Returns "true" if mail was sent OK and "false" if there was an error
 */
function setnew_password_and_mail($user, $fasthash = false)
{
    global $CFG, $DB;
    // We try to send the mail in language the user understands,
    // unfortunately the filter_string() does not support alternative langs yet
    // so multilang will not work properly for site->fullname.
    $lang = empty($user->lang) ? $CFG->lang : $user->lang;
    $site = get_site();
    $supportuser = core_user::get_support_user();
    $newpassword = generate_password();
    update_internal_user_password($user, $newpassword, $fasthash);
    $a = new stdClass();
    $a->firstname = fullname($user, true);
    $a->sitename = format_string($site->fullname);
    $a->username = $user->username;
    $a->newpassword = $newpassword;
    $a->link = $CFG->wwwroot . '/login/';
    $a->signoff = generate_email_signoff();
    $message = (string) new lang_string('newusernewpasswordtext', '', $a, $lang);
    $subject = format_string($site->fullname) . ': ' . (string) new lang_string('newusernewpasswordsubj', '', $a, $lang);
    // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
    return email_to_user($user, $supportuser, $subject, $message);
}
Пример #7
0
 /**
  * Create a Moodle user from Azure AD user data.
  *
  * @param array $aaddata Array of Azure AD user data.
  * @return \stdClass An object representing the created Moodle user.
  */
 public function create_user_from_aaddata($aaddata)
 {
     global $CFG;
     require_once $CFG->dirroot . '/user/profile/lib.php';
     require_once $CFG->dirroot . '/user/lib.php';
     $newuser = (object) ['auth' => 'oidc', 'username' => trim(\core_text::strtolower($aaddata['userPrincipalName'])), 'email' => isset($aaddata['mail']) ? $aaddata['mail'] : '', 'firstname' => isset($aaddata['givenName']) ? $aaddata['givenName'] : '', 'lastname' => isset($aaddata['surname']) ? $aaddata['surname'] : '', 'city' => isset($aaddata['city']) ? $aaddata['city'] : '', 'country' => isset($aaddata['country']) ? $aaddata['country'] : '', 'department' => isset($aaddata['department']) ? $aaddata['department'] : '', 'lang' => isset($aaddata['preferredLanguage']) ? substr($aaddata['preferredLanguage'], 0, 2) : 'en', 'confirmed' => 1, 'timecreated' => time(), 'mnethostid' => $CFG->mnet_localhost_id];
     $password = null;
     $newuser->idnumber = $newuser->username;
     if (!empty($newuser->email)) {
         if (email_is_not_allowed($newuser->email)) {
             unset($newuser->email);
         }
     }
     if (empty($newuser->lang) || !get_string_manager()->translation_exists($newuser->lang)) {
         $newuser->lang = $CFG->lang;
     }
     $newuser->timemodified = $newuser->timecreated;
     $newuser->id = user_create_user($newuser, false, false);
     // Save user profile data.
     profile_save_data($newuser);
     $user = get_complete_user_data('id', $newuser->id);
     if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) {
         set_user_preference('auth_forcepasswordchange', 1, $user);
     }
     // Set the password.
     update_internal_user_password($user, $password);
     // Trigger event.
     \core\event\user_created::create_from_userid($newuser->id)->trigger();
     return $user;
 }
Пример #8
0
/**
 * Compare password against hash stored in internal user table.
 * If necessary it also updates the stored hash to new format.
 *
 * @param object user
 * @param string plain text password
 * @return bool is password valid?
 */
function validate_internal_user_password(&$user, $password)
{
    global $CFG;
    if (!isset($CFG->passwordsaltmain)) {
        $CFG->passwordsaltmain = '';
    }
    $validated = false;
    // get password original encoding in case it was not updated to unicode yet
    $textlib = textlib_get_instance();
    $convpassword = $textlib->convert($password, 'utf-8', get_string('oldcharset'));
    if ($user->password == md5($password . $CFG->passwordsaltmain) or $user->password == md5($password) or $user->password == md5($convpassword . $CFG->passwordsaltmain) or $user->password == md5($convpassword)) {
        $validated = true;
    } else {
        for ($i = 1; $i <= 20; $i++) {
            //20 alternative salts should be enough, right?
            $alt = 'passwordsaltalt' . $i;
            if (!empty($CFG->{$alt})) {
                if ($user->password == md5($password . $CFG->{$alt}) or $user->password == md5($convpassword . $CFG->{$alt})) {
                    $validated = true;
                    break;
                }
            }
        }
    }
    if ($validated) {
        // force update of password hash using latest main password salt and encoding if needed
        update_internal_user_password($user, $password);
    }
    return $validated;
}
/**
 * Compare password against hash stored in user object to determine if it is valid.
 *
 * If necessary it also updates the stored hash to the current format.
 *
 * @param stdClass $user (Password property may be updated).
 * @param string $password Plain text password.
 * @return bool True if password is valid.
 */
function validate_internal_user_password($user, $password)
{
    global $CFG;
    require_once $CFG->libdir . '/password_compat/lib/password.php';
    if ($user->password === AUTH_PASSWORD_NOT_CACHED) {
        // Internal password is not used at all, it can not validate.
        return false;
    }
    // If hash isn't a legacy (md5) hash, validate using the library function.
    if (!password_is_legacy_hash($user->password)) {
        return password_verify($password, $user->password);
    }
    // Otherwise we need to check for a legacy (md5) hash instead. If the hash
    // is valid we can then update it to the new algorithm.
    $sitesalt = isset($CFG->passwordsaltmain) ? $CFG->passwordsaltmain : '';
    $validated = false;
    if ($user->password === md5($password . $sitesalt) or $user->password === md5($password) or $user->password === md5(addslashes($password) . $sitesalt) or $user->password === md5(addslashes($password))) {
        // Note: we are intentionally using the addslashes() here because we
        //       need to accept old password hashes of passwords with magic quotes.
        $validated = true;
    } else {
        for ($i = 1; $i <= 20; $i++) {
            // 20 alternative salts should be enough, right?
            $alt = 'passwordsaltalt' . $i;
            if (!empty($CFG->{$alt})) {
                if ($user->password === md5($password . $CFG->{$alt}) or $user->password === md5(addslashes($password) . $CFG->{$alt})) {
                    $validated = true;
                    break;
                }
            }
        }
    }
    if ($validated) {
        // If the password matches the existing md5 hash, update to the
        // current hash algorithm while we have access to the user's password.
        update_internal_user_password($user, $password);
    }
    return $validated;
}
Пример #10
0
 /**
  * Create a Moodle user from Azure AD user data.
  *
  * @param array $aaddata Array of Azure AD user data.
  * @return \stdClass An object representing the created Moodle user.
  */
 public function create_user_from_aaddata($aaddata)
 {
     global $CFG;
     require_once $CFG->dirroot . '/user/profile/lib.php';
     require_once $CFG->dirroot . '/user/lib.php';
     $creationallowed = $this->check_usercreationrestriction($aaddata);
     if ($creationallowed !== true) {
         mtrace('Cannot create user because they do not meet the configured user creation restrictions.');
         return false;
     }
     // Locate country code.
     if (isset($aaddata['country'])) {
         $countries = get_string_manager()->get_list_of_countries();
         foreach ($countries as $code => $name) {
             if ($aaddata['country'] == $name) {
                 $aaddata['country'] = $code;
             }
         }
         if (strlen($aaddata['country']) > 2) {
             // Limit string to 2 chars to prevent sql error.
             $aaddata['country'] = substr($aaddata['country'], 0, 2);
         }
     }
     $newuser = (object) ['auth' => 'oidc', 'username' => trim(\core_text::strtolower($aaddata['userPrincipalName'])), 'lang' => 'en', 'confirmed' => 1, 'timecreated' => time(), 'mnethostid' => $CFG->mnet_localhost_id];
     $newuser = static::apply_configured_fieldmap($aaddata, $newuser, 'create');
     $password = null;
     $newuser->idnumber = $newuser->username;
     if (!empty($newuser->email)) {
         if (email_is_not_allowed($newuser->email)) {
             unset($newuser->email);
         }
     }
     if (empty($newuser->lang) || !get_string_manager()->translation_exists($newuser->lang)) {
         $newuser->lang = $CFG->lang;
     }
     $newuser->timemodified = $newuser->timecreated;
     $newuser->id = user_create_user($newuser, false, false);
     // Save user profile data.
     profile_save_data($newuser);
     $user = get_complete_user_data('id', $newuser->id);
     if (!empty($CFG->{'auth_' . $newuser->auth . '_forcechangepassword'})) {
         set_user_preference('auth_forcepasswordchange', 1, $user);
     }
     // Set the password.
     update_internal_user_password($user, $password);
     // Trigger event.
     \core\event\user_created::create_from_userid($newuser->id)->trigger();
     return $user;
 }
Пример #11
0
 /**
  * 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->assertEquals($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->assertEquals($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));
     }
 }
Пример #12
0
    /**
     * 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));

        $sink = $this->redirectEvents();
        // Update the password.
        update_internal_user_password($user, 'password');
        $events = $sink->get_events();
        $sink->close();
        $event = array_pop($events);

        // Password should have been updated to a bcrypt hash.
        $this->assertFalse(password_is_legacy_hash($user->password));

        // Verify event information.
        $this->assertInstanceOf('\core\event\user_password_updated', $event);
        $this->assertSame($user->id, $event->relateduserid);
        $this->assertEquals(context_user::instance($user->id), $event->get_context());
        $this->assertEventContextNotUsed($event);

        // Verify recovery of property 'auth'.
        unset($user->auth);
        update_internal_user_password($user, 'newpassword');
        $this->assertDebuggingCalled('User record in update_internal_user_password() must include field auth',
                DEBUG_DEVELOPER);
        $this->assertEquals('manual', $user->auth);
    }
function authenticate_application_user($username, $password, $ignorelockout = false, &$failurereason = null)
{
    global $CFG, $DB;
    require_once $CFG->libdir . '/authlib.php';
    if ($user = get_complete_user_data('username', $username, $CFG->mnet_localhost_id)) {
        // We have found the user
    } else {
        if ($email = clean_param($username, PARAM_EMAIL)) {
            $select = "mnethostid = :mnethostid AND LOWER(email) = LOWER(:email) AND deleted = 0";
            $params = array('mnethostid' => $CFG->mnet_localhost_id, 'email' => strtolower($email));
            $users = $DB->get_records_select('user', $select, $params, 'id', 'id', 0, 2);
            if (count($users) === 1) {
                // Use email for login only if unique
                $user = reset($users);
                $user = get_complete_user_data('id', $user->id);
                $username = $user->username;
            }
            unset($users);
        }
    }
    $authsenabled = get_enabled_auth_plugins();
    if ($user) {
        // Use manual if auth not set (or is set to 'email' - we need to accept those even if normally excluded)
        $auth = empty($user->auth) || $user->auth == 'email' ? 'manual' : $user->auth;
        if (!empty($user->suspended)) {
            $failurereason = AUTH_LOGIN_SUSPENDED;
            // Trigger login failed event.
            $event = \core\event\user_login_failed::create(array('userid' => $user->id, 'other' => array('username' => $username, 'reason' => $failurereason)));
            $event->trigger();
            error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Suspended Login:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
            return false;
        }
        if ($auth == 'nologin' or !is_enabled_auth($auth)) {
            // Legacy way to suspend user.
            $failurereason = AUTH_LOGIN_SUSPENDED;
            // Trigger login failed event.
            $event = \core\event\user_login_failed::create(array('userid' => $user->id, 'other' => array('username' => $username, 'reason' => $failurereason)));
            $event->trigger();
            error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Disabled Login:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
            return false;
        }
        $auths = array($auth);
    } else {
        // Check if there's a deleted record (cheaply), this should not happen because we mangle usernames in delete_user().
        if ($DB->get_field('user', 'id', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 1))) {
            $failurereason = AUTH_LOGIN_NOUSER;
            // Trigger login failed event.
            $event = \core\event\user_login_failed::create(array('other' => array('username' => $username, 'reason' => $failurereason)));
            $event->trigger();
            error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Deleted Login:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
            return false;
        }
        // User does not exist.
        $auths = $authsenabled;
        $user = new stdClass();
        $user->id = 0;
    }
    if ($ignorelockout) {
        // Some other mechanism protects against brute force password guessing, for example login form might include reCAPTCHA
        // or this function is called from a SSO script.
    } else {
        if ($user->id) {
            // Verify login lockout after other ways that may prevent user login.
            if (login_is_lockedout($user)) {
                $failurereason = AUTH_LOGIN_LOCKOUT;
                // Trigger login failed event.
                $event = \core\event\user_login_failed::create(array('userid' => $user->id, 'other' => array('username' => $username, 'reason' => $failurereason)));
                $event->trigger();
                error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Login lockout:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
                return false;
            }
        } else {
            // We can not lockout non-existing accounts.
        }
    }
    foreach ($auths as $auth) {
        $authplugin = get_auth_plugin($auth);
        // On auth fail fall through to the next plugin.
        if (!$authplugin->user_login($username, $password)) {
            continue;
        }
        // Successful authentication.
        if ($user->id) {
            // User already exists in database.
            if (empty($user->auth)) {
                // For some reason auth isn't set yet.
                $DB->set_field('user', 'auth', $auth, array('id' => $user->id));
                $user->auth = $auth;
            }
            // If the existing hash is using an out-of-date algorithm (or the legacy md5 algorithm), then we should update to
            // the current hash algorithm while we have access to the user's password.
            update_internal_user_password($user, $password);
            if ($authplugin->is_synchronised_with_external()) {
                // Update user record from external DB.
                $user = update_user_record_by_id($user->id);
            }
        } else {
            // The user is authenticated but user creation may be disabled.
            if (!empty($CFG->authpreventaccountcreation)) {
                $failurereason = AUTH_LOGIN_UNAUTHORISED;
                // Trigger login failed event.
                $event = \core\event\user_login_failed::create(array('other' => array('username' => $username, 'reason' => $failurereason)));
                $event->trigger();
                error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Unknown user, can not create new accounts:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
                return false;
            } else {
                $user = create_user_record($username, $password, $auth);
            }
        }
        $authplugin->sync_roles($user);
        foreach ($authsenabled as $hau) {
            $hauth = get_auth_plugin($hau);
            $hauth->user_authenticated_hook($user, $username, $password);
        }
        if (empty($user->id)) {
            $failurereason = AUTH_LOGIN_NOUSER;
            // Trigger login failed event.
            $event = \core\event\user_login_failed::create(array('other' => array('username' => $username, 'reason' => $failurereason)));
            $event->trigger();
            return false;
        }
        if (!empty($user->suspended)) {
            // Just in case some auth plugin suspended account.
            $failurereason = AUTH_LOGIN_SUSPENDED;
            // Trigger login failed event.
            $event = \core\event\user_login_failed::create(array('userid' => $user->id, 'other' => array('username' => $username, 'reason' => $failurereason)));
            $event->trigger();
            error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Suspended Login:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
            return false;
        }
        login_attempt_valid($user);
        $failurereason = AUTH_LOGIN_OK;
        return $user;
    }
    // Failed if all the plugins have failed.
    if (debugging('', DEBUG_ALL)) {
        error_log('[client ' . getremoteaddr() . "]  {$CFG->wwwroot}  Failed Login:  {$username}  " . $_SERVER['HTTP_USER_AGENT']);
    }
    if ($user->id) {
        login_attempt_failed($user);
        $failurereason = AUTH_LOGIN_FAILED;
        // Trigger login failed event.
        $event = \core\event\user_login_failed::create(array('userid' => $user->id, 'other' => array('username' => $username, 'reason' => $failurereason)));
        $event->trigger();
    } else {
        $failurereason = AUTH_LOGIN_NOUSER;
        // Trigger login failed event.
        $event = \core\event\user_login_failed::create(array('other' => array('username' => $username, 'reason' => $failurereason)));
        $event->trigger();
    }
    return false;
}
Пример #14
0
 /**
  * Resets the user's password
  * @param bool $require If true, then the script will be terminated if the operation fails
  * @return string|bool The new password if successful, or false otherwise (if $require was false).
  */
 function reset_password($require = true)
 {
     // Check that the user is loaded
     if (empty($this->user_data)) {
         if ($require) {
             $this->_session->response->quick_output(-301, 'USER_AUTH', 'User data not loaded', false);
             exit;
         }
         return false;
     }
     // If the user has an email address on file, then we can't reset the password
     if (!empty($this->user_data->email)) {
         if ($require) {
             $this->_session->response->quick_output(-341, 'USER_AUTH', 'User has email address in database. Cannot use Sloodle password reset.', false);
             exit;
         }
         return false;
     }
     // Generate a new random password
     $password = sloodle_random_web_password();
     // Update the user's password data
     if (!update_internal_user_password($this->user_data, $password)) {
         if ($require) {
             $this->_session->response->quick_output(-103, 'SYSTEM', 'Failed to update user password', false);
             exit;
         }
         return false;
     }
     return $password;
 }
Пример #15
0
 /**
  * Updates the user's password.
  *
  * called when the user password is updated.
  *
  * @param  object  $user        User table object  (with system magic quotes)
  * @param  string  $newpassword Plaintext password (with system magic quotes)
  * @return boolean result
  *
  */
 function user_update_password($user, $newpassword)
 {
     global $CFG, $FULLME;
     // Enforce 6 char min google password rules.
     // TODO: fix error where page jumps to some random other page
     // Site Administration > Security > Site policies Dang
     if (strlen($newpassword) < 6) {
         //helpbutton inside of the notice ?
         $sixchar_msg = get_string('sixcharmsg', 'auth_gsaml');
         $link = $FULLME;
         notice($sixchar_msg, $link);
     }
     // TODO: if moodle user is not the same as google user
     //       use the mapping IF we go that route
     // Check and update on the moodle side
     $user = get_complete_user_data('id', $user->id);
     if (!update_internal_user_password($user, $newpassword)) {
         return false;
     }
     // if the user isn't synced or google sync fails
     // moodles password will be the new one but google will still
     // think it is the old one.
     // Basically we need OAuth for the GMail to make this code work
     // smoothly. Since there will no longer be  arequiremnet to keep the google and moodle
     // passwords the same.
     //
     // Assuming the user is synced so that this code has relevants
     // Choices.. if there is an error forgive it and change the moodle code anyway.
     // their gmail block would break but if we used OAuth for it someday it would
     // work anyway.
     //
     // perhaps resync the accounts later?
     //
     // Need to know if user is synced or not?
     //
     //
     //        require_once($CFG->dirroot.'/blocks/gdata/gapps.php');
     //
     //    	// Moodle Password change clears now adjust google account
     //        try {
     //        	$g = new blocks_gdata_gapps();
     //    		$m_user = $g->moodle_get_user($user->id);
     //        	$g_user = $g->gapps_get_user($user->username);
     //        	$g->sync_moodle_user_to_gapps($m_user, $g_user,false);
     //
     //        } catch (blocks_gdata_exception $e) {
     //            // we can now have google and moodle passwords be different and
     //            // Gmail will still work so we can forgive this error
     //        	debugging($e, DEBUG_DEVELOPER);
     //        	return false;
     //        }
     return true;
 }
Пример #16
0
 /**
  * Change a user's password
  *
  * @param  object  $user        User table object
  * @param  string  $newpassword Plaintext password
  *
  * @return bool                  True on success
  */
 function user_update_password($user, $newpassword)
 {
     global $DB;
     if ($this->is_internal()) {
         $puser = $DB->get_record('user', array('id' => $user->id), '*', MUST_EXIST);
         if (update_internal_user_password($puser, $newpassword)) {
             $user->password = $puser->password;
             return true;
         } else {
             return false;
         }
     } else {
         // we should have never been called!
         return false;
     }
 }
Пример #17
0
 /**
  * Sign up a new user ready for confirmation.
  * Password is passed in plaintext.
  *
  * @param object $user new user object (with system magic quotes)
  * @param boolean $notify print notice with link and terminate
  */
 function user_signup($user, $notify = true)
 {
     global $CFG;
     require_once $CFG->dirroot . '/user/profile/lib.php';
     if ($this->user_exists($user->username)) {
         print_error('auth_ldap_user_exists', 'auth');
     }
     $plainslashedpassword = $user->password;
     unset($user->password);
     if (!$this->user_create($user, $plainslashedpassword)) {
         print_error('auth_ldap_create_error', 'auth');
     }
     if (!($user->id = insert_record('user', $user))) {
         print_error('auth_emailnoinsert', 'auth');
     }
     /// Save any custom profile field information
     profile_save_data($user);
     $this->update_user_record($user->username);
     update_internal_user_password($user, $plainslashedpassword);
     $user = get_record('user', 'id', $user->id);
     events_trigger('user_created', $user);
     if (!send_confirmation_email($user)) {
         print_error('auth_emailnoemail', 'auth');
     }
     if ($notify) {
         global $CFG;
         $emailconfirm = get_string('emailconfirm');
         $navlinks = array();
         $navlinks[] = array('name' => $emailconfirm, 'link' => null, 'type' => 'misc');
         $navigation = build_navigation($navlinks);
         print_header($emailconfirm, $emailconfirm, $navigation);
         notice(get_string('emailconfirmsent', '', $user->email), "{$CFG->wwwroot}/index.php");
     } else {
         return true;
     }
 }
Пример #18
0
/**
 * Compare password against hash stored in internal user table.
 * If necessary it also updates the stored hash to new format.
 *
 * @param stdClass $user (password property may be updated)
 * @param string $password plain text password
 * @return bool is password valid?
 */
function validate_internal_user_password($user, $password)
{
    global $CFG;
    if (!isset($CFG->passwordsaltmain)) {
        $CFG->passwordsaltmain = '';
    }
    $validated = false;
    if ($user->password === 'not cached') {
        // internal password is not used at all, it can not validate
    } else {
        if ($user->password === md5($password . $CFG->passwordsaltmain) or $user->password === md5($password) or $user->password === md5(addslashes($password) . $CFG->passwordsaltmain) or $user->password === md5(addslashes($password))) {
            // note: we are intentionally using the addslashes() here because we
            //       need to accept old password hashes of passwords with magic quotes
            $validated = true;
        } else {
            for ($i = 1; $i <= 20; $i++) {
                //20 alternative salts should be enough, right?
                $alt = 'passwordsaltalt' . $i;
                if (!empty($CFG->{$alt})) {
                    if ($user->password === md5($password . $CFG->{$alt}) or $user->password === md5(addslashes($password) . $CFG->{$alt})) {
                        $validated = true;
                        break;
                    }
                }
            }
        }
    }
    if ($validated) {
        // force update of password hash using latest main password salt and encoding if needed
        update_internal_user_password($user, $password);
    }
    return $validated;
}
Пример #19
0
 /**
  * Change a user's password
  *
  * @param  object  $user        User table object
  * @param  string  $newpassword Plaintext password
  *
  * @return bool                  True on success
  */
 function user_update_password($user, $newpassword)
 {
     if ($this->is_internal()) {
         return update_internal_user_password($user, $newpassword);
     } else {
         // we should have never been called!
         return false;
     }
 }
Пример #20
0
 /**
  * Updates the user's password.
  *
  * called when the user password is updated.
  *
  * @param  object  $user        User table object  (with system magic quotes)
  * @param  string  $newpassword Plaintext password (with system magic quotes)
  * @return boolean result
  *
  */
 function user_update_password($user, $newpassword)
 {
     $user = get_complete_user_data('id', $user->id);
     return update_internal_user_password($user, $newpassword);
 }
Пример #21
0
 function create_moodle_only_user($user_data)
 {
     global $CFG, $DB;
     $username = $user_data['username'];
     $username = utf8_decode($username);
     $username = strtolower($username);
     /* Creamos el nuevo usuario de Moodle si no está creado */
     $conditions = array('username' => $username);
     $user = $DB->get_record('user', $conditions);
     if (!$user) {
         $user = create_user_record($username, "", "manual");
     }
     if (array_key_exists('password', $user_data)) {
         $password = utf8_decode($user_data['password']);
     } else {
         $password = '';
     }
     if (array_key_exists('email', $user_data)) {
         $email = utf8_decode($user_data['email']);
     } else {
         $email = '';
     }
     if (array_key_exists('firstname', $user_data)) {
         $firstname = utf8_decode($user_data['firstname']);
     } else {
         $firstname = '';
     }
     if (array_key_exists('lastname', $user_data)) {
         $lastname = utf8_decode($user_data['lastname']);
     } else {
         $lastname = '';
     }
     if (array_key_exists('city', $user_data)) {
         $city = utf8_decode($user_data['city']);
     } else {
         $city = '';
     }
     if (array_key_exists('country', $user_data)) {
         $country = utf8_decode($user_data['country']);
     } else {
         $country = '';
     }
     $conditions = array('id' => $user->id);
     if ($firstname) {
         $DB->set_field('user', 'firstname', $firstname, $conditions);
     }
     if ($lastname) {
         $DB->set_field('user', 'lastname', $lastname, $conditions);
     }
     if ($email) {
         $DB->set_field('user', 'email', $email, $conditions);
     }
     if ($city) {
         $DB->set_field('user', 'city', $city, $conditions);
     }
     if ($country) {
         $DB->set_field('user', 'country', $country, $conditions);
     }
     update_internal_user_password($user, $password);
 }
Пример #22
0
 /**
  * Sign up a new user ready for confirmation.
  * Password is passed in plaintext.
  *
  * @param object $user new user object
  * @param boolean $notify print notice with link and terminate
  * @return boolean success
  */
 function user_signup($user, $notify = true)
 {
     global $CFG, $DB, $PAGE, $OUTPUT;
     require_once $CFG->dirroot . '/user/profile/lib.php';
     require_once $CFG->dirroot . '/user/lib.php';
     if ($this->user_exists($user->username)) {
         print_error('auth_ldap_user_exists', 'auth_ldap');
     }
     $plainslashedpassword = $user->password;
     unset($user->password);
     if (!$this->user_create($user, $plainslashedpassword)) {
         print_error('auth_ldap_create_error', 'auth_ldap');
     }
     $user->id = user_create_user($user, false, false);
     user_add_password_history($user->id, $plainslashedpassword);
     // Save any custom profile field information
     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));
     \core\event\user_created::create_from_userid($user->id)->trigger();
     if (!send_confirmation_email($user)) {
         print_error('noemail', 'auth_ldap');
     }
     if ($notify) {
         $emailconfirm = get_string('emailconfirm');
         $PAGE->set_url('/auth/ldap/auth.php');
         $PAGE->navbar->add($emailconfirm);
         $PAGE->set_title($emailconfirm);
         $PAGE->set_heading($emailconfirm);
         echo $OUTPUT->header();
         notice(get_string('emailconfirmsent', '', $user->email), "{$CFG->wwwroot}/index.php");
     } else {
         return true;
     }
 }
Пример #23
0
 /**
  * Test logging in via LDAP calls a user_loggedin event.
  */
 public function test_ldap_user_loggedin_event()
 {
     global $CFG, $DB, $USER;
     require_once $CFG->dirroot . '/auth/ldap/auth.php';
     $this->resetAfterTest();
     $this->assertFalse(isloggedin());
     $user = $DB->get_record('user', array('username' => 'admin'));
     // Note: we are just going to trigger the function that calls the event,
     // not actually perform a LDAP login, for the sake of sanity.
     $ldap = new auth_plugin_ldap();
     // Set the key for the cache flag we want to set which is used by LDAP.
     set_cache_flag($ldap->pluginconfig . '/ntlmsess', sesskey(), $user->username, AUTH_NTLMTIMEOUT);
     // We are going to need to set the sesskey as the user's password in order for the LDAP log in to work.
     update_internal_user_password($user, sesskey());
     // The function ntlmsso_finish is responsible for triggering the event, so call it directly and catch the event.
     $sink = $this->redirectEvents();
     // We need to supress this function call, or else we will get the message "session_regenerate_id(): Cannot
     // regenerate session id - headers already sent" as the ntlmsso_finish function calls complete_user_login
     @$ldap->ntlmsso_finish();
     $events = $sink->get_events();
     $sink->close();
     // Check that the event is valid.
     $this->assertCount(1, $events);
     $event = reset($events);
     $this->assertInstanceOf('\\core\\event\\user_loggedin', $event);
     $this->assertEquals('user', $event->objecttable);
     $this->assertEquals('2', $event->objectid);
     $this->assertEquals(context_system::instance()->id, $event->contextid);
     $expectedlog = array(SITEID, 'user', 'login', 'view.php?id=' . $USER->id . '&course=' . SITEID, $user->id, 0, $user->id);
     $this->assertEventLegacyLogData($expectedlog, $event);
 }
Пример #24
0
 /**
  * Change a user's password
  *
  * @param  object  $user        User table object  (with system magic quotes)
  * @param  string  $newpassword Plaintext password (with system magic quotes)
  *
  * @return bool                  True on success
  */
 function user_update_password($user, $newpassword)
 {
     global $CFG;
     if ($this->config->passtype === 'internal') {
         return update_internal_user_password($user, $newpassword);
     } else {
         // we should have never been called!
         return false;
     }
 }
Пример #25
0
    /**
     * Sign up a new user ready for confirmation.
     * Password is passed in plaintext.
     *
     * @param object $user new user object
     * @param boolean $notify print notice with link and terminate
     */
    function user_signup($user, $notify=true) {
        global $CFG, $DB, $PAGE, $OUTPUT;

        require_once($CFG->dirroot.'/user/profile/lib.php');

        if ($this->user_exists($user->username)) {
            print_error('auth_ldap_user_exists', 'auth_ldap');
        }

        $plainslashedpassword = $user->password;
        unset($user->password);

        if (! $this->user_create($user, $plainslashedpassword)) {
            print_error('auth_ldap_create_error', 'auth_ldap');
        }

        $user->id = $DB->insert_record('user', $user);

        // Save any custom profile field information
        profile_save_data($user);

        $this->update_user_record($user->username);
        update_internal_user_password($user, $plainslashedpassword);

        $user = $DB->get_record('user', array('id'=>$user->id));
        events_trigger('user_created', $user);

        if (! send_confirmation_email($user)) {
            print_error('noemail', 'auth_ldap');
        }

        if ($notify) {
            $emailconfirm = get_string('emailconfirm');
            $PAGE->set_url('/auth/ldap/auth.php');
            $PAGE->navbar->add($emailconfirm);
            $PAGE->set_title($emailconfirm);
            $PAGE->set_heading($emailconfirm);
            echo $OUTPUT->header();
            notice(get_string('emailconfirmsent', '', $user->email), "{$CFG->wwwroot}/index.php");
        } else {
            return true;
        }
    }
Пример #26
0
 /**
  * Test user_updated event trigger by various apis.
  */
 public function test_user_updated_event()
 {
     global $DB, $CFG;
     $this->resetAfterTest();
     $user = $this->getDataGenerator()->create_user();
     // Set config to allow email_to_user() to be called.
     $CFG->noemailever = false;
     // Update user password.
     $sink = $this->redirectEvents();
     $sink2 = $this->redirectEmails();
     // Make sure we are redirecting emails.
     setnew_password_and_mail($user);
     update_internal_user_password($user, 'randompass');
     $events = $sink->get_events();
     $sink->close();
     $sink2->close();
     // Test updated value.
     $dbuser = $DB->get_record('user', array('id' => $user->id));
     $this->assertSame($user->firstname, $dbuser->firstname);
     $this->assertNotSame('M00dLe@T', $dbuser->password);
     // Test event.
     foreach ($events as $event) {
         $this->assertInstanceOf('\\core\\event\\user_updated', $event);
         $this->assertSame($user->id, $event->objectid);
         $this->assertSame('user_updated', $event->get_legacy_eventname());
         $this->assertEventLegacyData($user, $event);
         $this->assertEquals(context_user::instance($user->id), $event->get_context());
         $expectedlogdata = array(SITEID, 'user', 'update', 'view.php?id=' . $user->id, '');
         $this->assertEventLegacyLogData($expectedlogdata, $event);
     }
 }
Пример #27
0
 /**
  * Change a user's password.
  *
  * @param  stdClass  $user      User table object
  * @param  string  $newpassword Plaintext password
  * @return bool                 True on success
  */
 function user_update_password($user, $newpassword)
 {
     global $DB;
     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;
         } else {
             return false;
         }
     } else {
         // We should have never been called!
         return false;
     }
 }