/** * Method is called before user data is stored in the database. * * Changes the password in LDAP if the user changed their password. * * @param array $user Holds the old user data. * @param boolean $isNew True if a new user is stored. * @param array $new Holds the new user data. * * @return boolean Cancels the save if False. * * @since 2.0 */ public function onUserBeforeSave($user, $isNew, $new) { if ($isNew) { // We dont want to deal with new users here return; } // Get username and password to use for authenticating with Ldap $username = JArrayHelper::getValue($user, 'username', false, 'string'); $password = JArrayHelper::getValue($new, 'password_clear', null, 'string'); if (!empty($password)) { $auth = array('authenticate' => SHLdap::AUTH_USER, 'username' => $username, 'password' => $password); try { // We will double check the password for double safety (breaks password reset if on) $authenticate = $this->params->get('authenticate', 0); // Get the user adapter then set the password on it $adapter = SHFactory::getUserAdapter($auth); $adapter->setPassword($password, JArrayHelper::getValue($new, 'current-password', null, 'string'), $authenticate); SHLog::add(JText::sprintf('PLG_LDAP_PASSWORD_INFO_12411', $username), 12411, JLog::INFO, 'ldap'); } catch (Exception $e) { // Log and Error out SHLog::add($e, 12401, JLog::ERROR, 'ldap'); return false; } } }
/** * Deletes the user from LDAP if the deletion in the Joomla database was successful. * * Method is called after user data is deleted from the database. * * @param array $user Holds the user data. * @param boolean $success True if user was successfully deleted from the database. * @param string $msg An error message. * * @return void * * @since 2.0 * @deprecated */ public function onUserAfterDelete($user, $success, $msg) { if ($success) { try { $username = $user['username']; SHLog::add(JText::sprintf('PLG_LDAP_DELETION_DEBUG_12905', $username), 12905, JLog::DEBUG, 'ldap'); // Pick up the user and delete it using the User Adapter $adapter = SHFactory::getUserAdapter($username); $adapter->delete(); SHLog::add(JText::sprintf('PLG_LDAP_DELETION_INFO_12908', $username), 12908, JLog::INFO, 'ldap'); } catch (Exception $e) { SHLog::add($e, 12901, JLog::ERROR, 'ldap'); } } }
/** * Method to test the ldap password against the current ldap password * * @param SimpleXMLElement &$element The SimpleXMLElement object representing the <field /> tag for the form field object. * @param mixed $value The form field value to validate. * @param string $group The field name group control value. This acts as as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * @param JRegistry &$input An optional JRegistry object with the entire data set to validate against the entire form. * @param object &$form The form object for which the field is being tested. * * @return boolean True if the value is valid, false otherwise. * * @since 11.1 * @throws JException on invalid rule. */ public function test(&$element, $value, $group = null, &$input = null, &$form = null) { if ($form instanceof JForm && $form->getValue('id')) { try { // Gets the username from the user id $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select($db->quoteName('username'))->from($db->quoteName('#__users'))->where($db->quoteName('id') . ' = ' . $db->quote((int) $form->getValue('id'))); $db->setQuery($query)->execute(); if ($username = $db->loadResult()) { // Put username and password together for authenticating with Ldap $auth = array('username' => $username, 'password' => $value); // This is a valid username so lets check it against ldap return SHFactory::getUserAdapter($auth)->getId(true) ? true : false; } } catch (Exception $e) { // We ignore the exception for now return false; } } }
/** * Method is called after user data is stored in the database. * * Deletes the user if they're new and Joomla user creation failed. * * @param array $user Holds the new user data. * @param boolean $isNew True if a new user has been stored. * @param boolean $success True if user was successfully stored in the database. * @param string $msg An error message. * * @return void * * @since 2.0 */ public function onUserAfterSave($user, $isNew, $success, $msg) { if ($isNew && !$success && $this->params->get('onfail_delete', false) && $this->username) { try { // Check the session to ensure this user was created successfully last time if (JFactory::getSession()->get('creation', null, 'ldap') == $this->username) { $adapter = SHFactory::getUserAdapter($this->username); $adapter->delete(); SHLog::add(JTest::sprintf('PLG_LDAP_CREATION_INFO_12826', $this->username), 12826, JLog::INFO, 'ldap'); } } catch (Exception $e) { SHLog::add($e, 12803, JLog::ERROR, 'ldap'); } $this->username = null; } }
/** * Method is called after user data is stored in the database. * * @param array $user Holds the new user data. * @param boolean $isNew True if a new user has been stored. * @param boolean $success True if user was successfully stored in the database. * @param string $msg An error message. * * @return void * * @since 2.0 */ public function onUserAfterSave($user, $isNew, $success, $msg) { if ($this->isLdap) { if ($isNew && $success) { // Ensure Joomla knows this is a new Ldap user $adapter = SHFactory::getUserAdapter($user['username']); $options = array('adapter' => &$adapter); $instance = SHUserHelper::getUser($user, $options); // Silently resave the user without calling the onUserSave events SHUserHelper::save($instance, false); } SHLdapHelper::triggerEvent('onUserAfterSave', array($user, $isNew, $success, $msg)); JFactory::getSession()->clear('created', 'ldap'); } }
/** * This method handles the user adapter authorisation and reports * back to the subject. This method is also used for single sign on. * * There is no custom logging in the authentication. * * @param array $response Authentication response object from onUserAuthenticate() * @param array $options Array of extra options * * @return JAuthenticationResponse Authentication response object * * @since 2.0 */ public function onUserAuthorisation($response, $options = array()) { // Create a new authentication response $retResponse = new JAuthenticationResponse(); // Check if some other authentication system is dealing with this request if (!empty($response->type) && strtoupper($response->type) !== self::AUTH_TYPE) { return $retResponse; } // Check the Shmanic platform has been imported if (!$this->_checkPlatform()) { // Failed to import the platform $response->status = JAuthentication::STATUS_FAILURE; $response->error_message = JText::_('PLG_AUTHENTICATION_SHADAPTER_ERR_12601'); return false; } $response->type = self::AUTH_TYPE; /* * Attempt to authorise with User Adapter. This method will automatically detect * the correct configuration (if multiple ones are specified) and return a * SHUserAdapter object. If this method returns false, then the authorise was * unsuccessful - basically the user was not found or configuration was * bad. */ try { // Setup user adapter injecting the domain from SSO if specified $credentials = array('username' => $response->username); if (isset($options['domain'])) { $credentials['domain'] = $options['domain']; } $adapter = SHFactory::getUserAdapter($credentials); // Get the authorising user dn $id = $adapter->getId(false); } catch (Exception $e) { // Configuration or authorisation failure $response->status = JAuthentication::STATUS_FAILURE; $response->error_message = JText::_('JGLOBAL_AUTH_NO_USER'); return; } try { // Let's get the user attributes $attributes = $adapter->getAttributes(); if (!is_array($attributes) || !count($attributes)) { // No attributes therefore error throw new Exception(JText::_('PLG_AUTHENTICATION_SHADAPTER_ERR_12611'), 12611); } } catch (Exception $e) { // Error getting user attributes. $response->status = JAuthentication::STATUS_FAILURE; $response->error_message = JText::_('PLG_AUTHENTICATION_SHADAPTER_ERR_12611'); // Process a error log SHLog::add($e, 12622, JLog::ERROR, 'auth'); return false; } // Set the required Joomla specific user fields with the returned User Adapter Attributes $response->username = $adapter->getUid(); $response->fullname = $adapter->getFullname(); $response->email = $adapter->getEmail(); // The adapter type needs to be set before returning the response $response->type = $adapter->getType(); if (SHFactory::getConfig()->get('user.nullpassword')) { // Do not store password in Joomla database $response->password_clear = ''; } /* * Everything appears to be a success and therefore we shall log the user login * then report back to the subject. */ SHLog::add(JText::sprintf('PLG_AUTHENTICATION_SHADAPTER_INFO_12612', $response->username), 12612, JLog::INFO, 'auth'); $retResponse->status = JAuthentication::STATUS_SUCCESS; unset($adapter); return $retResponse; }
/** * Stage the profile to LDAP ready for committing. * * @param SimpleXMLElement $xml The XML profile to process. * @param string $username Username of profile owner to change. * @param array $profile Array of profile fields to save (key=>value). * * @return boolean True on success * * @since 2.0 * @throws Exception */ protected function saveProfileToLdap($xml, $username, $profile = array()) { // Setup the profile user in user adapter $adapter = SHFactory::getUserAdapter($username); $processed = array(); // Loop around each profile field foreach ($profile as $key => $value) { $delimiter = null; $xmlField = $xml->xpath("fieldset/field[@name='$key']"); if ($delimiter = (string) $xmlField[0]['delimiter']) { /* Multiple values - we will use a delimiter to represent * the extra data in Joomla. We also use a newline override * as this is probably going to be the most popular delimter. */ if (strToUpper($delimiter) == 'NEWLINE') { $delimiter = '\r\n|\r|\n'; } // Split up the delimited profile field $newValues = preg_split("/$delimiter/", $value); // Resave the split profile field into a new array set for ($i = 0; $i < count($newValues); ++$i) { $processed[$key][$i] = $newValues[$i]; } } else { // Single Value $processed[$key] = $value; } } if (count($processed)) { // Lets save the new (current) fields to the LDAP DN $adapter->setAttributes($processed); } return true; }
/** * Called during a ldap synchronisation. * * Checks to ensure that required variables are set before calling the main * do mapping library routine. * * @param JUser &$instance A JUser object for the authenticating user. * @param array $options Array holding options. * * @return boolean True on success * * @since 2.0 */ public function onLdapSync(&$instance, $options = array()) { if (!$this->doSetup()) { return; } try { // Gather the user adapter $username = $instance->username; $adapter = SHFactory::getUserAdapter($username); // Get the distinguished name of the user $dn = $adapter->getId(false); /* * Process the ldap attributes created from the source ldap * user into mapping entries, then evaulate which groups * are of interest when compared to the parameter list. */ $attribute = $this->lookup_type === self::LOOKUP_FORWARD ? $this->memberof_attribute : $this->member_attribute; $attributes = $adapter->getAttributes($attribute); $userGroups = JArrayHelper::getValue($attributes, $attribute); if (!(is_array($userGroups) && count($userGroups))) { // No groups to process SHLog::add(JText::sprintf('PLG_LDAP_MAPPING_DEBUG_12008', $username), 12008, JLog::DEBUG, 'ldap'); return; } $ldapUser = new SHLdapMappingEntry($dn, $userGroups, $this->dn_validate); // Do the actual compare $mapList = SHLdapMappingEntry::compareGroups($this->entries, $ldapUser); $changes = false; // Check if add groups are allowed if ($this->addition) { /* * Find the groups that require adding then add them to the JUser * instance. Any errors will results in the entire method failing. */ $toAdd = self::getGroupsToAdd($instance, $mapList); foreach ($toAdd as $group) { SHLog::add(JText::sprintf('PLG_LDAP_MAPPING_DEBUG_12011', $group, $username), 12011, JLog::DEBUG, 'ldap'); SHUserHelper::addUserToGroup($instance, $group); $changes = true; } } // Check if removal of groups are allowed if ($this->removal !== self::NO) { /* * Find the groups that require removing then remove them from the * JUser instance. */ $toRemove = self::getGroupsToRemove($instance, $mapList, $this->managed); foreach ($toRemove as $group) { SHLog::add(JText::sprintf('PLG_LDAP_MAPPING_DEBUG_12013', $group, $username), 12013, JLog::DEBUG, 'ldap'); SHUserHelper::removeUserFromGroup($instance, $group); $changes = true; } } /* If we have no groups left in our user then we must add * the public group otherwise Joomla won't save the changes * to the database. */ if (!count($instance->get('groups'))) { SHUserHelper::addUserToGroup($instance, $this->public_id); $changes = true; } if ($changes) { return true; } return; } catch (Exception $e) { SHLog::add($e, 12021, JLog::ERROR, 'ldap'); return false; } }
/** * Method is called after user data is stored in the database. * * @param array $user Holds the new user data. * @param boolean $isNew True if a new user has been stored. * @param boolean $success True if user was successfully stored in the database. * @param string $msg An error message. * * @return void * * @since 2.0 */ public function onUserAfterSave($user, $isNew, $success, $msg) { $adapter = SHFactory::getUserAdapter($user['username']); $adapterName = $adapter::getName(); if ($isNew && $success && $adapter->state === $adapter::STATE_CREATED) { // Ensure Joomla knows this is a new adapter user $options = array('adapter' => &$adapter); $instance = SHUserHelper::getUser($user, $options); // Silently resave the user without calling the onUserSave events SHUserHelper::save($instance, false); // Update the user map linker SHAdapterMap::setUser($adapter, $instance->id); SHAdapterEventHelper::triggerEvent($adapterName, 'onUserAfterSave', array($user, $isNew, $success, $msg)); } elseif ($adapter->state !== $adapter::STATE_UNKNOWN) { SHAdapterEventHelper::triggerEvent($adapterName, 'onUserAfterSave', array($user, $isNew, $success, $msg)); } }