00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 define('IL_LDAP_BIND_DEFAULT',0);
00025 define('IL_LDAP_BIND_ADMIN',1);
00026 define('IL_LDAP_BIND_TEST',2);
00027
00028 include_once('Services/LDAP/classes/class.ilLDAPAttributeMapping.php');
00029 include_once('Services/LDAP/classes/class.ilLDAPResult.php');
00030 include_once('Services/LDAP/classes/class.ilLDAPQueryException.php');
00031
00041 class ilLDAPQuery
00042 {
00043 private $ldap_server_url = null;
00044 private $settings = null;
00045 private $log = null;
00046
00047 private $user_fields = array();
00048
00057 public function __construct(ilLDAPServer $a_server,$a_url = '')
00058 {
00059 global $ilLog;
00060
00061 $this->settings = $a_server;
00062
00063 if(strlen($a_url))
00064 {
00065 $this->ldap_server_url = $a_url;
00066 }
00067 else
00068 {
00069 $this->ldap_server_url = $this->settings->getUrl();
00070 }
00071
00072 $this->mapping = ilLDAPAttributeMapping::_getInstanceByServerId($this->settings->getServerId());
00073 $this->log = $ilLog;
00074
00075 $this->fetchUserProfileFields();
00076 $this->connect();
00077 }
00078
00086 public function fetchUser($a_name)
00087 {
00088 $this->user_fields = array_merge(array($this->settings->getUserAttribute()),$this->mapping->getFields());
00089
00090 if(!$this->readUserData($a_name))
00091 {
00092 return array();
00093 }
00094 else
00095 {
00096 return $this->users;
00097 }
00098 }
00099
00100
00107 public function fetchUsers()
00108 {
00109
00110
00111
00112 if(strlen($this->settings->getGroupName()))
00113 {
00114 $this->log->write(__METHOD__.': Searching for group members.');
00115
00116 $groups = $this->settings->getGroupNames();
00117 if(count($groups) <= 1)
00118 {
00119 $this->fetchGroupMembers();
00120 }
00121 else
00122 {
00123 foreach($groups as $group)
00124 {
00125 $this->fetchGroupMembers($group);
00126 }
00127 }
00128
00129 }
00130 if(!strlen($this->settings->getGroupName()) or $this->settings->isMembershipOptional())
00131 {
00132 $this->log->write(__METHOD__.': Start reading all users...');
00133 $this->readAllUsers();
00134 #throw new ilLDAPQueryException('LDAP: Called import of users without specifying group restrictions. NOT IMPLEMENTED YET!');
00135 }
00136 return $this->users ? $this->users : array();
00137 }
00138
00150 public function query($a_search_base,$a_filter,$a_scope,$a_attributes)
00151 {
00152 $res = $this->queryByScope($a_scope,$a_search_base,$a_filter,$a_attributes);
00153 if($res === false)
00154 {
00155 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh).' '.
00156 sprintf('DN: %s, Filter: %s, Scope: %s',
00157 $a_search_base,
00158 $a_filter,
00159 $a_scope));
00160 }
00161 return new ilLDAPResult($this->lh,$res);
00162 }
00163
00170 public function modAdd($a_dn,$a_attribute)
00171 {
00172 if(@ldap_mod_add($this->lh,$a_dn,$a_attribute))
00173 {
00174 return true;
00175 }
00176 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
00177 }
00178
00185 public function modDelete($a_dn,$a_attribute)
00186 {
00187 if(@ldap_mod_del($this->lh,$a_dn,$a_attribute))
00188 {
00189 return true;
00190 }
00191 throw new ilLDAPQueryException(__METHOD__.' '.ldap_error($this->lh));
00192 }
00193
00202 private function readAllUsers()
00203 {
00204
00205 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
00206 {
00207 $dn .= ',';
00208 }
00209 $dn .= $this->settings->getBaseDN();
00210
00211
00212 $filter = $this->settings->getFilter();
00213 $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','-');
00214 $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');
00215
00216 foreach($page_filter as $letter)
00217 {
00218 $new_filter = '(&';
00219 $new_filter .= $filter;
00220
00221 switch($letter)
00222 {
00223 case '-':
00224 $new_filter .= ('(!(|');
00225 foreach($chars as $char)
00226 {
00227 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$char.'*)');
00228 }
00229 $new_filter .= ')))';
00230 break;
00231
00232 default:
00233 $new_filter .= ('('.$this->settings->getUserAttribute().'='.$letter.'*))');
00234 break;
00235 }
00236
00237 $this->log->write(__METHOD__.': Searching with ldap search and filter '.$new_filter.' in '.$dn);
00238 $res = $this->queryByScope($this->settings->getUserScope(),
00239 $dn,
00240 $new_filter,
00241 array($this->settings->getUserAttribute()));
00242
00243 $tmp_result = new ilLDAPResult($this->lh,$res);
00244 if(!$tmp_result->numRows())
00245 {
00246 $this->log->write(__METHOD__.': No users found. Aborting.');
00247 continue;
00248 }
00249 $this->log->write(__METHOD__.': Found '.$tmp_result->numRows().' users.');
00250 foreach($tmp_result->getRows() as $data)
00251 {
00252 if(isset($data[$this->settings->getUserAttribute()]))
00253 {
00254 $this->readUserData($data[$this->settings->getUserAttribute()],false,false);
00255 }
00256 else
00257 {
00258 $this->log->write(__METHOD__.': Unknown error. No user attribute found.');
00259 }
00260 }
00261 unset($tmp_result);
00262 }
00263 return true;
00264 }
00265
00266
00273 private function fetchGroupMembers($a_name = '')
00274 {
00275 $group_name = strlen($a_name) ? $a_name : $this->settings->getGroupName();
00276
00277
00278 $filter = sprintf('(&(%s=%s)%s)',
00279 $this->settings->getGroupAttribute(),
00280 $group_name,
00281 $this->settings->getGroupFilter());
00282
00283
00284
00285 if(($gdn = $this->settings->getGroupDN()) && substr($gdn,-1) != ',')
00286 {
00287 $gdn .= ',';
00288 }
00289 $gdn .= $this->settings->getBaseDN();
00290
00291 $this->log->write('LDAP: Using filter '.$filter);
00292 $this->log->write('LDAP: Using DN '.$gdn);
00293 $res = $this->queryByScope($this->settings->getGroupScope(),
00294 $gdn,
00295 $filter,
00296 array($this->settings->getGroupMember()));
00297
00298 $tmp_result = new ilLDAPResult($this->lh,$res);
00299 $group_data = $tmp_result->getRows();
00300
00301
00302 if(!$tmp_result->numRows())
00303 {
00304 $this->log->write(__METHOD__.': No group found.');
00305 return false;
00306 }
00307
00308 $attribute_name = strtolower($this->settings->getGroupMember());
00309
00310
00311 foreach($group_data as $data)
00312 {
00313 $this->log->write(__METHOD__.': found '.count($data[$attribute_name]).' group members for group '.$data['dn']);
00314 if(is_array($data[$attribute_name]))
00315 {
00316 foreach($data[$attribute_name] as $name)
00317 {
00318 $this->readUserData($name,true,true);
00319 }
00320 }
00321 else
00322 {
00323 $this->readUserData($data[$attribute_name],true,true);
00324 }
00325 }
00326 unset($tmp_result);
00327 return;
00328 }
00329
00336 private function readUserData($a_name,$a_check_dn = true,$a_try_group_user_filter = false)
00337 {
00338 $filter = $this->settings->getFilter();
00339 if($a_try_group_user_filter)
00340 {
00341 if($this->settings->isMembershipOptional())
00342 {
00343 $filter = $this->settings->getGroupUserFilter();
00344 }
00345 }
00346
00347
00348 if($this->settings->enabledGroupMemberIsDN() and $a_check_dn)
00349 {
00350 $dn = $a_name;
00351 $res = $this->queryByScope(IL_LDAP_SCOPE_BASE,$dn,$filter,$this->user_fields);
00352 }
00353 else
00354 {
00355 $filter = sprintf('(&(%s=%s)%s)',
00356 $this->settings->getUserAttribute(),
00357 $a_name,
00358 $filter);
00359
00360
00361 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
00362 {
00363 $dn .= ',';
00364 }
00365 $dn .= $this->settings->getBaseDN();
00366 $fields = array_merge($this->user_fields,array('useraccountcontrol'));
00367 $res = $this->queryByScope($this->settings->getUserScope(),strtolower($dn),$filter,$fields);
00368 }
00369
00370
00371 $tmp_result = new ilLDAPResult($this->lh,$res);
00372 if(!$tmp_result->numRows())
00373 {
00374 $this->log->write('LDAP: No user data found for: '.$a_name);
00375 unset($tmp_result);
00376 return false;
00377 }
00378
00379 if($user_data = $tmp_result->get())
00380 {
00381 if(isset($user_data['useraccountcontrol']))
00382 {
00383 if(($user_data['useraccountcontrol'] & 0x02))
00384 {
00385 $this->log->write(__METHOD__.': '.$a_name.' account disabled.');
00386 return;
00387 }
00388 }
00389
00390 $user_ext = $user_data[strtolower($this->settings->getUserAttribute())];
00391 $user_data['ilInternalAccount'] = ilObjUser::_checkExternalAuthAccount('ldap',$user_ext);
00392 $this->users[$user_ext] = $user_data;
00393 }
00394 return true;
00395 }
00396
00406 private function queryByScope($a_scope,$a_base_dn,$a_filter,$a_attributes)
00407 {
00408 switch($a_scope)
00409 {
00410 case IL_LDAP_SCOPE_SUB:
00411 #$this->log->write('LDAP: Scope is: sub, using ldap_search');
00412 $res = @ldap_search($this->lh,$a_base_dn,$a_filter,$a_attributes);
00413 break;
00414
00415 case IL_LDAP_SCOPE_ONE:
00416 #$this->log->write('LDAP: Scope is: one, using ldap_list');
00417 $res = @ldap_list($this->lh,$a_base_dn,$a_filter,$a_attributes);
00418 break;
00419
00420 case IL_LDAP_SCOPE_BASE:
00421 $res = @ldap_read($this->lh,$a_base_dn,$a_filter,$a_attributes);
00422 break;
00423
00424 default:
00425 $this->log->write("LDAP: LDAPQuery: Unknown search scope");
00426 }
00427
00428 return $res;
00429
00430 }
00431
00439 private function connect()
00440 {
00441 $this->lh = @ldap_connect($this->ldap_server_url);
00442
00443
00444 if(!$this->lh)
00445 {
00446 throw new ilLDAPQueryException("LDAP: Cannot connect to LDAP Server: ".$this->settings->getUrl());
00447 }
00448
00449 if(!ldap_set_option($this->lh,LDAP_OPT_PROTOCOL_VERSION,$this->settings->getVersion()))
00450 {
00451 throw new ilLDAPQueryException("LDAP: Cannot set version to: ".$this->settings->getVersion());
00452 }
00453
00454 if($this->settings->isActiveReferrer())
00455 {
00456 if(!ldap_set_option($this->lh,LDAP_OPT_REFERRALS,true))
00457 {
00458 throw new ilLDAPQueryException("LDAP: Cannot switch on LDAP referrals");
00459 }
00460 #@ldap_set_rebind_proc($this->lh,'referralRebind');
00461 }
00462 else
00463 {
00464 ldap_set_option($this->lh,LDAP_OPT_REFERRALS,false);
00465 $this->log->write(__METHOD__.': Switching referrals to false.');
00466 }
00467
00468 if($this->settings->isActiveTLS())
00469 {
00470 if(!ldap_start_tls($this->lh))
00471 {
00472 throw new ilLDAPQueryException("LDAP: Cannot start LDAP TLS");
00473 }
00474 }
00475 }
00476
00485 public function bind($a_binding_type = IL_LDAP_BIND_DEFAULT,$a_user_dn = '',$a_password = '')
00486 {
00487 switch($a_binding_type)
00488 {
00489 case IL_LDAP_BIND_DEFAULT:
00490
00491 if(strlen($this->settings->getBindUser()))
00492 {
00493 $user = $this->settings->getBindUser();
00494 $pass = $this->settings->getBindPassword();
00495
00496 define('IL_LDAP_REBIND_USER',$user);
00497 define('IL_LDAP_REBIND_PASS',$pass);
00498 $this->log->write(__METHOD__.': Bind as '.$user);
00499 }
00500 else
00501 {
00502 $user = $pass = '';
00503 $this->log->write(__METHOD__.': Bind anonymous');
00504 }
00505 break;
00506
00507 case IL_LDAP_BIND_ADMIN:
00508 $user = $this->settings->getRoleBindDN();
00509 $pass = $this->settings->getRoleBindPassword();
00510
00511 if(!strlen($user) or !strlen($pass))
00512 {
00513 $user = $this->settings->getBindUser();
00514 $pass = $this->settings->getBindPassword();
00515 }
00516
00517 define('IL_LDAP_REBIND_USER',$user);
00518 define('IL_LDAP_REBIND_PASS',$pass);
00519 break;
00520
00521 case IL_LDAP_BIND_TEST:
00522 if(!@ldap_bind($this->lh,$a_user_dn,$a_password))
00523 {
00524 return false;
00525 }
00526 return true;
00527
00528 default:
00529 throw new ilLDAPQueryException('LDAP: unknown binding type in: '.__METHOD__);
00530 }
00531
00532 if(!@ldap_bind($this->lh,$user,$pass))
00533 {
00534 throw new ilLDAPQueryException('LDAP: Cannot bind as '.$user);
00535 }
00536 else
00537 {
00538 $this->log->write(__METHOD__.': Bind successful.');
00539 }
00540 }
00541
00549 private function fetchUserProfileFields()
00550 {
00551 include_once('Services/LDAP/classes/class.ilLDAPRoleAssignments.php');
00552
00553 $this->user_fields = array_merge(
00554 array($this->settings->getUserAttribute()),
00555 array('dn'),
00556 $this->mapping->getFields(),
00557 ilLDAPRoleAssignments::_getDistinctAttributeNamesByServerId($this->settings->getServerId()));
00558 }
00559
00560
00568 private function unbind()
00569 {
00570 if($this->lh)
00571 {
00572 @ldap_unbind($this->lh);
00573 }
00574 }
00575
00576
00584 public function __destruct()
00585 {
00586 if($this->lh)
00587 {
00588 @ldap_unbind($this->lh);
00589 }
00590 }
00591 }
00592
00593 function referralRebind($a_ds,$a_url)
00594 {
00595 global $ilLog;
00596
00597 $ilLog->write('LDAP: Called referralRebind.');
00598
00599 ldap_set_option($a_ds, LDAP_OPT_PROTOCOL_VERSION, 3);
00600
00601 if (!ldap_bind($a_ds,IL_LDAP_REBIND_USER,IL_LDAP_REBIND_PASS))
00602 {
00603 $ilLog->write('LDAP: Rebind failed');
00604 }
00605 }
00606
00607 ?>