function adduser_validate(Pieform $form, $values) { global $USER, $TRANSPORTER; $authobj = AuthFactory::create($values['authinstance']); $institution = $authobj->institution; // Institutional admins can only set their own institutions' authinstances if (!$USER->get('admin') && !$USER->is_institutional_admin($authobj->institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } $institution = new Institution($authobj->institution); // Don't exceed max user accounts for the institution if ($institution->isFull()) { $institution->send_admin_institution_is_full_message(); $form->set_error('authinstance', get_string('institutionmaxusersexceeded', 'admin')); return; } $username = $values['username']; $firstname = sanitize_firstname($values['firstname']); $lastname = sanitize_lastname($values['lastname']); $email = sanitize_email($values['email']); $password = $values['password']; if ($USER->get('admin') || get_config_plugin('artefact', 'file', 'institutionaloverride')) { $maxquotaenabled = get_config_plugin('artefact', 'file', 'maxquotaenabled'); $maxquota = get_config_plugin('artefact', 'file', 'maxquota'); if ($maxquotaenabled && $values['quota'] > $maxquota) { $form->set_error('quota', get_string('maxquotaexceededform', 'artefact.file', display_size($maxquota))); } } if (method_exists($authobj, 'is_username_valid_admin')) { if (!$authobj->is_username_valid_admin($username)) { $form->set_error('username', get_string('usernameinvalidadminform', 'auth.internal')); } } else { if (method_exists($authobj, 'is_username_valid')) { if (!$authobj->is_username_valid($username)) { $form->set_error('username', get_string('usernameinvalidform', 'auth.internal')); } } } if (!$form->get_error('username') && record_exists_select('usr', 'LOWER(username) = ?', array(strtolower($username)))) { $form->set_error('username', get_string('usernamealreadytaken', 'auth.internal')); } if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $form->set_error('password', get_string('passwordinvalidform', 'auth.' . $authobj->type)); } if (isset($_POST['createmethod']) && $_POST['createmethod'] == 'leap2a') { $form->set_error('firstname', null); $form->set_error('lastname', null); $form->set_error('email', null); if (!$values['leap2afile'] && ($_FILES['leap2afile']['error'] == UPLOAD_ERR_INI_SIZE || $_FILES['leap2afile']['error'] == UPLOAD_ERR_FORM_SIZE)) { $form->reply(PIEFORM_ERR, array('message' => get_string('uploadedfiletoobig'), 'goto' => '/admin/users/add.php')); $form->set_error('leap2afile', get_string('uploadedfiletoobig')); return; } else { if (!$values['leap2afile']) { $form->set_error('leap2afile', $form->i18n('rule', 'required', 'required')); return; } } if ($values['leap2afile']['type'] == 'application/octet-stream') { require_once 'file.php'; $mimetype = file_mime_type($values['leap2afile']['tmp_name']); } else { $mimetype = trim($values['leap2afile']['type'], '"'); } $date = time(); $niceuser = preg_replace('/[^a-zA-Z0-9_-]/', '-', $values['username']); safe_require('import', 'leap'); $fakeimportrecord = (object) array('data' => array('importfile' => $values['leap2afile']['tmp_name'], 'importfilename' => $values['leap2afile']['name'], 'importid' => $niceuser . '-' . $date, 'mimetype' => $mimetype)); $TRANSPORTER = new LocalImporterTransport($fakeimportrecord); try { $TRANSPORTER->extract_file(); PluginImportLeap::validate_transported_data($TRANSPORTER); } catch (Exception $e) { $form->set_error('leap2afile', $e->getMessage()); } } else { if (!$form->get_error('firstname') && empty($firstname)) { $form->set_error('firstname', $form->i18n('rule', 'required', 'required')); } if (!$form->get_error('lastname') && empty($lastname)) { $form->set_error('lastname', $form->i18n('rule', 'required', 'required')); } if (!$form->get_error('email')) { if (!$form->get_error('email') && empty($email)) { $form->set_error('email', get_string('invalidemailaddress', 'artefact.internal')); } if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email)) { $form->set_error('email', get_string('emailalreadytaken', 'auth.internal')); } } } }
/** * Called when the login form is submitted. Validates the user and password, and * if they are valid, starts a new session for the user. * * @param object $form The Pieform form object * @param array $values The submitted values * @access private */ function login_submit(Pieform $form, $values) { global $SESSION, $USER; $username = trim($values['login_username']); $password = $values['login_password']; $authenticated = false; try { $authenticated = $USER->login($username, $password); if (empty($authenticated)) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // If the user doesn't exist, check for institutions that // want to create users automatically. try { // Reset the LiveUser object, since we are attempting to create a // new user $SESSION->destroy_session(); $USER = new LiveUser(); $authinstances = get_records_sql_array("\n SELECT a.id, a.instancename, a.priority, a.authname, a.institution, i.suspended, i.displayname\n FROM {institution} i JOIN {auth_instance} a ON a.institution = i.name\n WHERE a.authname != 'internal'\n ORDER BY a.institution, a.priority, a.instancename", null); if ($authinstances == false) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } $USER->username = $username; reset($authinstances); while ((list(, $authinstance) = each($authinstances)) && false == $authenticated) { $auth = AuthFactory::create($authinstance->id); if (!$auth->can_auto_create_users()) { continue; } // catch semi-fatal auth errors, but allow next auth instance to be // tried try { if ($auth->authenticate_user_account($USER, $password)) { $authenticated = true; } else { continue; } } catch (AuthInstanceException $e) { continue; } // Check now to see if the institution has its maximum quota of users require_once 'institution.php'; $institution = new Institution($authinstance->institution); if ($institution->isFull()) { $institution->send_admin_institution_is_full_message(); throw new AuthUnknownUserException('Institution has too many users'); } $USER->authinstance = $authinstance->id; $userdata = $auth->get_user_info($username); if (empty($userdata)) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } // Check for a suspended institution if ($authinstance->suspended) { $sitename = get_config('sitename'); throw new AccessTotallyDeniedException(get_string('accesstotallydenied_institutionsuspended', 'mahara', $authinstance->displayname, $sitename)); } // We have the data - create the user $USER->lastlogin = db_format_timestamp(time()); if (isset($userdata->firstname)) { $USER->firstname = sanitize_firstname($userdata->firstname); } if (isset($userdata->lastname)) { $USER->lastname = sanitize_firstname($userdata->lastname); } if (isset($userdata->email)) { $USER->email = sanitize_email($userdata->email); } else { // The user will be asked to populate this when they log in. $USER->email = null; } $profilefields = array(); foreach (array('studentid', 'preferredname') as $pf) { if (isset($userdata->{$pf})) { $sanitize = 'sanitize_' . $pf; if (($USER->{$pf} = $sanitize($userdata->{$pf})) !== '') { $profilefields[$pf] = $USER->{$pf}; } } } try { // If this authinstance is a parent auth for some xmlrpc authinstance, pass it along to create_user // so that this username also gets recorded as the username for sso from the remote sites. $remoteauth = $auth->is_parent_authority(); create_user($USER, $profilefields, $institution, $remoteauth); $USER->reanimate($USER->id, $authinstance->id); } catch (Exception $e) { db_rollback(); throw $e; } } if (!$authenticated) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // We weren't able to authenticate the user for some reason that // probably isn't their fault (e.g. ldap extension not available // when using ldap authentication) log_info($e->getMessage()); $SESSION->add_error_msg(get_string('loginfailed')); return; } } auth_check_admin_section(); // This is also checked in $USER->login(), but it's good to check it again here in case a buggy auth plugin // lets a suspended user through somehow. ensure_user_account_is_active(); // User is allowed to log in //$USER->login($userdata); auth_check_required_fields(); }
/** * Grab a delegate object for auth stuff */ public function request_user_authorise($token, $remotewwwroot) { global $USER, $SESSION; $this->must_be_ready(); $peer = get_peer($remotewwwroot); if ($peer->deleted != 0 || $this->config['theyssoin'] != 1) { throw new XmlrpcClientException('We don\'t accept SSO connections from ' . institution_display_name($peer->institution)); } $client = new Client(); $client->set_method('auth/mnet/auth.php/user_authorise')->add_param($token)->add_param(sha1($_SERVER['HTTP_USER_AGENT']))->send($remotewwwroot); $remoteuser = (object) $client->response; if (empty($remoteuser) or !property_exists($remoteuser, 'username')) { // Caught by land.php throw new AccessDeniedException(); } $create = false; $update = false; if ('1' == $this->config['updateuserinfoonlogin']) { $update = true; } // Retrieve a $user object. If that fails, create a blank one. try { $user = new User(); if (get_config('usersuniquebyusername')) { // When turned on, this setting means that it doesn't matter // which other application the user SSOs from, they will be // given the same account in Mahara. // // This setting is one that has security implications unless // only turned on by people who know what they're doing. In // particular, every system linked to Mahara should be making // sure that same username == same person. This happens for // example if two Moodles are using the same LDAP server for // authentication. // // If this setting is on, it must NOT be possible to self // register on the site for ANY institution - otherwise users // could simply pick usernames of people's accounts they wished // to steal. if ($institutions = get_column('institution', 'name', 'registerallowed', '1')) { log_warn("usersuniquebyusername is turned on but registration is allowed for an institution. " . "No institution can have registration allowed for it, for security reasons.\n" . "The following institutions have registration enabled:\n " . join("\n ", $institutions)); throw new AccessDeniedException(); } if (!get_config('usersallowedmultipleinstitutions')) { log_warn("usersuniquebyusername is turned on but usersallowedmultipleinstitutions is off. " . "This makes no sense, as users will then change institution every time they log in from " . "somewhere else. Please turn this setting on in Site Options"); throw new AccessDeniedException(); } $user->find_by_username($remoteuser->username); } else { $user->find_by_instanceid_username($this->instanceid, $remoteuser->username, true); } if ($user->get('suspendedcusr')) { die_info(get_string('accountsuspended', 'mahara', strftime(get_string('strftimedaydate'), $user->get('suspendedctime')), $user->get('suspendedreason'))); } } catch (AuthUnknownUserException $e) { if (!empty($this->config['weautocreateusers'])) { $institution = new Institution($this->institution); if ($institution->isFull()) { $institution->send_admin_institution_is_full_message(); throw new XmlrpcClientException('SSO attempt from ' . $institution->displayname . ' failed - institution is full'); } $user = new User(); $create = true; } else { log_debug("User authorisation request from {$remotewwwroot} failed - " . "remote user '{$remoteuser->username}' is unknown to us and auto creation of users is turned off"); return false; } } /*******************************************/ if ($create) { $user->passwordchange = 1; $user->active = 1; $user->deleted = 0; //TODO: import institution's expiry?: //$institution = new Institution($peer->institution); $user->expiry = null; $user->expirymailsent = 0; $user->lastlogin = time(); $user->firstname = $remoteuser->firstname; $user->lastname = $remoteuser->lastname; $user->email = $remoteuser->email; $imported = array('firstname', 'lastname', 'email'); //TODO: import institution's per-user-quota?: //$user->quota = $userrecord->quota; $user->authinstance = empty($this->config['parent']) ? $this->instanceid : $this->parent; db_begin(); $user->username = get_new_username($remoteuser->username); $user->id = create_user($user, array(), $this->institution, $this, $remoteuser->username); $locked = $this->import_user_settings($user, $remoteuser); $locked = array_merge($imported, $locked); /* * We need to convert the object to a stdclass with its own * custom method because it uses overloaders in its implementation * and its properties wouldn't be visible to a simple cast operation * like (array)$user */ $userobj = $user->to_stdclass(); $userarray = (array) $userobj; db_commit(); // Now we have fired the create event, we need to re-get the data // for this user $user = new User(); $user->find_by_id($userobj->id); } elseif ($update) { $imported = array('firstname', 'lastname', 'email'); foreach ($imported as $field) { if ($user->{$field} != $remoteuser->{$field}) { $user->{$field} = $remoteuser->{$field}; set_profile_field($user->id, $field, $user->{$field}); } } if (isset($remoteuser->idnumber)) { if ($user->studentid != $remoteuser->idnumber) { $user->studentid = $remoteuser->idnumber; set_profile_field($user->id, 'studentid', $user->studentid); } $imported[] = 'studentid'; } $locked = $this->import_user_settings($user, $remoteuser); $locked = array_merge($imported, $locked); $user->lastlastlogin = $user->lastlogin; $user->lastlogin = time(); //TODO: import institution's per-user-quota?: //$user->quota = $userrecord->quota; $user->commit(); } if (get_config('usersuniquebyusername')) { // Add them to the institution they have SSOed in by $user->join_institution($peer->institution); } // See if we need to create/update a profile Icon image if ($create || $update) { $client->set_method('auth/mnet/auth.php/fetch_user_image')->add_param($remoteuser->username)->send($remotewwwroot); $imageobject = (object) $client->response; $u = preg_replace('/[^A-Za-z0-9 ]/', '', $user->username); $filename = get_config('dataroot') . 'temp/mpi_' . intval($this->instanceid) . '_' . $u; if (array_key_exists('f1', $client->response)) { $imagecontents = base64_decode($client->response['f1']); if (file_put_contents($filename, $imagecontents)) { $imageexists = false; $icons = false; if ($update) { $newchecksum = sha1_file($filename); $icons = get_records_select_array('artefact', 'artefacttype = \'profileicon\' AND owner = ? ', array($user->id), '', 'id'); if (false != $icons) { foreach ($icons as $icon) { $iconfile = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $icon->id % 256 . '/' . $icon->id; $checksum = sha1_file($iconfile); if ($newchecksum == $checksum) { $imageexists = true; unlink($filename); break; } } } } if (false == $imageexists) { $filesize = filesize($filename); if (!$user->quota_allowed($filesize)) { $error = get_string('profileiconuploadexceedsquota', 'artefact.file', get_config('wwwroot')); } require_once 'file.php'; $imagesize = getimagesize($filename); if (!$imagesize || !is_image_type($imagesize[2])) { $error = get_string('filenotimage'); } $mime = $imagesize['mime']; $width = $imagesize[0]; $height = $imagesize[1]; $imagemaxwidth = get_config('imagemaxwidth'); $imagemaxheight = get_config('imagemaxheight'); if ($width > $imagemaxwidth || $height > $imagemaxheight) { $error = get_string('profileiconimagetoobig', 'artefact.file', $width, $height, $imagemaxwidth, $imagemaxheight); } try { $user->quota_add($filesize); } catch (QuotaException $qe) { $error = get_string('profileiconuploadexceedsquota', 'artefact.file', get_config('wwwroot')); } require_once get_config('docroot') . '/artefact/lib.php'; require_once get_config('docroot') . '/artefact/file/lib.php'; // Entry in artefact table $artefact = new ArtefactTypeProfileIcon(); $artefact->set('owner', $user->id); $artefact->set('parent', ArtefactTypeFolder::get_folder_id(get_string('imagesdir', 'artefact.file'), get_string('imagesdirdesc', 'artefact.file'), null, true, $user->id)); $artefact->set('title', ArtefactTypeFileBase::get_new_file_title(get_string('profileicon', 'artefact.file'), (int) $artefact->get('parent'), $user->id)); // unique title $artefact->set('description', get_string('uploadedprofileicon', 'artefact.file')); $artefact->set('note', get_string('profileicon', 'artefact.file')); $artefact->set('size', $filesize); $artefact->set('filetype', $mime); $artefact->set('width', $width); $artefact->set('height', $height); $artefact->commit(); $id = $artefact->get('id'); // Move the file into the correct place. $directory = get_config('dataroot') . 'artefact/file/profileicons/originals/' . $id % 256 . '/'; check_dir_exists($directory); rename($filename, $directory . $id); if ($create || empty($icons)) { $user->profileicon = $id; } } $user->commit(); } else { log_warn(get_string('cantcreatetempprofileiconfile', 'artefact.file', $filename)); } } if ($update) { $locked[] = 'profileicon'; } } /*******************************************/ // We know who our user is now. Bring her back to life. $USER->reanimate($user->id, $this->instanceid); // Set session variables to let the application know this session was // initiated by MNET. Don't forget that users could initiate their // sessions without MNET sometimes, which is why this data is stored in // the session object. $SESSION->set('mnetuser', $user->id); $SESSION->set('authinstance', $this->instanceid); if (isset($_SERVER['HTTP_REFERER'])) { $SESSION->set('mnetuserfrom', $_SERVER['HTTP_REFERER']); } if ($update && isset($locked)) { $SESSION->set('lockedfields', $locked); } return true; }
function edituser_institution_validate(Pieform $form, $values) { $user = new User(); if (!$user->find_by_id($values['id'])) { return false; } global $USER; $userinstitutions = $user->get('institutions'); if (isset($values['add']) && $USER->get('admin') && (empty($userinstitutions) || get_config('usersallowedmultipleinstitutions'))) { // check if the institution is full require_once get_config('docroot') . 'lib/institution.php'; $institution = new Institution($values['addinstitution']); if ($institution->isFull()) { $institution->send_admin_institution_is_full_message(); $form->set_error(null, get_string('institutionmaxusersexceeded', 'admin')); } } }
/** * Grab a delegate object for auth stuff */ public function request_user_authorise($attributes) { global $USER, $SESSION; $this->must_be_ready(); if (empty($attributes) or !array_key_exists($this->config['user_attribute'], $attributes) or !array_key_exists($this->config['institutionattribute'], $attributes)) { throw new AccessDeniedException(); } $remoteuser = $attributes[$this->config['user_attribute']][0]; $firstname = isset($attributes[$this->config['firstnamefield']][0]) ? $attributes[$this->config['firstnamefield']][0] : null; $lastname = isset($attributes[$this->config['surnamefield']][0]) ? $attributes[$this->config['surnamefield']][0] : null; $email = isset($attributes[$this->config['emailfield']][0]) ? $attributes[$this->config['emailfield']][0] : null; $institutionname = $this->institution; $create = false; $update = false; // Retrieve a $user object. If that fails, create a blank one. try { $isremote = $this->config['remoteuser'] ? true : false; $user = new User(); if (get_config('usersuniquebyusername')) { // When turned on, this setting means that it doesn't matter // which other application the user SSOs from, they will be // given the same account in Mahara. // // This setting is one that has security implications unless // only turned on by people who know what they're doing. In // particular, every system linked to Mahara should be making // sure that same username == same person. This happens for // example if two Moodles are using the same LDAP server for // authentication. // // If this setting is on, it must NOT be possible to self // register on the site for ANY institution - otherwise users // could simply pick usernames of people's accounts they wished // to steal. if ($institutions = get_column('institution', 'name', 'registerallowed', '1')) { log_warn("usersuniquebyusername is turned on but registration is allowed for an institution. " . "No institution can have registration allowed for it, for security reasons.\n" . "The following institutions have registration enabled:\n " . join("\n ", $institutions)); throw new AccessDeniedException(); } if (!get_config('usersallowedmultipleinstitutions')) { log_warn("usersuniquebyusername is turned on but usersallowedmultipleinstitutions is off. " . "This makes no sense, as users will then change institution every time they log in from " . "somewhere else. Please turn this setting on in Site Options"); throw new AccessDeniedException(); } } else { if (!$isremote) { log_warn("usersuniquebyusername is turned off but remoteuser has not been set on for this institution: {$institutionname}. " . "This is a security risk as users from different institutions with different IdPs can hijack " . "each others accounts. Fix this in the institution level auth/saml settings."); throw new AccessDeniedException(); } } if ($isremote) { $user->find_by_instanceid_username($this->instanceid, $remoteuser, $isremote); } else { $user->find_by_username($remoteuser); } if ($user->get('suspendedcusr')) { die_info(get_string('accountsuspended', 'mahara', strftime(get_string('strftimedaydate'), $user->get('suspendedctime')), $user->get('suspendedreason'))); } if ('1' == $this->config['updateuserinfoonlogin']) { $update = true; } } catch (AuthUnknownUserException $e) { if (!empty($this->config['weautocreateusers'])) { $institution = new Institution($this->institution); if ($institution->isFull()) { $institution->send_admin_institution_is_full_message(); throw new XmlrpcClientException('SSO attempt from ' . $institution->displayname . ' failed - institution is full'); } $user = new User(); $create = true; } else { log_debug("User authorisation request from SAML failed - " . "remote user '{$remoteuser}' is unknown to us and auto creation of users is turned off"); return false; } } /*******************************************/ if ($create) { $user->passwordchange = 1; $user->active = 1; $user->deleted = 0; $user->expiry = null; $user->expirymailsent = 0; $user->lastlogin = time(); $user->firstname = $firstname; $user->lastname = $lastname; $user->email = $email; // must have these values if (empty($firstname) || empty($lastname) || empty($email)) { throw new AccessDeniedException(get_string('errormissinguserattributes1', 'auth.saml', get_config('sitename'))); } $user->authinstance = empty($this->config['parent']) ? $this->instanceid : $this->parent; db_begin(); $user->username = get_new_username($remoteuser, 40); $user->id = create_user($user, array(), $institutionname, $this, $remoteuser); /* * We need to convert the object to a stdclass with its own * custom method because it uses overloaders in its implementation * and its properties wouldn't be visible to a simple cast operation * like (array)$user */ $userobj = $user->to_stdclass(); $userarray = (array) $userobj; db_commit(); // Now we have fired the create event, we need to re-get the data // for this user $user = new User(); $user->find_by_id($userobj->id); if (get_config('usersuniquebyusername')) { // Add them to the institution they have SSOed in by $user->join_institution($institutionname); } } elseif ($update) { if (!empty($firstname)) { set_profile_field($user->id, 'firstname', $firstname); $user->firstname = $firstname; } if (!empty($lastname)) { set_profile_field($user->id, 'lastname', $lastname); $user->lastname = $lastname; } if (!empty($email)) { set_profile_field($user->id, 'email', $email); $user->email = $email; } $user->lastlastlogin = $user->lastlogin; $user->lastlogin = time(); } $user->commit(); /*******************************************/ // We know who our user is now. Bring em back to life. $result = $USER->reanimate($user->id, $this->instanceid); log_debug("remote user '{$remoteuser}' is now reanimated as '{$USER->username}' "); $SESSION->set('authinstance', $this->instanceid); return true; }
/** * Create a test user * @param array $record * @throws SystemException if creating failed * @return int new user id */ public function create_user($record) { // Data validation // Set default auth method for a new user is 'internal' for 'No institution' if not set if (empty($record['institution']) || empty($record['authname'])) { $record['institution'] = 'mahara'; $record['authname'] = 'internal'; } if (!($auth = get_record('auth_instance', 'institution', $record['institution'], 'authname', $record['authname']))) { throw new SystemException("The authentication method authname" . $record['authname'] . " for institution '" . $record['institution'] . "' does not exist."); } $record['authinstance'] = $auth->id; // Don't exceed max user accounts for the institution $institution = new Institution($record['institution']); if ($institution->isFull()) { throw new SystemException("Can not add new users to the institution '" . $record['institution'] . "' as it is full."); } $record['firstname'] = sanitize_firstname($record['firstname']); $record['lastname'] = sanitize_lastname($record['lastname']); $record['email'] = sanitize_email($record['email']); $authobj = AuthFactory::create($auth->id); if (method_exists($authobj, 'is_username_valid_admin') && !$authobj->is_username_valid_admin($record['username'])) { throw new SystemException("New username'" . $record['username'] . "' is not valid."); } if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($record['username'])) { throw new SystemException("New username'" . $record['username'] . "' is not valid."); } if (record_exists_select('usr', 'LOWER(username) = ?', array(strtolower($record['username'])))) { throw new ErrorException("The username'" . $record['username'] . "' has been taken."); } if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($record['password'])) { throw new ErrorException("The password'" . $record['password'] . "' is not valid."); } if (record_exists('usr', 'email', $record['email']) || record_exists('artefact_internal_profile_email', 'email', $record['email'])) { throw new ErrorException("The email'" . $record['email'] . "' has been taken."); } // Create new user db_begin(); raise_time_limit(180); $user = (object) array('authinstance' => $record['authinstance'], 'username' => $record['username'], 'firstname' => $record['firstname'], 'lastname' => $record['lastname'], 'email' => $record['email'], 'password' => $record['password'], 'passwordchange' => 0); if ($record['institution'] == 'mahara') { if ($record['role'] == 'admin') { $user->admin = 1; } else { if ($record['role'] == 'staff') { $user->staff = 1; } } } $remoteauth = $record['authname'] != 'internal'; if (!isset($record['remoteusername'])) { $record['remoteusername'] = null; } $user->id = create_user($user, array(), $record['institution'], $remoteauth, $record['remoteusername'], $record); if (isset($user->admin) && $user->admin) { require_once 'activity.php'; activity_add_admin_defaults(array($user->id)); } if ($record['institution'] != 'mahara') { if ($record['role'] == 'admin') { set_field('usr_institution', 'admin', 1, 'usr', $user->id, 'institution', $record['institution']); } else { if ($record['role'] == 'staff') { set_field('usr_institution', 'staff', 1, 'usr', $user->id, 'institution', $record['institution']); } } } db_commit(); $this->usercounter++; return $user->id; }
/** * Process an authorization request. * * Operations: * - Auto creates users. * - Sets up user object for linked accounts. * * @param string $oidcuniqid The OIDC unique identifier received. * @param array $tokenparams Received token parameters. * @param \auth_oidc\jwt $idtoken Received id token. * @return bool Success/Failure. */ public function request_user_authorise($oidcuniqid, $tokenparams, $idtoken) { global $USER, $SESSION; $this->must_be_ready(); $username = $oidcuniqid; $email = $idtoken->claim('email'); $firstname = $idtoken->claim('given_name'); $lastname = $idtoken->claim('family_name'); // Office 365 uses "upn". $upn = $idtoken->claim('upn'); if (!empty($upn)) { $username = $upn; $email = $upn; } $create = false; try { $user = new \User(); $user->find_by_instanceid_username($this->instanceid, $username, true); if ($user->get('suspendedcusr')) { die_info(get_string('accountsuspended', 'mahara', strftime(get_string('strftimedaydate'), $user->get('suspendedctime')), $user->get('suspendedreason'))); } } catch (\AuthUnknownUserException $e) { if ($this->can_auto_create_users() === true) { $institution = new \Institution($this->institution); if ($institution->isFull()) { throw new \XmlrpcClientException('OpenID Connect login attempt failed because the institution is full.'); } $user = new \User(); $create = true; } else { return false; } } if ($create === true) { $user->passwordchange = 0; $user->active = 1; $user->deleted = 0; $user->expiry = null; $user->expirymailsent = 0; $user->lastlogin = time(); $user->firstname = $firstname; $user->lastname = $lastname; $user->email = $email; $user->authinstance = $this->instanceid; db_begin(); $user->username = get_new_username($username); $user->id = create_user($user, array(), $this->institution, $this, $username); $userobj = $user->to_stdclass(); $userarray = (array) $userobj; db_commit(); $user = new User(); $user->find_by_id($userobj->id); } $user->commit(); $USER->reanimate($user->id, $this->instanceid); $SESSION->set('authinstance', $this->instanceid); return true; }
function adduser_validate(Pieform $form, $values) { global $USER; $authobj = AuthFactory::create($values['authinstance']); $institution = $authobj->institution; // Institutional admins can only set their own institutions' authinstances if (!$USER->get('admin') && !$USER->is_institutional_admin($authobj->institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } $institution = new Institution($authobj->institution); // Don't exceed max user accounts for the institution if ($institution->isFull()) { $SESSION->add_error_msg(get_string('institutionmaxusersexceeded', 'admin')); redirect('/admin/users/add.php'); } $username = $values['username']; $firstname = $values['firstname']; $lastname = $values['lastname']; $email = $values['email']; $password = $values['password']; if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) { $form->set_error('username', get_string('addusererrorinvalidusername', 'admin')); return; } if (!$form->get_error('username') && record_exists_select('usr', 'LOWER(username) = ?', strtolower($username))) { $form->set_error('username', get_string('usernamealreadytaken', 'auth.internal')); return; } if (!$form->get_error('firstname') && !preg_match('/\\S/', $firstname)) { $form->set_error('firstname', $form->i18n('required')); } if (!$form->get_error('lastname') && !preg_match('/\\S/', $lastname)) { $form->set_error('lastname', $form->i18n('required')); } if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email)) { $form->set_error('email', get_string('emailalreadytaken', 'auth.internal')); } if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $form->set_error('password', get_string('passwordinvalidform', 'auth.' . $authobj->type)); return; } }
/** * Called when the login form is submitted. Validates the user and password, and * if they are valid, starts a new session for the user. * * @param object $form The Pieform form object * @param array $values The submitted values * @access private */ function login_submit(Pieform $form, $values) { global $SESSION, $USER; $username = $values['login_username']; $password = $values['login_password']; $authenticated = false; $oldlastlogin = 0; try { $authenticated = $USER->login($username, $password); if (empty($authenticated)) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // If the user doesn't exist, check for institutions that // want to create users automatically. try { // Reset the LiveUser object, since we are attempting to create a // new user $SESSION->destroy_session(); $USER = new LiveUser(); $authinstances = get_records_sql_array(' SELECT a.id, a.instancename, a.priority, a.authname, a.institution, i.suspended, i.displayname FROM {institution} i JOIN {auth_instance} a ON a.institution = i.name ORDER BY a.institution, a.priority, a.instancename', null); if ($authinstances == false) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } $USER->username = $username; reset($authinstances); while ((list(, $authinstance) = each($authinstances)) && false == $authenticated) { $auth = AuthFactory::create($authinstance->id); if (!$auth->can_auto_create_users()) { continue; } if ($auth->authenticate_user_account($USER, $password)) { $authenticated = true; } else { continue; } // Check now to see if the institution has its maximum quota of users require_once 'institution.php'; $institution = new Institution($authinstance->institution); if ($institution->isFull()) { throw new AuthUnknownUserException('Institution has too many users'); } $USER->authinstance = $authinstance->id; $userdata = $auth->get_user_info($username); if (empty($userdata)) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } // Check for a suspended institution if ($authinstance->suspended) { $sitename = get_config('sitename'); throw new AccessTotallyDeniedException(get_string('accesstotallydenied_institutionsuspended', 'mahara', $authinstance->displayname, $sitename)); } // We have the data - create the user $USER->lastlogin = db_format_timestamp(time()); if (isset($userdata->firstname)) { $USER->firstname = $userdata->firstname; } if (isset($userdata->lastname)) { $USER->lastname = $userdata->lastname; } if (isset($userdata->email)) { $USER->email = $userdata->email; } else { // The user will be asked to populate this when they log in. $USER->email = null; } try { create_user($USER, array(), $institution); $USER->reanimate($USER->id, $authinstance->id); } catch (Exception $e) { db_rollback(); throw $e; } } if (!$authenticated) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // We weren't able to authenticate the user for some reason that // probably isn't their fault (e.g. ldap extension not available // when using ldap authentication) log_info($e->getMessage()); $SESSION->add_error_msg(get_string('loginfailed')); return; } } // Only admins in the admin section! if (!$USER->get('admin') && (defined('ADMIN') || defined('INSTITUTIONALADMIN') && !$USER->is_institutional_admin())) { $SESSION->add_error_msg(get_string('accessforbiddentoadminsection')); redirect(); } // Check if the user's account has been deleted if ($USER->deleted) { $USER->logout(); die_info(get_string('accountdeleted')); } // Check if the user's account has expired if ($USER->expiry > 0 && time() > $USER->expiry) { $USER->logout(); die_info(get_string('accountexpired')); } // Check if the user's account has become inactive $inactivetime = get_config('defaultaccountinactiveexpire'); if ($inactivetime && $oldlastlogin > 0 && $oldlastlogin + $inactivetime < time()) { $USER->logout(); die_info(get_string('accountinactive')); } // Check if the user's account has been suspended if ($USER->suspendedcusr) { $suspendedctime = $USER->suspendedctime; $suspendedreason = $USER->suspendedreason; $USER->logout(); die_info(get_string('accountsuspended', 'mahara', $suspendedctime, $suspendedreason)); } // User is allowed to log in //$USER->login($userdata); auth_check_password_change(); auth_check_required_fields(); }
/** * Called when the login form is submitted. Validates the user and password, and * if they are valid, starts a new session for the user. * * @param object $form The Pieform form object * @param array $values The submitted values * @access private */ function login_submit(Pieform $form, $values) { global $SESSION, $USER; $username = $values['login_username']; $password = $values['login_password']; $authenticated = false; $oldlastlogin = 0; try { $authenticated = $USER->login($username, $password); if (empty($authenticated)) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // If the user doesn't exist, check for institutions that // want to create users automatically. try { // Reset the LiveUser object, since we are attempting to create a // new user $SESSION->destroy_session(); $USER = new LiveUser(); $authinstances = get_records_sql_array(' SELECT a.id, a.instancename, a.priority, a.authname, a.institution, i.suspended, i.displayname FROM {institution} i JOIN {auth_instance} a ON a.institution = i.name ORDER BY a.institution, a.priority, a.instancename', null); if ($authinstances == false) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } $USER->username = $username; reset($authinstances); while ((list(, $authinstance) = each($authinstances)) && false == $authenticated) { $auth = AuthFactory::create($authinstance->id); if (!$auth->can_auto_create_users()) { continue; } // catch semi-fatal auth errors, but allow next auth instance to be // tried try { if ($auth->authenticate_user_account($USER, $password)) { $authenticated = true; } else { continue; } } catch (AuthInstanceException $e) { continue; } // Check now to see if the institution has its maximum quota of users require_once 'institution.php'; $institution = new Institution($authinstance->institution); if ($institution->isFull()) { throw new AuthUnknownUserException('Institution has too many users'); } $USER->authinstance = $authinstance->id; $userdata = $auth->get_user_info($username); if (empty($userdata)) { throw new AuthUnknownUserException("\"{$username}\" is not known"); } // Check for a suspended institution if ($authinstance->suspended) { $sitename = get_config('sitename'); throw new AccessTotallyDeniedException(get_string('accesstotallydenied_institutionsuspended', 'mahara', $authinstance->displayname, $sitename)); } // We have the data - create the user $USER->lastlogin = db_format_timestamp(time()); if (isset($userdata->firstname)) { $USER->firstname = $userdata->firstname; } if (isset($userdata->lastname)) { $USER->lastname = $userdata->lastname; } if (isset($userdata->email)) { $USER->email = $userdata->email; } else { // The user will be asked to populate this when they log in. $USER->email = null; } try { // If this authinstance is a parent auth for some xmlrpc authinstance, pass it along to create_user // so that this username also gets recorded as the username for sso from the remote sites. $remoteauth = count_records('auth_instance_config', 'field', 'parent', 'value', $authinstance->id) ? $authinstance : null; create_user($USER, array(), $institution, $remoteauth); $USER->reanimate($USER->id, $authinstance->id); } catch (Exception $e) { db_rollback(); throw $e; } } if (!$authenticated) { $SESSION->add_error_msg(get_string('loginfailed')); return; } } catch (AuthUnknownUserException $e) { // We weren't able to authenticate the user for some reason that // probably isn't their fault (e.g. ldap extension not available // when using ldap authentication) log_info($e->getMessage()); $SESSION->add_error_msg(get_string('loginfailed')); return; } } // Only admins in the admin section! if (!$USER->get('admin') && (defined('ADMIN') || defined('INSTITUTIONALADMIN') && !$USER->is_institutional_admin())) { $SESSION->add_error_msg(get_string('accessforbiddentoadminsection')); redirect(); } // Check if the user's account has been deleted if ($USER->deleted) { $USER->logout(); die_info(get_string('accountdeleted')); } // Check if the user's account has expired if ($USER->expiry > 0 && time() > $USER->expiry) { $USER->logout(); die_info(get_string('accountexpired')); } // Check if the user's account has become inactive $inactivetime = get_config('defaultaccountinactiveexpire'); if ($inactivetime && $oldlastlogin > 0 && $oldlastlogin + $inactivetime < time()) { $USER->logout(); die_info(get_string('accountinactive')); } // Check if the user's account has been suspended if ($USER->suspendedcusr) { $suspendedctime = strftime(get_string('strftimedaydate'), $USER->suspendedctime); $suspendedreason = $USER->suspendedreason; $USER->logout(); die_info(get_string('accountsuspended', 'mahara', $suspendedctime, $suspendedreason)); } // User is allowed to log in //$USER->login($userdata); auth_check_required_fields(); if (get_config('httpswwwroot') && !defined('JSON')) { // If we are using HTTPS for logins we need to go back to // non-HTTPS URLs. Otherwise, Javascript (and possibly CSS) // breaks. Don't use get_full_script_path(), as it doesn't // work if someone sets httpswwwroot to something like // 'https://x.y.z.w:443/...' (unlikely, but // possible). get_full_script_path() doesn't gives us the // ':443' part and things break horribly. $parts = parse_url(get_config('httpswwwroot')); $httpsrequest = rtrim($parts['path'], '/'); redirect(hsc(substr(get_script_path(), strlen($httpsrequest)))); } }
function adduser_validate(Pieform $form, $values) { global $USER, $TRANSPORTER; $authobj = AuthFactory::create($values['authinstance']); $institution = $authobj->institution; // Institutional admins can only set their own institutions' authinstances if (!$USER->get('admin') && !$USER->is_institutional_admin($authobj->institution)) { $form->set_error('authinstance', get_string('notadminforinstitution', 'admin')); return; } $institution = new Institution($authobj->institution); // Don't exceed max user accounts for the institution if ($institution->isFull()) { $form->set_error('authinstance', get_string('institutionmaxusersexceeded', 'admin')); return; } $username = $values['username']; $firstname = $values['firstname']; $lastname = $values['lastname']; $email = $values['email']; $password = $values['password']; if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) { $form->set_error('username', get_string('usernameinvalidform', 'auth.internal')); } if (!$form->get_error('username') && record_exists_select('usr', 'LOWER(username) = ?', strtolower($username))) { $form->set_error('username', get_string('usernamealreadytaken', 'auth.internal')); } if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) { $form->set_error('password', get_string('passwordinvalidform', 'auth.' . $authobj->type)); } if (isset($_POST['createmethod']) && $_POST['createmethod'] == 'leap2a') { $form->set_error('firstname', null); $form->set_error('lastname', null); $form->set_error('email', null); if (!$values['leap2afile']) { $form->set_error('leap2afile', $form->i18n('rule', 'required', 'required')); return; } if ($values['leap2afile']['type'] == 'application/octet-stream') { require_once 'file.php'; $mimetype = file_mime_type($values['leap2afile']['tmp_name']); } else { $mimetype = $values['leap2afile']['type']; } $date = time(); $niceuser = preg_replace('/[^a-zA-Z0-9_-]/', '-', $values['username']); safe_require('import', 'leap'); $fakeimportrecord = (object) array('data' => array('importfile' => $values['leap2afile']['tmp_name'], 'importfilename' => $values['leap2afile']['name'], 'importid' => $niceuser . '-' . $date, 'mimetype' => $mimetype)); $TRANSPORTER = new LocalImporterTransport($fakeimportrecord); try { $TRANSPORTER->extract_file(); PluginImportLeap::validate_transported_data($TRANSPORTER); } catch (Exception $e) { $form->set_error('leap2afile', $e->getMessage()); } } else { if (!$form->get_error('firstname') && !preg_match('/\\S/', $firstname)) { $form->set_error('firstname', $form->i18n('rule', 'required', 'required')); } if (!$form->get_error('lastname') && !preg_match('/\\S/', $lastname)) { $form->set_error('lastname', $form->i18n('rule', 'required', 'required')); } if (!$form->get_error('email')) { require_once 'phpmailer/class.phpmailer.php'; if (!$form->get_error('email') && !PHPMailer::ValidateAddress($email)) { $form->set_error('email', get_string('invalidemailaddress', 'artefact.internal')); } if (record_exists('usr', 'email', $email) || record_exists('artefact_internal_profile_email', 'email', $email)) { $form->set_error('email', get_string('emailalreadytaken', 'auth.internal')); } } } }