/** * 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]; }
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); }
/** * 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('============================'); }
/** * Find the correct Ldap parameters based on the authorised and configuration * specified. If found then return the successful Ldap object. * * Note: you can use SHLdap::lastUserDn for the user DN instead of rechecking again. * * @param integer|string $id Optional configuration record ID. * @param Array $authorised Optional authorisation/authentication options (authenticate, username, password). * @param JRegistry $registry Optional override for platform configuration registry. * * @return SHLdap An Ldap object on successful authorisation or False on error. * * @since 2.0 * @throws InvalidArgumentException Invalid configurations * @throws SHExceptionStacked User or configuration issues (may not be important) */ public static function getInstance($id = null, array $authorised = array(), JRegistry $registry = null) { // Get the platform registry config from the factory if required $registry = is_null($registry) ? SHFactory::getConfig() : $registry; // Get the optional authentication/authorisation options $authenticate = SHUtilArrayhelper::getValue($authorised, 'authenticate', self::AUTH_NONE); $username = SHUtilArrayhelper::getValue($authorised, 'username', null); $password = SHUtilArrayhelper::getValue($authorised, 'password', null); // Get all the Ldap configs that are enabled and available $configs = SHLdapHelper::getConfig($id, $registry); // Check if only one configuration result was found if ($configs instanceof JRegistry) { // Wrap this around an array so we can use the same code below $configs = array($configs); } // Keep a record of any exceptions called and only log them after $errors = array(); // Loop around each of the Ldap configs until one authenticates foreach ($configs as $config) { try { // Get a new SHLdap object $ldap = new SHLdap($config); // Check if the authenticate/authentication is successful if ($ldap->authenticate($authenticate, $username, $password)) { // This is the correct configuration so return the new client return $ldap; } } catch (Exception $e) { // Add the error to the stack $errors[] = $e; } unset($ldap); } // Failed to find any configs to match if (count($errors) > 1) { // More than one config caused issues, use the stacked exception throw new SHExceptionStacked(JText::_('LIB_SHLDAP_ERR_10411'), 10411, $errors); } else { // Just rethrow the one exception throw $errors[0]; } }
/** * 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(); } }