This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | // Codendi |
||
3 | // Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved |
||
4 | // http://www.codendi.com |
||
5 | |||
6 | /** |
||
7 | * LDAP class definition |
||
8 | * Provides LDAP facilities to Codendi: |
||
9 | * - directory search |
||
10 | * - user authentication |
||
11 | * The ldap object is initialized with global parameters (from local.inc): |
||
12 | * servers, query templates, etc. |
||
13 | */ |
||
14 | class LDAP { |
||
15 | /** |
||
16 | * This is equivalent to searching the entire directory. |
||
17 | */ |
||
18 | const SCOPE_SUBTREE = 1; |
||
19 | const SCOPE_SUBTREE_TEXT = 'subtree'; |
||
20 | |||
21 | /** |
||
22 | * LDAP_SCOPE_ONELEVEL means that the search should only return information |
||
23 | * that is at the level immediately below the base_dn given in the call. |
||
24 | * (Equivalent to typing "ls" and getting a list of files and folders in |
||
25 | * the current working directory.) |
||
26 | */ |
||
27 | const SCOPE_ONELEVEL = 2; |
||
28 | const SCOPE_ONELEVEL_TEXT = 'onelevel'; |
||
29 | |||
30 | /** |
||
31 | * It is equivalent to reading an entry from the directory. |
||
32 | */ |
||
33 | const SCOPE_BASE = 3; |
||
34 | |||
35 | /** |
||
36 | * Error value when search exceed either server or client size limit. |
||
37 | */ |
||
38 | const ERR_SIZELIMIT = 0x04 ; |
||
39 | |||
40 | const ERR_SUCCESS = 0x00; |
||
41 | |||
42 | const SERVER_TYPE_ACTIVE_DIRECTORY = "ActiveDirectory"; |
||
43 | const SERVER_TYPE_OPEN_LDAP = "OpenLDAP"; |
||
44 | |||
45 | private $ds; |
||
46 | private $bound; |
||
47 | private $errorsTrapped; |
||
48 | private $ldapParams; |
||
49 | private $query_escaper; |
||
50 | |||
51 | /** @var Logger */ |
||
52 | private $logger; |
||
53 | |||
54 | /** |
||
55 | * LDAP object constructor. Use gloabals for initialization. |
||
56 | */ |
||
57 | function __construct(array $ldapParams, Logger $logger, LdapQueryEscaper $query_escaper) { |
||
58 | $this->ldapParams = $ldapParams; |
||
59 | $this->bound = false; |
||
60 | $this->errorsTrapped = true; |
||
61 | $this->logger = $logger; |
||
62 | $this->query_escaper = $query_escaper; |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Returns the whole LDAP parameters set by admin |
||
67 | * |
||
68 | * @return array |
||
69 | */ |
||
70 | function getLDAPParams() { |
||
71 | return $this->ldapParams; |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Returns one parameter from the list set by admin |
||
76 | * |
||
77 | * @param String $key Parameter name |
||
78 | * |
||
79 | * @return String |
||
80 | */ |
||
81 | function getLDAPParam($key) { |
||
82 | return isset($this->ldapParams[$key]) ? $this->ldapParams[$key] : null; |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Connect to LDAP server. |
||
87 | * If several servers are listed, try first server first, then second, etc. |
||
88 | * This funtion should not be called directly: it is always called |
||
89 | * by a public function: authenticate() or search(). |
||
90 | * |
||
91 | * @return Boolean true if connect was successful, false otherwise. |
||
92 | */ |
||
93 | function connect() { |
||
94 | if (!$this->ds) { |
||
95 | foreach (explode('[,;]', $this->ldapParams['server']) as $ldap_server) { |
||
96 | $this->ds = ldap_connect($ldap_server); |
||
97 | if($this->ds) { |
||
98 | // Force protocol to LDAPv3 (for AD & recent version of OpenLDAP) |
||
99 | ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, 3); |
||
100 | ldap_set_option($this->ds, LDAP_OPT_REFERRALS, 0); |
||
101 | |||
102 | // Since ldap_connect always return a resource with |
||
103 | // OpenLdap 2.2.x, we have to check that this ressource is |
||
104 | // valid with a bind, If bind success: that's great, if |
||
105 | // not, this is a connexion failure. |
||
106 | if($this->bind()) { |
||
107 | $this->logger->debug('Bound to LDAP server: '.$ldap_server); |
||
108 | return true; |
||
109 | } else { |
||
110 | $this->logger->warn('Cannot bind to LDAP server: '.$ldap_server. |
||
111 | ' ***ERROR MESSSAGE:'. ldap_error($this->ds). |
||
112 | ' ***ERROR no:'. $this->getErrno() |
||
113 | ); |
||
114 | } |
||
115 | } else { |
||
116 | $this->logger->warn('Cannot connect to LDAP server: '.$ldap_server. |
||
117 | ' ***ERROR:'. ldap_error($this->ds) . |
||
118 | ' ***ERROR no:'. $this->getErrno() |
||
119 | ); |
||
120 | } |
||
121 | } |
||
122 | $this->logger->warn('Cannot connect to any LDAP server: '.$this->ldapParams['server']. |
||
123 | ' ***ERROR:'. ldap_error($this->ds). |
||
124 | ' ***ERROR no:'. $this->getErrno() |
||
125 | ); |
||
126 | return false; |
||
127 | } else { |
||
128 | return true; |
||
129 | } |
||
130 | } |
||
131 | |||
132 | private function authenticatedBindConnect($servers, $binddn, $bindpwd) { |
||
133 | $ds = false; |
||
134 | foreach (split('[,;]', $servers) as $ldap_server) { |
||
135 | $ds = ldap_connect($ldap_server); |
||
136 | if ($ds) { |
||
137 | // Force protocol to LDAPv3 (for AD & recent version of OpenLDAP) |
||
138 | ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); |
||
139 | ldap_set_option($ds, LDAP_OPT_REFERRALS, 0); |
||
140 | |||
141 | // Since ldap_connect always return a resource with |
||
142 | // OpenLdap 2.2.x, we have to check that this ressource is |
||
143 | // valid with a bind, If bind success: that's great, if |
||
144 | // not, this is a connexion failure. |
||
145 | if (@ldap_bind($ds, $binddn, $bindpwd)) { |
||
146 | return $ds; |
||
147 | } else { |
||
148 | throw new LDAP_Exception_BindException(ldap_error($ds)); |
||
149 | } |
||
150 | } |
||
151 | } |
||
152 | throw new LDAP_Exception_ConnexionException(ldap_error($ds)); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Perform LDAP binding. |
||
157 | * - Some servers allow anonymous bindings for searching. Otherwise, set |
||
158 | * sys_ldap_bind_dn and sys_ldap_bind_passwd in local.inc |
||
159 | * - binding is also used for user authentication. A successful bind |
||
160 | * means that the user/password is valid. |
||
161 | * |
||
162 | * @param String $binddn DN to use to bind with |
||
163 | * @param String $bindpw Password associated to the DN |
||
164 | * |
||
165 | * @return Boolean true if bind was successful, false otherwise. |
||
166 | */ |
||
167 | function bind($binddn=null, $bindpw=null) { |
||
168 | if(!$this->bound) { |
||
169 | if (!$binddn) { |
||
0 ignored issues
–
show
|
|||
170 | $binddn=isset($this->ldapParams['bind_dn']) ? $this->ldapParams['bind_dn'] : null; |
||
171 | $bindpw=isset($this->ldapParams['bind_passwd']) ? $this->ldapParams['bind_passwd'] : null; |
||
172 | } |
||
173 | if ($binddn && (!$bindpw)) { |
||
174 | // Prevent successful binding if a username is given and the server |
||
175 | // accepts anonymous connections |
||
176 | //$this->setError($Language->getText('ldap_class','err_bind_nopasswd',$binddn)); |
||
177 | $this->logger->error('Cannot connect to LDAP server: '.$this->ldapParams['server']. |
||
178 | ' ***ERROR: will not bind if a username is given and the server accepts anonymous connections' |
||
179 | ); |
||
180 | $this->bound = false; |
||
181 | } |
||
182 | |||
183 | if ($bind_result = @ldap_bind($this->ds, $binddn, $bindpw)) { |
||
184 | $this->bound = true; |
||
185 | } else { |
||
186 | $this->logger->error('Unable to bind to LDAP server: '.$this->ldapParams['server']. |
||
187 | ' ***ERROR:'. ldap_error($this->ds) . |
||
188 | ' ***ERROR no:'. $this->getErrno() |
||
189 | ); |
||
190 | //$this->setError($Language->getText('ldap_class','err_bind_invpasswd',$binddn)); |
||
191 | $this->bound = false; |
||
192 | } |
||
193 | } |
||
194 | return $this->bound; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * Unbinds from the LDAP directory |
||
199 | * |
||
200 | * According to http://www.php.net/manual/en/function.ldap-unbind.php#17203 |
||
201 | * ldap_unbind kills the link descriptor so we just have to force the rebind |
||
202 | * for next query |
||
203 | */ |
||
204 | function unbind() { |
||
205 | $this->bound = false; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Connect and bind to the LDAP Directory |
||
210 | * |
||
211 | * @return Boolean |
||
212 | */ |
||
213 | function _connectAndBind() { |
||
214 | if (!$this->connect()) { |
||
215 | //$this->setError($Language->getText('ldap_class','err_cant_connect')); |
||
216 | return false; |
||
217 | } |
||
218 | if (!$this->bind()) { |
||
219 | //$this->setError($Language->getText('ldap_class','err_cant_bind')); |
||
220 | return false; |
||
221 | } |
||
222 | return true; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Return last error state |
||
227 | * |
||
228 | * @return Integer |
||
229 | */ |
||
230 | function getErrno() { |
||
231 | return ldap_errno($this->ds); |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Perform LDAP authentication of a user based on its login. |
||
236 | * |
||
237 | * First search the DN of the user based on its login then try to bind |
||
238 | * with this DN and the given password |
||
239 | * |
||
240 | * @param String $login Login name to authenticate with |
||
241 | * @param String $passwd Password associated to the login |
||
242 | * |
||
243 | * @return Boolean true if the login and password match, false otherwise |
||
244 | */ |
||
245 | function authenticate($login, $passwd) { |
||
246 | if (!$passwd) { |
||
247 | // avoid a successful bind on LDAP servers accepting anonymous connections |
||
248 | //$this->setError($Language->getText('ldap_class','err_nopasswd')); |
||
249 | return false; |
||
250 | } |
||
251 | |||
252 | // Do a search to recover the right DN based on given login |
||
253 | $lri = $this->searchLogin($login); |
||
254 | if ($lri && count($lri) === 1) { |
||
255 | $auth_dn = $lri->current()->getDn(); |
||
256 | } else { |
||
257 | return false; |
||
258 | } |
||
259 | |||
260 | // Now bind with DN/password to check authentication |
||
261 | // /!\ Be sure not to reuse a previously bound connexion (otherwise |
||
262 | // authentication will always be successfull. |
||
263 | $this->unbind(); |
||
264 | if (!$this->bind($auth_dn,$passwd)) { |
||
265 | //$this->setError($Language->getText('ldap_class','err_badpasswd')); |
||
266 | return false; |
||
267 | } |
||
268 | return true; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * Search in the LDAP directory |
||
273 | * |
||
274 | * @see http://php.net/ldap_search |
||
275 | * |
||
276 | * @param String $baseDn Base DN where to search |
||
277 | * @param String $filter Specific LDAP query |
||
278 | * @param Integer $scope How to search (SCOPE_ SUBTREE, ONELEVEL or BASE) |
||
279 | * @param Array $attributes LDAP fields to retreive |
||
280 | * @param Integer $attrsOnly Retreive both field value and name (keep it to 0) |
||
281 | * @param Integer $sizeLimit Limit the size of the result set |
||
282 | * @param Integer $timeLimit Limit the time spend to search for results |
||
283 | * @param Integer $deref Dereference result |
||
284 | * |
||
285 | * @return LDAPResultIterator |
||
286 | */ |
||
287 | function search($baseDn, $filter, $scope=self::SCOPE_SUBTREE, $attributes=array(), $attrsOnly=0, $sizeLimit=0, $timeLimit=0, $deref=LDAP_DEREF_NEVER) { |
||
288 | if($this->_connectAndBind()) { |
||
289 | $this->_initErrorHandler(); |
||
290 | switch ($scope) { |
||
291 | case self::SCOPE_BASE: |
||
292 | $sr = ldap_read($this->ds, $baseDn, $filter, $attributes, $attrsOnly, $sizeLimit, $timeLimit, $deref); |
||
293 | break; |
||
294 | |||
295 | case self::SCOPE_ONELEVEL: |
||
296 | $sr = ldap_list($this->ds, $baseDn, $filter, $attributes, $attrsOnly, $sizeLimit, $timeLimit, $deref); |
||
297 | break; |
||
298 | |||
299 | case self::SCOPE_SUBTREE: |
||
300 | default: |
||
301 | $sr = ldap_search($this->ds, $baseDn, $filter, $attributes, $attrsOnly, $sizeLimit, $timeLimit, $deref); |
||
302 | } |
||
303 | $this->_restoreErrorHandler(); |
||
304 | |||
305 | if ($sr !== false) { |
||
306 | $this->logger->debug('LDAP search success '.$baseDn.' '.$filter. ' *** SCOPE: '.$scope . ' *** ATTRIBUTES: '.implode(', ', $attributes)); |
||
307 | $entries = ldap_get_entries($this->ds, $sr); |
||
308 | if ($entries !== false) { |
||
309 | return new LDAPResultIterator($entries, $this->ldapParams); |
||
310 | } |
||
311 | } else { |
||
312 | $this->logger->warn('LDAP search error: '.$baseDn.' '.$filter.' '.$this->ldapParams['server']. |
||
313 | ' ***ERROR:'. ldap_error($this->ds). |
||
314 | ' ***ERROR no:'. $this->getErrno() |
||
315 | ); |
||
316 | } |
||
317 | } |
||
318 | return false; |
||
319 | } |
||
320 | |||
321 | public function getDefaultAttributes() { |
||
322 | return array( |
||
323 | $this->ldapParams['mail'], |
||
324 | $this->ldapParams['cn'], |
||
325 | $this->ldapParams['uid'], |
||
326 | $this->ldapParams['eduid'], |
||
327 | 'dn' |
||
328 | ); |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Search a specific Distinguish Name |
||
333 | * |
||
334 | * @param String $dn DN to retreive |
||
335 | * @param Array $attributes Restrict the LDAP fields to fetch |
||
336 | * |
||
337 | * @return LDAPResultIterator |
||
338 | */ |
||
339 | function searchDn($dn, $attributes=array()) { |
||
340 | $attributes = count($attributes) > 0 ? $attributes : $this->getDefaultAttributes(); |
||
341 | return $this->search($dn, 'objectClass=*', self::SCOPE_BASE, $attributes); |
||
342 | } |
||
343 | |||
344 | /** |
||
345 | * Search if given argument correspond to a LDAP login (generally this |
||
346 | * correspond to ldap 'uid' field). |
||
347 | * |
||
348 | * @param String $name login |
||
349 | * @param array $attributes |
||
350 | * |
||
351 | * @return LDAPResultIterator |
||
352 | */ |
||
353 | public function searchLogin($name, $attributes = array()) { |
||
354 | $name = $this->query_escaper->escapeFilter($name); |
||
355 | if (! $attributes) { |
||
0 ignored issues
–
show
The expression
$attributes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
356 | $attributes = $this->getDefaultAttributes(); |
||
357 | } |
||
358 | |||
359 | $filter = $this->ldapParams['uid'].'='.$name; |
||
360 | return $this->search($this->ldapParams['dn'], $filter, self::SCOPE_SUBTREE, $attributes); |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Search if given argument correspond to a LDAP Identifier. This is the |
||
365 | * uniq number that represent a user. |
||
366 | * |
||
367 | * @param String $name LDAP Id |
||
368 | * |
||
369 | * @return LDAPResultIterator |
||
370 | */ |
||
371 | function searchEdUid($name) { |
||
372 | $name = $this->query_escaper->escapeFilter($name); |
||
373 | $filter = $this->ldapParams['eduid'].'='.$name; |
||
374 | return $this->search($this->ldapParams['dn'], $filter, self::SCOPE_SUBTREE, $this->getDefaultAttributes()); |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * Search if a LDAP user match a filter defined in local conf. |
||
379 | * |
||
380 | * @param String $words User name to search |
||
381 | * |
||
382 | * @return LDAPResultIterator |
||
383 | */ |
||
384 | function searchUser($words) { |
||
385 | $words = $this->query_escaper->escapeFilter($words); |
||
386 | $filter = str_replace("%words%", $words, $this->ldapParams['search_user']); |
||
387 | return $this->search($this->ldapParams['dn'], $filter, self::SCOPE_SUBTREE, $this->getDefaultAttributes()); |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Search if given identifier match a Common Name in the LDAP. |
||
392 | * |
||
393 | * @param String $name Common name to search |
||
394 | * |
||
395 | * @return LDAPResultIterator |
||
396 | */ |
||
397 | function searchCommonName($name) { |
||
398 | $name = $this->query_escaper->escapeFilter($name); |
||
399 | $filter = $this->ldapParams['cn'].'='.$name; |
||
400 | return $this->search($this->ldapParams['dn'], $filter, self::SCOPE_SUBTREE, $this->getDefaultAttributes()); |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * Search ldap group by name |
||
405 | * |
||
406 | * @param String $name Group name to search |
||
407 | * |
||
408 | * @return LDAPResultIterator |
||
409 | */ |
||
410 | function searchGroup($name) { |
||
411 | $name = $this->query_escaper->escapeFilter($name); |
||
412 | |||
413 | if (isset($this->ldapParams['server_type']) && $this->ldapParams['server_type'] === self::SERVER_TYPE_ACTIVE_DIRECTORY) { |
||
414 | $filter = $this->ldapParams['grp_uid'] . '=' . $name; |
||
415 | return $this->search($this->ldapParams['grp_dn'], $filter, self::SCOPE_SUBTREE); |
||
416 | } |
||
417 | |||
418 | $filter = $this->ldapParams['grp_cn'].'='.$name; |
||
419 | return $this->search($this->ldapParams['dn'], $filter, self::SCOPE_SUBTREE); |
||
420 | } |
||
421 | |||
422 | /** |
||
423 | * List members of a LDAP group |
||
424 | * |
||
425 | * @param String $groupDn Group DN |
||
426 | * |
||
427 | * @return LDAPResultIterator |
||
428 | */ |
||
429 | function searchGroupMembers($groupDn) { |
||
430 | return $this->search($groupDn, 'objectClass=*', self::SCOPE_SUBTREE, array($this->ldapParams['grp_member'])); |
||
431 | } |
||
432 | |||
433 | /** |
||
434 | * Specific search of user common name, only the common name is returned |
||
435 | * |
||
436 | * This method is designed for speed and to limit the number of returned values. |
||
437 | * |
||
438 | * @param String $name Name of the group to look for |
||
439 | * @param Integer $sizeLimit Limit the amount of result sent |
||
440 | * |
||
441 | * @return LDAPResultIterator |
||
442 | */ |
||
443 | function searchUserAsYouType($name, $sizeLimit, $validEmail=false) { |
||
444 | $apIt = new AppendIterator(); |
||
445 | if($name && $this->_connectAndBind()) { |
||
446 | $name = $this->query_escaper->escapeFilter($name); |
||
447 | if (isset($this->ldapParams['tooltip_search_user'])) { |
||
448 | $filter = str_replace("%words%", $name, $this->ldapParams['tooltip_search_user']); |
||
449 | } else { |
||
450 | $filter = '('.$this->ldapParams['cn'].'='.$name.'*)'; |
||
451 | } |
||
452 | if($validEmail) { |
||
453 | // Only search people with a non empty mail field |
||
454 | $mail = $this->query_escaper->escapeFilter($this->ldapParams['mail']); |
||
455 | $filter = '(&'.$filter.'('.$mail.'=*))'; |
||
456 | } |
||
457 | // We only care about Common name and Login (lower the amount of data |
||
458 | // to fetch speed up the request. |
||
459 | if (isset($this->ldapParams['tooltip_search_attrs'])) { |
||
460 | $attrs = explode(';', $this->ldapParams['tooltip_search_attrs']); |
||
461 | } else { |
||
462 | $attrs = array($this->ldapParams['cn'], $this->ldapParams['uid']); |
||
463 | } |
||
464 | // We want types and values |
||
465 | $attrsOnly = 0; |
||
466 | // Catch errors to detect if there are more results available than |
||
467 | // the list actually returned (helps to refine the search) |
||
468 | $this->trapErrors(); |
||
469 | // Use SCOPE_ONELEVEL to only search in "sys_ldap_people_dn" branch |
||
470 | // of the directory to speed up the search. |
||
471 | $peopleDn = explode(';', $this->ldapParams['people_dn']); |
||
472 | foreach ($peopleDn as $count) { |
||
473 | $ds[] = $this->ds; |
||
474 | } |
||
475 | if (isset($this->ldapParams['tooltip_search_user'])) { |
||
476 | $asr = ldap_search($ds, $peopleDn, $filter, $attrs, $attrsOnly, $sizeLimit, 0, LDAP_DEREF_NEVER); |
||
477 | $this->logger->debug('LDAP in-depth search as you type '.$filter. ' ***PEOPLEDN: '.$peopleDn . ' ***errors:'. ldap_error($this->ds)); |
||
478 | } else { |
||
479 | $asr = ldap_list($ds, $peopleDn, $filter, $attrs, $attrsOnly, $sizeLimit, 0, LDAP_DEREF_NEVER); |
||
480 | $this->logger->debug('LDAP high-level search as you type '.$filter. ' ***PEOPLEDN: '.print_r($peopleDn, true) . ' ***errors:'. ldap_error($this->ds)); |
||
481 | } |
||
482 | if ($asr !== false) { |
||
483 | foreach ($asr as $sr) { |
||
0 ignored issues
–
show
|
|||
484 | $entries = ldap_get_entries($this->ds, $sr); |
||
485 | if ($entries !== false) { |
||
486 | // AppendIterator doesn't seem to handle invalid iterator well. |
||
487 | // So don't append invalid iterators... |
||
488 | $it = new LDAPResultIterator($entries, $this->ldapParams); |
||
489 | if ($it->valid()) { |
||
490 | $apIt->append($it); |
||
491 | } |
||
492 | } |
||
493 | } |
||
494 | } |
||
495 | } |
||
496 | return $apIt; |
||
497 | } |
||
498 | |||
499 | /** |
||
500 | * Specific search of group common name, only the common name is returned |
||
501 | * |
||
502 | * This method is designed for speed and to limit the number of returned values. |
||
503 | * |
||
504 | * @param String $name Name of the group to look for |
||
505 | * @param Integer $sizeLimit Limit the amount of result sent |
||
506 | * |
||
507 | * @return LDAPResultIterator |
||
508 | */ |
||
509 | function searchGroupAsYouType($name, $sizeLimit) { |
||
510 | $lri = false; |
||
511 | if($this->_connectAndBind()) { |
||
512 | $name = $this->query_escaper->escapeFilter($name); |
||
513 | $filter = '('.$this->ldapParams['grp_cn'].'=*'.$name.'*)'; |
||
514 | // We only care about Common name |
||
515 | $attrs = array($this->ldapParams['grp_cn']); |
||
516 | // We want types and values |
||
517 | $attrsOnly = 0; |
||
518 | // Catch errors to detect if there are more results available than |
||
519 | // the list actually returned (helps to refine the search) |
||
520 | $this->trapErrors(); |
||
521 | // Use SCOPE_ONELEVEL to only search in "sys_ldap_grp_dn" branch |
||
522 | // of the directory to speed up the search. |
||
523 | $lri = $this->search($this->ldapParams['grp_dn'], $filter, self::SCOPE_ONELEVEL, $attrs, $attrsOnly, $sizeLimit); |
||
524 | } |
||
525 | if ($lri === false) { |
||
526 | return new LDAPResultIterator(array(), array()); |
||
527 | } else { |
||
528 | return $lri; |
||
529 | } |
||
530 | } |
||
531 | |||
532 | public function add($dn, array $info) { |
||
533 | $ds = $this->getWriteConnexion(); |
||
534 | if (@ldap_add($ds, $dn, $info)) { |
||
535 | return true; |
||
536 | } |
||
537 | throw new LDAP_Exception_AddException(ldap_error($ds), $dn); |
||
538 | } |
||
539 | |||
540 | public function update($dn, array $info) { |
||
541 | $ds = $this->getWriteConnexion(); |
||
542 | if (@ldap_modify($ds, $dn, $info)) { |
||
543 | return true; |
||
544 | } |
||
545 | throw new LDAP_Exception_UpdateException(ldap_error($ds), $dn); |
||
546 | } |
||
547 | |||
548 | public function delete($dn) { |
||
549 | $ds = $this->getWriteConnexion(); |
||
550 | if (@ldap_delete($ds, $dn)) { |
||
551 | return true; |
||
552 | } |
||
553 | throw new LDAP_Exception_DeleteException(ldap_error($ds), $dn); |
||
554 | } |
||
555 | |||
556 | public function renameUser($old_dn, $new_root_dn) { |
||
557 | return $this->rename($old_dn, $new_root_dn, $this->getLDAPParam('write_people_dn')); |
||
558 | } |
||
559 | |||
560 | private function rename($old_dn, $newrdn, $newparent) { |
||
561 | $ds = $this->getWriteConnexion(); |
||
562 | if (@ldap_rename($ds, $old_dn, $newrdn, $newparent, true)) { |
||
563 | return true; |
||
564 | } |
||
565 | throw new LDAP_Exception_RenameException(ldap_error($ds), $old_dn, $newrdn.','.$newparent); |
||
566 | } |
||
567 | |||
568 | private function getWriteConnexion() { |
||
569 | return $this->authenticatedBindConnect( |
||
570 | $this->getLDAPParam('write_server'), |
||
571 | $this->getLDAPParam('write_dn'), |
||
572 | $this->getLDAPParam('write_password') |
||
573 | ); |
||
574 | } |
||
575 | |||
576 | /** |
||
577 | * Enable fake error handler |
||
578 | * |
||
579 | * The fake error handler is enabled only for one query. |
||
580 | * |
||
581 | * @see _initErrorHandler() |
||
582 | */ |
||
583 | private function trapErrors() { |
||
584 | $this->errorsTrapped = true; |
||
585 | } |
||
586 | |||
587 | /** |
||
588 | * Setup fake error handler to be able to catch an error without displaying it |
||
589 | * |
||
590 | * This is not very clean but it's the only way to get some ldap errors |
||
591 | * without displaying them to final users. In some cases errors are meaningful |
||
592 | * and even expected (see searchAsYouType*) because we set very restrictive |
||
593 | * limits and of course the limit is exceeded easily. We need to catch it |
||
594 | * but not to display a warning to the user. |
||
595 | * |
||
596 | * Note: don't enable it for each request, otherwise, you may hide unwanted |
||
597 | * errors. |
||
598 | */ |
||
599 | private function _initErrorHandler() { |
||
600 | if ($this->errorsTrapped) { |
||
601 | set_error_handler(create_function('','')); |
||
602 | } |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * After LDAP query, restore the PHP error handler to its previous state. |
||
607 | */ |
||
608 | private function _restoreErrorHandler() { |
||
609 | if ($this->errorsTrapped) { |
||
610 | restore_error_handler(); |
||
611 | } |
||
612 | $this->errorsTrapped = false; |
||
613 | } |
||
614 | } |
||
615 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: