PageRenderTime 121ms CodeModel.GetById 97ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/libraries/joomla/client/ldap.php

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