ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilLDAPQuery.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
24define('IL_LDAP_BIND_DEFAULT',0);
25define('IL_LDAP_BIND_ADMIN',1);
26define('IL_LDAP_BIND_TEST',2);
27
28include_once('Services/LDAP/classes/class.ilLDAPAttributeMapping.php');
29include_once('Services/LDAP/classes/class.ilLDAPResult.php');
30include_once('Services/LDAP/classes/class.ilLDAPQueryException.php');
31
42{
43 private $ldap_server_url = null;
44 private $settings = null;
45 private $log = null;
46
47 private $user_fields = array();
48
57 public function __construct(ilLDAPServer $a_server,$a_url = '')
58 {
59 global $ilLog;
60
61 $this->settings = $a_server;
62
63 if(strlen($a_url))
64 {
65 $this->ldap_server_url = $a_url;
66 }
67 else
68 {
69 $this->ldap_server_url = $this->settings->getUrl();
70 }
71
72 $this->mapping = ilLDAPAttributeMapping::_getInstanceByServerId($this->settings->getServerId());
73 $this->log = ilLoggerFactory::getLogger('auth');
74
76 $this->connect();
77 }
78
79 // begin-patch ldap_multiple
84 public function getServer()
85 {
86 return $this->settings;
87 }
88
96 public function fetchUser($a_name)
97 {
98 $this->user_fields = array_merge(array($this->settings->getUserAttribute()),$this->mapping->getFields());
99
100 if(!$this->readUserData($a_name))
101 {
102 return array();
103 }
104 else
105 {
106 return $this->users;
107 }
108 }
109
110
117 public function fetchUsers()
118 {
119 // First of all check if a group restriction is enabled
120 // YES: => fetch all group members
121 // No: => fetch all users
122 if(strlen($this->settings->getGroupName()))
123 {
124 $this->log->debug('Searching for group members.');
125
126 $groups = $this->settings->getGroupNames();
127 if(count($groups) <= 1)
128 {
129 $this->fetchGroupMembers();
130 }
131 else
132 {
133 foreach($groups as $group)
134 {
135 $this->fetchGroupMembers($group);
136 }
137 }
138
139 }
140 if(!strlen($this->settings->getGroupName()) or $this->settings->isMembershipOptional())
141 {
142 $this->log->info('Start reading all users...');
143 $this->readAllUsers();
144 #throw new ilLDAPQueryException('LDAP: Called import of users without specifying group restrictions. NOT IMPLEMENTED YET!');
145 }
146 return $this->users ? $this->users : array();
147 }
148
160 public function query($a_search_base,$a_filter,$a_scope,$a_attributes)
161 {
162 $res = $this->queryByScope($a_scope,$a_search_base,$a_filter,$a_attributes);
163 if($res === false)
164 {
165 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh).' '.
166 sprintf('DN: %s, Filter: %s, Scope: %s',
167 $a_search_base,
168 $a_filter,
169 $a_scope));
170 }
171 return new ilLDAPResult($this->lh,$res);
172 }
173
180 public function modAdd($a_dn,$a_attribute)
181 {
182 if(@ldap_mod_add($this->lh,$a_dn,$a_attribute))
183 {
184 return true;
185 }
186 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
187 }
188
195 public function modDelete($a_dn,$a_attribute)
196 {
197 if(@ldap_mod_del($this->lh,$a_dn,$a_attribute))
198 {
199 return true;
200 }
201 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
202 }
203
212 private function readAllUsers()
213 {
214 // Build search base
215 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
216 {
217 $dn .= ',';
218 }
219 $dn .= $this->settings->getBaseDN();
220
221 // page results
222 $filter = $this->settings->getFilter();
223 $page_filter = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','-');
224 $chars = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
225
226 foreach($page_filter as $letter)
227 {
228 $new_filter = '(&';
229 $new_filter .= $filter;
230
231 switch($letter)
232 {
233 case '-':
234 $new_filter .= ('(!(|');
235 foreach($chars as $char)
236 {
237 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$char.'*)');
238 }
239 $new_filter .= ')))';
240 break;
241
242 default:
243 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$letter.'*))');
244 break;
245 }
246
247 $this->log->info('Searching with ldap search and filter '.$new_filter.' in '.$dn);
248 $res = $this->queryByScope($this->settings->getUserScope(),
249 $dn,
250 $new_filter,
251 array($this->settings->getUserAttribute()));
252
253 $tmp_result = new ilLDAPResult($this->lh,$res);
254 if(!$tmp_result->numRows())
255 {
256 $this->log->notice('No users found. Aborting.');
257 continue;
258 }
259 $this->log->info('Found '.$tmp_result->numRows().' users.');
260 $attribute = strtolower($this->settings->getUserAttribute());
261 foreach($tmp_result->getRows() as $data)
262 {
263 if(isset($data[$attribute]))
264 {
265 $this->readUserData($data[$attribute],false,false);
266 }
267 else
268 {
269 $this->log->warning('Unknown error. No user attribute found.');
270 }
271 }
272 unset($tmp_result);
273 }
274 return true;
275 }
276
277
284 private function fetchGroupMembers($a_name = '')
285 {
286 $group_name = strlen($a_name) ? $a_name : $this->settings->getGroupName();
287
288 // Build filter
289 $filter = sprintf('(&(%s=%s)%s)',
290 $this->settings->getGroupAttribute(),
291 $group_name,
292 $this->settings->getGroupFilter());
293
294
295 // Build search base
296 if(($gdn = $this->settings->getGroupDN()) && substr($gdn,-1) != ',')
297 {
298 $gdn .= ',';
299 }
300 $gdn .= $this->settings->getBaseDN();
301
302 $this->log->debug('Using filter '.$filter);
303 $this->log->debug('Using DN '.$gdn);
304 $res = $this->queryByScope($this->settings->getGroupScope(),
305 $gdn,
306 $filter,
307 array($this->settings->getGroupMember()));
308
309 $tmp_result = new ilLDAPResult($this->lh,$res);
310 $group_data = $tmp_result->getRows();
311
312
313 if(!$tmp_result->numRows())
314 {
315 $this->log->info('No group found.');
316 return false;
317 }
318
319 $attribute_name = strtolower($this->settings->getGroupMember());
320
321 // All groups
322 foreach($group_data as $data)
323 {
324 $this->log->debug('Found '.count($data[$attribute_name]).' group members for group '.$data['dn']);
325 if(is_array($data[$attribute_name]))
326 {
327 foreach($data[$attribute_name] as $name)
328 {
329 $this->readUserData($name,true,true);
330 }
331 }
332 else
333 {
334 $this->readUserData($data[$attribute_name],true,true);
335 }
336 }
337 unset($tmp_result);
338 return;
339 }
340
347 private function readUserData($a_name,$a_check_dn = true,$a_try_group_user_filter = false)
348 {
349 $filter = $this->settings->getFilter();
350 if($a_try_group_user_filter)
351 {
352 if($this->settings->isMembershipOptional())
353 {
354 $filter = $this->settings->getGroupUserFilter();
355 }
356 }
357
358 // Build filter
359 if($this->settings->enabledGroupMemberIsDN() and $a_check_dn)
360 {
361 $dn = $a_name;
362 #$res = $this->queryByScope(IL_LDAP_SCOPE_BASE,$dn,$filter,$this->user_fields);
363
364 $fields = array_merge($this->user_fields,array('useraccountcontrol'));
365 $res = $this->queryByScope(IL_LDAP_SCOPE_BASE,strtolower($dn),$filter,$fields);
366 }
367 else
368 {
369 $filter = sprintf('(&(%s=%s)%s)',
370 $this->settings->getUserAttribute(),
371 $a_name,
372 $filter);
373
374 // Build search base
375 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
376 {
377 $dn .= ',';
378 }
379 $dn .= $this->settings->getBaseDN();
380 $fields = array_merge($this->user_fields,array('useraccountcontrol'));
381 $res = $this->queryByScope($this->settings->getUserScope(),strtolower($dn),$filter,$fields);
382 }
383
384
385 $tmp_result = new ilLDAPResult($this->lh,$res);
386 if(!$tmp_result->numRows())
387 {
388 $this->log->info('LDAP: No user data found for: '.$a_name);
389 unset($tmp_result);
390 return false;
391 }
392
393 if($user_data = $tmp_result->get())
394 {
395 if(isset($user_data['useraccountcontrol']))
396 {
397 if(($user_data['useraccountcontrol'] & 0x02))
398 {
399 $this->log->notice('LDAP: '.$a_name.' account disabled.');
400 return;
401 }
402 }
403
404 $user_ext = $user_data[strtolower($this->settings->getUserAttribute())];
405
406 // auth mode depends on ldap server settings
407 $auth_mode = $this->settings->getAuthenticationMappingKey();
408 $user_data['ilInternalAccount'] = ilObjUser::_checkExternalAuthAccount($auth_mode,$user_ext);
409 $this->users[$user_ext] = $user_data;
410 }
411 return true;
412 }
413
418 private function parseAuthMode()
419 {
420 return $this->settings->getAuthenticationMappingKey();
421 }
422
432 private function queryByScope($a_scope,$a_base_dn,$a_filter,$a_attributes)
433 {
434 $a_filter = $a_filter ? $a_filter : "(objectclass=*)";
435
436 switch($a_scope)
437 {
439 $res = @ldap_search($this->lh,$a_base_dn,$a_filter,$a_attributes);
440 break;
441
443 $res = @ldap_list($this->lh,$a_base_dn,$a_filter,$a_attributes);
444 break;
445
447
448 $res = @ldap_read($this->lh,$a_base_dn,$a_filter,$a_attributes);
449 break;
450
451 default:
452 $this->log->warning("LDAP: LDAPQuery: Unknown search scope");
453 }
454
455 return $res;
456
457 }
458
466 private function connect()
467 {
468 $this->lh = @ldap_connect($this->ldap_server_url);
469
470 // LDAP Connect
471 if(!$this->lh)
472 {
473 throw new ilLDAPQueryException("LDAP: Cannot connect to LDAP Server: ".$this->settings->getUrl());
474 }
475 // LDAP Version
476 if(!ldap_set_option($this->lh,LDAP_OPT_PROTOCOL_VERSION,$this->settings->getVersion()))
477 {
478 throw new ilLDAPQueryException("LDAP: Cannot set version to: ".$this->settings->getVersion());
479 }
480 // Switch on referrals
481 if($this->settings->isActiveReferrer())
482 {
483 if(!ldap_set_option($this->lh,LDAP_OPT_REFERRALS,true))
484 {
485 throw new ilLDAPQueryException("LDAP: Cannot switch on LDAP referrals");
486 }
487 #@ldap_set_rebind_proc($this->lh,'referralRebind');
488 }
489 else
490 {
491 ldap_set_option($this->lh,LDAP_OPT_REFERRALS,false);
492 $this->log->debug('Switching referrals to false.');
493 }
494 // Start TLS
495 if($this->settings->isActiveTLS())
496 {
497 if(!ldap_start_tls($this->lh))
498 {
499 throw new ilLDAPQueryException("LDAP: Cannot start LDAP TLS");
500 }
501 }
502 }
503
512 public function bind($a_binding_type = IL_LDAP_BIND_DEFAULT,$a_user_dn = '',$a_password = '')
513 {
514 switch($a_binding_type)
515 {
517 ldap_set_option($this->lh, LDAP_OPT_NETWORK_TIMEOUT, ilLDAPServer::DEFAULT_NETWORK_TIMEOUT);
518 // fall through
520 // Now bind anonymously or as user
521 if(
522 IL_LDAP_BIND_USER == $this->settings->getBindingType() &&
523 strlen($this->settings->getBindUser())
524 )
525 {
526 $user = $this->settings->getBindUser();
527 $pass = $this->settings->getBindPassword();
528
529 define('IL_LDAP_REBIND_USER',$user);
530 define('IL_LDAP_REBIND_PASS',$pass);
531 $this->log->debug('Bind as '.$user);
532 }
533 else
534 {
535 $user = $pass = '';
536 $this->log->debug('Bind anonymous');
537 }
538 break;
539
541 $user = $this->settings->getRoleBindDN();
542 $pass = $this->settings->getRoleBindPassword();
543
544 if(!strlen($user) or !strlen($pass))
545 {
546 $user = $this->settings->getBindUser();
547 $pass = $this->settings->getBindPassword();
548 }
549
550 define('IL_LDAP_REBIND_USER',$user);
551 define('IL_LDAP_REBIND_PASS',$pass);
552 break;
553
554 default:
555 throw new ilLDAPQueryException('LDAP: unknown binding type in: '.__METHOD__);
556 }
557
558 if(!@ldap_bind($this->lh,$user,$pass))
559 {
560 throw new ilLDAPQueryException('LDAP: Cannot bind as '.$user.' with message: '. ldap_err2str(ldap_errno($this->lh)).' Trying fallback...', ldap_errno($this->lh));
561 }
562 else
563 {
564 $this->log->debug('Bind successful.');
565 }
566 }
567
575 private function fetchUserProfileFields()
576 {
577 include_once('Services/LDAP/classes/class.ilLDAPRoleAssignmentRules.php');
578
579 $this->user_fields = array_merge(
580 array($this->settings->getUserAttribute()),
581 array('dn'),
582 $this->mapping->getFields(),
583 ilLDAPRoleAssignmentRules::getAttributeNames($this->getServer()->getServerId())
584 );
585 }
586
587
595 private function unbind()
596 {
597 if($this->lh)
598 {
599 @ldap_unbind($this->lh);
600 }
601 }
602
603
611 public function __destruct()
612 {
613 if($this->lh)
614 {
615 @ldap_unbind($this->lh);
616 }
617 }
618}
619
620function referralRebind($a_ds,$a_url)
621{
622 global $ilLog;
623
624 $ilLog->write('LDAP: Called referralRebind.');
625
626 ldap_set_option($a_ds, LDAP_OPT_PROTOCOL_VERSION, 3);
627
628 if (!ldap_bind($a_ds,IL_LDAP_REBIND_USER,IL_LDAP_REBIND_PASS))
629 {
630 $ilLog->write('LDAP: Rebind failed');
631 }
632}
633
634?>
const IL_LDAP_BIND_DEFAULT
referralRebind($a_ds, $a_url)
const IL_LDAP_BIND_ADMIN
const IL_LDAP_BIND_TEST
const IL_LDAP_BIND_USER
const IL_LDAP_SCOPE_BASE
const IL_LDAP_SCOPE_SUB
const IL_LDAP_SCOPE_ONE
static _getInstanceByServerId($a_server_id)
Get instance of class.
modAdd($a_dn, $a_attribute)
Add value to an existing attribute.
fetchUsers()
Fetch all users.
readUserData($a_name, $a_check_dn=true, $a_try_group_user_filter=false)
Read user data.
queryByScope($a_scope, $a_base_dn, $a_filter, $a_attributes)
Query by scope IL_SCOPE_SUB => ldap_search IL_SCOPE_ONE => ldap_list.
fetchGroupMembers($a_name='')
Fetch group member ids.
fetchUserProfileFields()
fetch required fields of user profile data
getServer()
Get server.
bind($a_binding_type=IL_LDAP_BIND_DEFAULT, $a_user_dn='', $a_password='')
Bind to LDAP server.
connect()
Connect to LDAP server.
parseAuthMode()
Parse authentication mode.
__destruct()
Destructor unbind from ldap server.
readAllUsers()
Fetch all users This function splits the query to filters like e.g (uid=a*) (uid=b*)....
__construct(ilLDAPServer $a_server, $a_url='')
Constructur.
fetchUser($a_name)
Get one user by login name.
query($a_search_base, $a_filter, $a_scope, $a_attributes)
Perform a query.
modDelete($a_dn, $a_attribute)
Delete value from an existing attribute.
static getAttributeNames($a_server_id)
get all possible attribute names
const DEFAULT_NETWORK_TIMEOUT
static getLogger($a_component_id)
Get component logger.
static _checkExternalAuthAccount($a_auth, $a_account)
check whether external account and authentication method matches with a user
$data