Пример #1
0
 /**
  * Gets a user link from the adapter map table.
  *
  * @param   string|integer  $user  Either a username or Joomla user ID.
  * @param   boolean         $isId  If the user input is a user ID then set to true.
  *
  * @return  array           Array of links for user or empty array if none found.
  *
  * @since   2.1
  */
 public static function getUser($user = null, $isId = false)
 {
     // Use I_ for joomla_id and U_ for usernames
     $cacheKey = ($isId ? 'I_' : 'U_') . $user;
     if (isset(self::$userCache[$cacheKey])) {
         return self::$userCache[$cacheKey];
     }
     if ($isId) {
         $links = self::lookupFromJoomlaId(self::TYPE_USER, $user);
     } else {
         $links = self::lookupFromUsername($user);
     }
     if ($links) {
         self::$userCache[$cacheKey] = $links;
         if (!$isId) {
             // There should be only ever one Joomla_Id for a user therefore we can cache that now
             foreach ($links as $link) {
                 self::$userCache['I_' . $link['joomla_id']] = array($link);
             }
         }
         return self::$userCache[$cacheKey];
     }
     // Backwards compatibility for 2.0 (*inefficient methods*)
     if ($type = SHUserHelper::getTypeParam($user)) {
         $domain = SHUserHelper::getDomainParam($user);
         return array(array('type' => self::TYPE_USER, 'adapter' => $type, 'domain' => $domain, 'adapter_id' => null, 'joomla_id' => null));
     }
     return array();
 }
Пример #2
0
	/**
	 * 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;
	}
Пример #3
0
	/**
	 * Method is called before user data is stored in the database.
	 *
	 * Saves profile data to LDAP if a profile form is detected.
	 *
	 * @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 (!$this->params->get('allow_ldap_save', 1))
		{
			// Not allowed to save back to LDAP
			return;
		}

		// Default the return result to true
		$result = true;

		try
		{
			// Get username for adapter
			$username = SHUtilArrayhelper::getValue($user, 'username', false, 'string');

			if (empty($username))
			{
				// The old username isn't present so use new username
				$username = SHUtilArrayhelper::getValue($new, 'username', false, 'string');
			}

			// Include the mandatory Joomla fields (fullname and email)
			$this->saveMandatoryToLdap($username, $new['name'], $new['email']);

			// Check there is a profile to save (i.e. this event may not have been called from the profile form)
			if ($this->use_profile && (isset($new[self::FORM_FIELDS_NAME]) && (count($new[self::FORM_FIELDS_NAME]))))
			{
				$xml = $this->getXMLFields(SHUserHelper::getDomainParam($new));

				// Only get profile data and enabled elements from the input
				$profileData = $this->cleanInput($xml, $new[self::FORM_FIELDS_NAME]);

				// Save the profile back to LDAP
				$result = $this->saveProfileToLdap($xml, $username, $profileData);
			}
		}
		catch (Exception $e)
		{
			SHLog::add($e, 12232, JLog::ERROR, 'ldap');

			return false;
		}

		return $result;
	}
Пример #4
0
 /**
  * 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('============================');
 }
Пример #5
0
 /**
  * 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;
 }
Пример #6
0
	/**
	 * Gets the user adapter for the user specified. Creates a new user
	 * adapter if one doesnt already exist for the user.
	 *
	 * @param   array|string  $user     Either a username string or array of credentials including JUser ID and domain.
	 * @param   string        $type     Type of adapter (e.g. ldap, xml, federated).
	 * @param   array         $options  An array of optional options including isNew.
	 *
	 * @return  SHUserAdapter  Object to user adapter.
	 *
	 * @since   2.0
	 * @throws  Exception
	 */
	public static function getUserAdapter($user, $type = null, $options = array())
	{
		if (is_array($user))
		{
			$username = strtolower(SHUtilArrayhelper::getValue($user, 'username', null, 'string'));
			$credentials = $user;
		}
		else
		{
			$username = strtolower((string) $user);
			$credentials = array('username' => $username);
		}

		if (empty($username))
		{
			throw new RuntimeException(JText::_('LIB_SHFACTORY_ERR_2121'), 2121);
		}

		if (!isset(self::$adapters[$username]))
		{
			$config = self::getConfig();

			// Check if this user is in the blacklist
			if ($blacklist = (array) json_decode($config->get('user.blacklist')))
			{
				if (in_array($username, $blacklist))
				{
					throw new RuntimeException(JText::sprintf('LIB_SHFACTORY_ERR_2125', $username), 2125);
				}
			}

			// If the JUser ID has been specified then use it (more efficient)
			if ($id = isset($credentials['id']) ? (int) $credentials['id'] : JUserHelper::getUserId($username))
			{
				$jUser = JFactory::getUser($id);

				if ((boolean) $config->get('user.usedomain', true))
				{
					if (!isset($credentials['domain']))
					{
						// Attempt to get the domain for this user
						$credentials['domain'] = SHUserHelper::getDomainParam($jUser);
					}
				}
				else
				{
					unset($credentials['domain']);
				}

				if (!isset($credentials['type']))
				{
					// Attempt to get the User Adapter type
					$type = SHUserHelper::getTypeParam($jUser);
				}
			}

			if (is_null($type))
			{
				// Get the default/primary user adpater type from the database
				$type = $config->get('user.type');
			}

			// Camel case friendly for class name
			$type = ucfirst(strtolower($type));
			$class = "SHUserAdapters${type}";

			if (class_exists($class))
			{
				// Create the adapter (note: remember to unset if using multiple adapters!)
				self::$adapters[$username] = new $class($credentials, null, $options);
			}
			else
			{
				throw new RuntimeException(JText::sprintf('LIB_SHFACTORY_ERR_2123', $class), 2123);
			}
		}
		else
		{
			// Update credentials if required
			if ($password = SHUtilArrayhelper::getValue($user, 'password', false))
			{
				self::$adapters[$username]->updateCredential($password, $options);
			}
		}

		return self::$adapters[$username];
	}
Пример #7
0
	/**
	 * Returns if the current or specified user was authenticated
	 * via LDAP.
	 *
	 * @param   JUser|integer|array  $user  Optional user id (if null then uses current user).
	 *
	 * @return  boolean  True if user is Ldap authenticated or False otherwise.
	 *
	 * @since   2.0
	 */
	public static function isUserLdap($user = null)
	{
		$type = SHUserHelper::getTypeParam($user);

		// Create a new adapter
		if ($type = ucfirst(strtolower($type)))
		{
			$class = "SHUserAdapters${type}";

			$adapter = new $class(array('username' => '', 'password' => ''));

			return $adapter->getType('LDAP') ? true : false;
		}

		return false;
	}