BurningFlipside /
CommonCode
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * LDAPAuthenticator class |
||
| 4 | * |
||
| 5 | * This file describes the LDAPAuthenticator class |
||
| 6 | * |
||
| 7 | * PHP version 5 and 7 |
||
| 8 | * |
||
| 9 | * @author Patrick Boyd / [email protected] |
||
| 10 | * @copyright Copyright (c) 2015, Austin Artistic Reconstruction |
||
| 11 | * @license http://www.apache.org/licenses/ Apache 2.0 License |
||
| 12 | */ |
||
| 13 | |||
| 14 | namespace Auth; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * Sort the provided array by the keys in $orderby |
||
| 18 | * |
||
| 19 | * @param array $array The array to sort |
||
| 20 | * @param array $orderby An array of keys to sort the array by |
||
| 21 | */ |
||
| 22 | function sort_array(&$array, $orderby) |
||
| 23 | { |
||
| 24 | $count = count($array); |
||
| 25 | $keys = array_keys($orderby); |
||
| 26 | for($i = 0; $i < $count; $i++) |
||
| 27 | { |
||
| 28 | for($j = $i; $j < $count; $j++) |
||
| 29 | { |
||
| 30 | $data = strcasecmp($array[$i][$keys[0]][0], $array[$j][$keys[0]][0]); |
||
| 31 | switch($orderby[$keys[0]]) |
||
| 32 | { |
||
| 33 | case 1: |
||
| 34 | if($data > 0) |
||
| 35 | { |
||
| 36 | swap($array, $i, $j); |
||
| 37 | } |
||
| 38 | break; |
||
| 39 | case 0: |
||
| 40 | if($data < 0) |
||
| 41 | { |
||
| 42 | swap($array, $i, $j); |
||
| 43 | } |
||
| 44 | break; |
||
| 45 | } |
||
| 46 | } |
||
| 47 | } |
||
| 48 | } |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Swap two elements of the provided array |
||
| 52 | * |
||
| 53 | * @param array $array The array to swap values in |
||
| 54 | * @param mixed $indexA The key of the first element to swap |
||
| 55 | * @param mixed $indexB The key of the second element to swap |
||
| 56 | */ |
||
| 57 | function swap(&$array, $indexA, $indexB) |
||
| 58 | { |
||
| 59 | $tmp = $array[$indexA]; |
||
| 60 | $array[$indexA] = $array[$indexB]; |
||
| 61 | $array[$indexB] = $tmp; |
||
| 62 | } |
||
| 63 | |||
| 64 | /** |
||
| 65 | * An Authenticator class which uses LDAP as its backend storage mechanism |
||
| 66 | */ |
||
| 67 | class LDAPAuthenticator extends Authenticator |
||
| 68 | { |
||
| 69 | /** The URL for the LDAP host */ |
||
| 70 | private $host; |
||
| 71 | /** The base DN for all users in the LDAP server */ |
||
| 72 | public $user_base; |
||
| 73 | /** The base DN for all groups in the LDAP server */ |
||
| 74 | public $group_base; |
||
| 75 | /** The DN to use to bind if not binding as the user */ |
||
| 76 | private $bindDistinguishedName; |
||
| 77 | /** The password to use to bind if not binding as the user */ |
||
| 78 | private $bindPassword; |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Create an LDAP Authenticator |
||
| 82 | * |
||
| 83 | * @param array $params Parementers needed to initialize the authenticator |
||
| 84 | */ |
||
| 85 | public function __construct($params) |
||
| 86 | { |
||
| 87 | parent::__construct($params); |
||
| 88 | $this->host = $this->getHostParam($params); |
||
| 89 | $this->user_base = $this->getParam($params, 'user_base'); |
||
| 90 | $this->group_base = $this->getParam($params, 'group_base'); |
||
| 91 | $this->bindDistinguishedName = $this->getParam($params, 'bind_dn', '$ldap_auth', 'read_write_pass'); |
||
| 92 | $this->bindPassword = $this->getParam($params, 'bind_pass', '$ldap_auth', 'read_write_user'); |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * Return the host string for this authenticator |
||
| 97 | * |
||
| 98 | * @param array $params The initial parameters of the authenticator |
||
| 99 | * |
||
| 100 | * @return string The host string |
||
| 101 | * |
||
| 102 | * @SuppressWarnings("StaticAccess") |
||
| 103 | */ |
||
| 104 | private function getHostParam($params) |
||
| 105 | { |
||
| 106 | if(isset($params['host'])) |
||
| 107 | { |
||
| 108 | return $params['host']; |
||
| 109 | } |
||
| 110 | $settings = \Settings::getInstance(); |
||
| 111 | return $settings->getLDAPSetting('host'); |
||
| 112 | } |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Return the required paramter for this authenticator |
||
| 116 | * |
||
| 117 | * @param array $params The initial parameters of the authenticator |
||
| 118 | * @param string $paramName The name of the parameter in the $paramsArray |
||
| 119 | * @param string $settingsLocation The location in the Settings class |
||
| 120 | * @param string $settingsName The name in the Settings class |
||
| 121 | * |
||
| 122 | * @return mixed The paramter value |
||
| 123 | * |
||
| 124 | * @SuppressWarnings("StaticAccess") |
||
| 125 | */ |
||
| 126 | private function getParam($params, $paramName, $settingsLocation = '$ldap', $settingsName = false) |
||
| 127 | { |
||
| 128 | if($settingsName === false) |
||
| 129 | { |
||
| 130 | $settingsName = $paramName; |
||
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||
| 131 | } |
||
| 132 | if(isset($params[$paramName])) |
||
| 133 | { |
||
| 134 | return $params[$paramName]; |
||
| 135 | } |
||
| 136 | $settings = \Settings::getInstance(); |
||
| 137 | return $settings->getLDAPSetting($settingsName, ($settingsLocation !== '$ldap')); |
||
| 138 | } |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Return an instance to the \LDAP\LDAPServer object instance |
||
| 142 | * |
||
| 143 | * @param boolean $bindWrite Should we be able to write to the server? |
||
| 144 | * |
||
| 145 | * @return \LDAP\LDAPServer|false The server instance if the binding was successful, otherwise false |
||
| 146 | * |
||
| 147 | * @SuppressWarnings("StaticAccess") |
||
| 148 | */ |
||
| 149 | public function getAndBindServer($bindWrite = false) |
||
| 150 | { |
||
| 151 | $server = \LDAP\LDAPServer::getInstance(); |
||
| 152 | $server->user_base = $this->user_base; |
||
| 153 | $server->group_base = $this->group_base; |
||
| 154 | $server->connect($this->host); |
||
| 155 | if($bindWrite === false) |
||
| 156 | { |
||
| 157 | $ret = $server->bind(); |
||
| 158 | } |
||
| 159 | else |
||
| 160 | { |
||
| 161 | $ret = $server->bind($this->bindDistinguishedName, $this->bindPassword); |
||
| 162 | } |
||
| 163 | if($ret === false) |
||
| 164 | { |
||
| 165 | return false; |
||
| 166 | } |
||
| 167 | return $server; |
||
| 168 | } |
||
| 169 | |||
| 170 | /** |
||
| 171 | * Log the user in provided the credetials |
||
| 172 | * |
||
| 173 | * @param string $username The UID or email address for the user |
||
| 174 | * @param string $password The password for the user |
||
| 175 | * |
||
| 176 | * @return mixed False if the login failed and array otherwise |
||
| 177 | */ |
||
| 178 | public function login($username, $password) |
||
| 179 | { |
||
| 180 | $server = $this->getAndBindServer(); |
||
| 181 | if($server === false) |
||
| 182 | { |
||
| 183 | return false; |
||
| 184 | } |
||
| 185 | $filter = new \Data\Filter("uid eq $username or mail eq $username"); |
||
| 186 | $user = $server->read($this->user_base, $filter); |
||
| 187 | if($user === false || count($user) === 0) |
||
| 188 | { |
||
| 189 | return false; |
||
| 190 | } |
||
| 191 | $user = $user[0]; |
||
| 192 | $server->unbind(); |
||
| 193 | $ret = $server->bind($user->dn, $password); |
||
| 194 | if($ret !== false) |
||
| 195 | { |
||
| 196 | return array('res'=>true, 'extended'=>$user); |
||
| 197 | } |
||
| 198 | return false; |
||
| 199 | } |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Does this array represent a successful login? |
||
| 203 | * |
||
| 204 | * @param array $data The array data stored in the session after a login call |
||
| 205 | * |
||
| 206 | * @return boolean True if the user is logged in, false otherwise |
||
| 207 | */ |
||
| 208 | public function isLoggedIn($data) |
||
| 209 | { |
||
| 210 | if(isset($data['res'])) |
||
| 211 | { |
||
| 212 | return $data['res']; |
||
| 213 | } |
||
| 214 | return false; |
||
| 215 | } |
||
| 216 | |||
| 217 | /** |
||
| 218 | * Obtain the currently logged in user from the session data |
||
| 219 | * |
||
| 220 | * @param \stdClass $data The AuthData from the session |
||
| 221 | * |
||
| 222 | * @return null|\Auth\LDAPUser The LDAPUser represented by this data |
||
| 223 | */ |
||
| 224 | public function getUser($data) |
||
| 225 | { |
||
| 226 | return new LDAPUser($data); |
||
| 227 | } |
||
| 228 | |||
| 229 | /** |
||
| 230 | * Obtain the group based on the group name |
||
| 231 | * |
||
| 232 | * @param string $name The Group's name |
||
| 233 | * |
||
| 234 | * @return null|\Auth\LDAPGroup The LDAPGroup represented by the name or null if not found |
||
| 235 | */ |
||
| 236 | public function getGroupByName($name) |
||
| 237 | { |
||
| 238 | $server = $this->getAndBindServer(); |
||
| 239 | if($server === false) |
||
| 240 | { |
||
| 241 | return null; |
||
| 242 | } |
||
| 243 | return LDAPGroup::from_name($name, $server); |
||
| 244 | } |
||
| 245 | |||
| 246 | public function getGroupsByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false) |
||
| 247 | { |
||
| 248 | $server = $this->getAndBindServer(); |
||
| 249 | if($server === false) |
||
| 250 | { |
||
| 251 | return false; |
||
| 252 | } |
||
| 253 | if($filter === false) |
||
| 254 | { |
||
| 255 | $filter = new \Data\Filter('cn eq *'); |
||
|
0 ignored issues
–
show
|
|||
| 256 | } |
||
| 257 | $groups = $server->read($this->group_base, $filter); |
||
| 258 | if($groups === false) |
||
| 259 | { |
||
| 260 | return false; |
||
| 261 | } |
||
| 262 | $this->processFilteringParams($groups, $select, $top, $skip, $orderby); |
||
| 263 | $count = count($groups); |
||
| 264 | for($i = 0; $i < $count; $i++) |
||
| 265 | { |
||
| 266 | $groups[$i] = new LDAPGroup($groups[$i]); |
||
| 267 | if($select !== false) |
||
| 268 | { |
||
| 269 | $groups[$i] = json_decode(json_encode($groups[$i]), true); |
||
| 270 | $groups[$i] = array_intersect_key($groups[$i], array_flip($select)); |
||
| 271 | } |
||
| 272 | } |
||
| 273 | return $groups; |
||
| 274 | } |
||
| 275 | |||
| 276 | public function getActiveUserCount() |
||
| 277 | { |
||
| 278 | $server = $this->getAndBindServer(); |
||
| 279 | if($server === false) |
||
| 280 | { |
||
| 281 | return 0; |
||
| 282 | } |
||
| 283 | return $server->count($this->user_base); |
||
| 284 | } |
||
| 285 | |||
| 286 | /** |
||
| 287 | * @param array $data The array data to filter and sort |
||
| 288 | * @param boolean|array $select The fields to return |
||
| 289 | * @param boolean|integer $top The number of records to return |
||
| 290 | * @param boolean|integer $skip The number of records to skip |
||
| 291 | * @param boolean|array $orderby The fields to sort by |
||
| 292 | */ |
||
| 293 | private function processFilteringParams(&$data, &$select, $top, $skip, $orderby) |
||
| 294 | { |
||
| 295 | if($orderby !== false) |
||
| 296 | { |
||
| 297 | sort_array($data, $orderby); |
||
| 298 | } |
||
| 299 | if($select !== false) |
||
| 300 | { |
||
| 301 | $select = array_flip($select); |
||
| 302 | } |
||
| 303 | if($skip !== false && $top !== false) |
||
| 304 | { |
||
| 305 | $data = array_slice($data, $skip, $top); |
||
| 306 | } |
||
| 307 | else if($top !== false) |
||
| 308 | { |
||
| 309 | $data = array_slice($data, 0, $top); |
||
| 310 | } |
||
| 311 | else if($skip !== false) |
||
| 312 | { |
||
| 313 | $data = array_slice($data, $skip); |
||
| 314 | } |
||
| 315 | } |
||
| 316 | |||
| 317 | |||
| 318 | /** |
||
| 319 | * @param boolean|\Data\Filter $filter The filter to user when reading users |
||
| 320 | * @param boolean|array $select The fields to return |
||
| 321 | * @param boolean|integer $top The number of records to return |
||
| 322 | * @param boolean|integer $skip The number of records to skip |
||
| 323 | * @param boolean|array $orderby The fields to sort by |
||
| 324 | * |
||
| 325 | * @return array|boolean False if no users found, an array of user objects otherwise |
||
| 326 | */ |
||
| 327 | public function getUsersByFilter($filter, $select = false, $top = false, $skip = false, $orderby = false) |
||
| 328 | { |
||
| 329 | $server = $this->getAndBindServer(); |
||
| 330 | if($server === false) |
||
| 331 | { |
||
| 332 | return false; |
||
| 333 | } |
||
| 334 | if($filter === false) |
||
| 335 | { |
||
| 336 | $filter = new \Data\Filter('cn eq *'); |
||
|
0 ignored issues
–
show
|
|||
| 337 | } |
||
| 338 | $users = $server->read($this->user_base, $filter, false, $select); |
||
| 339 | if($users === false) |
||
| 340 | { |
||
| 341 | return false; |
||
| 342 | } |
||
| 343 | $this->processFilteringParams($users, $select, $top, $skip, $orderby); |
||
| 344 | $count = count($users); |
||
| 345 | for($i = 0; $i < $count; $i++) |
||
| 346 | { |
||
| 347 | $tmp = new LDAPUser($users[$i]); |
||
| 348 | if($select !== false) |
||
| 349 | { |
||
| 350 | $tmp = $tmp->jsonSerialize(); |
||
| 351 | $tmp = array_intersect_key($tmp, $select); |
||
| 352 | } |
||
| 353 | $users[$i] = $tmp; |
||
| 354 | } |
||
| 355 | return $users; |
||
| 356 | } |
||
| 357 | |||
| 358 | public function activatePendingUser($user) |
||
| 359 | { |
||
| 360 | $this->getAndBindServer(true); |
||
| 361 | $newUser = new LDAPUser(); |
||
| 362 | $newUser->uid = $user->uid; |
||
| 363 | $newUser->mail = $user->mail; |
||
| 364 | $newUser->sn = $user->sn; |
||
| 365 | $newUser->givenName = $user->givenName; |
||
| 366 | $newUser->host = $user->host; |
||
| 367 | $pass = $user->getPassword(); |
||
| 368 | if($pass !== false) |
||
| 369 | { |
||
| 370 | $newUser->setPass($pass); |
||
| 371 | } |
||
| 372 | $ret = $newUser->flushUser(); |
||
| 373 | if($ret) |
||
| 374 | { |
||
| 375 | $user->delete(); |
||
| 376 | } |
||
| 377 | $users = $this->getUsersByFilter(new \Data\Filter('mail eq '.$user->mail)); |
||
| 378 | if(empty($users)) |
||
| 379 | { |
||
| 380 | throw new \Exception('Error creating user!'); |
||
| 381 | } |
||
| 382 | return $users[0]; |
||
| 383 | } |
||
| 384 | |||
| 385 | public function getUserByResetHash($hash) |
||
| 386 | { |
||
| 387 | $users = $this->getUsersByFilter(new \Data\Filter("uniqueIdentifier eq $hash")); |
||
| 388 | if($users === false || !isset($users[0])) |
||
| 389 | { |
||
| 390 | return false; |
||
| 391 | } |
||
| 392 | return $users[0]; |
||
| 393 | } |
||
| 394 | } |
||
| 395 | /* vim: set tabstop=4 shiftwidth=4 expandtab: */ |
||
| 396 |