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