[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/plugins/authentication/ldap/ -> ldap.php (source)

   1  <?php
   2  
   3  /**
   4   * @package     Joomla.Plugin
   5   * @subpackage  Authentication.ldap
   6   *
   7   * @copyright   (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license     GNU General Public License version 2 or later; see LICENSE.txt
   9  
  10   * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
  11   */
  12  
  13  use Joomla\CMS\Authentication\Authentication;
  14  use Joomla\CMS\Language\Text;
  15  use Joomla\CMS\Plugin\CMSPlugin;
  16  use Symfony\Component\Ldap\Entry;
  17  use Symfony\Component\Ldap\Exception\ConnectionException;
  18  use Symfony\Component\Ldap\Exception\LdapException;
  19  use Symfony\Component\Ldap\Ldap;
  20  
  21  // phpcs:disable PSR1.Files.SideEffects
  22  \defined('_JEXEC') or die;
  23  // phpcs:enable PSR1.Files.SideEffects
  24  
  25  /**
  26   * LDAP Authentication Plugin
  27   *
  28   * @since  1.5
  29   */
  30  class PlgAuthenticationLdap extends CMSPlugin
  31  {
  32      /**
  33       * This method should handle any authentication and report back to the subject
  34       *
  35       * @param   array   $credentials  Array holding the user credentials
  36       * @param   array   $options      Array of extra options
  37       * @param   object  &$response    Authentication response object
  38       *
  39       * @return  boolean
  40       *
  41       * @since   1.5
  42       */
  43      public function onUserAuthenticate($credentials, $options, &$response)
  44      {
  45          // If LDAP not correctly configured then bail early.
  46          if (!$this->params->get('host')) {
  47              return false;
  48          }
  49  
  50          // For JLog
  51          $response->type = 'LDAP';
  52  
  53          // Strip null bytes from the password
  54          $credentials['password'] = str_replace(chr(0), '', $credentials['password']);
  55  
  56          // LDAP does not like Blank passwords (tries to Anon Bind which is bad)
  57          if (empty($credentials['password'])) {
  58              $response->status = Authentication::STATUS_FAILURE;
  59              $response->error_message = Text::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
  60  
  61              return false;
  62          }
  63  
  64          // Load plugin params info
  65          $ldap_email    = $this->params->get('ldap_email');
  66          $ldap_fullname = $this->params->get('ldap_fullname');
  67          $ldap_uid      = $this->params->get('ldap_uid');
  68          $auth_method   = $this->params->get('auth_method');
  69  
  70          $ldap = Ldap::create(
  71              'ext_ldap',
  72              [
  73                  'host'       => $this->params->get('host'),
  74                  'port'       => (int) $this->params->get('port'),
  75                  'version'    => $this->params->get('use_ldapV3', '0') == '1' ? 3 : 2,
  76                  'referrals'  => (bool) $this->params->get('no_referrals', '0'),
  77                  'encryption' => $this->params->get('negotiate_tls', '0') == '1' ? 'tls' : 'none',
  78              ]
  79          );
  80  
  81          switch ($auth_method) {
  82              case 'search':
  83                  try {
  84                      $dn = str_replace('[username]', $this->params->get('username', ''), $this->params->get('users_dn', ''));
  85  
  86                      $ldap->bind($dn, $this->params->get('password', ''));
  87                  } catch (ConnectionException | LdapException $exception) {
  88                      $response->status = Authentication::STATUS_FAILURE;
  89                      $response->error_message = Text::_('JGLOBAL_AUTH_NOT_CONNECT');
  90  
  91                      return;
  92                  }
  93  
  94                  // Search for users DN
  95                  try {
  96                      $entry = $this->searchByString(
  97                          str_replace(
  98                              '[search]',
  99                              str_replace(';', '\3b', $ldap->escape($credentials['username'], '', LDAP_ESCAPE_FILTER)),
 100                              $this->params->get('search_string')
 101                          ),
 102                          $ldap
 103                      );
 104                  } catch (LdapException $exception) {
 105                      $response->status = Authentication::STATUS_FAILURE;
 106                      $response->error_message = Text::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED');
 107  
 108                      return;
 109                  }
 110  
 111                  if (!$entry) {
 112                      $response->status = Authentication::STATUS_FAILURE;
 113                      $response->error_message = Text::_('JGLOBAL_AUTH_NOT_CONNECT');
 114  
 115                      return;
 116                  }
 117  
 118                  try {
 119                      // Verify Users Credentials
 120                      $ldap->bind($entry->getDn(), $credentials['password']);
 121                  } catch (ConnectionException $exception) {
 122                      $response->status = Authentication::STATUS_FAILURE;
 123                      $response->error_message = Text::_('JGLOBAL_AUTH_INVALID_PASS');
 124  
 125                      return;
 126                  }
 127  
 128                  break;
 129  
 130              case 'bind':
 131                  // We just accept the result here
 132                  try {
 133                      $ldap->bind($ldap->escape($credentials['username'], '', LDAP_ESCAPE_DN), $credentials['password']);
 134                  } catch (ConnectionException | LdapException $exception) {
 135                      $response->status = Authentication::STATUS_FAILURE;
 136                      $response->error_message = Text::_('JGLOBAL_AUTH_INVALID_PASS');
 137  
 138                      return;
 139                  }
 140  
 141                  try {
 142                      $entry = $this->searchByString(
 143                          str_replace(
 144                              '[search]',
 145                              str_replace(';', '\3b', $ldap->escape($credentials['username'], '', LDAP_ESCAPE_FILTER)),
 146                              $this->params->get('search_string')
 147                          ),
 148                          $ldap
 149                      );
 150                  } catch (LdapException $exception) {
 151                      $response->status = Authentication::STATUS_FAILURE;
 152                      $response->error_message = Text::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED');
 153  
 154                      return;
 155                  }
 156  
 157                  break;
 158  
 159              default:
 160                  // Unsupported configuration
 161                  $response->status = Authentication::STATUS_FAILURE;
 162                  $response->error_message = Text::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED');
 163  
 164                  return;
 165          }
 166  
 167          // Grab some details from LDAP and return them
 168          $response->username = $entry->getAttribute($ldap_uid)[0] ?? false;
 169          $response->email    = $entry->getAttribute($ldap_email)[0] ?? false;
 170          $response->fullname = $entry->getAttribute($ldap_fullname)[0] ?? trim($entry->getAttribute($ldap_fullname)[0]) ?: $credentials['username'];
 171  
 172          // Were good - So say so.
 173          $response->status        = Authentication::STATUS_SUCCESS;
 174          $response->error_message = '';
 175  
 176          // The connection is no longer needed, destroy the object to close it
 177          unset($ldap);
 178      }
 179  
 180      /**
 181       * Shortcut method to perform a LDAP search based on a semicolon separated string
 182       *
 183       * Note that this method requires that semicolons which should be part of the search term to be escaped
 184       * to correctly split the search string into separate lookups
 185       *
 186       * @param   string  $search  search string of search values
 187       * @param   Ldap    $ldap    The LDAP client
 188       *
 189       * @return  Entry|null The search result entry if a matching record was found
 190       *
 191       * @since   3.8.2
 192       */
 193      private function searchByString($search, Ldap $ldap)
 194      {
 195          $dn = $this->params->get('base_dn');
 196  
 197          // We return the first entry from the first search result which contains data
 198          foreach (explode(';', $search) as $key => $result) {
 199              $results = $ldap->query($dn, '(' . str_replace('\3b', ';', $result) . ')')->execute();
 200  
 201              if (count($results)) {
 202                  return $results[0];
 203              }
 204          }
 205      }
 206  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer