"Fossies" - the Fresh Open Source Software Archive

Member "fogproject-1.5.9/packages/web/lib/plugins/ldap/class/ldap.class.php" (13 Sep 2020, 25344 Bytes) of package /linux/misc/fogproject-1.5.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "ldap.class.php": 1.5.8_vs_1.5.9.

    1 <?php
    2 /**
    3  * LDAP Authentication plugin
    4  *
    5  * PHP version 5
    6  *
    7  * @category LDAP
    8  * @package  FOGProject
    9  * @author   Fernando Gietz <nah@nah.com>
   10  * @author   george1421 <nah@nah.com>
   11  * @author   Tom Elliott <tommygunsster@gmail.com>
   12  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   13  * @link     https://fogproject.org
   14  */
   15 /**
   16  * LDAP Authentication plugin
   17  *
   18  * @category LDAP
   19  * @package  FOGProject
   20  * @author   Fernando Gietz <nah@nah.com>
   21  * @author   george1421 <nah@nah.com>
   22  * @author   Tom Elliott <tommygunsster@gmail.com>
   23  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   24  * @link     https://fogproject.org
   25  */
   26 class LDAP extends FOGController
   27 {
   28     /**
   29      * Ldap connection itself
   30      *
   31      * @var resource
   32      */
   33     private static $_ldapconn;
   34     /**
   35      * The ldap table
   36      *
   37      * @var string
   38      */
   39     protected $databaseTable = 'LDAPServers';
   40     /**
   41      * The LDAP table fields and common names
   42      *
   43      * @var array
   44      */
   45     protected $databaseFields = array(
   46         'id' => 'lsID',
   47         'name' => 'lsName',
   48         'description' => 'lsDesc',
   49         'createdBy' => 'lsCreatedBy',
   50         'createdTime' => 'lsCreatedTime',
   51         'address' => 'lsAddress',
   52         'port' => 'lsPort',
   53         'searchDN' => 'lsUserSearchDN',
   54         'userNamAttr' => 'lsUserNamAttr',
   55         'grpMemberAttr' => 'lsGrpMemberAttr',
   56         'adminGroup' => 'lsAdminGroup',
   57         'userGroup' => 'lsUserGroup',
   58         'searchScope' => 'lsSearchScope',
   59         'bindDN' => 'lsBindDN',
   60         'bindPwd' => 'lsBindPwd',
   61         'grpSearchDN' => 'lsGrpSearchDN',
   62         'useGroupMatch' => 'lsUseGroupMatch',
   63     );
   64     /**
   65      * The required fields
   66      *
   67      * @var array
   68      */
   69     protected $databaseFieldsRequired = array(
   70         'name',
   71         'address',
   72         'port',
   73         'searchDN',
   74         //'userNamAttr',
   75         //'grpMemberAttr',
   76         'searchScope',
   77         'useGroupMatch',
   78         // 'grpSearchDN',
   79         /**
   80          * I think it's fine these are not "required"
   81          * What if you want admin group to only be done by
   82          * a particular ldap server?
   83          *
   84          * Same for a "user group" why should we require both?
   85          */
   86         // 'adminGroup',
   87         // 'userGroup',
   88     );
   89     /**
   90      * Magic function to enable ldap_ function calls using
   91      * an object oriented call structure
   92      *
   93      * @param string $function the function to call (only the back half).
   94      * @param array  $args     the functions required arguments
   95      *
   96      * @throws Exception
   97      * @return function return
   98      */
   99     public function __call($function, $args)
  100     {
  101         $func = $function;
  102         $function = 'ldap_'.$func;
  103         if (!function_exists($function)) {
  104             throw new Exception(
  105                 sprintf(
  106                     '%s %s',
  107                     _('Function does not exist'),
  108                     $function
  109                 )
  110             );
  111         }
  112         $nonresourcefuncs = array(
  113             '8859_to_t61',
  114             'connect',
  115             'dn2ufn',
  116             'err2str',
  117             'escape',
  118             'explode_dn',
  119             't61_to_8859',
  120         );
  121         if (!in_array($func, $nonresourcefuncs)) {
  122             array_unshift($args, self::$_ldapconn);
  123         }
  124         $ret = call_user_func_array($function, $args);
  125         return $ret;
  126     }
  127     /**
  128      * Tests if the server is up and available
  129      *
  130      * @param int $timeout how long before timeout
  131      *
  132      * @return bool|string
  133      */
  134     private function _ldapUp($timeout = 3)
  135     {
  136         $ldap = 'ldap';
  137         $ports = array_map(
  138             'trim',
  139             explode(
  140                 ',',
  141                 self::getSetting('LDAP_PORTS')
  142             )
  143         );
  144         $port = $this->get('port');
  145         $address = preg_replace('#^.*://#i', '', $this->get('address'));
  146         if (!in_array($port, $ports)) {
  147             throw new Exception(_('Port is not valid ldap/ldaps port'));
  148         }
  149         $sock = @pfsockopen(
  150             $address,
  151             $port,
  152             $errno,
  153             $errstr,
  154             $timeout
  155         );
  156         if ($sock === false) {
  157             return false;
  158         }
  159         fclose($sock);
  160         return sprintf(
  161             '%s%s://%s',
  162             $ldap,
  163             (
  164                 in_array($port, [ 636, 686, 3269, 7636 ]) ?
  165                 's' :
  166                 ''
  167             ),
  168             $address
  169         );
  170     }
  171     /**
  172      * Parses the DN
  173      *
  174      * @param string $dn the DN to parse
  175      *
  176      * @return array
  177      */
  178     private function _ldapParseDn($dn)
  179     {
  180         /**
  181          * Explode the DN into it's sub components.
  182          */
  183         $parser = $this->explode_dn($dn, 0);
  184         /**
  185          * Initialize our out array.
  186          */
  187         $out = array();
  188         /**
  189          * Loop the parsed information so we get
  190          * the values in a mroe usable and joinable form.
  191          */
  192         foreach ((array)$parser as $key => &$value) {
  193             if (false !== strstr($value, '=')) {
  194                 list(
  195                     $prefix,
  196                     $data
  197                 ) = explode('=', $value);
  198                 $prefix = strtoupper($prefix);
  199                 preg_replace_callback(
  200                     "/\\\([0-9A-Fa-f]{2})/",
  201                     function ($matches) {
  202                         foreach ((array)$matches as &$match) {
  203                             return chr(hexdec($match));
  204                         }
  205                     },
  206                     $data
  207                 );
  208                 if (isset($current_prefix)
  209                     && $prefix == $current_prefix
  210                 ) {
  211                     $out[$prefix][] = $data;
  212                 } else {
  213                     $current_prefix = $prefix;
  214                     $out[$prefix][] = $data;
  215                 }
  216             }
  217             unset($value);
  218         }
  219         return $out;
  220     }
  221     /**
  222      * Checks if the user/pass are valid
  223      *
  224      * @param string $user the username to validate
  225      * @param string $pass the password to validate
  226      *
  227      * @return bool|int
  228      */
  229     public function authLDAP($user, $pass)
  230     {
  231         /**
  232          * Ensure any trailing bindings are removed
  233          */
  234         @$this->unbind();
  235         /**
  236          * Trim the values just incase somebody is trying
  237          * to break in by using spaces -- prevent dos attack I imagine.
  238          */
  239         $user = trim($user);
  240         $pass = trim($pass);
  241         /**
  242          * User and/or Pass is empty
  243          *
  244          * @return bool
  245          */
  246         if (empty($user)
  247             || empty($pass)
  248         ) {
  249             return false;
  250         }
  251         /**
  252          * Server is not reachable
  253          *
  254          * @return bool
  255          */
  256         if (!$server = $this->_ldapUp()) {
  257             return false;
  258         }
  259         /**
  260          * Test the username for funky characters and return
  261          * immediately if found.
  262          */
  263         $test = preg_match(
  264             '/(?=^.{3,40}$)^[\w][\w0-9]*[._-]?[\w0-9]*[.]?[\w0-9]+$/i',
  265             $user
  266         );
  267         if (!$test) {
  268             return false;
  269         }
  270         /**
  271          * If, after character checking, the user is empty
  272          *
  273          * @return bool
  274          */
  275         if (empty($user)) {
  276             return false;
  277         }
  278         $port = (int)$this->get('port');
  279         /**
  280          * Open connection to the server
  281          */
  282         self::$_ldapconn = ldap_connect(
  283             $server,
  284             $port
  285         );
  286         /**
  287          * If we can't connect return immediately
  288          */
  289         if (!self::$_ldapconn) {
  290             error_log(
  291                 sprintf(
  292                     '%s %s() %s %s:%d',
  293                     _('Plugin'),
  294                     __METHOD__,
  295                     _('We cannot connect to LDAP server'),
  296                     $server,
  297                     $port
  298                 )
  299             );
  300             return false;
  301         }
  302         /**
  303          * Sets the ldap options we need
  304          */
  305         $this->set_option(
  306             LDAP_OPT_PROTOCOL_VERSION,
  307             3
  308         );
  309         $this->set_option(
  310             LDAP_OPT_REFERRALS,
  311             0
  312         );
  313         /**
  314          * Sets our default accessLevel to 0.
  315          * 0 = fail
  316          * 1 = mobile
  317          * 2 = admin
  318          */
  319         $accessLevel = 0;
  320         /**
  321          * Flag to tell if we use ldap groups or not
  322          */
  323         $useGroupMatch = $this->get('useGroupMatch');
  324         /**
  325          * Setup bind dn and password
  326          */
  327         $bindDN = $this->get('bindDN');
  328         /**
  329          * The bind password.
  330          */
  331         $bindPass = $this->get('bindPwd');
  332         /**
  333          * The user name attribute in use (e.g. uid=)
  334          */
  335         $usrNamAttr = strtolower($this->get('userNamAttr'));
  336         /**
  337          * The group member attribute in use (e.g. memberOf=)
  338          */
  339         $grpMemAttr = strtolower($this->get('grpMemberAttr'));
  340         /**
  341          * Set up our search/group information
  342          */
  343         $searchDN = $this->get('searchDN');
  344         /**
  345          * Parse our user search DN
  346          */
  347         $parsedDN = $this->_ldapParseDn($searchDN);
  348         /**
  349          * If binddn is set run through it.
  350          * Of course we don't need to do this if the
  351          * use group match isn't set.  We do still need
  352          * to run the main parsing checks.
  353          */
  354         if ($useGroupMatch > 0 && !empty($bindDN)) {
  355             /**
  356              * Trims the bind pass.
  357              */
  358             $bindPass = trim($bindPass);
  359             /**
  360              * We need to decrypt the stored pass.
  361              */
  362             $bindPasstest = self::aesdecrypt($bindPass);
  363             if ($test_base64 = base64_decode($bindPasstest)) {
  364                 if (mb_detect_encoding($test_base64, 'utf-8', true)) {
  365                     $bindPass = $test_base64;
  366                 } elseif (mb_detect_encoding($bindPasstest, 'utf-8', true)) {
  367                     $bindPass = $bindPasstest;
  368                 }
  369             }
  370             /**
  371              * If no bind password return immediately
  372              */
  373             if (empty($bindPass)) {
  374                 error_log(
  375                     sprintf(
  376                         '%s %s() %s %s!',
  377                         _('Plugin'),
  378                         __METHOD__,
  379                         _('Using the group match function'),
  380                         _('but bind password is not set')
  381                     )
  382                 );
  383                 return false;
  384             }
  385             /**
  386              * Make our bindDN/pass connection
  387              */
  388             $bind = @$this->bind($bindDN, $bindPass);
  389             /**
  390              * If we cannot bind return immediately
  391              */
  392             if (!$bind) {
  393                 error_log(
  394                     sprintf(
  395                         '%s %s() %s %s:%d',
  396                         _('Plugin'),
  397                         __METHOD__,
  398                         _('Cannot bind to the LDAP server'),
  399                         $server,
  400                         $port
  401                     )
  402                 );
  403                 return false;
  404             }
  405             /**
  406              * Set our filter to return our object
  407              */
  408             $filter = sprintf(
  409                 '(&(|(objectcategory=person)(objectclass=person))(%s=%s))',
  410                 $usrNamAttr,
  411                 $user
  412             );
  413             /**
  414              * Setup bind DN attribute
  415              */
  416             $attr = array('dn');
  417             /**
  418              * Get our results
  419              */
  420             $result = $this->_result($searchDN, $filter, $attr);
  421             /**
  422              * Return immediately if the result is false
  423              */
  424             if ($result === false) {
  425                 error_log(
  426                     sprintf(
  427                         '%s %s() %s. %s: %s; %s: %s',
  428                         _('Plugin'),
  429                         __METHOD__,
  430                         _('Search results returned false'),
  431                         _('Search DN'),
  432                         $searchDN,
  433                         _('Filter'),
  434                         $filter
  435                     )
  436                 );
  437                 return false;
  438             }
  439             /**
  440              * Only one entry
  441              */
  442             $entries = $this->get_entries($result);
  443             /**
  444              * Pull out the user dn
  445              */
  446             $userDN = $entries[0]['dn'];
  447             /**
  448              * Rebind as the user
  449              */
  450             $bind = @$this->bind($userDN, $pass);
  451             /**
  452              * If user unable to bind return immediately
  453              */
  454             if (!$bind) {
  455                 error_log(
  456                     sprintf(
  457                         '%s %s() %s. %s: %s',
  458                         _('Plugin'),
  459                         __METHOD__,
  460                         _('User was not authorized by the LDAP server'),
  461                         _('User DN'),
  462                         $userDN
  463                     )
  464                 );
  465                 return false;
  466             }
  467         } else {
  468             /**
  469              * Parse the search dn
  470              */
  471             $parsedDN = $this->_ldapParseDn($searchDN);
  472             /**
  473              * Combine to get the Domain in information.
  474              */
  475             $userDomain = implode('.', (array)$parsedDN['DC']);
  476             /**
  477              * Setup a multitude of ways to bind
  478              */
  479             $userDN = sprintf(
  480                 '%s=%s,%s',
  481                 $usrNamAttr,
  482                 $user,
  483                 $searchDN
  484             );
  485             $userDN1 = sprintf(
  486                 '%s@%s',
  487                 $user,
  488                 $userDomain
  489             );
  490             $userDN2 = sprintf(
  491                 '%s\%s',
  492                 $userDomain,
  493                 $user
  494             );
  495             /**
  496              * If our ways here don't work, return immediately
  497              */
  498             if (!@$this->bind($userDN, $pass)) {
  499                 $userDN = $userDN1;
  500             }
  501             if (!@$this->bind($userDN, $pass)) {
  502                 $userDN = $userDN2;
  503             }
  504             if (!@$this->bind($userDN, $pass)) {
  505                 error_log(
  506                     sprintf(
  507                         '%s %s() %s.',
  508                         _('Plugin'),
  509                         __METHOD__,
  510                         _('All methods of binding have failed')
  511                     )
  512                 );
  513                 @$this->unbind();
  514                 return false;
  515             }
  516         }
  517         $attr = array('dn');
  518         $filter = sprintf(
  519             '(&(|(objectcategory=person)(objectclass=person))(%s=%s))',
  520             $usrNamAttr,
  521             $user
  522         );
  523         $result = $this->_result($searchDN, $filter, $attr);
  524         if (false === $result) {
  525             error_log(
  526                 sprintf(
  527                     '%s %s() %s. %s: %s; %s: %s',
  528                     _('Plugin'),
  529                     __METHOD__,
  530                     _('Search DN did not return any results'),
  531                     _('Search DN'),
  532                     $searchDN,
  533                     _('Filter'),
  534                     $filter
  535                 )
  536             );
  537             @$this->unbind();
  538             return false;
  539         }
  540         /**
  541          * Only one entry
  542          */
  543         $entries = $this->get_entries($result);
  544         /**
  545          * Pull out the user dn
  546          */
  547         $userDN = $entries[0]['dn'];
  548         /**
  549          * If use group match is used, get access level,
  550          * otherwise group scanning isn't used. Assume all
  551          * are admins.
  552          */
  553         if ($useGroupMatch) {
  554             $accessLevel = $this->_getAccessLevel($grpMemAttr, $userDN);
  555         } else {
  556             $accessLevel = 2;
  557         }
  558         /**
  559          * Close our connection
  560          */
  561         @$this->unbind();
  562         /**
  563          * If access level is not changed
  564          *
  565          * @return bool
  566          */
  567         if ($accessLevel == 0) {
  568             error_log(
  569                 sprintf(
  570                     '%s %s() %s. %s!',
  571                     _('Plugin'),
  572                     __METHOD__,
  573                     _('Access level is still 0 or false'),
  574                     _('No access is allowed')
  575                 )
  576             );
  577             return false;
  578         }
  579         /**
  580          * Return the access level
  581          *
  582          * @return int
  583          */
  584         return $accessLevel;
  585     }
  586     /**
  587      * Get's the access level
  588      *
  589      * @param string $grpMemAttr the group finder item
  590      * @param string $userDN     the user dn information
  591      *
  592      * @return int
  593      */
  594     private function _getAccessLevel($grpMemAttr, $userDN)
  595     {
  596         /**
  597          * Preset our access level value
  598          */
  599         $accessLevel = false;
  600         /**
  601          * Get our admin group
  602          */
  603         $adminGroup = $this->get('adminGroup');
  604         /**
  605          * Get our user group
  606          */
  607         $userGroup = $this->get('userGroup');
  608         /**
  609          * Use search base where the groups are located
  610          */
  611         $grpSearchDN = $this->get('grpSearchDN');
  612         if (!$grpSearchDN) {
  613             $parsedDN = $this->_ldapParseDn($userDN);
  614             $grpSearchDN = 'dc='.implode(',dc=', $parsedDN['DC']);
  615         }
  616         /**
  617          * Setup our new filter
  618          */
  619         $adminGroups = explode(',', $adminGroup);
  620         $adminGroups = array_map('trim', $adminGroups);
  621         $filter = sprintf(
  622             '(&(|(name=%s))(%s=%s))',
  623             implode(')(name=', (array)$adminGroups),
  624             $grpMemAttr,
  625             $this->escape($userDN, null, LDAP_ESCAPE_FILTER)
  626         );
  627         /**
  628          * The attribute to get.
  629          */
  630         $attr = array($grpMemAttr);
  631         /**
  632          * Read in the attributes
  633          */
  634         $result = $this->_result($grpSearchDN, $filter, $attr);
  635         if (false !== $result) {
  636             return 2;
  637         }
  638         /**
  639          * If no record is returned then user is not in the
  640          * admin group. Change the filter and check the mobile
  641          * group for membership.
  642          */
  643         $userGroups = explode(',', $userGroup);
  644         $userGroups = array_map('trim', $userGroups);
  645         $filter = sprintf(
  646             '(&(|(name=%s))(%s=%s))',
  647             implode(')(name=', (array)$userGroups),
  648             $grpMemAttr,
  649             $this->escape($userDN, null, LDAP_ESCAPE_FILTER)
  650         );
  651         /**
  652          * The attribute to get.
  653          */
  654         $attr = array($grpMemAttr);
  655         /**
  656          * Execute the ldap query
  657          */
  658         $result = $this->_result($grpSearchDN, $filter, $attr);
  659         /**
  660          * If no record is returned then lets try the looping method
  661          */
  662         if (false !== $result) {
  663             return 1;
  664         }
  665         /**
  666          * Setup the generalized filter
  667          */
  668         $filter = sprintf(
  669             '(%s=*)',
  670             $grpMemAttr
  671         );
  672         /**
  673          * The attribute to get.
  674          */
  675         $attr = array($grpMemAttr);
  676         /**
  677          * Read in the attributes
  678          */
  679         $result = $this->_result($grpSearchDN, $filter, $attr);
  680         /**
  681          * Return immediately if the result is false
  682          */
  683         if (false === $result) {
  684             error_log(
  685                 sprintf(
  686                     '%s %s() %s. %s: %s',
  687                     _('Plugin'),
  688                     __METHOD__,
  689                     _('Group Search DN did not return any results'),
  690                     _('Group Search DN'),
  691                     $grpSearchDN
  692                 )
  693             );
  694             @$this->unbind();
  695             return false;
  696         }
  697         /**
  698          * Get the entries found
  699          */
  700         $entries = $this->get_entries($result);
  701         /**
  702          * Setup pattern for later, the i means ignore case
  703          */
  704         $pat = sprintf(
  705             '#%s#i',
  706             $userDN
  707         );
  708         /**
  709          * Check groups for membership
  710          */
  711         foreach ((array)$entries as &$entry) {
  712             /**
  713              * If this cycle doesn't have the dn, skip it
  714              */
  715             if (!isset($entry['dn'])) {
  716                 continue;
  717             }
  718             /**
  719              * Get the dn entry we need to test against
  720              */
  721             $dn = $entry['dn'];
  722             /**
  723              * Get the users related to this dn
  724              */
  725             $users = $entry[$grpMemAttr];
  726             /**
  727              * Tests the presence of our admin group
  728              */
  729             $admin = false;
  730             if ($adminGroup) {
  731                 $admin = strpos($dn, $adminGroup);
  732             }
  733             /**
  734              * Tests the presence of our mobile group
  735              */
  736             $user = false;
  737             if ($userGroup) {
  738                 $user = strpos($dn, $userGroup);
  739             }
  740             /**
  741              * If we can't find our relative dn
  742              * set go back to top of loop.
  743              */
  744             if (false === $admin
  745                 && false === $user
  746             ) {
  747                 continue;
  748             }
  749             /**
  750              * If the dn is in the admin scope
  751              */
  752             if (false !== $admin) {
  753                 /**
  754                  * Test if the user dn exists in this group
  755                  */
  756                 $adm = preg_grep($pat, $users);
  757                 /**
  758                  * Ensure we only return "filled" items
  759                  */
  760                 $adm = array_filter($adm);
  761                 /**
  762                  * If so, no need to move on, set access level and break loop
  763                  */
  764                 if (count($adm) > 0) {
  765                     $accessLevel = 2;
  766                     break;
  767                 }
  768             }
  769             /**
  770              * If the dn is in the mobile scope
  771              */
  772             if (false !== $user) {
  773                 /**
  774                  * Test if the user dn exists in this group
  775                  */
  776                 $usr = preg_grep($pat, $users);
  777                 /**
  778                  * Ensure we only return "filled" items
  779                  */
  780                 $usr = array_filter($usr);
  781                 /**
  782                  * If so, set our access level. We remain in loop
  783                  * so if another group has this same user as admin
  784                  * it can get it's proper permissions.
  785                  */
  786                 if (count($usr) > 0) {
  787                     $accessLevel = 1;
  788                 }
  789             }
  790         }
  791         /**
  792          * Return the access level
  793          */
  794         return $accessLevel;
  795     }
  796     /**
  797      * Get the results
  798      *
  799      * @param string $searchDN the search dn
  800      * @param string $filter   filter string
  801      * @param array  $attr     attributes to get
  802      *
  803      * @return resource
  804      */
  805     private function _result($searchDN, $filter, array $attr)
  806     {
  807         /**
  808          * Search scope
  809          * 0 = read
  810          * 1 = list (ls on current directory)
  811          * 2 = search (ls -R on current directory)
  812          */
  813         $searchScope = (int)$this->get('searchScope');
  814         /**
  815          * Set our method caller
  816          */
  817         switch ($searchScope) {
  818         case 1:
  819             $method = 'list';
  820             break;
  821         case 2:
  822             $method = 'search';
  823             break;
  824         default:
  825             $method = 'read';
  826         }
  827         /**
  828          * Ensure our search dn is utf-8 encoded for searching
  829          */
  830         $searchDN = mb_convert_encoding($searchDN, 'utf-8');
  831         /**
  832          * Get the results
  833          */
  834         $result = $this->{$method}($searchDN, $filter, $attr);
  835         /**
  836          * Count our entries
  837          */
  838         $retcount = $this->count_entries($result);
  839         /**
  840          * If multiple entries or no entries return immediately
  841          */
  842         if ($retcount < 1) {
  843             error_log(
  844                 sprintf(
  845                     '%s %s(). %s: %s; %s: %s; %s: %s',
  846                     _('Plugin'),
  847                     __METHOD__,
  848                     _('Search Method'),
  849                     $method,
  850                     _('Filter'),
  851                     $filter,
  852                     _('Result'),
  853                     $retcount
  854                 )
  855             );
  856             return false;
  857         }
  858         /**
  859          * Return the result
  860          */
  861         return $result;
  862     }
  863     /**
  864      * Gets an item from the key sent, if no key all object data is returned.
  865      *
  866      * @param string $key the key to get.
  867      *
  868      * @return mixed
  869      */
  870     public function get($key = '')
  871     {
  872         $keys = array(
  873             'searchDN',
  874             'grpSearchDN',
  875             'bindDN',
  876             'adminGroup',
  877             'userGroup'
  878         );
  879         if (in_array($key, $keys)) {
  880             $dn = trim(parent::get($key));
  881             $dn = strtolower($dn);
  882             $dn = html_entity_decode(
  883                 $dn,
  884                 ENT_QUOTES,
  885                 'utf-8'
  886             );
  887             $dn = mb_convert_case(
  888                 $dn,
  889                 MB_CASE_LOWER,
  890                 'utf-8'
  891             );
  892             $this->set($key, $dn);
  893         }
  894         return parent::get($key);
  895     }
  896 }