[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 | |
---|
[27285] | 43 | public function load_default_config() |
---|
[27036] | 44 | { |
---|
| 45 | $this->config['host'] = 'localhost'; |
---|
[28534] | 46 | $this->config['basedn'] = 'dc=example,dc=com'; // racine ! |
---|
| 47 | $this->config['usersbranch'] = 'ou=people'; |
---|
| 48 | $this->config['groupbranch'] = 'ou=group'; |
---|
| 49 | $this->config['ld_search_users'] = False; |
---|
| 50 | $this->config['ld_search_groups'] = False; |
---|
[27036] | 51 | $this->config['port'] = ''; // if port is empty, I count on the software to care of it ! |
---|
| 52 | $this->config['ld_attr'] = 'uid'; |
---|
[28534] | 53 | $this->config['ld_group'] = 'cn'; |
---|
| 54 | //$this->config['ld_class'] = 'posixAccount'; |
---|
[27036] | 55 | $this->config['ld_use_ssl'] = False; |
---|
| 56 | $this->config['ld_bindpw'] =''; |
---|
| 57 | $this->config['ld_binddn'] =''; |
---|
| 58 | $this->config['allow_newusers'] = False; |
---|
| 59 | $this->config['advertise_admin_new_ldapuser'] = False; |
---|
| 60 | $this->config['send_password_by_mail_ldap'] = False; |
---|
[28534] | 61 | |
---|
| 62 | $this->config['users_group'] = False; |
---|
| 63 | $this->config['webmasters_group'] = False; |
---|
| 64 | $this->config['admins_group'] = False; |
---|
[27285] | 65 | } |
---|
| 66 | |
---|
| 67 | function load_config() { |
---|
[28534] | 68 | $this->load_default_config(); |
---|
| 69 | |
---|
| 70 | // after the default, we can load the actual conf. That way, no holes ! |
---|
[27285] | 71 | $conf_file = @file_get_contents( LDAP_LOGIN_PATH.'data.dat' ); |
---|
| 72 | if ($conf_file!==false) |
---|
[27036] | 73 | { |
---|
[27285] | 74 | $this->config = unserialize($conf_file); |
---|
[28534] | 75 | $this->config['full_usersbranch'] = $this->config['usersbranch'].','.$this->config['basedn']; |
---|
| 76 | $this->config['full_groupbranch'] = $this->config['groupbranch'].','.$this->config['basedn']; |
---|
[27036] | 77 | } |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | function save_config() |
---|
| 81 | { |
---|
| 82 | $file = fopen( LDAP_LOGIN_PATH.'/data.dat', 'w' ); |
---|
| 83 | fwrite($file, serialize($this->config) ); |
---|
| 84 | fclose( $file ); |
---|
| 85 | } |
---|
| 86 | |
---|
| 87 | function ldap_admin_menu($menu) |
---|
| 88 | { |
---|
| 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'])){ |
---|
| 123 | if (@ldap_bind($this->cnx,$this->config['ld_binddn'],$this->config['ld_bindpw'])){ |
---|
| 124 | return true; |
---|
| 125 | } |
---|
| 126 | else { return false; } |
---|
| 127 | } |
---|
| 128 | // if anonymous search is allowed, we still need a fake auth using ldap_bind |
---|
| 129 | else { |
---|
| 130 | if (@ldap_bind($this->cnx)){ |
---|
| 131 | return true; |
---|
| 132 | } |
---|
| 133 | else { return false; } |
---|
| 134 | } |
---|
[27036] | 135 | } |
---|
[28534] | 136 | else { return false; } |
---|
[27036] | 137 | } |
---|
| 138 | |
---|
| 139 | // return ldap error |
---|
| 140 | public function getErrorString(){ |
---|
| 141 | return ldap_err2str(ldap_errno($this->cnx)); |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | // return the name ldap understand |
---|
| 145 | public function ldap_name($name){ |
---|
[28534] | 146 | if ($this->config['ld_search_users']) { |
---|
| 147 | return $this->ldap_search_dn($name); |
---|
| 148 | } |
---|
| 149 | else { return $this->config['ld_attr'].'='.$name.','.$this->config['full_usersbranch']; } |
---|
[27036] | 150 | } |
---|
[28534] | 151 | |
---|
| 152 | public function ldap_group($groupname){ |
---|
| 153 | // this should return an array, even if it's only one ! |
---|
| 154 | if ($this->config['ld_search_groups']) { |
---|
| 155 | return $this->ldap_search_group($groupname); |
---|
| 156 | } |
---|
| 157 | else { |
---|
| 158 | $result[] = $this->config['ld_group'].'='.$groupname.','.$this->config['full_groupbranch']; |
---|
| 159 | return $result; |
---|
| 160 | } |
---|
| 161 | } |
---|
[27036] | 162 | |
---|
| 163 | // authentication |
---|
| 164 | public function ldap_bind_as($user,$user_passwd){ |
---|
| 165 | if (@ldap_bind($this->cnx,$this->ldap_name($user),$user_passwd)){ |
---|
| 166 | return true; |
---|
| 167 | } |
---|
| 168 | return false; |
---|
| 169 | } |
---|
| 170 | |
---|
| 171 | public function ldap_mail($name){ |
---|
| 172 | $sr=@ldap_read($this->cnx, $this->ldap_name($name), "(objectclass=*)", array('mail')); |
---|
| 173 | $entry = @ldap_get_entries($this->cnx, $sr); |
---|
| 174 | |
---|
| 175 | if (!empty($entry[0]['mail'])) { |
---|
| 176 | return $entry[0]['mail'][0]; |
---|
| 177 | } |
---|
| 178 | return False; |
---|
| 179 | } |
---|
| 180 | |
---|
[28534] | 181 | public function ldap_search_group($to_search){ |
---|
| 182 | $ld_group = $this->config['ld_group']; |
---|
| 183 | |
---|
| 184 | $sr=@ldap_search($this->cnx, $this->config['full_groupbranch'], "($ld_group=$to_search)", array('dn'),0,0); |
---|
| 185 | $groups = @ldap_get_entries($this->cnx, $sr); |
---|
| 186 | $result = array(); |
---|
| 187 | foreach ($groups as $group) { |
---|
| 188 | $result[] = $group['dn']; |
---|
| 189 | } |
---|
| 190 | return $result; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | public function ldap_search_dn($to_search){ |
---|
| 194 | $ld_attr = $this->config['ld_attr']; |
---|
| 195 | |
---|
| 196 | $sr=@ldap_search($this->cnx, $this->config['full_usersbranch'], "($ld_attr=$to_search)", array('dn','mail'),0,0); |
---|
| 197 | $entry = @ldap_get_entries($this->cnx, $sr); |
---|
| 198 | |
---|
| 199 | if (!empty($entry[0]['dn'])) { |
---|
| 200 | return $entry[0]['dn']; |
---|
[27036] | 201 | } |
---|
[28534] | 202 | else { return False; } |
---|
| 203 | } |
---|
| 204 | |
---|
| 205 | public function user_membership($user, $groups){ |
---|
| 206 | // $groups is an array of groupdn ! (there is a possibility of several groups, we search the user in each of them). |
---|
| 207 | foreach ($groups as $groupdn) { |
---|
| 208 | $filter = '(objectClass=*)'; |
---|
| 209 | $result = @ldap_read($this->cnx,$groupdn,$filter,array('memberUid')); |
---|
| 210 | $result2 = @ldap_get_entries($this->cnx, $result); |
---|
| 211 | if(isset($result2[0]['memberuid'])){ |
---|
| 212 | foreach($result2[0]['memberuid'] as $item){ |
---|
| 213 | if ($item == $user){ |
---|
| 214 | return True; |
---|
| 215 | } |
---|
| 216 | } |
---|
| 217 | } |
---|
[27036] | 218 | } |
---|
[28534] | 219 | return False; |
---|
| 220 | } |
---|
[27036] | 221 | |
---|
[28534] | 222 | public function ldap_status($username){ |
---|
| 223 | if ($this->config['webmasters_group']) { |
---|
| 224 | if ($this->user_membership($username,$this->ldap_group($this->config['webmasters_group']))) { |
---|
| 225 | // set status to webmaster and quit (more powerfull, no need to get further) |
---|
| 226 | return 'webmaster'; |
---|
| 227 | } |
---|
| 228 | } |
---|
| 229 | if ($this->config['admins_group']) { |
---|
| 230 | if ($this->user_membership($username,$this->ldap_group($this->config['admins_group']))) { |
---|
| 231 | // set status to admin |
---|
| 232 | return 'admin'; |
---|
| 233 | } |
---|
| 234 | } |
---|
| 235 | else |
---|
| 236 | { |
---|
| 237 | return 'normal'; |
---|
| 238 | } |
---|
| 239 | } |
---|
[27036] | 240 | |
---|
[28534] | 241 | public function getAttr(){ |
---|
[27036] | 242 | $search = @ldap_read($this->cnx, "cn=subschema", "(objectClass=*)", array('*', 'subschemasubentry')); |
---|
| 243 | $entries = @ldap_get_entries($this->cnx, $search); |
---|
| 244 | } |
---|
| 245 | |
---|
[28534] | 246 | public function getRootDse(){ |
---|
[27036] | 247 | |
---|
| 248 | $search = @ldap_read($this->cnx, NULL, 'objectClass=*', array("*", "+")); |
---|
| 249 | $entries = @ldap_get_entries($this->cnx, $search); |
---|
| 250 | return $entries[0]; |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | public function ldap_check_basedn(){ |
---|
| 254 | if ($read = @ldap_read($this->cnx,$this->config['basedn'],'(objectClass=*)',array('dn'))){ |
---|
| 255 | $entry = @ldap_get_entries($this->cnx, $read); |
---|
| 256 | if (!empty($entry[0]['dn'])) { |
---|
| 257 | return true; |
---|
| 258 | } |
---|
| 259 | } |
---|
| 260 | return false; |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | } |
---|
| 264 | ?> |
---|