• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Services/LDAP/classes/class.ilLDAPQuery.php

Go to the documentation of this file.
00001 <?php
00002 /*
00003         +-----------------------------------------------------------------------------+
00004         | ILIAS open source                                                           |
00005         +-----------------------------------------------------------------------------+
00006         | Copyright (c) 1998-2006 ILIAS open source, University of Cologne            |
00007         |                                                                             |
00008         | This program is free software; you can redistribute it and/or               |
00009         | modify it under the terms of the GNU General Public License                 |
00010         | as published by the Free Software Foundation; either version 2              |
00011         | of the License, or (at your option) any later version.                      |
00012         |                                                                             |
00013         | This program is distributed in the hope that it will be useful,             |
00014         | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00015         | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
00016         | GNU General Public License for more details.                                |
00017         |                                                                             |
00018         | You should have received a copy of the GNU General Public License           |
00019         | along with this program; if not, write to the Free Software                 |
00020         | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
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                 // First of all check if a group restriction is enabled
00110                 // YES: => fetch all group members
00111                 // No:  => fetch all users
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                 // Build search base
00205                 if(($dn = $this->settings->getSearchBase()) && substr($dn,-1) != ',')
00206                 {
00207                         $dn .= ',';
00208                 }
00209                 $dn .=  $this->settings->getBaseDN();
00210                 
00211                 // page results
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                 // Build filter
00278                 $filter = sprintf('(&(%s=%s)%s)',
00279                         $this->settings->getGroupAttribute(),
00280                         $group_name,
00281                         $this->settings->getGroupFilter());
00282                 
00283                 
00284                 // Build search base
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                 // All groups
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                 // Build filter
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                         // Build search base
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                 // LDAP Connect
00444                 if(!$this->lh)
00445                 {
00446                         throw new ilLDAPQueryException("LDAP: Cannot connect to LDAP Server: ".$this->settings->getUrl());
00447                 }
00448                 // LDAP Version
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                 // Switch on referrals
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                 // Start TLS
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                                 // Now bind anonymously or as user
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 ?>

Generated on Fri Dec 13 2013 17:56:57 for ILIAS Release_3_9_x_branch .rev 46835 by  doxygen 1.7.1