/** * 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); }
/** * 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); }
/** * 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); } }
/** * 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); }
/** * 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); } } }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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)); } }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; } }
/** * 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; } }
/** * 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; }
/** * 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; } }
/** * 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); }
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); }
/** * 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; } }
/** * 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); }
/** * 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; } }
/** * 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; } }
/** * 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); } }
/** * 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; } }