[27036] | 1 | <?php |
---|
[27285] | 2 | global $conf; |
---|
[27036] | 3 | class Ldap { |
---|
| 4 | var $cnx; |
---|
| 5 | var $config; |
---|
| 6 | |
---|
| 7 | // for debug |
---|
| 8 | public function write_log($message){ |
---|
| 9 | @file_put_contents('/var/log/ldap_login.log',$message."\n",FILE_APPEND); |
---|
| 10 | } |
---|
| 11 | |
---|
| 12 | /** |
---|
| 13 | * check ldap configuration |
---|
| 14 | * |
---|
| 15 | * Dans le cas ou l'acces au ldap est anonyme il faut impérativement faire une recherche |
---|
| 16 | * pour tester la connection. |
---|
| 17 | * |
---|
| 18 | * When OpenLDAP 2.x.x is used, ldap_connect() will always return a resource as it does not actually connect |
---|
| 19 | * but just initializes the connecting parameters. The actual connect happens with the next calls |
---|
| 20 | * to ldap_* funcs, usually with ldap_bind(). |
---|
| 21 | */ |
---|
| 22 | public function check_ldap(){ |
---|
| 23 | |
---|
| 24 | if (!$this->ldap_conn()) { |
---|
| 25 | return $this->getErrorString(); |
---|
| 26 | } |
---|
| 27 | |
---|
| 28 | // test du compte root si renseigné |
---|
| 29 | if (!empty($this->config['ld_binddn']) && !empty($this->config['ld_bindpw'])){ // if empty ld_binddn, anonymous search |
---|
| 30 | // authentication with rootdn and rootpw for search |
---|
| 31 | if (!$this->ldap_bind_as($this->config['ld_binddn'],$this->config['ld_bindpw'])){ |
---|
| 32 | return $this->getErrorString(); |
---|
| 33 | } |
---|
| 34 | } else { |
---|
| 35 | // sinon recherche du basedn (cf comportement ldap_connect avec OpenLDAP) |
---|
| 36 | if (!$this->ldap_check_basedn()){ // search userdn |
---|
| 37 | return $this->getErrorString(); |
---|
| 38 | } |
---|
| 39 | } |
---|
| 40 | return true; |
---|
| 41 | } |
---|
| 42 | |
---|
[29135] | 43 | public function load_default_config(){ |
---|
[27036] | 44 | $this->config['host'] = 'localhost'; |
---|
[28534] | 45 | $this->config['basedn'] = 'dc=example,dc=com'; // racine ! |
---|
| 46 | $this->config['usersbranch'] = 'ou=people'; |
---|
| 47 | $this->config['groupbranch'] = 'ou=group'; |
---|
| 48 | $this->config['ld_search_users'] = False; |
---|
| 49 | $this->config['ld_search_groups'] = False; |
---|
[27036] | 50 | $this->config['port'] = ''; // if port is empty, I count on the software to care of it ! |
---|
| 51 | $this->config['ld_attr'] = 'uid'; |
---|
[28534] | 52 | $this->config['ld_group'] = 'cn'; |
---|
| 53 | //$this->config['ld_class'] = 'posixAccount'; |
---|
[27036] | 54 | $this->config['ld_use_ssl'] = False; |
---|
| 55 | $this->config['ld_bindpw'] =''; |
---|
| 56 | $this->config['ld_binddn'] =''; |
---|
| 57 | $this->config['allow_newusers'] = False; |
---|
| 58 | $this->config['advertise_admin_new_ldapuser'] = False; |
---|
| 59 | $this->config['send_password_by_mail_ldap'] = False; |
---|
[28534] | 60 | |
---|
| 61 | $this->config['users_group'] = False; |
---|
| 62 | $this->config['webmasters_group'] = False; |
---|
| 63 | $this->config['admins_group'] = False; |
---|
[27285] | 64 | } |
---|
| 65 | |
---|
[29135] | 66 | function load_config(){ |
---|
[28534] | 67 | $this->load_default_config(); |
---|
| 68 | |
---|
| 69 | // after the default, we can load the actual conf. That way, no holes ! |
---|
[27285] | 70 | $conf_file = @file_get_contents( LDAP_LOGIN_PATH.'data.dat' ); |
---|
| 71 | if ($conf_file!==false) |
---|
[27036] | 72 | { |
---|
[27285] | 73 | $this->config = unserialize($conf_file); |
---|
[29135] | 74 | // $this->config['full_usersbranch'] = $this->config['usersbranch'].','.$this->config['basedn']; |
---|
| 75 | // $this->config['full_groupbranch'] = $this->config['groupbranch'].','.$this->config['basedn']; |
---|
| 76 | // I don't place it in config['..'] because it will save it in the config file, and I don't want that ! |
---|
| 77 | $this->full_usersbranch = $this->config['usersbranch'].','.$this->config['basedn']; |
---|
| 78 | $this->full_groupbranch = $this->config['groupbranch'].','.$this->config['basedn']; |
---|
[27036] | 79 | } |
---|
| 80 | } |
---|
| 81 | |
---|
[29135] | 82 | function save_config(){ |
---|
[27036] | 83 | $file = fopen( LDAP_LOGIN_PATH.'/data.dat', 'w' ); |
---|
| 84 | fwrite($file, serialize($this->config) ); |
---|
| 85 | fclose( $file ); |
---|
| 86 | } |
---|
| 87 | |
---|
[29135] | 88 | function ldap_admin_menu($menu){ |
---|
[27036] | 89 | array_push($menu, |
---|
| 90 | array( |
---|
| 91 | 'NAME' => 'Ldap Login', |
---|
| 92 | 'URL' => get_admin_plugin_menu_link(LDAP_LOGIN_PATH.'/admin.php') ) |
---|
| 93 | ); |
---|
| 94 | return $menu; |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | public function ldap_conn(){ |
---|
[27285] | 98 | if ($this->config['ld_use_ssl'] == 1){ |
---|
[27036] | 99 | if (empty($this->config['port'])){ |
---|
| 100 | $this->config['uri'] = 'ldaps://'.$this->config['host']; |
---|
| 101 | } |
---|
| 102 | else { |
---|
| 103 | $this->config['uri'] = 'ldaps://'.$this->config['host'].':'.$this->config['port']; |
---|
| 104 | } |
---|
| 105 | } |
---|
| 106 | |
---|
| 107 | // now, it's without ssl |
---|
| 108 | else { |
---|
| 109 | if (empty($this->config['port'])){ |
---|
| 110 | $this->config['uri'] = 'ldap://'.$this->config['host']; |
---|
| 111 | } |
---|
| 112 | else { |
---|
| 113 | $this->config['uri'] = 'ldap://'.$this->config['host'].':'.$this->config['port']; |
---|
| 114 | } |
---|
| 115 | } |
---|
| 116 | |
---|
[28534] | 117 | // first, we initializes connection to ldap |
---|
[27036] | 118 | if ($this->cnx = @ldap_connect($this->config['uri'])){ |
---|
[28534] | 119 | @ldap_set_option($this->cnx, LDAP_OPT_PROTOCOL_VERSION, 3); // LDAPv3 if possible |
---|
[27036] | 120 | |
---|
[28534] | 121 | // then we authenticate if anonymous search is forbidden |
---|
| 122 | if (!empty($obj->config['ld_binddn']) && !empty($obj->config['ld_bindpw'])){ |
---|
[29135] | 123 | $password = strtr($obj->config['ld_bindpw'], array("\'"=>"'")); |
---|
| 124 | |
---|
| 125 | if (@ldap_bind($this->cnx,$this->config['ld_binddn'],$password)){ |
---|
[28534] | 126 | return true; |
---|
| 127 | } |
---|
| 128 | else { return false; } |
---|
| 129 | } |
---|
| 130 | // if anonymous search is allowed, we still need a fake auth using ldap_bind |
---|
| 131 | else { |
---|
| 132 | if (@ldap_bind($this->cnx)){ |
---|
| 133 | return true; |
---|
| 134 | } |
---|
| 135 | else { return false; } |
---|
| 136 | } |
---|
[27036] | 137 | } |
---|
[28534] | 138 | else { return false; } |
---|
[27036] | 139 | } |
---|
| 140 | |
---|
| 141 | // return ldap error |
---|
| 142 | public function getErrorString(){ |
---|
| 143 | return ldap_err2str(ldap_errno($this->cnx)); |
---|
| 144 | } |
---|
| 145 | |
---|
| 146 | // return the name ldap understand |
---|
| 147 | public function ldap_name($name){ |
---|
[28534] | 148 | if ($this->config['ld_search_users']) { |
---|
| 149 | return $this->ldap_search_dn($name); |
---|
| 150 | } |
---|
[29135] | 151 | else { return $this->config['ld_attr'].'='.$name.','.$this->full_usersbranch; } |
---|
[27036] | 152 | } |
---|
[28534] | 153 | |
---|
| 154 | public function ldap_group($groupname){ |
---|
| 155 | // this should return an array, even if it's only one ! |
---|
| 156 | if ($this->config['ld_search_groups']) { |
---|
| 157 | return $this->ldap_search_group($groupname); |
---|
| 158 | } |
---|
| 159 | else { |
---|
[29135] | 160 | $result[] = $this->config['ld_group'].'='.$groupname.','.$this->full_groupbranch; |
---|
[28534] | 161 | return $result; |
---|
| 162 | } |
---|
| 163 | } |
---|
[27036] | 164 | |
---|
| 165 | // authentication |
---|
| 166 | public function ldap_bind_as($user,$user_passwd){ |
---|
[29135] | 167 | $user_passwd = strtr($user_passwd, array("\'"=>"'")); |
---|
| 168 | |
---|
[27036] | 169 | if (@ldap_bind($this->cnx,$this->ldap_name($user),$user_passwd)){ |
---|
| 170 | return true; |
---|
| 171 | } |
---|
| 172 | return false; |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | public function ldap_mail($name){ |
---|
| 176 | $sr=@ldap_read($this->cnx, $this->ldap_name($name), "(objectclass=*)", array('mail')); |
---|
| 177 | $entry = @ldap_get_entries($this->cnx, $sr); |
---|
| 178 | |
---|
| 179 | if (!empty($entry[0]['mail'])) { |
---|
| 180 | return $entry[0]['mail'][0]; |
---|
| 181 | } |
---|
| 182 | return False; |
---|
| 183 | } |
---|
| 184 | |
---|
[28534] | 185 | public function ldap_search_group($to_search){ |
---|
| 186 | $ld_group = $this->config['ld_group']; |
---|
| 187 | |
---|
[29135] | 188 | $sr=@ldap_search($this->cnx, $this->full_groupbranch, "($ld_group=$to_search)", array('dn'),0,0); |
---|
[28534] | 189 | $groups = @ldap_get_entries($this->cnx, $sr); |
---|
| 190 | $result = array(); |
---|
| 191 | foreach ($groups as $group) { |
---|
| 192 | $result[] = $group['dn']; |
---|
| 193 | } |
---|
| 194 | return $result; |
---|
| 195 | } |
---|
| 196 | |
---|
[29135] | 197 | /* $filter="(sAMAccountName=".$user.")"; |
---|
| 198 | |
---|
| 199 | if(($results=ldap_search($this->cnx,$this->config['basedn'],$filter,array('dn',$this->config['ld_attr'])))!==false) |
---|
| 200 | { $firstEntry=ldap_first_entry($this->cnx,$results); |
---|
| 201 | |
---|
| 202 | if($firstEntry==null) |
---|
| 203 | { return false; |
---|
| 204 | } |
---|
| 205 | else |
---|
| 206 | { if(($userDn=ldap_get_dn($this->cnx,$firstEntry))!==false) |
---|
| 207 | { if(($isBound=wpDirAuth_bindTest($this->cnx,$userDn,$user_passwd,$this->config['basedn']))===true) |
---|
| 208 | { return true; |
---|
| 209 | } |
---|
| 210 | else |
---|
| 211 | { return false; |
---|
| 212 | } |
---|
| 213 | } |
---|
| 214 | } |
---|
| 215 | } */ |
---|
| 216 | |
---|
| 217 | |
---|
| 218 | |
---|
[28534] | 219 | public function ldap_search_dn($to_search){ |
---|
| 220 | $ld_attr = $this->config['ld_attr']; |
---|
| 221 | |
---|
[29135] | 222 | if(($results=@ldap_search($this->cnx,$this->config['basedn'],"($ld_attr=$to_search)",array('dn','mail',$ld_attr)))!==false) |
---|
| 223 | //$sr= @ldap_search($this->cnx, $this->full_usersbranch, "($ld_attr=$to_search)", array('dn','mail'),0,0); |
---|
| 224 | $entry = @ldap_first_entry($this->cnx, $results); |
---|
[28534] | 225 | |
---|
[29135] | 226 | if($entry==null) |
---|
| 227 | { |
---|
| 228 | return false; |
---|
| 229 | } |
---|
| 230 | |
---|
| 231 | else |
---|
| 232 | { if(($userDn=ldap_get_dn($this->cnx,$entry))!==false) |
---|
| 233 | { |
---|
| 234 | return $userDN; |
---|
[27036] | 235 | } |
---|
[29135] | 236 | else |
---|
| 237 | { |
---|
| 238 | return null; |
---|
| 239 | } |
---|
| 240 | } |
---|
| 241 | // if (!empty($entry[0]['dn'])) { |
---|
| 242 | // return $entry[0]['dn']; |
---|
| 243 | // } |
---|
| 244 | // else { return False; } |
---|
[28534] | 245 | } |
---|
| 246 | |
---|
| 247 | public function user_membership($user, $groups){ |
---|
| 248 | // $groups is an array of groupdn ! (there is a possibility of several groups, we search the user in each of them). |
---|
| 249 | foreach ($groups as $groupdn) { |
---|
| 250 | $filter = '(objectClass=*)'; |
---|
| 251 | $result = @ldap_read($this->cnx,$groupdn,$filter,array('memberUid')); |
---|
| 252 | $result2 = @ldap_get_entries($this->cnx, $result); |
---|
| 253 | if(isset($result2[0]['memberuid'])){ |
---|
| 254 | foreach($result2[0]['memberuid'] as $item){ |
---|
| 255 | if ($item == $user){ |
---|
| 256 | return True; |
---|
| 257 | } |
---|
| 258 | } |
---|
| 259 | } |
---|
[27036] | 260 | } |
---|
[28534] | 261 | return False; |
---|
| 262 | } |
---|
[27036] | 263 | |
---|
[28534] | 264 | public function ldap_status($username){ |
---|
| 265 | if ($this->config['webmasters_group']) { |
---|
| 266 | if ($this->user_membership($username,$this->ldap_group($this->config['webmasters_group']))) { |
---|
| 267 | // set status to webmaster and quit (more powerfull, no need to get further) |
---|
| 268 | return 'webmaster'; |
---|
| 269 | } |
---|
| 270 | } |
---|
| 271 | if ($this->config['admins_group']) { |
---|
| 272 | if ($this->user_membership($username,$this->ldap_group($this->config['admins_group']))) { |
---|
| 273 | // set status to admin |
---|
| 274 | return 'admin'; |
---|
| 275 | } |
---|
| 276 | } |
---|
| 277 | else |
---|
| 278 | { |
---|
| 279 | return 'normal'; |
---|
| 280 | } |
---|
| 281 | } |
---|
[27036] | 282 | |
---|
[28534] | 283 | public function getAttr(){ |
---|
[27036] | 284 | $search = @ldap_read($this->cnx, "cn=subschema", "(objectClass=*)", array('*', 'subschemasubentry')); |
---|
| 285 | $entries = @ldap_get_entries($this->cnx, $search); |
---|
| 286 | } |
---|
| 287 | |
---|
[28534] | 288 | public function getRootDse(){ |
---|
[27036] | 289 | |
---|
| 290 | $search = @ldap_read($this->cnx, NULL, 'objectClass=*', array("*", "+")); |
---|
| 291 | $entries = @ldap_get_entries($this->cnx, $search); |
---|
| 292 | return $entries[0]; |
---|
| 293 | } |
---|
| 294 | |
---|
| 295 | public function ldap_check_basedn(){ |
---|
| 296 | if ($read = @ldap_read($this->cnx,$this->config['basedn'],'(objectClass=*)',array('dn'))){ |
---|
| 297 | $entry = @ldap_get_entries($this->cnx, $read); |
---|
| 298 | if (!empty($entry[0]['dn'])) { |
---|
| 299 | return true; |
---|
| 300 | } |
---|
| 301 | } |
---|
| 302 | return false; |
---|
| 303 | } |
---|
| 304 | |
---|
| 305 | } |
---|
| 306 | ?> |
---|