Example #1
0
 /**
  * Authenticates using LDAP and returns a user record or FALSE
  * if operation fails.
  *
  * @param string $username
  * @param string $password
  * @return bool|array TRUE or array of user info on success, otherwise FALSE
  * @throws \Causal\IgLdapSsoAuth\Exception\UnresolvedPhpDependencyException when LDAP extension for PHP is not available
  */
 public static function ldapAuthenticate($username, $password = NULL)
 {
     static::$lastAuthenticationDiagnostic = '';
     if ($username && Configuration::getValue('forceLowerCaseUsername')) {
         // Possible enhancement: use \TYPO3\CMS\Core\Charset\CharsetConverter::conv_case instead
         $username = strtolower($username);
     }
     // Valid user only if username and connect to LDAP server.
     if ($username && Ldap::getInstance()->connect(Configuration::getLdapConfiguration())) {
         // Set extension configuration from TYPO3 mode (BE/FE).
         static::initializeConfiguration();
         // Valid user from LDAP server
         if ($userdn = Ldap::getInstance()->validateUser($username, $password, static::$config['users']['basedn'], static::$config['users']['filter'])) {
             static::getLogger()->info(sprintf('Successfully authenticated' . ($password === NULL ? ' SSO' : '') . ' user "%s" with LDAP', $username));
             if ($userdn === TRUE) {
                 return TRUE;
             }
             return static::synchroniseUser($userdn, $username);
         } else {
             static::$lastAuthenticationDiagnostic = Ldap::getInstance()->getLastBindDiagnostic();
             if (!empty(static::$lastAuthenticationDiagnostic)) {
                 static::getLogger()->notice(static::$lastAuthenticationDiagnostic);
             }
         }
         // LDAP authentication failed.
         Ldap::getInstance()->disconnect();
         // This is a notice because it is fine to fallback to standard TYPO3 authentication
         static::getLogger()->notice(sprintf('Could not authenticate user "%s" with LDAP', $username));
         return FALSE;
     }
     // LDAP authentication failed.
     static::getLogger()->warning('Cannot connect to LDAP or username is empty', array('username' => $username));
     Ldap::getInstance()->disconnect();
     return FALSE;
 }
Example #2
0
 /**
  * Checks the LDAP connection and prepares a Flash message if unavailable.
  *
  * @return bool
  */
 protected function checkLdapConnection()
 {
     try {
         $success = $this->ldap->connect(Configuration::getLdapConfiguration());
     } catch (\Causal\IgLdapSsoAuth\Exception\UnresolvedPhpDependencyException $e) {
         // Possible known exception: 1409566275, LDAP extension is not available for PHP
         $this->addFlashMessage($e->getMessage(), 'Error ' . $e->getCode(), \TYPO3\CMS\Core\Messaging\FlashMessage::ERROR);
         return FALSE;
     }
     return $success;
 }
Example #3
0
 /**
  * Returns the corresponding DN if a given user is provided, otherwise FALSE.
  *
  * @param string $username
  * @param string $password User's password. If NULL password will not be checked
  * @param string $baseDn
  * @param string $filter
  * @return bool|string
  */
 public function validateUser($username = NULL, $password = NULL, $baseDn = NULL, $filter = NULL)
 {
     // If user found on ldap server.
     if ($this->ldapUtility->search($baseDn, str_replace('{USERNAME}', $username, $filter), array('dn'))) {
         // Validate with password.
         if ($password !== NULL) {
             // Bind DN of user with password.
             if (empty($password)) {
                 $this->lastBindDiagnostic = 'Empty password provided!';
                 return FALSE;
             } elseif ($this->ldapUtility->bind($this->ldapUtility->getDn(), $password)) {
                 $dn = $this->ldapUtility->getDn();
                 // Restore last LDAP binding
                 $config = Configuration::getLdapConfiguration();
                 $this->ldapUtility->bind($config['binddn'], $config['password']);
                 $this->lastBindDiagnostic = '';
                 return $dn;
             } else {
                 $status = $this->ldapUtility->getStatus();
                 $this->lastBindDiagnostic = $status['bind']['diagnostic'];
                 return FALSE;
                 // Password does not match
             }
             // If enable, SSO authentication without password
         } elseif ($password === NULL && Configuration::getValue('SSOAuthentication')) {
             return $this->ldapUtility->getDn();
         } else {
             // User invalid. Authentication failed.
             return FALSE;
         }
     }
     return FALSE;
 }
Example #4
0
 /**
  * Performs the synchronization of LDAP users according to selected parameters.
  *
  * @return boolean Returns TRUE on successful execution, FALSE on error
  * @throws ImportUsersException
  */
 public function execute()
 {
     // Assemble a list of configuration and contexts for import
     /** @var \Causal\IgLdapSsoAuth\Domain\Repository\ConfigurationRepository $configurationRepository */
     $configurationRepository = GeneralUtility::makeInstance('Causal\\IgLdapSsoAuth\\Domain\\Repository\\ConfigurationRepository');
     if (empty($this->configuration)) {
         $ldapConfigurations = $configurationRepository->findAll();
     } else {
         $configuration = $configurationRepository->findByUid($this->configuration);
         $ldapConfigurations = array();
         if ($configuration !== NULL) {
             $ldapConfigurations[] = $configuration;
         }
     }
     if ($this->context === 'both') {
         $executionContexts = array('fe', 'be');
     } else {
         $executionContexts = array($this->context);
     }
     $mode = $this->getMode();
     // Start a database transaction with all our changes
     // Syntax is compatible with MySQL, Oracle, MSSQL and PostgreSQL
     $this->getDatabaseConnection()->sql_query('START TRANSACTION');
     // Loop on each configuration and context and import the related users
     $failures = 0;
     foreach ($ldapConfigurations as $configuration) {
         foreach ($executionContexts as $aContext) {
             /** @var \Causal\IgLdapSsoAuth\Utility\UserImportUtility $importUtility */
             $importUtility = GeneralUtility::makeInstance('Causal\\IgLdapSsoAuth\\Utility\\UserImportUtility', $configuration, $aContext);
             $config = $importUtility->getConfiguration();
             if (empty($config['users']['filter'])) {
                 // Current context is not configured for this LDAP configuration record
                 static::getLogger()->debug(sprintf('Configuration record %s is not configured for context "%s"', $configuration->getUid(), $aContext));
                 unset($importUtility);
                 continue;
             }
             // Start by connecting to the designated LDAP/AD server
             $success = Ldap::getInstance()->connect(Configuration::getLdapConfiguration());
             // Proceed with import if successful
             if (!$success) {
                 $failures++;
                 unset($importUtility);
                 continue;
             }
             $ldapUsers = $importUtility->fetchLdapUsers();
             // Consider that fetching no users from LDAP is an error
             if (count($ldapUsers) === 0) {
                 static::getLogger()->error(sprintf('No users (%s) found for configuration record %s', $aContext, $configuration->getUid()));
                 $failures++;
             } else {
                 // Disable or delete users, according to settings
                 if ($this->missingUsersHandling === 'disable') {
                     static::getLogger()->debug(sprintf('Disabling users (%s) for configuration record %s', $aContext, $configuration->getUid()));
                     $importUtility->disableUsers();
                 } elseif ($this->missingUsersHandling === 'delete') {
                     static::getLogger()->debug(sprintf('Deleting users (%s) for configuration record %s', $aContext, $configuration->getUid()));
                     $importUtility->deleteUsers();
                 }
                 // Proceed with import (handle partial result sets until every LDAP record has been returned)
                 do {
                     $typo3Users = $importUtility->fetchTypo3Users($ldapUsers);
                     // Loop on all users and import them
                     foreach ($ldapUsers as $index => $aUser) {
                         if ($mode === 'sync' && empty($typo3Users[$index]['uid'])) {
                             // New LDAP user => skip it since only existing TYPO3 users should get synchronized
                             continue;
                         }
                         // Merge LDAP and TYPO3 information
                         $user = Authentication::merge($aUser, $typo3Users[$index], $config['users']['mapping']);
                         // Import the user using information from LDAP
                         $importUtility->import($user, $aUser, $this->restoredUsersHandling);
                     }
                     static::getLogger()->info(sprintf('Configuration record %s: processed %s LDAP users (%s)', $configuration->getUid(), count($ldapUsers), $aContext));
                     // Free memory before going on
                     $typo3Users = NULL;
                     $ldapUsers = NULL;
                     $ldapUsers = $importUtility->hasMoreLdapUsers() ? $importUtility->fetchLdapUsers(TRUE) : array();
                 } while (count($ldapUsers) > 0);
             }
             // Clean up
             unset($importUtility);
             Ldap::getInstance()->disconnect();
         }
     }
     // If some failures were registered, rollback the whole transaction and report error
     if ($failures > 0) {
         $this->getDatabaseConnection()->sql_query('ROLLBACK');
         $message = 'Some or all imports failed. Synchronisation was aborted. Check your settings or your network connection';
         static::getLogger()->error($message);
         throw new ImportUsersException($message, 1410774015);
     } else {
         // Everything went fine, commit the changes
         $this->getDatabaseConnection()->sql_query('COMMIT');
     }
     return TRUE;
 }