/** * Commits the changes to the adapter and parses the result. * If any errors occurred then optionally log them and throw an exception. * * @param SHAdapter $adapter Adapter. * @param boolean $log Log any errors directly to SHLog. * @param boolean $throw Throws an exception on error OR return array on error. * * @return true|SHAdapterResponseCommits * * @since 2.1 */ public static function commitChanges($adapter, $log = false, $throw = true) { $results = $adapter->commitChanges(); $adapterName = $adapter->getName(); if ($log) { // Lets log all the commits foreach ($results->getCommits() as $commit) { if ($commit->status === JLog::INFO) { SHLog::addAdapter($adapter, $commit->getSummary(), 10634, JLog::INFO); } else { SHLog::addAdapter($adapter, $commit->getSummary(), 10636, JLog::ERROR); SHLog::add($commit->exception, 10637, JLog::ERROR, $adapterName); } } } // Check if any of the commits failed if (!$results->status) { if ($throw) { throw new RuntimeException(JText::_('LIB_SHADAPTERHELPER_ERR_10638'), 10638); } else { return $results; } } return true; }
/** * 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'); } } }
/** * Initialises and imports the Shmanic platform and project libraries. * This is fired on application initialise typically by the CMS. * * @return void * * @since 2.0 */ public function onAfterInitialise() { // Check if the Shmanic platform has already been imported if (!defined('SHPATH_PLATFORM')) { $platform = JPATH_PLATFORM . '/shmanic/import.php'; if (!file_exists($platform)) { // Failed to find the import file return false; } // Shmanic Platform import if (!(include_once $platform)) { // Failed to import the Shmanic platform return false; } } // Import the logging method SHLog::import($this->params->get('log_group', 'shlog')); // Container to store project specific import results $results = array(); // Use the default SQL configuration $config = SHFactory::getConfig(); // Get all the importable projects if ($imports = json_decode($config->get('platform.import'))) { foreach ($imports as $project) { // Attempts to import the specified project $results[] = shImport(trim($project)); } } // Fire the onAfterInitialise for all the registered imports/projects JDispatcher::getInstance()->trigger('onSHPlaformInitialise'); if (in_array(false, $results, true)) { // One of the specific projects failed to import return false; } // Everything imported successfully return true; }
/** * 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 handles login logic and report back to the subject. * * @param array $user Holds the user data. * @param array $options Extra options such as autoregister. * * @return boolean Cancels login on False. * * @since 2.0 */ public function onUserLogin($user, $options = array()) { // Check if we have a user adapter already established for this user if (!isset(SHFactory::$adapters[strtolower($user['username'])])) { // SHAdapter did not log this in, get out now return; } // Get the processed user adapter directly from the static adapter holder $adapter = SHFactory::$adapters[strtolower($user['username'])]; if (!(isset($user['type']) && $adapter::getType($user['type']) && $adapter::getType('LDAP'))) { // Incorrect authentication type for this adapter OR is not compatible with LDAP return; } // Lets pass the getUser method the adapter so it can get extra values $options['adapter'] = $adapter; try { // Get a handle to the Joomla User object ready to be passed to the individual plugins $instance = SHUserHelper::getUser($user, $options); } catch (Exception $e) { // Failed to get the user either due to save error or autoregister SHLog::add($e, 10991, JLog::ERROR, 'ldap'); return false; } // Fire the ldap specific on login events $result = SHLdapHelper::triggerEvent('onUserLogin', array(&$instance, $options)); if ($result === false) { // Due to Joomla's inbuilt User Plugin, we have to raise an exception to abort login throw new RuntimeException(JText::sprintf('LIB_SHLDAPEVENTBOUNCER_ERR_10999', $user['username']), 10999); } // Check if any changes were made that need to be saved if ($result === true || isset($options['change'])) { SHLog::add(JText::sprintf('LIB_SHLDAPEVENTBOUNCER_DEBUG_10984', $user['username']), 10984, JLog::DEBUG, 'ldap'); try { // Save the user back to the Joomla database if (!SHUserHelper::save($instance)) { SHLog::add(JText::sprintf('LIB_SHLDAPEVENTBOUNCER_ERR_10988', $user['username']), 10988, JLog::ERROR, 'ldap'); } } catch (Exception $e) { SHLog::add($e, 10989, JLog::ERROR, 'ldap'); } } // Allow Ldap events to be called $this->isLdap = true; return true; }
/** * 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; }
/** * Save the users profile to the database. * * @param integer $userId Joomla user ID to save. * @param string $username Joomla username to save. * @param SHUserAdapter $adapter User adapter of LDAP user. * @param array $options An optional set of options. * * @return boolean True on success * * @since 2.0 */ protected function saveProfile($userId, $username, $adapter, $options = array()) { $xml = $this->getXMLFields($adapter->getDomain()); SHLog::add(JText::sprintf('PLG_LDAP_PROFILE_DEBUG_12221', $username), 12221, JLog::DEBUG, 'ldap'); $addRecords = array(); $updateRecords = array(); $deleteRecords = array(); $db = JFactory::getDBO(); $query = $db->getQuery(true); // Lets get a list of current SQL entries if (is_null($current = $this->queryProfile($userId, true))) { return false; } /* We want to process each attribute in the XML * then find out if it exists in the LDAP directory. * If it does, then we compare that to the value * currently in the SQL database. */ $attributes = $this->getAttributes($xml); foreach ($attributes as $attribute) { // Lets check for a delimiter (this is the indicator that multiple values are supported) $delimiter = null; $xmlField = $xml->xpath("fieldset/field[@name='$attribute']"); $value = null; if ($delimiter = (string) $xmlField[0]['delimiter']) { // These are potentially multiple values if (strToUpper($delimiter) == 'NEWLINE') { $delimiter = "\n"; } $value = ''; if ($v = $adapter->getAttributes($attribute)) { if (is_array($v[$attribute])) { foreach ($v[$attribute] as $values) { $value .= $values . $delimiter; } } } } else { // These are single values if ($v = $adapter->getAttributes($attribute)) { if (isset($v[$attribute][0])) { $value = $v[$attribute][0]; } } } // Get the action status required against the SQL table $status = $this->checkSqlField($current, $attribute, $value); switch ($status) { case 1: $updateRecords[$attribute] = $value; break; case 2: $addRecords[$attribute] = $value; break; case 3: $deleteRecords[] = $attribute; break; } } /* Lets commit these differences to the database * in steps (delete, add, update) and return the * result. */ $results = array(); if (count($deleteRecords)) { $results[] = $this->deleteRecords($userId, $deleteRecords); } if (count($addRecords)) { $results[] = $this->addRecords($userId, $addRecords, count($current) + 1); } if (count($updateRecords)) { $results[] = $this->updateRecords($userId, $updateRecords); } $return = (!in_array(false, $results, true)); if (count($results)) { // Changes occurred so lets log it SHLog::add( JText::sprintf( 'PLG_LDAP_PROFILE_DEBUG_12225', $username, $return == 1 ? JText::_('PLG_LDAP_PROFILE_SUCCESS') : JText::_('PLG_LDAP_PROFILE_FAIL') ), 12225, JLog::DEBUG, 'ldap' ); if (!$return) { // There was an error return false; } // Everything went well - we have updated both LDAP and the J! database. SHLog::add(JText::sprintf('PLG_LDAP_PROFILE_INFO_12224', $username), 12224, JLog::INFO, 'ldap'); // Return this was successful and something was updated return true; } else { // No changes occurred so log that the profile was up to date SHLog::add( JText::sprintf('PLG_LDAP_PROFILE_DEBUG_12226', $username), 12226, JLog::DEBUG, 'ldap' ); return; } }
/** * Inform any listening loggers of the debug message and add to debug stack. * * @param string $message String to push to stack * * @return void * * @since 2.0 */ public function addDebug($message) { // Add the debug message to any listening loggers SHLog::add($message, 101, JLog::DEBUG, 'ldap'); $this->debug[] = $message; }
/** * Attempts to login a user via Single Sign On. * Only if a username is detected can a login been attempted. * * @param array $detection Optional SSO user. * @param array $options An optional array of options to override config settings. * * @return boolean True on successful login or False on fail. * * @since 1.0 * @throws RuntimeException */ public function login($detection = null, $options = array()) { $config = SHFactory::getConfig(); // Get the SSO username and optional details from the plug-ins if (is_null($detection)) { $detection = $this->detect(); } if (!$detection) { return false; } SHLog::add(JText::sprintf('LIB_SHSSO_DEBUG_15066', $detection['username'], $detection['sso']), 15066, JLog::DEBUG, 'sso'); // Set the action if its currently unset if (!isset($options['action'])) { $options['action'] = JFactory::getApplication()->isAdmin() ? 'core.login.admin' : 'core.login.site'; } // Set the autoregister if its currently unset if (!isset($options['autoregister'])) { $options['autoregister'] = $config->get('sso.autoregister', false); } // Set the doauthorise if its currently unset if (!isset($options['doauthorise'])) { $options['doauthorise'] = $config->get('sso.doauthorise', self::AUTHORISE_INHERIT); } $username = $detection['username']; // Check if do authorised is based on the plug-in if ((int) $options['doauthorise'] === self::AUTHORISE_INHERIT) { if (isset($detection['doauthorise'])) { // Set the do authorised to the plug-in option $options['doauthorise'] = (bool) $detection['doauthorise'] ? self::AUTHORISE_TRUE : self::AUTHORISE_FALSE; } else { // Default the doauthorise to true $options['doauthorise'] = self::AUTHORISE_TRUE; } } // Check for a domain if (isset($detection['domain'])) { $options['domain'] = $detection['domain']; } // Check for any extra user attributes gathered from SSO if (isset($detection['attributes'])) { $options['attributes'] = $detection['attributes']; } /* * Authorising will call on onUserAuthorise() to attempt * to authorise the detected SSO user. If this * is disabled, then it will attempt to authorise with the * Joomla database. If autoregister is turned on then * it'll attempt to create the user in the Joomla database. */ if ($options['doauthorise'] !== self::AUTHORISE_FALSE) { // Do authentication plug-in authorisation $response = $this->authorise($username, $options); } else { // Do Joomla database authorisation $response = $this->jAuthorise($username, $options); } // Check the response status for invalid status' if (!(JAuthentication::STATUS_SUCCESS + JAuthentication::STATUS_UNKNOWN & $response->status)) { // We can only process success and unknown status' throw new RuntimeException(JText::sprintf('LIB_SHSSO_ERR_15072', $username), 15072); } elseif ($response->status === JAuthentication::STATUS_UNKNOWN && !$options['autoregister']) { // The user is unknown and there is no autoregister - fail. throw new RuntimeException(JText::sprintf('LIB_SHSSO_ERR_15074', $username), 15074); } elseif (empty($response->email)) { // There is not email set for this user - fail. throw new RuntimeException(JText::sprintf('LIB_SHSSO_ERR_15076', $username), 15076); } /* * Username has been authorised. We can now proceed with the * standard Joomla log-on by calling the onUserLogin event. */ $options[SHSsoHelper::SESSION_PLUGIN_KEY] = $detection['sso']; JPluginHelper::importPlugin('user'); $results = JFactory::getApplication()->triggerEvent('onUserLogin', array((array) $response, $options)); // Save the SSO plug-in name for logout later $session = JFactory::getSession(); $session->set(SHSsoHelper::SESSION_PLUGIN_KEY, $detection['sso']); // Check if any of the events failed if (in_array(false, $results, true)) { throw new RuntimeException(JText::sprintf('LIB_SHSSO_ERR_15078', $username), 15078); } SHLog::add(JText::sprintf('LIB_SHSSO_INFO_15079', $username), 15079, JLog::INFO, 'sso'); // Do a check if URL redirect is required SHSsoHelper::redirect(); // Everything successful - user should be logged on. return true; }
/** * Gets the IP address of the client machine, translates it to a compatiable * eDirectory netadress and queries it against the LDAP server using a filter. * * @return mixed Username of detected user or False. * * @since 1.0 */ public function detectRemoteUser() { // Import languages for frontend errors $this->loadLanguage(); /* * When legacy flag is true, it ensures compatibility with JSSOMySite 1.x by * only returning a string username or false can be returned. This also means * keeping compatibility with Joomla 1.6. * When it is set to False, it can return an array and compatible with Joomla 2.5. */ $legacy = $this->params->get('use_legacy', false); if ($legacy) { // Use legacy way of getting paramters $authParams = new JRegistry(); $authName = $this->params->get('auth_plugin', 'jmapmyldap'); $authPlugin = JPluginHelper::getPlugin('authentication', $authName); $authParams->loadString($authPlugin->params); $ldapUid = $authParams->get('ldap_uid', 'uid'); // Attempt to load up a LDAP instance using the legacy method jimport('shmanic.jldap2'); $ldap = new JLDAP2($authParams); // Lets try to bind using proxy user if (!$ldap->connect() || !$ldap->bind($ldap->connect_username, $ldap->connect_password)) { JError::raiseWarning('SOME_ERROR_CODE', JText::_('PLG_EDIR_ERROR_LDAP_BIND')); return; } // Get IP of client machine $myip = JRequest::getVar('REMOTE_ADDR', 0, 'server'); // Convert this to some net address thing that edir likes $na = JLDAPHelper::ipToNetAddress($myip); // Find the network address and return the uid for it $filter = "(networkAddress={$na})"; $dn = $authParams->get('base_dn'); // Do the LDAP filter search now $result = new JLDAPResult($ldap->search($dn, $filter, array($ldapUid))); $ldap->close(); } else { try { // We will only check the first LDAP config $ldap = SHLdap::getInstance(); $ldap->proxyBind(); $ldapUid = $ldap->getUid; // Get the IP address of this client and convert to netaddress for LDAP searching $input = new JInput($_SERVER); $myIp = $input->get('REMOTE_ADDR', false, 'string'); $na = SHLdapHelper::ipToNetAddress($myIp); $result = $ldap->search(null, "(networkAddress={$na})", array($ldapUid)); } catch (Exception $e) { SHLog::add($e, 16010, JLog::ERROR, 'sso'); return; } } if ($value = $result->getValue(0, $ldapuid, 0)) { // Username was found logged in on this client machine return $value; } }
/** * Method to initialise all the properties based on the parameters * specified in the plugin. * * @return boolean True on valid entries in the mapping list. * * @since 2.0 */ protected function doSetup() { static $done = null; if (is_null($done)) { // Assign class properties based on parameters from the plugin $this->sync_groups = (bool) $this->params->get('sync_groups', false); $this->addition = (bool) $this->params->get('addition', true); $this->removal = (int) $this->params->get('removal', self::YESDEFAULT); $this->unmanaged = array_map('intval', explode(';', $this->params->get('unmanaged'))); $this->public_id = (int) $this->params->get('public_id'); $this->dn_validate = $this->params->get('dn_validate', 1); $this->lookup_type = (int) $this->params->get('lookup_type', self::LOOKUP_FORWARD); $this->memberof_attribute = $this->params->get('memberof_attribute'); $this->member_attribute = $this->params->get('member_attribute', 'member'); $this->member_dn = $this->params->get('member_dn', 'dn'); $this->recursion = (bool) $this->params->get('recursion', false); $this->dn_attribute = $this->params->get('dn_attribute', 'distinguishedName'); $this->recursion_depth = (int) $this->params->get('recursion_depth', 0); $this->entries = array(); $this->list = array(); $list = preg_split('/\\r\\n|\\n|\\r/', $this->params->get('list')); // Loops around each mapping entry parameter foreach ($list as $item) { // Remove any accidental whitespace from the entry $item = trim($item); // Find the right most (outside of the distinguished name) to split groups if ($pos = strrpos($item, ':')) { // Store distinguished name in a string and Joomla groups in an array $entryDn = trim(substr($item, 0, $pos)); if ($entryGroups = array_map('intval', explode(',', substr($item, $pos + 1)))) { // Store as a parameter for validation later $this->list[$entryDn] = $entryGroups; } } } // Get all the Joomla user groups $JUserGroups = SHUserHelper::getJUserGroups(); $JUserGroupsKey = array_fill_keys($JUserGroups, ''); /* * Process the map list parameter into validated entries. * Then ensure that there is atleast 1 valid entry to * proceed with the mapping process. */ foreach ($this->list as $dn => $groups) { foreach ($groups as $key => $group) { if (!isset($JUserGroupsKey[$group])) { // This isn't a valid Joomla group unset($this->list[$dn][$key]); continue; } } if (empty($this->list[$dn])) { // This DN doesn't have any valid Joomla groups unset($this->list[$dn]); continue; } /* * Add the entry to a new mapping entry object then check if it is * valid. If so then we can assume this entry has no syntax errors. */ $entry = new SHLdapMappingEntry($dn, $this->list[$dn], $this->dn_validate); if ($entry->isValid()) { // Add as a valid entry $this->entries[] = $entry; // Add as a managed group if ($this->removal === self::YES) { /* * Yes means we want to add only groups that are defined in the mapping list. * Looping around dn group parameter list, ensuring its not already there and not in unmanaged. */ $this->managed = array_merge($this->managed, array_diff(array_diff($this->list[$dn], $this->unmanaged), $this->managed)); } } } if ($this->removal === self::YESDEFAULT) { // Yesdefault means we want to add all Joomla groups to the managed pool $this->managed = array_diff($JUserGroups, $this->unmanaged); } $done = true; if (!count($this->entries)) { // No valid entries here SHLog::add(JText::_('PLG_LDAP_MAPPING_DEBUG_12006'), 12006, JLog::DEBUG, 'ldap'); $done = false; } } return $done; }
/** * Method for attempting single sign on. * * @return boolean True on successful SSO or False on failure. * * @since 2.0 */ protected function _attemptSSO() { // Check the required SSO libraries exist if (!(class_exists('SHSsoHelper') && class_exists('SHSso'))) { // Error: classes missing SHLog::add(JText::_('LIB_SHSSOMONITOR_ERR_15001'), 15001, JLog::ERROR, 'sso'); return; } try { $config = SHFactory::getConfig(); // Check if SSO is disabled via the session if (SHSsoHelper::status() !== SHSsoHelper::STATUS_ENABLE) { // It is disabled so do not continue return; } SHSsoHelper::enable(); $forceLogin = false; $userId = JFactory::getUser()->get('id'); if ($config->get('sso.forcelogin', false)) { if ($userId) { // Log out current user if detect user is not equal $forceLogin = true; } } else { if ($userId) { // User already logged in and no forcelogout return; } } /* * Lets check the IP rule is valid before we continue - * if the IP rule is false then SSO is not allowed here. */ jimport('joomla.application.input'); $input = new JInput($_SERVER); // Get the IP address of this client $myIp = $input->get('REMOTE_ADDR', false, 'string'); // Get a list of the IP addresses specific to the specified rule $ipList = json_decode($config->get('sso.iplist')); // Get the rule value $ipRule = $config->get('sso.iprule', SHSsoHelper::RULE_ALLOW_ALL); if (!SHSsoHelper::doIPCheck($myIp, $ipList, $ipRule)) { if (!$forceLogin) { // This IP isn't allowed SHLog::add(JText::_('LIB_SHSSO_DEBUG_15004'), 15004, JLog::DEBUG, 'sso'); } return; } /* * We are going to check if we are in backend. * If so then we need to check if sso is allowed * to execute on the backend. */ if (JFactory::getApplication()->isAdmin()) { if (!$config->get('sso.backend', false)) { if (!$forceLogin) { // Not allowed to SSO on backend SHLog::add(JText::_('LIB_SHSSO_DEBUG_15006'), 15006, JLog::DEBUG, 'sso'); } return; } } // Instantiate the main SSO library for detection & authentication $sso = new SHSso($config->get('sso.plugintype', 'sso')); $detection = $sso->detect(); if ($detection) { // Check the detected user is not blacklisted $blacklist = (array) json_decode($config->get('user.blacklist')); if (in_array($detection['username'], $blacklist)) { SHLog::add(JText::sprintf('LIB_SHSSO_DEBUG_15007', $detection['username']), 15007, JLog::DEBUG, 'sso'); // Detected user is blacklisted return; } // Check if the current logged in user matches the detection if ($forceLogin && strtolower($detection['username']) != strtolower(JFactory::getUser()->get('username'))) { SHLog::add(JText::sprintf('LIB_SHSSO_DEBUG_15008', $detection['username']), 15008, JLog::DEBUG, 'sso'); // Need to logout the current user JFactory::getApplication()->logout(); } } // Attempt the login return $sso->login($detection); } catch (Exception $e) { SHLog::add($e, 15002, JLog::ERROR, 'sso'); } }
public function onUserBeforeSaveGroup($form, $table, $isNew) { $groupname = $table->title; try { // We want to check if this group is an existing group in an Adapter $adapter = SHFactory::getGroupAdapter($groupname); $adapter->getId(); // We need to gather the adapter name to call the correct dispatcher $adapterName = $adapter::getName(); } catch (Exception $e) { // We will assume this group doesnt exist in an Adapter $adapterName = false; } if ($adapterName) { $event = SHAdapterEventHelper::triggerEvent($adapterName, 'onGroupBeforeSave', array($groupname, $isNew)); if ($event !== false) { try { // Commit the changes to the Adapter if present SHAdapterHelper::commitChanges($adapter, true, true); //TODO: newId SHLog::add(JText::sprintf('LIB_SHADAPTEREVENTBOUNCER_DEBUG_10986', $groupname), 10986, JLog::DEBUG, $adapterName); return true; } catch (Excpetion $e) { //TODO: newId SHLog::add($e, 10981, JLog::ERROR, $adapterName); } } return $event; } elseif ($isNew) { // Use a default group adapter $name = SHFactory::getConfig()->get('user.type'); // We must create and save the group as plugins may talk to adapter driver and expect a group object if (SHAdapterEventHelper::triggerEvent($name, 'onGroupCreation', array($groupname)) === true) { JFactory::getSession()->set('created', $groupname, SHGroupHelper::SESSION_KEY); $event = SHAdapterEventHelper::triggerEvent($adapterName, 'onGroupBeforeSave', array($groupname, $isNew)); if ($event !== false) { try { // Commit the changes to the Adapter if present $adapter = SHFactory::getGroupAdapter($groupname); SHAdapterHelper::commitChanges($adapter, true, true); return true; } catch (Exception $e) { //TODO: newId SHLog::add($e, 10981, JLog::ERROR, $name); } } return $event; } // Something went wrong with the group creation return false; } }
/** * Method prepares a form in the way of fields. * Note: Ldap user validation, if required, has to be done in plugin. * * @param JForm $form The form to be alterted. * @param object $data The associated data for the form. * * @return boolean True on success or False on error. * * @since 2.0 */ public function onContentPrepareForm($form, $data) { SHLog::add(JText::sprintf('LIB_SHLDAPEVENTDEBUG_CALLED', __METHOD__), 11910, JLog::DEBUG, 'ldap'); }
/** * Get a users Ldap distinguished name with optional bind authentication. * * @param boolean $authenticate Attempt to authenticate the user (i.e. * bind the user with the password supplied) * * @return string User DN. * * @since 2.1 * @throws InvalidArgumentException Invalid argument in config related error * @throws SHLdapException Ldap specific error. * @throws SHExceptionInvaliduser User invalid error. */ private function _getDn($authenticate = false) { $replaced = str_replace(SHLdap::USERNAME_REPLACE, $this->username, $this->_userParams['user_query']); /* * A basic detection check for LDAP filter. * (i.e. distinguished names do not start and end with brackets). */ $useSearch = preg_match('/(?<!\\S)[\\(]([\\S]+)[\\)](?!\\S)/', $this->_userParams['user_query']) ? true : false; SHLog::add("Attempt to retrieve user distinguished name using '{$replaced}' " . ($useSearch ? ' with search.' : ' with direct bind.'), 102, JLog::DEBUG, 'ldap'); // Get a array of distinguished names from either the search or direct bind methods. $DNs = $useSearch ? $this->_getDnBySearch() : $this->_getDnDirect(); if (empty($DNs)) { /* * Cannot find the specified username. We are going to throw * a special user not found error to try to split between * configuration errors and invalid errors. However, this might * still be a configuration error. */ throw new SHExceptionInvaliduser(JText::_('LIB_SHLDAP_ERR_10302'), 10302, $this->username); } // Check if we have to authenticate the distinguished name with a password if ($authenticate) { // Attempt to bind each distinguished name with the specified password then return it foreach ($DNs as $dn) { if ($this->client->bind($dn, $this->password)) { // Successfully binded with this distinguished name SHLog::add("Successfully authenticated {$this->username} with distinguished name {$dn}.", 102, JLog::DEBUG, 'ldap'); return $dn; } } if ($useSearch) { // User found, but was unable to bind with the supplied password throw new SHExceptionInvaliduser(JText::_('LIB_SHLDAP_ERR_10303'), 10303, $this->username); } else { // Unable to bind directly to the given distinguished name parameters throw new SHExceptionInvaliduser(JText::_('LIB_SHLDAP_ERR_10304'), 10304, $this->username); } } else { $result = false; if ($useSearch) { /* We can be sure the distinguished name(s) exists in the Ldap * directory. However, we cannot be sure if the correct * distinguished name is returned for the specified user without * authenticating. Therefore, we have to assume the first (and * hopefully only) distinguished name is correct. * If the correct configuration has been given and the Ldap * directory is well organised, this will always be correct. */ $result = $DNs[0]; } else { /* Unlike searching, binding directly means we cannot be sure * if the distinguished name(s) exists in the Ldap directory. * Therefore, lets attempt to bind with a proxy user, then Ldap * read each distinguished name's entity to check if it exists. * If binding with the proxy user fails, then we have no option * but to assume the first distinguished name exists. */ if ($this->client->proxyBind()) { foreach ($DNs as $dn) { try { $read = $this->client->read($dn, null, array('dn')); } catch (Exception $e) { // We don't need to worry about the exception too much SHLog::add("Failed to read direct bind without auth DN {$dn}.", 102, JLog::DEBUG, 'ldap'); continue; } // Check if the distinguished name entity exists if ($read->countEntries() > 0) { // It exists so we assume this is the correct distinguished name. $result = $dn; break; } } if ($result === false) { // Failed to find any of the distinguished name(s) in the Ldap directory. throw new SHExceptionInvaliduser(JText::_('LIB_SHLDAP_ERR_10305'), 10305, $this->username); } } else { // Unable to check Ldap directory, so have to assume the first is correct $result = $DNs[0]; } } SHLog::add("Using distinguished name {$result} for user {$this->username}.", 102, JLog::DEBUG, 'ldap'); return $result; } }