1<?php 2// must be run within Dokuwiki 3if(!defined('DOKU_INC')) die(); 4 5/** 6 * Chained authentication backend 7 * 8 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 9 * @author Philipp Nesuer <pneuser@physik.fu-berlin.de> 10 */ 11class auth_plugin_authchained extends DokuWiki_Auth_Plugin { 12 public $success = true; 13 //arry with authentication plugins 14 protected $chained_plugins = array(); 15 protected $chained_auth = NULL; 16 17 /** 18 * Constructor. 19 * 20 * Loads all configured plugins or the authentication plugin of the 21 * logged in user. 22 * 23 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 24 */ 25 public function __construct() { 26 global $conf; 27 // call parent 28# parent::__constructor(); 29 30 //check if there is allready an authentication plugin selected 31 if(isset($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']) && 32 !empty($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']) ) 33 { 34 //get previously selected authentication plugin 35 $tmp_plugin = $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']; 36 require_once(DOKU_INC."lib/plugins/".$tmp_plugin."/auth.php"); 37 $tmp_classname = "auth_plugin_".$tmp_plugin; 38 $this->chained_auth = new $tmp_classname; 39 } 40 else { 41 //get authentication plugins 42 if(isset($conf['plugin']['authchained']['authtypes'])){ 43 foreach(explode(":",$conf['plugin']['authchained']['authtypes']) as 44 $tmp_plugin){ 45 require_once(DOKU_INC."lib/plugins/".$tmp_plugin."/auth.php"); 46 $tmp_classname = "auth_plugin_".$tmp_plugin; 47 $tmp_class = new $tmp_classname; 48 $tmp_module = array($tmp_plugin,$tmp_class); 49 array_push($this->chained_plugins, $tmp_module); 50 } 51 }else{ 52 $success = false; 53 } 54 } 55 //debug 56// print_r($chained_plugins); 57 } 58 59 /** 60 * Forwards the authentication to configured authplugins. 61 * Returns true, if the usermanager authtype has the capability and no user 62 * is logged in. 63 * 64 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 65 * @param string $cap the capability to check 66 * @return bool 67 */ 68 public function canDo($cap) { 69 global $conf; 70# print_r($cap); 71 if(is_null($this->chained_auth)) 72 { 73 foreach($this->chained_plugins as $module) 74 { 75 #echo "TEST AUTHMANAGER!!!"; 76 if($module[0] == 77 $conf['plugin']['authchained']['usermanager_authtype']){ 78 $module[1]->canDo($cap); 79 } 80 } 81 return false; 82 } 83 else{ 84 #echo "canDo $cap ".$this->chained_auth->canDo($cap)."\n"; 85 return $this->chained_auth->canDo($cap); 86 } 87 } 88 89 /** 90 * Forwards the result of the auth plugin of the logged in user or 91 * returns false 92 * 93 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 94 * @param string $type Modification type ('create', 'modify', 'delete') 95 * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type 96 * @return mixed Result from the modification function or false if an event handler has canceled the action 97 */ 98 public function triggerUserMod($type, $params) { 99 if(is_null($this->chained_auth)) 100 return false; 101 else 102 return $this->chained_auth->triggerUserMod($type, $params); 103 } 104 105 /** 106 * Forwards the result of the auth plugin of the logged in user and 107 * unsets our session variable. 108 * @see auth_logoff() 109 * @author Philipp Neuser <pneuser@physik.fu-berlin.de 110 */ 111 public function logOff() { 112 if(!is_null($this->chained_auth)) 113 $this->chained_auth->logOff(); 114 unset($_SESSION[DOKU_COOKIE]['plugin']['authchained']['module']); 115 } 116 117 /** 118 * Do all authentication [ OPTIONAL ] 119 * If the current plugin is external, be external. 120 * 121 * @see auth_login() 122 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 123 * 124 * @param string $user Username 125 * @param string $pass Cleartext Password 126 * @param bool $sticky Cookie should not expire 127 * @return bool true on successful auth 128 */ 129 public function trustExternal($user, $pass, $sticky = false) { 130 if(!is_null($this->chained_auth) && $this->chained_auth->canDo('external')) 131 $this->chained_auth->trustExternal($user, $pass, $sticky); 132 } 133 134 /** 135 * Check user+password [ MUST BE OVERRIDDEN ] 136 * 137 * Checks if the given user exists in one of the plugins and checks 138 * against the given password. The first plugin returning true becomes 139 * auth plugin of the user session. 140 * 141 * @author Philipp Neuser <pneuser@physik.fu-berlin.de 142 * @param string $user the user name 143 * @param string $pass the clear text password 144 * @return bool 145 */ 146 public function checkPass($user, $pass) { 147 //debug 148 //print_r($this->chained_plugins); 149 if(is_null($this->chained_auth)) { 150 foreach($this->chained_plugins as $module) 151 { 152 if($module[1]->canDo('external')) 153 { 154 if($module[1]->trustExternal($user, $pass)) 155 { 156 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 157 $module[0]; 158 $this->chained_auth = $module[1]; 159 return true; 160 }else{ 161 if($module[1]->checkPass($user, $pass)) 162 { 163 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 164 $module[0]; 165 $this->chained_auth = $module[1]; 166 return true; 167 } 168 } 169 }else{ 170 if($module[1]->checkPass($user, $pass)) 171 { 172 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 173 $module[0]; 174 $this->this->chained_auth = $module[1]; 175 return true; 176 } 177 } 178 } 179 } else return $this->chained_auth->checkPass($user, $pass); 180 return false; 181 } 182 183 /** 184 * Forwards the result of the auth plugin of the logged in user or 185 * checks all plugins if the users exists. The first plugin returning 186 * data is used. 187 * 188 * name string full name of the user 189 * mail string email addres of the user 190 * grps array list of groups the user is in 191 * 192 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 193 * @param string $user the user name 194 * @return array containing user data or false 195 */ 196 public function getUserData($user) { 197 //if(!$this->cando['external']) msg("no valid authorisation system in use", -1); 198// echo "TESTSETEST"; 199 if(is_null($this->chained_auth)) 200 { 201 foreach($this->chained_plugins as $module) 202 { 203 $tmp_array = $module[1]->getUserData($user); 204 if(!is_bool($tmp_array)) 205 $tmp_chk_arr =array_filter($tmp_array); 206 if(!empty($tmp_chk_arr) && $tmp_array) 207 return $tmp_array; 208 } 209 return false; 210 } 211 else 212 { 213 return $this->chained_auth->getUserData($user); 214 } 215 } 216 217 /** 218 * Forwards the result of the auth plugin of the logged in user or 219 * returns null. 220 * 221 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 222 * @param string $user 223 * @param string $pass 224 * @param string $name 225 * @param string $mail 226 * @param null|array $grps 227 * @return bool|null 228 */ 229 public function createUser($user, $pass, $name, $mail, $grps = null) { 230 if(is_null($this->chained_auth)){ 231 msg("authorisation method does not allow creation of new users", 232 -1); 233 return null; 234 } 235 else{ 236 //please note: users will be added to the module, to which the 237 //current user is logged into 238 if($this->canDo('addUser')){ 239 return $this->chained_auth->createUser($user, $pass, $name, $mail, 240 $grps); 241 }else{ 242 msg("authorisation method does not allow creation of new 243 users", -1); 244 return null; 245 } 246 } 247 } 248 249 /** 250 * Forwards the result of the auth plugin of the logged in user or 251 * returns false 252 * 253 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 254 * @param string $user nick of the user to be changed 255 * @param array $changes array of field/value pairs to be changed (password will be clear text) 256 * @return bool 257 */ 258 public function modifyUser($user, $changes) { 259 if(is_null($this->chained_auth)){ 260 msg("authorisation method does not allow modifying of user data", 261 -1); 262 return false; 263 } 264 else{ 265 //please note: users will be modified in the module, to which the 266 //current user is logged into 267 if($this->canDo('modLogin') && $this->canDo('modPass') && 268 $this->canDo('modName') && $this->canDo('modMail') && 269 $this->canDo('modGroups')){ 270 return $this->chained_auth->createUser($user, $changes); 271 }else{ 272 msg("authorisation method does not allow modifying of user 273 data", -1); 274 return false; 275 } 276 } 277 278 } 279 280 /** 281 * Forwards the result of the auth plugin of the logged in user or 282 * returns false 283 * 284 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 285 * @param array $users 286 * @return int number of users deleted 287 */ 288 public function deleteUsers($users) { 289 if(is_null($this->chained_auth)){ 290 msg("authorisation method does not allow deleting of users", 291 -1); 292 return false; 293 } 294 else{ 295 //please note: users will be added to the module, to which the 296 //current user is logged into 297 if($this->canDo('delUser')){ 298 return $this->chained_auth->createUser($users); 299 }else{ 300 msg("authorisation method does not allow deleting of users", -1); 301 return false; 302 } 303 } 304 } 305 306 /** 307 * Forwards the result of the auth plugin of the logged in user or 308 * returns 0 309 * 310 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 311 * @param array $filter array of field/pattern pairs, empty array for no filter 312 * @return int 313 */ 314 public function getUserCount($filter = array()) { 315 if(is_null($this->chained_auth)){ 316 msg("authorisation method does not provide user counts", 317 -1); 318 return 0; 319 } 320 else{ 321 //please note: users will be counted in the module, to which the 322 //current user is logged into 323 if($this->canDo('getUserCount')){ 324 return $this->chained_auth->getUserCount($filter); 325 }else{ 326 msg("authorisation method does not provide user counts", -1); 327 return 0; 328 } 329 } 330 331 } 332 333 /** 334 * Forwards the result of the auth plugin of the logged in user or 335 * returns empty array 336 * 337 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 338 * @param int $start index of first user to be returned 339 * @param int $limit max number of users to be returned 340 * @param array $filter array of field/pattern pairs, null for no filter 341 * @return array list of userinfo (refer getUserData for internal userinfo details) 342 */ 343 public function retrieveUsers($start = 0, $limit = -1, $filter = null) { 344 if(is_null($this->chained_auth)){ 345 msg("authorisation method does not support mass retrievals", 346 -1); 347 return array(); 348 } 349 else{ 350 //please note: users will be retrieved from the module, to which the 351 //current user is logged into 352 if($this->canDo('getUsers')){ 353 return $this->chained_auth->retrieveUsers($start, $limit, $filter); 354 }else{ 355 msg("authorisation method does not support mass retrievals", -1); 356 return array(); 357 } 358 } 359 } 360 361 /** 362 * Forwards the result of the auth plugin of the logged in user or 363 * returns false 364 * 365 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 366 * @param string $group 367 * @return bool 368 */ 369 public function addGroup($group) { 370 if(is_null($this->chained_auth)){ 371 msg("authorisation method does not support independent group 372 creation", 373 -1); 374 return false; 375 } 376 else{ 377 //please note: users will be added to the module, to which the 378 //current user is logged into 379 if($this->canDo('addGroup')){ 380 return $this->chained_auth->addGroup($group); 381 }else{ 382 msg("authorisation method does not support independent group 383 creation", -1); 384 return false; 385 } 386 } 387 } 388 389 /** 390 * Forwards the result of the auth plugin of the logged in user or 391 * returns empty array 392 * 393 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 394 * @param int $start 395 * @param int $limit 396 * @return array 397 */ 398 public function retrieveGroups($start = 0, $limit = 0) { 399 if(is_null($this->chained_auth)){ 400 msg("authorisation method does not support group list retrieval", 401 -1); 402 return array(); 403 } 404 else{ 405 //please note: users will be retrieved from the module, to which the 406 //current user is logged into 407 if($this->canDo('getGroups')){ 408 return $this->chained_auth->retrieveGroups($start,$limit); 409 }else{ 410 msg("authorisation method does not support group list 411 retrieval", -1); 412 return array(); 413 } 414 } 415 } 416 417 /** 418 * Forwards the result of the auth plugin of the logged in user or 419 * returns true 420 * 421 * @return bool 422 */ 423 public function isCaseSensitive() { 424 if(is_null($this->chained_auth)) 425 return true; 426 else 427 return $this->chained_auth->isCaseSensitive(); 428 } 429 430 /** 431 * Sanitize a given username [OPTIONAL] 432 * Forwards the result of the auth plugin of the logged in user or 433 * returns false 434 * 435 * 436 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 437 * @param string $user username 438 * @return string the cleaned username 439 */ 440 public function cleanUser($user) { 441 //print_r($this->chained_auth); 442 if(is_null($this->chained_auth)) 443 return $user; 444 else 445 return $this->chained_auth->cleanUser($user); 446 } 447 448 /** 449 * Sanitize a given groupname [OPTIONAL] 450 * Forwards the result of the auth plugin of the logged in user or 451 * returns false 452 * 453 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 454 * @param string $group groupname 455 * @return string the cleaned groupname 456 */ 457 public function cleanGroup($group) { 458 if(is_null($this->chained_auth)) 459 { 460 return $group; 461 } 462 else 463 return $this->chained_auth->cleanGroup($group); 464 } 465 466 467 public function useSessionCache($user) { 468 global $conf; 469 if(is_null($this->chained_auth)) 470 return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= 471 @filemtime($conf['cachedir'].'/sessionpurge')); 472 else 473 return $this->chained_auth->useSessionCache($user); 474 } 475} 476