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