/** * 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; } }
/** * Checks whether a user exists in the LDAP directory. * * @return boolean True if user exists. * * @since 2.0 */ private function _checkUserExists() { try { $this->client->getUserDn($this->username, null, false); return true; } catch (Exception $e) { return false; } }
/** * Get a user's dn by attempting to search for it in the directory. * * This method uses the query as a filter to find where the user is located in the directory * * @return array An array containing user DNs. * * @since 2.1 * @throws InvalidArgumentException Invalid argument in config related error * @throws SHLdapException Ldap search error */ private function _getDnBySearch() { // Fixes special usernames and provides simple protection against ldap injections $username = SHLdapHelper::escape($this->username); $search = str_replace(SHLdap::USERNAME_REPLACE, $username, $this->_userParams['user_query']); // We can either use a specific user base dn or use SHLdap's default $baseDn = isset($this->_userParams['user_base_dn']) && !empty($this->_userParams['user_base_dn']) ? $this->_userParams['user_base_dn'] : null; // Bind using the proxy user so the user can be found in the Ldap directory. if (!$this->client->proxyBind()) { // Failed to bind with proxy user throw new InvalidArgumentException(JText::_('LIB_SHLDAP_ERR_10322'), 10322); } // Search the directory for the user $result = $this->client->search($baseDn, $search, array($this->_userParams['user_uid'])); $return = array(); $count = $result->countEntries(); // Store the distinguished name for each user found for ($i = 0; $i < $count; ++$i) { $return[] = $result->getValue($i, 'dn', 0); } return $return; }
/** * 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('============================'); }
public function testSlapdExplodeDn() { $actual = SHLdap::explodeDn('uid=oracle, ou=Matrix, ou = People, dc=shmanic, dc=net', 0); $this->assertEquals(array('count' => 5, 'uid=oracle', 'ou=Matrix', 'ou=People', 'dc=shmanic', 'dc=net'), $actual); }
/** * Converts the Ldap Error ID into a readable message. * * @return string Error Message. * * @since 2.0 */ public final function getLdapMessage() { if (!is_null($this->ldapCode)) { // Convert ID to string return SHLdap::errorToString($this->ldapCode); } return null; }
/** * 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]; } }
/** * Compare the DN in the parameter against the groups in * the ldap groups. This is used to compare if one of the * group mapping list dn entries matches any of the ldap user * groups and if so returns true. * * @param self $parameter Group mapping list parameters. * @param self &$ldapGroups Ldap user groups. * * @return Boolean True on parameter entry is in the ldap user group. * * @since 1.0 */ public static function compareGroup(self $parameter, self &$ldapGroups) { $matches = array(); if ($parameter->dn === false || $ldapGroups->dn === false) { // Distinguished Name has invalid syntax return false; } foreach ($ldapGroups->groups as $ldapGroup) { /* * If there is currently no RDNs (i.e. non validated DN) * then we will use a simple string comparison. */ if (count($parameter->rdn)) { $explode = SHLdap::explodeDn($ldapGroup, 0); if (is_array($explode) && count($explode)) { // We need to convert to lower because escape characters return with uppercase hex ascii codes $explode = array_map('strToLower', SHLdap::explodeDn($ldapGroup, 0)); if (self::compareValidatedDN($parameter->rdn, $explode)) { return true; } } } else { // Simple string comparison instead of the validated DN method if (strToLower(trim($ldapGroup)) == strToLower(trim($parameter->dn))) { return true; } } } }
/** * 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(); } }