/** * 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('============================'); }
/** * 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)); } } } }
/** * 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)); }