Source for file ldap.php

Documentation is available at ldap.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Client
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM') or die;
  11.  
  12. /**
  13.  * LDAP client class
  14.  *
  15.  * @package     Joomla.Platform
  16.  * @subpackage  Client
  17.  * @since       12.1
  18.  */
  19. {
  20.     /**
  21.      * @var    string  Hostname of LDAP server
  22.      * @since  12.1
  23.      */
  24.     public $host = null;
  25.  
  26.     /**
  27.      * @var    bool  Authorization Method to use
  28.      * @since  12.1
  29.      */
  30.     public $auth_method = null;
  31.  
  32.     /**
  33.      * @var    int  Port of LDAP server
  34.      * @since  12.1
  35.      */
  36.     public $port = null;
  37.  
  38.     /**
  39.      * @var    string  Base DN (e.g. o=MyDir)
  40.      * @since  12.1
  41.      */
  42.     public $base_dn = null;
  43.  
  44.     /**
  45.      * @var    string  User DN (e.g. cn=Users,o=MyDir)
  46.      * @since  12.1
  47.      */
  48.     public $users_dn = null;
  49.  
  50.     /**
  51.      * @var    string  Search String
  52.      * @since  12.1
  53.      */
  54.     public $search_string = null;
  55.  
  56.     /**
  57.      * @var    boolean  Use LDAP Version 3
  58.      * @since  12.1
  59.      */
  60.     public $use_ldapV3 = null;
  61.  
  62.     /**
  63.      * @var    boolean  No referrals (server transfers)
  64.      * @since  11.1
  65.      */
  66.     public $no_referrals = null;
  67.  
  68.     /**
  69.      * @var    boolean  Negotiate TLS (encrypted communications)
  70.      * @since  12.1
  71.      */
  72.     public $negotiate_tls = null;
  73.  
  74.     /**
  75.      * @var    string  Username to connect to server
  76.      * @since  12.1
  77.      */
  78.     public $username = null;
  79.  
  80.     /**
  81.      *
  82.      * @var    string  Password to connect to server
  83.      * @since  12.1
  84.      */
  85.     public $password = null;
  86.  
  87.     /**
  88.      * @var    mixed  LDAP Resource Identifier
  89.      * @since  12.1
  90.      */
  91.     private $_resource = null;
  92.  
  93.     /**
  94.      *
  95.      * @var    string  Current DN
  96.      * @since  12.1
  97.      */
  98.     private $_dn = null;
  99.  
  100.     /**
  101.      * Constructor
  102.      *
  103.      * @param   object  $configObj  An object of configuration variables
  104.      *
  105.      * @since   12.1
  106.      */
  107.     public function __construct($configObj = null)
  108.     {
  109.         if (is_object($configObj))
  110.         {
  111.             $vars = get_class_vars(get_class($this));
  112.  
  113.             foreach (array_keys($vars) as $var)
  114.             {
  115.                 if (substr($var, 0, 1) != '_')
  116.                 {
  117.                     $param = $configObj->get($var);
  118.  
  119.                     if ($param)
  120.                     {
  121.                         $this->$var = $param;
  122.                     }
  123.                 }
  124.             }
  125.         }
  126.     }
  127.  
  128.     /**
  129.      * Connect to server
  130.      *
  131.      * @return  boolean  True if successful
  132.      *
  133.      * @since   12.1
  134.      */
  135.     public function connect()
  136.     {
  137.         if ($this->host == '')
  138.         {
  139.             return false;
  140.         }
  141.  
  142.         $this->_resource = @ ldap_connect($this->host, $this->port);
  143.  
  144.         if ($this->_resource)
  145.         {
  146.             if ($this->use_ldapV3)
  147.             {
  148.                 if (!@ldap_set_option($this->_resource, LDAP_OPT_PROTOCOL_VERSION, 3))
  149.                 {
  150.                     return false;
  151.                 }
  152.             }
  153.  
  154.             if (!@ldap_set_option($this->_resource, LDAP_OPT_REFERRALS, (int) $this->no_referrals))
  155.             {
  156.                 return false;
  157.             }
  158.  
  159.             if ($this->negotiate_tls)
  160.             {
  161.                 if (!@ldap_start_tls($this->_resource))
  162.                 {
  163.                     return false;
  164.                 }
  165.             }
  166.  
  167.             return true;
  168.         }
  169.         else
  170.         {
  171.             return false;
  172.         }
  173.     }
  174.  
  175.     /**
  176.      * Close the connection
  177.      *
  178.      * @return  void 
  179.      *
  180.      * @since   12.1
  181.      */
  182.     public function close()
  183.     {
  184.         @ ldap_close($this->_resource);
  185.     }
  186.  
  187.     /**
  188.      * Sets the DN with some template replacements
  189.      *
  190.      * @param   string  $username  The username
  191.      * @param   string  $nosub     ...
  192.      *
  193.      * @return  void 
  194.      *
  195.      * @since   12.1
  196.      */
  197.     public function setDN($username, $nosub = 0)
  198.     {
  199.         if ($this->users_dn == '' || $nosub)
  200.         {
  201.             $this->_dn = $username;
  202.         }
  203.         elseif (strlen($username))
  204.         {
  205.             $this->_dn = str_replace('[username]', $username, $this->users_dn);
  206.         }
  207.         else
  208.         {
  209.             $this->_dn = '';
  210.         }
  211.     }
  212.  
  213.     /**
  214.      * Get the DN
  215.      *
  216.      * @return  string  The current dn
  217.      *
  218.      * @since   12.1
  219.      */
  220.     public function getDN()
  221.     {
  222.         return $this->_dn;
  223.     }
  224.  
  225.     /**
  226.      * Anonymously binds to LDAP directory
  227.      *
  228.      * @return  array 
  229.      *
  230.      * @since   12.1
  231.      */
  232.     public function anonymous_bind()
  233.     {
  234.         $bindResult = @ldap_bind($this->_resource);
  235.  
  236.         return $bindResult;
  237.     }
  238.  
  239.     /**
  240.      * Binds to the LDAP directory
  241.      *
  242.      * @param   string  $username  The username
  243.      * @param   string  $password  The password
  244.      * @param   string  $nosub     ...
  245.      *
  246.      * @return  boolean 
  247.      *
  248.      * @since   12.1
  249.      */
  250.     public function bind($username = null, $password = null, $nosub = 0)
  251.     {
  252.         if (is_null($username))
  253.         {
  254.             $username = $this->username;
  255.         }
  256.  
  257.         if (is_null($password))
  258.         {
  259.             $password = $this->password;
  260.         }
  261.  
  262.         $this->setDN($username, $nosub);
  263.         $bindResult = @ldap_bind($this->_resource, $this->getDN(), $password);
  264.  
  265.         return $bindResult;
  266.     }
  267.  
  268.     /**
  269.      * Perform an LDAP search using comma separated search strings
  270.      *
  271.      * @param   string  $search  search string of search values
  272.      *
  273.      * @return  array  Search results
  274.      *
  275.      * @since   12.1
  276.      */
  277.     public function simple_search($search)
  278.     {
  279.         $results = explode(';', $search);
  280.  
  281.         foreach ($results as $key => $result)
  282.         {
  283.             $results[$key] = '(' . $result . ')';
  284.         }
  285.  
  286.         return $this->search($results);
  287.     }
  288.  
  289.     /**
  290.      * Performs an LDAP search
  291.      *
  292.      * @param   array   $filters     Search Filters (array of strings)
  293.      * @param   string  $dnoverride  DN Override
  294.      * @param   array   $attributes  An array of attributes to return (if empty, all fields are returned).
  295.      *
  296.      * @return  array  Multidimensional array of results
  297.      *
  298.      * @since   12.1
  299.      */
  300.     public function search(array $filters, $dnoverride = null, array $attributes = array())
  301.     {
  302.         $result = array();
  303.  
  304.         if ($dnoverride)
  305.         {
  306.             $dn = $dnoverride;
  307.         }
  308.         else
  309.         {
  310.             $dn = $this->base_dn;
  311.         }
  312.  
  313.         $resource = $this->_resource;
  314.  
  315.         foreach ($filters as $search_filter)
  316.         {
  317.             $search_result = @ldap_search($resource, $dn, $search_filter, $attributes);
  318.  
  319.             if ($search_result && ($count = @ldap_count_entries($resource, $search_result)) > 0)
  320.             {
  321.                 for ($i = 0; $i < $count; $i++)
  322.                 {
  323.                     $result[$i] = array();
  324.  
  325.                     if (!$i)
  326.                     {
  327.                         $firstentry = @ldap_first_entry($resource, $search_result);
  328.                     }
  329.                     else
  330.                     {
  331.                         $firstentry = @ldap_next_entry($resource, $firstentry);
  332.                     }
  333.  
  334.                     // Load user-specified attributes
  335.                     $result_array = @ldap_get_attributes($resource, $firstentry);
  336.  
  337.                     // LDAP returns an array of arrays, fit this into attributes result array
  338.                     foreach ($result_array as $ki => $ai)
  339.                     {
  340.                         if (is_array($ai))
  341.                         {
  342.                             $subcount = $ai['count'];
  343.                             $result[$i][$ki] = array();
  344.  
  345.                             for ($k = 0; $k < $subcount; $k++)
  346.                             {
  347.                                 $result[$i][$ki][$k] = $ai[$k];
  348.                             }
  349.                         }
  350.                     }
  351.  
  352.                     $result[$i]['dn'] = @ldap_get_dn($resource, $firstentry);
  353.                 }
  354.             }
  355.         }
  356.  
  357.         return $result;
  358.     }
  359.  
  360.     /**
  361.      * Replace an entry and return a true or false result
  362.      *
  363.      * @param   string  $dn         The DN which contains the attribute you want to replace
  364.      * @param   string  $attribute  The attribute values you want to replace
  365.      *
  366.      * @return  mixed  result of comparison (true, false, -1 on error)
  367.      *
  368.      * @since   12.1
  369.      */
  370.     public function replace($dn, $attribute)
  371.     {
  372.         return @ldap_mod_replace($this->_resource, $dn, $attribute);
  373.     }
  374.  
  375.     /**
  376.      * Modifies an entry and return a true or false result
  377.      *
  378.      * @param   string  $dn         The DN which contains the attribute you want to modify
  379.      * @param   string  $attribute  The attribute values you want to modify
  380.      *
  381.      * @return  mixed  result of comparison (true, false, -1 on error)
  382.      *
  383.      * @since   12.1
  384.      */
  385.     public function modify($dn, $attribute)
  386.     {
  387.         return @ldap_modify($this->_resource, $dn, $attribute);
  388.     }
  389.  
  390.     /**
  391.      * Removes attribute value from given dn and return a true or false result
  392.      *
  393.      * @param   string  $dn         The DN which contains the attribute you want to remove
  394.      * @param   string  $attribute  The attribute values you want to remove
  395.      *
  396.      * @return  mixed  result of comparison (true, false, -1 on error)
  397.      *
  398.      * @since   12.1
  399.      */
  400.     public function remove($dn, $attribute)
  401.     {
  402.         $resource = $this->_resource;
  403.  
  404.         return @ldap_mod_del($resource, $dn, $attribute);
  405.     }
  406.  
  407.     /**
  408.      * Compare an entry and return a true or false result
  409.      *
  410.      * @param   string  $dn         The DN which contains the attribute you want to compare
  411.      * @param   string  $attribute  The attribute whose value you want to compare
  412.      * @param   string  $value      The value you want to check against the LDAP attribute
  413.      *
  414.      * @return  mixed  result of comparison (true, false, -1 on error)
  415.      *
  416.      * @since   12.1
  417.      */
  418.     public function compare($dn, $attribute, $value)
  419.     {
  420.         return @ldap_compare($this->_resource, $dn, $attribute, $value);
  421.     }
  422.  
  423.     /**
  424.      * Read all or specified attributes of given dn
  425.      *
  426.      * @param   string  $dn  The DN of the object you want to read
  427.      *
  428.      * @return  mixed  array of attributes or -1 on error
  429.      *
  430.      * @since   12.1
  431.      */
  432.     public function read($dn)
  433.     {
  434.         $base = substr($dn, strpos($dn, ',') + 1);
  435.         $cn = substr($dn, 0, strpos($dn, ','));
  436.         $result = @ldap_read($this->_resource, $base, $cn);
  437.  
  438.         if ($result)
  439.         {
  440.             return @ldap_get_entries($this->_resource, $result);
  441.         }
  442.         else
  443.         {
  444.             return $result;
  445.         }
  446.     }
  447.  
  448.     /**
  449.      * Deletes a given DN from the tree
  450.      *
  451.      * @param   string  $dn  The DN of the object you want to delete
  452.      *
  453.      * @return  boolean  Result of operation
  454.      *
  455.      * @since   12.1
  456.      */
  457.     public function delete($dn)
  458.     {
  459.         return @ldap_delete($this->_resource, $dn);
  460.     }
  461.  
  462.     /**
  463.      * Create a new DN
  464.      *
  465.      * @param   string  $dn       The DN where you want to put the object
  466.      * @param   array   $entries  An array of arrays describing the object to add
  467.      *
  468.      * @return  boolean  Result of operation
  469.      *
  470.      * @since   12.1
  471.      */
  472.     public function create($dn, array $entries)
  473.     {
  474.         return @ldap_add($this->_resource, $dn, $entries);
  475.     }
  476.  
  477.     /**
  478.      * Add an attribute to the given DN
  479.      * Note: DN has to exist already
  480.      *
  481.      * @param   string  $dn     The DN of the entry to add the attribute
  482.      * @param   array   $entry  An array of arrays with attributes to add
  483.      *
  484.      * @return  boolean   Result of operation
  485.      *
  486.      * @since   12.1
  487.      */
  488.     public function add($dn, array $entry)
  489.     {
  490.         return @ldap_mod_add($this->_resource, $dn, $entry);
  491.     
  492.  
  493.     /**
  494.      * Rename the entry
  495.      *
  496.      * @param   string   $dn           The DN of the entry at the moment
  497.      * @param   string   $newdn        The DN of the entry should be (only cn=newvalue)
  498.      * @param   string   $newparent    The full DN of the parent (null by default)
  499.      * @param   boolean  $deleteolddn  Delete the old values (default)
  500.      *
  501.      * @return  boolean  Result of operation
  502.      *
  503.      * @since   12.1
  504.      */
  505.     public function rename($dn, $newdn, $newparent, $deleteolddn)
  506.     {
  507.         return @ldap_rename($this->_resource, $dn, $newdn, $newparent, $deleteolddn);
  508.     }
  509.  
  510.     /**
  511.      * Returns the error message
  512.      *
  513.      * @return  string   error message
  514.      *
  515.      * @since   12.1
  516.      */
  517.     public function getErrorMsg()
  518.     {
  519.         return @ldap_error($this->_resource);
  520.     }
  521.  
  522.     /**
  523.      * Converts a dot notation IP address to net address (e.g. for Netware, etc)
  524.      *
  525.      * @param   string  $ip  IP Address (e.g. xxx.xxx.xxx.xxx)
  526.      *
  527.      * @return  string  Net address
  528.      *
  529.      * @since   12.1
  530.      */
  531.     public static function ipToNetAddress($ip)
  532.     {
  533.         $parts = explode('.', $ip);
  534.         $address = '1#';
  535.  
  536.         foreach ($parts as $int)
  537.         {
  538.             $tmp = dechex($int);
  539.  
  540.             if (strlen($tmp) != 2)
  541.             {
  542.                 $tmp = '0' . $tmp;
  543.             }
  544.  
  545.             $address .= '\\' . $tmp;
  546.         }
  547.  
  548.         return $address;
  549.     }
  550.  
  551.     /**
  552.      * Extract readable network address from the LDAP encoded networkAddress attribute.
  553.      *
  554.      * Please keep this document block and author attribution in place.
  555.      *
  556.      * Novell Docs, see: http://developer.novell.com/ndk/doc/ndslib/schm_enu/data/sdk5624.html#sdk5624
  557.      * for Address types: http://developer.novell.com/ndk/doc/ndslib/index.html?page=/ndk/doc/ndslib/schm_enu/data/sdk4170.html
  558.      * LDAP Format, String:
  559.      * taggedData = uint32String "#" octetstring
  560.      * byte 0 = uint32String = Address Type: 0= IPX Address; 1 = IP Address
  561.      * byte 1 = char = "#" - separator
  562.      * byte 2+ = octetstring - the ordinal value of the address
  563.      * Note: with eDirectory 8.6.2, the IP address (type 1) returns
  564.      * correctly, however, an IPX address does not seem to.  eDir 8.7 may correct this.
  565.      * Enhancement made by Merijn van de Schoot:
  566.      * If addresstype is 8 (UDP) or 9 (TCP) do some additional parsing like still returning the IP address
  567.      *
  568.      * @param   string  $networkaddress  The network address
  569.      *
  570.      * @return  array 
  571.      *
  572.      * @author  Jay Burrell, Systems & Networks, Mississippi State University
  573.      * @since   12.1
  574.      */
  575.     public static function LDAPNetAddr($networkaddress)
  576.     {
  577.         $addr = "";
  578.         $addrtype = (int) substr($networkaddress, 0, 1);
  579.  
  580.         // Throw away bytes 0 and 1 which should be the addrtype and the "#" separator
  581.         $networkaddress = substr($networkaddress, 2);
  582.  
  583.         if (($addrtype == 8) || ($addrtype = 9))
  584.         {
  585.             // TODO 1.6: If UDP or TCP, (TODO fill addrport and) strip portnumber information from address
  586.             $networkaddress = substr($networkaddress, (strlen($networkaddress) - 4));
  587.         }
  588.  
  589.         $addrtypes = array(
  590.             'IPX',
  591.             'IP',
  592.             'SDLC',
  593.             'Token Ring',
  594.             'OSI',
  595.             'AppleTalk',
  596.             'NetBEUI',
  597.             'Socket',
  598.             'UDP',
  599.             'TCP',
  600.             'UDP6',
  601.             'TCP6',
  602.             'Reserved (12)',
  603.             'URL',
  604.             'Count');
  605.         $len = strlen($networkaddress);
  606.  
  607.         if ($len > 0)
  608.         {
  609.             for ($i = 0; $i < $len; $i++)
  610.             {
  611.                 $byte = substr($networkaddress, $i, 1);
  612.                 $addr .= ord($byte);
  613.  
  614.                 if (($addrtype == 1) || ($addrtype == 8) || ($addrtype = 9))
  615.                 {
  616.                     // Dot separate IP addresses...
  617.                     $addr .= ".";
  618.                 }
  619.             }
  620.             if (($addrtype == 1) || ($addrtype == 8) || ($addrtype = 9))
  621.             {
  622.                 // Strip last period from end of $addr
  623.                 $addr = substr($addr, 0, strlen($addr) - 1);
  624.             }
  625.         }
  626.         else
  627.         {
  628.             $addr .= JText::_('JLIB_CLIENT_ERROR_LDAP_ADDRESS_NOT_AVAILABLE');
  629.         }
  630.         return array('protocol' => $addrtypes[$addrtype], 'address' => $addr);
  631.     }
  632.  
  633.     /**
  634.      * Generates a LDAP compatible password
  635.      *
  636.      * @param   string  $password  Clear text password to encrypt
  637.      * @param   string  $type      Type of password hash, either md5 or SHA
  638.      *
  639.      * @return  string   Encrypted password
  640.      *
  641.      * @since   12.1
  642.      */
  643.     public static function generatePassword($password, $type = 'md5')
  644.     {
  645.         switch (strtolower($type))
  646.         {
  647.             case 'sha':
  648.                 $userpassword = '{SHA}' . base64_encode(pack('H*', sha1($password)));
  649.                 break;
  650.             case 'md5':
  651.             default:
  652.                 $userpassword = '{MD5}' . base64_encode(pack('H*', md5($password)));
  653.                 break;
  654.         }
  655.  
  656.         return $userpassword;
  657.     }
  658. }
  659.  
  660. /**
  661.  * Deprecated class placeholder. You should use JClientLdap instead.
  662.  *
  663.  * @package     Joomla.Platform
  664.  * @subpackage  Client
  665.  * @since       11.1
  666.  * @deprecated  12.3 (Platform) & 4.0 (CMS)
  667.  */
  668. class JLDAP extends JClientLdap
  669. {
  670.     /**
  671.      * Constructor
  672.      *
  673.      * @param   object  $configObj  An object of configuration variables
  674.      *
  675.      * @since   11.1
  676.      */
  677.     public function __construct($configObj = null)
  678.     {
  679.         JLog::add('JLDAP is deprecated. Use JClientLdap instead.', JLog::WARNING, 'deprecated');
  680.         parent::__construct($configObj);
  681.     }
  682. }

Documentation generated on Tue, 19 Nov 2013 15:06:44 +0100 by phpDocumentor 1.4.3