/** * Injects several fields into specific forms. * * @param JForm $form The form to be altered. * @param array $data The associated data for the form. * * @return boolean * * @since 2.0 */ public function onContentPrepareForm($form, $data) { // Check we are manipulating a valid form if (!$form instanceof JForm) { $this->_subject->setError('JERROR_NOT_A_FORM'); return false; } // Check if the password field needs injecting if ($this->params->get('use_ldap_password', false) && in_array($form->getName(), $this->passwordForms)) { // Check if this user should have a profile if (SHLdapHelper::isUserLdap(isset($data->id) ? $data->id : 0)) { if ($this->params->get('ldap_password_layout_edit', true)) { // Check if this is in the 'edit' layout or in the save state if (strtolower(JFactory::getApplication()->input->get('layout')) === 'edit' || strtolower(JFactory::getApplication()->input->get('task')) === 'save') { $form->loadFile(realpath(__DIR__) . '/forms/ldap_password.xml', false, false); } } else { $form->loadFile(realpath(__DIR__) . '/forms/ldap_password.xml', false, false); } } } // Check if the domain field needs injecting if ($this->params->get('use_ldap_domain', false) && in_array($form->getName(), $this->domainForms)) { $form->loadFile(realpath(__DIR__) . '/forms/ldap_domain.xml', false, false); } 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; } }
/** * Gets all the LDAP configurations. * * @return array Array of objects containing LDAP config information. * * @since 2.0 */ public function getItems() { $store = $this->getStoreId(); // Try to load the data from internal storage. if (isset($this->cache[$store])) { return $this->cache[$store]; } $config = SHFactory::getConfig(); // Config managed default domain $default = $config->get('ldap.defaultconfig'); // Config managed LDAP host source $source = (int) $config->get('ldap.config', SHLdapHelper::CONFIG_SQL); if ($source === SHLdapHelper::CONFIG_SQL) { parent::getItems(); foreach ($this->cache[$store] as $row) { /* * We need to mark the LDAP hosts that is default. */ $row->default = $row->name == $default ? true : false; /* * Count the ID number of users in each LDAP host. */ $row->users = $this->getCountDomain($row->id, $row->name); /* * Decode the paramters to get the host and port */ $decode = json_decode($row->params); $row->host = $decode->host; $row->port = $decode->port; } } else { try { // Get all the Ldap config IDs and Names $ids = SHLdapHelper::getConfigIDs(); $this->cache[$store] = array(); foreach ($ids as $id => $name) { // Get this specific Ldap configuration based on name $config = SHLdapHelper::getConfig($name); $result = new stdClass(); $result->id = $id; $result->name = $name; $result->host = $config->get('host'); $result->port = $config->get('port'); $result->users = $this->getCountDomain($result->id, $result->name); // Lets add this config to our results pool $this->cache[$store][] = $result; } } catch (Exception $e) { // We need to look for a string instead of an array on error return $e->getMessage(); } } return $this->cache[$store]; }
/** * Method to get the Ldap domains field options. * * @return array The field option objects. * * @since 2.0 */ protected function getOptions() { // Initialize variables. $options = array(); // Get the Ldap Domains $configs = SHLdapHelper::getConfigIDs(); // Present the Ldap domains in the list foreach ($configs as $id => $config) { $options[] = JHtml::_('select.option', $config, $config, 'value', 'text'); } // Merge any additional options in the XML definition. $options = array_merge(parent::getOptions(), $options); return $options; }
public function testConfigInvalidSource() { $this->setExpectedException('InvalidArgumentException', 'LIB_SHLDAPHELPER_ERR_10601', 10601); // Change it to a invalid LDAP config source $platform = SHFactory::getConfig('file', array('file' => static::PLATFORM_CONFIG_FILE, 'namespace' => 'single')); $platform->set('ldap.config', 84); SHLdapHelper::getConfig(null, $platform); }
/** * Loads the profile XML and passes it to the form to load the fields (excluding data). * * @param JForm $form The form to be altered. * @param array $data The associated data for the form. * * @return boolean * * @since 2.0 */ public function onContentPrepareForm($form, $data) { // Check if the profile parameter is enabled if (!$this->use_profile) { return true; } if (!($form instanceof JForm)) { $this->_subject->setError('JERROR_NOT_A_FORM'); return false; } // Check we are manipulating a valid form if (!in_array($form->getName(), $this->permittedForms)) { return true; } $showForm = true; $domain = null; // Check if this user should have a profile if ($userId = isset($data->id) ? $data->id : 0) { if (SHLdapHelper::isUserLdap($userId)) { $domain = SHUserHelper::getDomainParam($data); } else { $showForm = false; } } elseif (!JFactory::getUser()->guest) { /* * Sometimes the $data variable is not populated even when an edit is required. * This means we have to check the form post data directly for the user ID. * We do not worry about frontend registrations as we check for guest. * If there is no form posted then this could be a backend registration. */ if ($inForm = JFactory::getApplication()->input->get('jform', false, 'array')) { $id = SHUtilArrayhelper::getValue($inForm, 'id', 0, 'int'); if ($id === 0) { // Ask all plugins if there is a plugin willing to deal with user creation for ldap if (count($results = SHFactory::getDispatcher('ldap')->trigger('askUserCreation'))) { // Due to being unaware of the domain for this new user, we are forced to use the default domain $domain = SHFactory::getConfig()->get('ldap.defaultconfig'); } else { // LDAP creation not enabled $showForm = false; } } else { if (SHLdapHelper::isUserLdap($id)) { // Existing ldap user $domain = SHUserHelper::getDomainParam($id); } else { // Existing non-ldap user $showForm = false; } } } } if ($showForm) { // We have to launch the getxmlfields to correctly include languages $this->getXMLFields($domain); // Get the File and Path for the Profile XML $file = $this->getXMLFileName($domain); $xmlPath = $this->profile_base . '/' . $file . '.xml'; // Load in the profile XML file to the form if (($xml = JFactory::getXML($xmlPath, true)) && ($form->load($xml, false, false))) { // Successfully loaded in the XML return true; } } }
/** * This method is similar to SHLdap::getInstance but also it stores * all instantiated SHLdap objects in a static variable for later use. * * @param integer|string $domain Optional domain or configuration record ID. * @param JRegistry $config Optional LDAP config (can also be single JRegistry without array). * @param JRegistry $registry Optional override for platform configuration registry. * * @return SHLdap[] An array of SHLdap objects. * * @since 2.1 * @throws InvalidArgumentException Invalid configurations */ public static function getLdapClient($domain = null, $config = array(), JRegistry $registry = null) { // Get the platform registry config from the factory $domain . d $registry = is_null($registry) ? self::getConfig() : $registry; $cache = JFactory::getCache('shldap', ''); $domain = is_null($domain) ? $domain : strtolower($domain); // Generate a unique hash for this configuration depending on the domain requested $domainHash = empty($domain) ? '' : $domain; if (!empty($domain)) { $hash = md5($domain . serialize($config) . serialize($registry)); if (isset(self::$ldap[$hash])) { return array(self::$ldap[$hash]); } // Reconstruct the LDAP configuration object from cache and ensure it is valid if ($cachedConfig = $cache->get($hash) && $cachedConfig instanceof SHLdap) { self::$ldap[$hash] = $cachedConfig; return array(self::$ldap[$hash]); } } else { $hash = md5('all_domains' . serialize($config) . serialize($registry)); if (isset(self::$ldap[$hash])) { $valid = true; $configs = array(); // Reconstruct all domains in order foreach (self::$ldap[$hash] as $hash) { if (isset(self::$ldap[$hash])) { $configs[] = self::$ldap[$hash]; } else { // One of the configs are invalid and therefore we must run everything again $valid = false; break; } if ($valid) { return $configs; } } } else { // Check if we have done a "all domain" LDAP config retrieve if (($cachedConfigs = $cache->get($hash)) && is_array($cachedConfigs)) { $valid = true; $configs = array(); foreach ($cachedConfigs as $configHash) { // Reconstruct the "all domain" configurations from cache and check they are valid if (($cachedConfig = $cache->get($configHash)) && $cachedConfig instanceof SHLdap) { $configs[] = $cachedConfig; } else { // One of the configs are invalid and therefore we must run everything again $valid = false; break; } } if ($valid) { return $configs; } } } } // Potentially we will need the original input config later $inputConfig = $config; if (empty($config)) { /* * Get all the Ldap configs that are enabled and available. An optional * domain is passed - when this is passed, only one config will be returned. */ $configs = SHLdapHelper::getConfig($domain, $registry); } else { // Use the specified config $configs = $config instanceof JRegistry ? $config : new JRegistry($config); } if (!empty($configs)) { // If only 1 config result, wrap around an array so we can use the same code $configs = $configs instanceof JRegistry ? array($configs) : $configs; // This will be all the LDAP clients that match the domain $clients = array(); // Store all the hashes that we generate for caching purposes $hashes = array(); // Loop around each of the Ldap configs until one authenticates foreach ($configs as $config) { // Validate the config from any registered listeners (this can also change the config) SHUtilValidate::getInstance()->validate($config); /* * We won't catch exceptions now as it will mean either ldap * extension missing OR a very bad problem with this LDAP configuraiton. */ $ldap = new SHLdap($config); $hash = md5(strtolower($ldap->domain) . serialize($inputConfig) . serialize($registry)); if (!isset(self::$ldap[$hash])) { // We want to store this client for potential use later on self::$ldap[$hash] = $ldap; // Lets cache the LDAP client for future use $cache->store(self::$ldap[$hash], $hash); } $hashes[] = $hash; $clients[] = self::$ldap[$hash]; unset($ldap); } if (count($clients)) { if (empty($domain)) { // Cache all domains in the correct order so we can use it for future use $hash = md5('all_domains' . serialize($inputConfig) . serialize($registry)); $cache->store($hashes, $hash); self::$ldap[$hash] = $hashes; } // Found some LDAP configs - lets return them return $clients; } } // No errors happened, but unable to find suitable LDAP config for the domain throw new InvalidArgumentException(JText::_('LIB_SHFACTORY_ERR_2131'), 2131); }
public function testConfigSqlStringInvalid() { $this->setExpectedException('InvalidArgumentException', 'LIB_SHLDAPHELPER_ERR_10606', 10606); $config = SHLdapHelper::getConfig('notexist'); }
/** * Entry point for the script. * * @return void * * @since 2.0 */ public function doExecute() { // Setup some stats $failed = 0; $success = 0; $errors = array(); // It appears we have to tell the system we are running with the site otherwise bad things happen JFactory::getApplication('site'); $this->out(JText::_('CLI_SHMANIC_LDAP_INFO_13001')); // Get all the valid configurations if (!($configs = SHLdapHelper::getConfig())) { // Failed to find any Ldap configs $this->out(JText::_('CLI_SHMANIC_LDAP_ERR_13003')); $this->close(1); } // Check if only a single config was found if ($configs instanceof JRegistry) { /* * To make things easier, we pretend we returned multiple Ldap configs * by casting the single entry into an array. */ $configs = array($configs); } $count = count($configs); $this->out(JText::sprintf('CLI_SHMANIC_LDAP_INFO_13002', $count))->out(); // Loop around each LDAP configuration foreach ($configs as $config) { try { // Get a new Ldap object $ldap = new SHLdap($config); // Bind with the proxy user if (!$ldap->authenticate(SHLdap::AUTH_PROXY)) { // Something is wrong with this LDAP configuration - cannot bind to proxy user $errors[] = new Exception(JText::sprintf('CLI_SHMANIC_LDAP_ERR_13011', $ldap->info), 13011); unset($ldap); continue; } // Get all the Ldap users in the directory if (!($result = $ldap->search(null, $ldap->allUserFilter, array('dn', $ldap->keyUid)))) { // Failed to search for all users in the directory $errors[] = new Exception(JText::sprintf('CLI_SHMANIC_LDAP_ERR_13012', $ldap->getErrorMsg()), 13012); unset($ldap); continue; } // Loop around each Ldap user for ($i = 0; $i < $result->countEntries(); ++$i) { // Get the Ldap username (case insensitive) if (!($username = strtolower($result->getValue($i, $ldap->keyUid, 0)))) { continue; } try { // Check if this user is in the blacklist if ($blacklist = (array) json_decode(SHFactory::getConfig()->get('user.blacklist'))) { if (in_array($username, $blacklist)) { throw new RuntimeException(JText::_('CLI_SHMANIC_LDAP_ERR_13025'), 13025); } } // Create the new user adapter $adapter = new SHUserAdaptersLdap(array('username' => $username), $config); // Get the Ldap DN if (!($dn = $adapter->getId(false))) { continue; } $this->out(JText::sprintf('CLI_SHMANIC_LDAP_INFO_13020', $username)); // Get the Ldap user attributes $source = $adapter->getAttributes(); // Get the core mandatory J! user fields $username = $adapter->getUid(); $fullname = $adapter->getFullname(); $email = $adapter->getEmail(); if (empty($fullname)) { // Full name doesnt exist; use the username instead $fullname = $username; } if (empty($email)) { // Email doesnt exist; cannot proceed throw new Exception(JText::_('CLI_SHMANIC_LDAP_ERR_13022'), 13022); } // Create the user array to enable creating a JUser object $user = array('fullname' => $fullname, 'username' => $username, 'password_clear' => null, 'email' => $email); // Create a JUser object from the Ldap user $options = array('adapter' => &$adapter); $instance = SHUserHelper::getUser($user, $options); if ($instance === false) { // Failed to get the user either due to save error or autoregister throw new Exception(JText::_('CLI_SHMANIC_LDAP_ERR_13024'), 13024); } // Fire the Ldap specific on Sync feature $sync = SHLdapHelper::triggerEvent('onLdapSync', array(&$instance, $options)); // Check if the synchronise was successfully and report if ($sync !== false) { // Even if the sync does not need a save, do it anyway as Cron efficiency doesnt matter too much SHUserHelper::save($instance); // Update the user map linker SHAdapterMap::setUser($adapter, $instance->id); // Above should throw an exception on error so therefore we can report success $this->out(JText::sprintf('CLI_SHMANIC_LDAP_INFO_13029', $username)); ++$success; } else { throw new Exception(JText::_('CLI_SHMANIC_LDAP_ERR_13026'), 13026); } unset($adapter); } catch (Exception $e) { unset($adapter); ++$failed; $errors[] = new Exception(JText::sprintf('CLI_SHMANIC_LDAP_ERR_13028', $username, $e->getMessage()), $e->getCode()); } } } catch (Exception $e) { $errors[] = new Exception(JText::_('CLI_SHMANIC_LDAP_ERR_13004'), 13004); } } // Print out some results and stats $this->out()->out()->out(JText::_('CLI_SHMANIC_LDAP_INFO_13032'))->out(); $this->out(JText::_('CLI_SHMANIC_LDAP_INFO_13038')); foreach ($errors as $error) { if ($error instanceof Exception) { $this->out(' ' . $error->getCode() . ': ' . $error->getMessage()); } else { $this->out(' ' . (string) $error); } } $this->out()->out(JText::sprintf('CLI_SHMANIC_LDAP_INFO_13034', $success)); $this->out(JText::sprintf('CLI_SHMANIC_LDAP_INFO_13036', $failed)); $this->out()->out('============================'); }
/** * Gets all the LDAP configs and attempts to bind with each. * This is presented on the dashboard. * * @return array Array of objects containing LDAP config information. * * @since 2.0 */ public function getBinds() { try { $results = array(); // Get all the Ldap config IDs and Names $ids = SHLdapHelper::getConfigIDs(); foreach ($ids as $name) { // Get this specific Ldap configuration based on name $config = SHLdapHelper::getConfig($name); $result = new stdClass(); $result->name = $name; $result->host = $config->get('host'); $result->port = $config->get('port'); $result->connect = false; $ldap = new SHLdap($config); // Need to process the ldap formatting for the host configuration ready for a fsockopen $processed = str_replace(array('ldap://', 'ldaps://'), '', $config->get('host')); if ($pos = strpos($processed, chr(32))) { $processed = substr($processed, 0, $pos); } // Check if we can open a socket to the LDAP server:port to check the connection if (@fsockopen($processed, $config->get('port'))) { $result->connect = true; } // Attempt to connect and bind and record the result if ($ldap->connect()) { if ($ldap->proxyBind()) { $result->bind = true; } } // Lets add this config to our results pool $results[] = $result; } return $results; } catch (Exception $e) { // We need to look for a string instead of an array on error return $e->getMessage(); } }
/** * Get a user's distinguished name by attempting to replace the username keyword * in the query. Supports multiple distinguished names in a list. * * @param string $username Authenticating username. * * @return array An array containing distinguished names. * * @since 1.0 * @throws InvalidArgumentException Invalid argument in config related error */ public function getUserDnDirectly($username) { $return = array(); // Fixes special usernames and provides protection against distinguished name injection $username = SHLdapHelper::escape($username, true); // Replace the username placeholder with the authenticating username $search = str_replace(self::USERNAME_REPLACE, $username, $this->user_qry); // Splits each of the distinguished names into indivdual elements $DNs = explode(';', $search); // We need to find the correct distinguished name from the set of elements foreach ($DNs as $dn) { // Remove whitespacing from the distinguished name and check there is a length > 1 if ($dn = trim($dn)) { $return[] = $dn; } } return $return; }
/** * Get an array of all the nested groups through the use of group recursion. * This is required usually only for Active Directory, however there could * be other LDAP platforms that cannot pick up nested groups. * * @param shldap &$ldap Reference to the LDAP object. * @param array $searchDNs Initial user groups (or ones that have already been discovered). * @param string $depth How far to search down until it should give up (0 means unlimited). * @param array &$result Holds the result of every alliteration (by reference). * @param string $attribute The LDAP attribute to store after each ldap search. * @param string $queryAttribute The LDAP filter attribute to query. * * @return array All user groups including the initial user groups. * * @since 1.0 * @throws SHLdapException */ public static function getRecursiveGroups(SHLdap &$ldap, $searchDNs, $depth, &$result, $attribute, $queryAttribute = null) { $search = null; $next = array(); $filters = array(); // As this is recursive, we want to be able to specify a optional depth --$depth; if (!isset($searchDNs)) { return $result; } foreach ($searchDNs as $dn) { // Build one or more partial filters from the DN user groups $filters[] = $queryAttribute . '=' . $dn; } if (!count($filters)) { // If there is no filter to process then we are finished return $result; } // Build the full filter using the OR operator $search = SHLdapHelper::buildFilter($filters, '|'); // Search for any groups that also contain the groups we have in the filter $results = $ldap->search(null, $search, array($attribute)); // Lets process each group that was found $entryCount = $results->countEntries(); for ($i = 0; $i < $entryCount; ++$i) { $dn = $results->getDN($i); // We don't want to re-process a group that was processed previously if (!in_array($dn, $result)) { $result[] = $dn; // Check if there are more groups we should process from the groups just discovered $valueCount = $results->countValues($i, $attribute); for ($j = 0; $j < $valueCount; ++$j) { // We want to process this object $value = $results->getValue($i, $attribute, $j); $next[] = $value; } } } /* * Only start the recursion when we have something to process next * otherwise, we would loop forever. */ if (count($next) && $depth != 0) { self::getRecursiveGroups($ldap, $next, $depth, $result, $attribute, $queryAttribute); } return $result; }
/** * Return specified user attributes from LDAP. * * @param string|array $input Optional string or array of attributes to return. * @param boolean $null Include null or non existent values. * @param boolean $changes Use the attribute changes (before change commit). * * @return mixed Ldap attribute results. * * @since 2.0 * @throws SHLdapException */ public function getAttributes($input = null, $null = false, $changes = false) { if (is_null($this->_dn)) { $this->getId(false); } elseif ($this->_dn instanceof Exception) { // Do not retry. Ldap configuration or user has problems. throw $this->_dn; } $needToFind = array(); $inputFilled = array(); if (!is_null($input)) { // Have to make sure that unless its null then its in an array $input = is_string($input) ? array($input) : $input; $inputFilled = array_fill_keys($input, null); // This array is what we must find (i.e. not in the cached variable) $needToFind = (array_keys(array_diff_key($inputFilled, $this->_attributes))); /* * Combines the current cached attributes with the input attributes with null values. * This will stop the input values from being re-queried on another method call even * if they don't exist. */ $this->_attributes = (array_merge($inputFilled, $this->_attributes)); } /* * We use the "plugin get attributes" method for efficiency purposes. On the * first execution of this method, we attempt to gather Ldap user attributes * that are required from this call in addition to what the Ldap plugins require. * * This means we should only have to call for the user attributes once from Ldap. */ if ($this->_usePlugins) { // Only run the sequence once $this->_usePlugins = false; /* * -- Get the Ldap user attributes via plugins -- * This section will get an array of user detail attributes for the user * using Ldap plugins to help with discovery of required Ldap attributes. */ $extras = SHFactory::getDispatcher('ldap')->trigger( 'onLdapBeforeRead', array(&$this, array('dn' => $this->_dn, 'source' => __METHOD__)) ); // For each of the LDAP plug-ins returned, merge their extra attributes. foreach ($extras as $extra) { $needToFind = array_merge($needToFind, $extra); } // Add both of the uid and fullname to the set of attributes to get. $needToFind[] = $this->client->ldap_fullname; $needToFind[] = $this->client->ldap_uid; // Check for a fake email $fakeEmail = (strpos($this->client->ldap_email, (SHLdap::USERNAME_REPLACE)) !== false) ? true : false; // Add the email attribute only if not a fake email is supplied. if (!$fakeEmail) { $needToFind[] = $this->client->ldap_email; } // Re-order array to ensure an LDAP read is successful and no duplicates exist. $needToFind = array_values(array_unique($needToFind)); // Swap the attribute names to array keys ready for the result $filled = array_fill_keys($needToFind, null); /* * Combines the current cached attributes with the input attributes with null values. * This will stop the input values from being re-queried on another method call even * if they don't exist. */ $this->_attributes = (array_merge($filled, $this->_attributes)); // Get Ldap user attributes $result = $this->client->read($this->_dn, null, $needToFind); if ($result->countEntries()) { // Merge the extra attributes to the cache ready for returning $this->_attributes = array_replace($this->_attributes, array_intersect_key($result->getEntry(0), $this->_attributes)); } /* * Save any attributes that weren't found in Ldap and then make it unique * so theres no duplicates in the null attributes list. */ $unreturnedVals = array_diff($needToFind, array_keys($result->getEntry(0, array()))); $this->_nullAttributes = array_merge(array_diff($unreturnedVals, $this->_nullAttributes), $this->_nullAttributes); if ($fakeEmail) { // Inject the fake email by replacing the username placeholder with the username from ldap $email = str_replace(SHLdap::USERNAME_REPLACE, $this->_attributes[$this->client->ldap_uid][0], $this->client->ldap_email); $this->_attributes[$this->client->ldap_email] = array($email); // As the last instruction from the fakeEmail condition added email to null, lets remove it if (($index = array_search($this->client->ldap_email, $this->_nullAttributes)) !== false) { unset ($this->_nullAttributes[$index]); } } if (SHLdapHelper::triggerEvent( 'onLdapAfterRead', array(&$this, &$this->_attributes, array('dn' => $this->_dn, 'source' => __METHOD__)) ) === false) { // Cancelled login due to plug-in throw new RuntimeException(JText::_('LIB_SHUSERADAPTERSLDAP_ERR_10912'), 10912); } // Blank need to find as there isn't anything more need finding $needToFind = array(); } // Check if extra attributes are required if (count($needToFind)) { $result = $this->client->read($this->_dn, null, $needToFind); if ($result->countEntries()) { // Merge the extra attributes to the cache ready for returning $this->_attributes = array_replace($this->_attributes, array_intersect_key($result->getEntry(0), $this->_attributes)); } /* * Save any attributes that weren't found in Ldap and then make it unique * so theres no duplicates in the null attributes list. */ $unreturnedVals = array_diff($needToFind, array_keys($result->getEntry(0, array()))); $this->_nullAttributes = array_merge(array_diff($unreturnedVals, $this->_nullAttributes), $this->_nullAttributes); } else { // If there are no attributes then get them all from LDAP if (!count($this->_attributes)) { $this->_attributes = $this->client->read($this->_dn, null)->getEntry(0, array()); } } $return = $this->_attributes; // Remove null values from the attributes if we dont want them if (!$null) { $return = array_diff_key($this->_attributes, array_flip($this->_nullAttributes)); $inputFilled = array_diff_key($inputFilled, array_flip($this->_nullAttributes)); } // Include staged changes to the attributes $return = $changes ? array_merge($return, $this->_changes) : $return; // Returns only the specified inputs unless all attributes are wanted return is_null($input) ? $return : array_replace($inputFilled, array_intersect_key($return, $inputFilled)); }
/** * Method is called on user login failure. * * @param array $response The authentication response. * * @return void * * @since 2.0 */ public function onUserLoginFailure($response) { // Check if the attempted login was an Ldap user, if so then fire the event if ($username = SHUtilArrayhelper::getValue($response, 'username', false, 'string')) { // Check if the user exists in the J! database if ($id = JUserHelper::getUserId($username)) { if (SHLdapHelper::isUserLdap($id)) { SHLdapHelper::triggerEvent('onUserLoginFailure', array($response)); } } } }
/** * Returns the distinguished name. * * @param array $form Registration form. * * @return string Distinguished name. * * @since 2.0 */ public function getMandatoryDN($form) { $name = SHLdapHelper::escape($form['name'], true); return "CN={$name},OU=People,DC=shmanic,DC=net"; }
/** * Create the user to LDAP (before onUserBeforeSave). * * @param array $user Populated LDAP attributes from the form. * * @return boolean Cancels the user creation to Joomla if False. * * @since 2.0 */ public function onUserCreation($user) { try { $dn = null; $attributes = array(); // Populate defaults for the mandatory $mandatory = array( 'username' => SHUtilArrayhelper::getValue($user, 'username'), 'password' => SHUtilArrayhelper::getValue($user, 'password_clear'), 'email' => SHUtilArrayhelper::getValue($user, 'email'), 'name' => SHUtilArrayhelper::getValue($user, 'name') ); // Include the helper file only if it exists if ($this->helper = $this->_getHelperFile()) { // Calculate the correct domain to insert user on if (method_exists($this->helper, 'getDomain')) { $this->domain = $this->helper->getDomain($user); } } $fields = $this->_getXMLFields(); // Loops around everything in the template XML foreach ($fields as $key => $value) { // Convert the value to a string $stringValue = (string) $value; // Convert the key to a string $stringKey = (string) $key; $name = (string) $value->attributes()->name; if ($stringKey == 'dn') { $name = 'mandatory' . $stringKey; // The dn which isn't an array $attribute =& $dn; } elseif ($stringKey == 'username' || $stringKey == 'password' || $stringKey == 'email' || $stringKey == 'name') { $name = 'mandatory' . $stringKey; // The mandatory fields use something a bit different $attribute =& $mandatory[$stringKey]; } else { // Standard multi-array attributes if (!isset($attributes[$name])) { $attributes[$name] = array(); } $attribute =& $attributes[$name][]; } // Get the value of the attributes using a variety of types switch ((string) $value->attributes()->type) { case 'form': $attribute = $user[$stringValue]; break; case 'string': $attribute = $stringValue; break; case 'eval': $attribute = $this->_execEval($stringValue, $user); break; case 'helper': $method = 'get' . (string) $name; $attribute = $this->helper->{$method}($user); break; } } $credentials = array( 'username' => $mandatory['username'], 'password' => $mandatory['password'], 'domain' => $this->domain, 'dn' => $dn ); // Kill any previous adapters for this user (though this plugin should be ordered first!!) SHFactory::$adapters[strtolower($user['username'])] = null; // Create an adapter and save core attributes $adapter = SHFactory::getUserAdapter($credentials, 'ldap', array('isNew' => true)); // Add core Joomla fields $adapter->setAttributes( array( 'username' => $mandatory['username'], 'password' => $mandatory['password'], 'fullname' => $mandatory['name'], 'email' => $mandatory['email'] ) ); // Add extra fields based from the template xml $adapter->setAttributes($attributes); // Create the LDAP user now SHLdapHelper::commitChanges($adapter, true, true); SHLog::add(JText::sprintf('PLG_LDAP_CREATION_INFO_12821', $mandatory['username']), 12821, JLog::INFO, 'ldap'); $this->username = $mandatory['username']; /* * Call onAfterCreation method in the helper which can be used to run * external scripts (such as creating home directories) and/or adding * groups to the new user. * * This method will be passed: * - $user Values directly from the user registration form. * - $attributes The attributes passed to the LDAP server for creation. * - $adapter The user adapter object. */ if ($this->helper && method_exists($this->helper, 'onAfterCreation')) { $this->helper->onAfterCreation($user, $attributes, $adapter); } return true; } catch (Exception $e) { SHLog::add($e, 12802, JLog::ERROR, 'ldap'); return false; } }
/** * Returns the distinguished name. * * @param array $form Registration form. * * @return string Distinguished name. * * @since 2.0 */ public function getMandatoryDN($form) { $username = SHLdapHelper::escape($form['username'], true); return "uid={$username},ou=People,dc=shmanic,dc=net"; }