ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
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 = $ilLog;
74
76 $this->connect();
77 }
78
86 public function fetchUser($a_name)
87 {
88 $this->user_fields = array_merge(array($this->settings->getUserAttribute()),$this->mapping->getFields());
89
90 if(!$this->readUserData($a_name))
91 {
92 return array();
93 }
94 else
95 {
96 return $this->users;
97 }
98 }
99
100
107 public function fetchUsers()
108 {
109 // First of all check if a group restriction is enabled
110 // YES: => fetch all group members
111 // No: => fetch all users
112 if(strlen($this->settings->getGroupName()))
113 {
114 $this->log->write(__METHOD__.': Searching for group members.');
115
116 $groups = $this->settings->getGroupNames();
117 if(count($groups) <= 1)
118 {
119 $this->fetchGroupMembers();
120 }
121 else
122 {
123 foreach($groups as $group)
124 {
125 $this->fetchGroupMembers($group);
126 }
127 }
128
129 }
130 if(!strlen($this->settings->getGroupName()) or $this->settings->isMembershipOptional())
131 {
132 $this->log->write(__METHOD__.': Start reading all users...');
133 $this->readAllUsers();
134 #throw new ilLDAPQueryException('LDAP: Called import of users without specifying group restrictions. NOT IMPLEMENTED YET!');
135 }
136 return $this->users ? $this->users : array();
137 }
138
150 public function query($a_search_base,$a_filter,$a_scope,$a_attributes)
151 {
152 $res = $this->queryByScope($a_scope,$a_search_base,$a_filter,$a_attributes);
153 if($res === false)
154 {
155 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh).' '.
156 sprintf('DN: %s, Filter: %s, Scope: %s',
157 $a_search_base,
158 $a_filter,
159 $a_scope));
160 }
161 return new ilLDAPResult($this->lh,$res);
162 }
163
170 public function modAdd($a_dn,$a_attribute)
171 {
172 if(@ldap_mod_add($this->lh,$a_dn,$a_attribute))
173 {
174 return true;
175 }
176 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
177 }
178
185 public function modDelete($a_dn,$a_attribute)
186 {
187 if(@ldap_mod_del($this->lh,$a_dn,$a_attribute))
188 {
189 return true;
190 }
191 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
192 }
193
202 private function readAllUsers()
203 {
204 // Build search base
205 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
206 {
207 $dn .= ',';
208 }
209 $dn .= $this->settings->getBaseDN();
210
211 // page results
212 $filter = $this->settings->getFilter();
213 $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','-');
214 $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');
215
216 foreach($page_filter as $letter)
217 {
218 $new_filter = '(&';
219 $new_filter .= $filter;
220
221 switch($letter)
222 {
223 case '-':
224 $new_filter .= ('(!(|');
225 foreach($chars as $char)
226 {
227 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$char.'*)');
228 }
229 $new_filter .= ')))';
230 break;
231
232 default:
233 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$letter.'*))');
234 break;
235 }
236
237 $this->log->write(__METHOD__.': Searching with ldap search and filter '.$new_filter.' in '.$dn);
238 $res = $this->queryByScope($this->settings->getUserScope(),
239 $dn,
240 $new_filter,
241 array($this->settings->getUserAttribute()));
242
243 $tmp_result = new ilLDAPResult($this->lh,$res);
244 if(!$tmp_result->numRows())
245 {
246 $this->log->write(__METHOD__.': No users found. Aborting.');
247 continue;
248 }
249 $this->log->write(__METHOD__.': Found '.$tmp_result->numRows().' users.');
250 foreach($tmp_result->getRows() as $data)
251 {
252 if(isset($data[$this->settings->getUserAttribute()]))
253 {
254 $this->readUserData($data[$this->settings->getUserAttribute()],false,false);
255 }
256 else
257 {
258 $this->log->write(__METHOD__.': Unknown error. No user attribute found.');
259 }
260 }
261 unset($tmp_result);
262 }
263 return true;
264 }
265
266
273 private function fetchGroupMembers($a_name = '')
274 {
275 $group_name = strlen($a_name) ? $a_name : $this->settings->getGroupName();
276
277 // Build filter
278 $filter = sprintf('(&(%s=%s)%s)',
279 $this->settings->getGroupAttribute(),
280 $group_name,
281 $this->settings->getGroupFilter());
282
283
284 // Build search base
285 if(($gdn = $this->settings->getGroupDN()) && substr($gdn,-1) != ',')
286 {
287 $gdn .= ',';
288 }
289 $gdn .= $this->settings->getBaseDN();
290
291 $this->log->write('LDAP: Using filter '.$filter);
292 $this->log->write('LDAP: Using DN '.$gdn);
293 $res = $this->queryByScope($this->settings->getGroupScope(),
294 $gdn,
295 $filter,
296 array($this->settings->getGroupMember()));
297
298 $tmp_result = new ilLDAPResult($this->lh,$res);
299 $group_data = $tmp_result->getRows();
300
301
302 if(!$tmp_result->numRows())
303 {
304 $this->log->write(__METHOD__.': No group found.');
305 return false;
306 }
307
308 $attribute_name = strtolower($this->settings->getGroupMember());
309
310 // All groups
311 foreach($group_data as $data)
312 {
313 $this->log->write(__METHOD__.': found '.count($data[$attribute_name]).' group members for group '.$data['dn']);
314 if(is_array($data[$attribute_name]))
315 {
316 foreach($data[$attribute_name] as $name)
317 {
318 $this->readUserData($name,true,true);
319 }
320 }
321 else
322 {
323 $this->readUserData($data[$attribute_name],true,true);
324 }
325 }
326 unset($tmp_result);
327 return;
328 }
329
336 private function readUserData($a_name,$a_check_dn = true,$a_try_group_user_filter = false)
337 {
338 $filter = $this->settings->getFilter();
339 if($a_try_group_user_filter)
340 {
341 if($this->settings->isMembershipOptional())
342 {
343 $filter = $this->settings->getGroupUserFilter();
344 }
345 }
346
347 // Build filter
348 if($this->settings->enabledGroupMemberIsDN() and $a_check_dn)
349 {
350 $dn = $a_name;
351 #$res = $this->queryByScope(IL_LDAP_SCOPE_BASE,$dn,$filter,$this->user_fields);
352
353 $fields = array_merge($this->user_fields,array('useraccountcontrol'));
354 $res = $this->queryByScope(IL_LDAP_SCOPE_BASE,strtolower($dn),$filter,$fields);
355 }
356 else
357 {
358 $filter = sprintf('(&(%s=%s)%s)',
359 $this->settings->getUserAttribute(),
360 $a_name,
361 $filter);
362
363 // Build search base
364 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
365 {
366 $dn .= ',';
367 }
368 $dn .= $this->settings->getBaseDN();
369 $fields = array_merge($this->user_fields,array('useraccountcontrol'));
370 $res = $this->queryByScope($this->settings->getUserScope(),strtolower($dn),$filter,$fields);
371 }
372
373
374 $tmp_result = new ilLDAPResult($this->lh,$res);
375 if(!$tmp_result->numRows())
376 {
377 $this->log->write('LDAP: No user data found for: '.$a_name);
378 unset($tmp_result);
379 return false;
380 }
381
382 if($user_data = $tmp_result->get())
383 {
384 if(isset($user_data['useraccountcontrol']))
385 {
386 if(($user_data['useraccountcontrol'] & 0x02))
387 {
388 $this->log->write(__METHOD__.': '.$a_name.' account disabled.');
389 return;
390 }
391 }
392
393 $user_ext = $user_data[strtolower($this->settings->getUserAttribute())];
394
395 // auth mode depends on ldap server settings
396 $auth_mode = $this->parseAuthMode();
397
398 $user_data['ilInternalAccount'] = ilObjUser::_checkExternalAuthAccount($auth_mode,$user_ext);
399 $this->users[$user_ext] = $user_data;
400 }
401 return true;
402 }
403
408 private function parseAuthMode()
409 {
410 if($this->settings->isAuthenticationEnabled() or !$this->settings->getAuthenticationMapping())
411 {
412 return 'ldap';
413 }
414 return ilAuthUtils::_getAuthModeName($this->settings->getAuthenticationMapping());
415 }
416
426 private function queryByScope($a_scope,$a_base_dn,$a_filter,$a_attributes)
427 {
428 $a_filter = $a_filter ? $a_filter : "(objectclass=*)";
429
430 switch($a_scope)
431 {
433 $res = @ldap_search($this->lh,$a_base_dn,$a_filter,$a_attributes);
434 break;
435
437 $res = @ldap_list($this->lh,$a_base_dn,$a_filter,$a_attributes);
438 break;
439
441
442 $res = ldap_read($this->lh,$a_base_dn,$a_filter,$a_attributes);
443 break;
444
445 default:
446 $this->log->write("LDAP: LDAPQuery: Unknown search scope");
447 }
448
449 return $res;
450
451 }
452
460 private function connect()
461 {
462 $this->lh = @ldap_connect($this->ldap_server_url);
463
464 // LDAP Connect
465 if(!$this->lh)
466 {
467 throw new ilLDAPQueryException("LDAP: Cannot connect to LDAP Server: ".$this->settings->getUrl());
468 }
469 // LDAP Version
470 if(!ldap_set_option($this->lh,LDAP_OPT_PROTOCOL_VERSION,$this->settings->getVersion()))
471 {
472 throw new ilLDAPQueryException("LDAP: Cannot set version to: ".$this->settings->getVersion());
473 }
474 // Switch on referrals
475 if($this->settings->isActiveReferrer())
476 {
477 if(!ldap_set_option($this->lh,LDAP_OPT_REFERRALS,true))
478 {
479 throw new ilLDAPQueryException("LDAP: Cannot switch on LDAP referrals");
480 }
481 #@ldap_set_rebind_proc($this->lh,'referralRebind');
482 }
483 else
484 {
485 ldap_set_option($this->lh,LDAP_OPT_REFERRALS,false);
486 $this->log->write(__METHOD__.': Switching referrals to false.');
487 }
488 // Start TLS
489 if($this->settings->isActiveTLS())
490 {
491 if(!ldap_start_tls($this->lh))
492 {
493 throw new ilLDAPQueryException("LDAP: Cannot start LDAP TLS");
494 }
495 }
496 }
497
506 public function bind($a_binding_type = IL_LDAP_BIND_DEFAULT,$a_user_dn = '',$a_password = '')
507 {
508 switch($a_binding_type)
509 {
511 ldap_set_option($this->lh, LDAP_OPT_NETWORK_TIMEOUT, ilLDAPServer::DEFAULT_NETWORK_TIMEOUT);
512 // fall through
514 // Now bind anonymously or as user
515 if(
516 IL_LDAP_BIND_USER == $this->settings->getBindingType() &&
517 strlen($this->settings->getBindUser())
518 )
519 {
520 $user = $this->settings->getBindUser();
521 $pass = $this->settings->getBindPassword();
522
523 define('IL_LDAP_REBIND_USER',$user);
524 define('IL_LDAP_REBIND_PASS',$pass);
525 $this->log->write(__METHOD__.': Bind as '.$user);
526 }
527 else
528 {
529 $user = $pass = '';
530 $this->log->write(__METHOD__.': Bind anonymous');
531 }
532 break;
533
535 $user = $this->settings->getRoleBindDN();
536 $pass = $this->settings->getRoleBindPassword();
537
538 if(!strlen($user) or !strlen($pass))
539 {
540 $user = $this->settings->getBindUser();
541 $pass = $this->settings->getBindPassword();
542 }
543
544 define('IL_LDAP_REBIND_USER',$user);
545 define('IL_LDAP_REBIND_PASS',$pass);
546 break;
547
548 default:
549 throw new ilLDAPQueryException('LDAP: unknown binding type in: '.__METHOD__);
550 }
551
552 if(!@ldap_bind($this->lh,$user,$pass))
553 {
554 throw new ilLDAPQueryException('LDAP: Cannot bind as '.$user.' with message: '. ldap_err2str(ldap_errno($this->lh)).' Trying fallback...', ldap_errno($this->lh));
555 }
556 else
557 {
558 $this->log->write(__METHOD__.': Bind successful.');
559 }
560 }
561
569 private function fetchUserProfileFields()
570 {
571 include_once('Services/LDAP/classes/class.ilLDAPRoleAssignmentRules.php');
572
573 $this->user_fields = array_merge(
574 array($this->settings->getUserAttribute()),
575 array('dn'),
576 $this->mapping->getFields(),
578 );
579 }
580
581
589 private function unbind()
590 {
591 if($this->lh)
592 {
593 @ldap_unbind($this->lh);
594 }
595 }
596
597
605 public function __destruct()
606 {
607 if($this->lh)
608 {
609 @ldap_unbind($this->lh);
610 }
611 }
612}
613
614function referralRebind($a_ds,$a_url)
615{
616 global $ilLog;
617
618 $ilLog->write('LDAP: Called referralRebind.');
619
620 ldap_set_option($a_ds, LDAP_OPT_PROTOCOL_VERSION, 3);
621
622 if (!ldap_bind($a_ds,IL_LDAP_REBIND_USER,IL_LDAP_REBIND_PASS))
623 {
624 $ilLog->write('LDAP: Rebind failed');
625 }
626}
627
628?>
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 _getAuthModeName($a_auth_key)
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
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()
get all possible attribute names
const DEFAULT_NETWORK_TIMEOUT
static _checkExternalAuthAccount($a_auth, $a_account)
check whether external account and authentication method matches with a user