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 foreach($this->chained_plugins as $module) 150 { 151 if($module[1]->canDo('external')) 152 { 153 if($module[1]->trustExternal($user, $pass)) 154 { 155 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 156 $module[0]; 157 $this->chained_auth = $module[1]; 158 return true; 159 }else{ 160 if($module[1]->checkPass($user, $pass)) 161 { 162 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 163 $module[0]; 164 $this->chained_auth = $module[1]; 165 return true; 166 } 167 } 168 }else{ 169 if($module[1]->checkPass($user, $pass)) 170 { 171 $_SESSION[DOKU_COOKIE]['plugin']['authchained']['module'] = 172 $module[0]; 173 $this->this->chained_auth = $module[1]; 174 return true; 175 } 176 } 177 } 178 return false; 179 } 180 181 /** 182 * Forwards the result of the auth plugin of the logged in user or 183 * checks all plugins if the users exists. The first plugin returning 184 * data is used. 185 * 186 * name string full name of the user 187 * mail string email addres of the user 188 * grps array list of groups the user is in 189 * 190 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 191 * @param string $user the user name 192 * @return array containing user data or false 193 */ 194 public function getUserData($user) { 195 //if(!$this->cando['external']) msg("no valid authorisation system in use", -1); 196// echo "TESTSETEST"; 197 if(is_null($this->chained_auth)) 198 { 199 foreach($this->chained_plugins as $module) 200 { 201 $tmp_array = $module[1]->getUserData($user); 202 if(!is_bool($tmp_array)) 203 $tmp_chk_arr =array_filter($tmp_array); 204 if(!empty($tmp_chk_arr) && $tmp_array) 205 return $tmp_array; 206 } 207 return false; 208 } 209 else 210 { 211 return $this->chained_auth->getUserData($user); 212 } 213 } 214 215 /** 216 * Forwards the result of the auth plugin of the logged in user or 217 * returns null. 218 * 219 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 220 * @param string $user 221 * @param string $pass 222 * @param string $name 223 * @param string $mail 224 * @param null|array $grps 225 * @return bool|null 226 */ 227 public function createUser($user, $pass, $name, $mail, $grps = null) { 228 if(is_null($this->chained_auth)){ 229 msg("authorisation method does not allow creation of new users", 230 -1); 231 return null; 232 } 233 else{ 234 //please note: users will be added to the module, to which the 235 //current user is logged into 236 if($this->canDo('addUser')){ 237 return $this->chained_auth->createUser($user, $pass, $name, $mail, 238 $grps); 239 }else{ 240 msg("authorisation method does not allow creation of new 241 users", -1); 242 return null; 243 } 244 } 245 } 246 247 /** 248 * Forwards the result of the auth plugin of the logged in user or 249 * returns false 250 * 251 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 252 * @param string $user nick of the user to be changed 253 * @param array $changes array of field/value pairs to be changed (password will be clear text) 254 * @return bool 255 */ 256 public function modifyUser($user, $changes) { 257 if(is_null($this->chained_auth)){ 258 msg("authorisation method does not allow modifying of user data", 259 -1); 260 return false; 261 } 262 else{ 263 //please note: users will be modified in the module, to which the 264 //current user is logged into 265 if($this->canDo('modLogin') && $this->canDo('modPass') && 266 $this->canDo('modName') && $this->canDo('modMail') && 267 $this->canDo('modGroups')){ 268 return $this->chained_auth->createUser($user, $changes); 269 }else{ 270 msg("authorisation method does not allow modifying of user 271 data", -1); 272 return false; 273 } 274 } 275 276 } 277 278 /** 279 * Forwards the result of the auth plugin of the logged in user or 280 * returns false 281 * 282 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 283 * @param array $users 284 * @return int number of users deleted 285 */ 286 public function deleteUsers($users) { 287 if(is_null($this->chained_auth)){ 288 msg("authorisation method does not allow deleting of users", 289 -1); 290 return false; 291 } 292 else{ 293 //please note: users will be added to the module, to which the 294 //current user is logged into 295 if($this->canDo('delUser')){ 296 return $this->chained_auth->createUser($users); 297 }else{ 298 msg("authorisation method does not allow deleting of users", -1); 299 return false; 300 } 301 } 302 } 303 304 /** 305 * Forwards the result of the auth plugin of the logged in user or 306 * returns 0 307 * 308 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 309 * @param array $filter array of field/pattern pairs, empty array for no filter 310 * @return int 311 */ 312 public function getUserCount($filter = array()) { 313 if(is_null($this->chained_auth)){ 314 msg("authorisation method does not provide user counts", 315 -1); 316 return 0; 317 } 318 else{ 319 //please note: users will be counted in the module, to which the 320 //current user is logged into 321 if($this->canDo('getUserCount')){ 322 return $this->chained_auth->getUserCount($filter); 323 }else{ 324 msg("authorisation method does not provide user counts", -1); 325 return 0; 326 } 327 } 328 329 } 330 331 /** 332 * Forwards the result of the auth plugin of the logged in user or 333 * returns empty array 334 * 335 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 336 * @param int $start index of first user to be returned 337 * @param int $limit max number of users to be returned 338 * @param array $filter array of field/pattern pairs, null for no filter 339 * @return array list of userinfo (refer getUserData for internal userinfo details) 340 */ 341 public function retrieveUsers($start = 0, $limit = -1, $filter = null) { 342 if(is_null($this->chained_auth)){ 343 msg("authorisation method does not support mass retrievals", 344 -1); 345 return array(); 346 } 347 else{ 348 //please note: users will be retrieved from the module, to which the 349 //current user is logged into 350 if($this->canDo('getUsers')){ 351 return $this->chained_auth->retrieveUsers($start, $limit, $filter); 352 }else{ 353 msg("authorisation method does not support mass retrievals", -1); 354 return array(); 355 } 356 } 357 } 358 359 /** 360 * Forwards the result of the auth plugin of the logged in user or 361 * returns false 362 * 363 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 364 * @param string $group 365 * @return bool 366 */ 367 public function addGroup($group) { 368 if(is_null($this->chained_auth)){ 369 msg("authorisation method does not support independent group 370 creation", 371 -1); 372 return false; 373 } 374 else{ 375 //please note: users will be added to the module, to which the 376 //current user is logged into 377 if($this->canDo('addGroup')){ 378 return $this->chained_auth->addGroup($group); 379 }else{ 380 msg("authorisation method does not support independent group 381 creation", -1); 382 return false; 383 } 384 } 385 } 386 387 /** 388 * Forwards the result of the auth plugin of the logged in user or 389 * returns empty array 390 * 391 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 392 * @param int $start 393 * @param int $limit 394 * @return array 395 */ 396 public function retrieveGroups($start = 0, $limit = 0) { 397 if(is_null($this->chained_auth)){ 398 msg("authorisation method does not support group list retrieval", 399 -1); 400 return array(); 401 } 402 else{ 403 //please note: users will be retrieved from the module, to which the 404 //current user is logged into 405 if($this->canDo('getGroups')){ 406 return $this->chained_auth->retrieveGroups($start,$limit); 407 }else{ 408 msg("authorisation method does not support group list 409 retrieval", -1); 410 return array(); 411 } 412 } 413 } 414 415 /** 416 * Forwards the result of the auth plugin of the logged in user or 417 * returns true 418 * 419 * @return bool 420 */ 421 public function isCaseSensitive() { 422 if(is_null($this->chained_auth)) 423 return true; 424 else 425 return $this->chained_auth->isCaseSensitive(); 426 } 427 428 /** 429 * Sanitize a given username [OPTIONAL] 430 * Forwards the result of the auth plugin of the logged in user or 431 * returns false 432 * 433 * 434 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 435 * @param string $user username 436 * @return string the cleaned username 437 */ 438 public function cleanUser($user) { 439 //print_r($this->chained_auth); 440 if(is_null($this->chained_auth)) 441 return $user; 442 else 443 return $this->chained_auth->cleanUser($user); 444 } 445 446 /** 447 * Sanitize a given groupname [OPTIONAL] 448 * Forwards the result of the auth plugin of the logged in user or 449 * returns false 450 * 451 * @author Philipp Neuser <pneuser@physik.fu-berlin.de> 452 * @param string $group groupname 453 * @return string the cleaned groupname 454 */ 455 public function cleanGroup($group) { 456 if(is_null($this->chained_auth)) 457 { 458 return $group; 459 } 460 else 461 return $this->chained_auth->cleanGroup($group); 462 } 463 464 465 public function useSessionCache($user) { 466 global $conf; 467 if(is_null($this->chained_auth)) 468 return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= 469 @filemtime($conf['cachedir'].'/sessionpurge')); 470 else 471 return $this->chained_auth->useSessionCache($user); 472 } 473} 474