1<?php 2/** 3 * Auth Plugin Prototype 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Jan Schumann <js@jschumann-it.com> 7 */ 8// must be run within Dokuwiki 9if(!defined('DOKU_INC')) die(); 10 11/** 12 * auth/basic.class.php 13 * 14 * foundation authorisation class 15 * all auth classes should inherit from this class 16 * 17 * @author Chris Smith <chris@jalakai.co.uk> 18 * @author Jan Schumann <js@jschumann-it.com> 19 */ 20class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { 21 22 var $success = true; 23 24 25 /** 26 * Posible things an auth backend module may be able to 27 * do. The things a backend can do need to be set to true 28 * in the constructor. 29 */ 30 var $cando = array ( 31 'addUser' => false, // can Users be created? 32 'delUser' => false, // can Users be deleted? 33 'modLogin' => false, // can login names be changed? 34 'modPass' => false, // can passwords be changed? 35 'modName' => false, // can real names be changed? 36 'modMail' => false, // can emails be changed? 37 'modGroups' => false, // can groups be changed? 38 'getUsers' => false, // can a (filtered) list of users be retrieved? 39 'getUserCount'=> false, // can the number of users be retrieved? 40 'getGroups' => false, // can a list of available groups be retrieved? 41 'external' => false, // does the module do external auth checking? 42 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) 43 ); 44 45 46 /** 47 * Constructor. 48 * 49 * Carry out sanity checks to ensure the object is 50 * able to operate. Set capabilities in $this->cando 51 * array here 52 * 53 * Set $this->success to false if checks fail 54 * 55 * @author Christopher Smith <chris@jalakai.co.uk> 56 */ 57 function auth_basic() { 58 // the base class constructor does nothing, derived class 59 // constructors do the real work 60 } 61 62 /** 63 * Capability check. [ DO NOT OVERRIDE ] 64 * 65 * Checks the capabilities set in the $this->cando array and 66 * some pseudo capabilities (shortcutting access to multiple 67 * ones) 68 * 69 * ususal capabilities start with lowercase letter 70 * shortcut capabilities start with uppercase letter 71 * 72 * @author Andreas Gohr <andi@splitbrain.org> 73 * @return bool 74 */ 75 function canDo($cap) { 76 switch($cap){ 77 case 'Profile': 78 // can at least one of the user's properties be changed? 79 return ( $this->cando['modPass'] || 80 $this->cando['modName'] || 81 $this->cando['modMail'] ); 82 break; 83 case 'UserMod': 84 // can at least anything be changed? 85 return ( $this->cando['modPass'] || 86 $this->cando['modName'] || 87 $this->cando['modMail'] || 88 $this->cando['modLogin'] || 89 $this->cando['modGroups'] || 90 $this->cando['modMail'] ); 91 break; 92 default: 93 // print a helping message for developers 94 if(!isset($this->cando[$cap])){ 95 msg("Check for unknown capability '$cap' - Do you use an outdated Plugin?",-1); 96 } 97 return $this->cando[$cap]; 98 } 99 } 100 101 /** 102 * Trigger the AUTH_USERDATA_CHANGE event and call the modification function. [ DO NOT OVERRIDE ] 103 * 104 * You should use this function instead of calling createUser, modifyUser or 105 * deleteUsers directly. The event handlers can prevent the modification, for 106 * example for enforcing a user name schema. 107 * 108 * @author Gabriel Birke <birke@d-scribe.de> 109 * @param string $type Modification type ('create', 'modify', 'delete') 110 * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type 111 * @return mixed Result from the modification function or false if an event handler has canceled the action 112 */ 113 function triggerUserMod($type, $params) 114 { 115 $validTypes = array( 116 'create' => 'createUser', 117 'modify' => 'modifyUser', 118 'delete' => 'deleteUsers' 119 ); 120 if(empty($validTypes[$type])) 121 return false; 122 $eventdata = array('type' => $type, 'params' => $params, 'modification_result' => null); 123 $evt = new Doku_Event('AUTH_USER_CHANGE', $eventdata); 124 if ($evt->advise_before(true)) { 125 $result = call_user_func_array(array($this, $validTypes[$type]), $params); 126 $evt->data['modification_result'] = $result; 127 } 128 $evt->advise_after(); 129 unset($evt); 130 return $result; 131 } 132 133 /** 134 * Log off the current user [ OPTIONAL ] 135 * 136 * Is run in addition to the ususal logoff method. Should 137 * only be needed when trustExternal is implemented. 138 * 139 * @see auth_logoff() 140 * @author Andreas Gohr <andi@splitbrain.org> 141 */ 142 function logOff(){ 143 } 144 145 /** 146 * Do all authentication [ OPTIONAL ] 147 * 148 * Set $this->cando['external'] = true when implemented 149 * 150 * If this function is implemented it will be used to 151 * authenticate a user - all other DokuWiki internals 152 * will not be used for authenticating, thus 153 * implementing the checkPass() function is not needed 154 * anymore. 155 * 156 * The function can be used to authenticate against third 157 * party cookies or Apache auth mechanisms and replaces 158 * the auth_login() function 159 * 160 * The function will be called with or without a set 161 * username. If the Username is given it was called 162 * from the login form and the given credentials might 163 * need to be checked. If no username was given it 164 * the function needs to check if the user is logged in 165 * by other means (cookie, environment). 166 * 167 * The function needs to set some globals needed by 168 * DokuWiki like auth_login() does. 169 * 170 * @see auth_login() 171 * @author Andreas Gohr <andi@splitbrain.org> 172 * 173 * @param string $user Username 174 * @param string $pass Cleartext Password 175 * @param bool $sticky Cookie should not expire 176 * @return bool true on successful auth 177 */ 178 function trustExternal($user,$pass,$sticky=false){ 179# // some example: 180# 181# global $USERINFO; 182# global $conf; 183# $sticky ? $sticky = true : $sticky = false; //sanity check 184# 185# // do the checking here 186# 187# // set the globals if authed 188# $USERINFO['name'] = 'FIXME'; 189# $USERINFO['mail'] = 'FIXME'; 190# $USERINFO['grps'] = array('FIXME'); 191# $_SERVER['REMOTE_USER'] = $user; 192# $_SESSION[DOKU_COOKIE]['auth']['user'] = $user; 193# $_SESSION[DOKU_COOKIE]['auth']['pass'] = $pass; 194# $_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO; 195# return true; 196 } 197 198 /** 199 * Check user+password [ MUST BE OVERRIDDEN ] 200 * 201 * Checks if the given user exists and the given 202 * plaintext password is correct 203 * 204 * May be ommited if trustExternal is used. 205 * 206 * @author Andreas Gohr <andi@splitbrain.org> 207 * @return bool 208 */ 209 function checkPass($user,$pass){ 210 msg("no valid authorisation system in use", -1); 211 return false; 212 } 213 214 /** 215 * Return user info [ MUST BE OVERRIDDEN ] 216 * 217 * Returns info about the given user needs to contain 218 * at least these fields: 219 * 220 * name string full name of the user 221 * mail string email addres of the user 222 * grps array list of groups the user is in 223 * 224 * @author Andreas Gohr <andi@splitbrain.org> 225 * @return array containing user data or false 226 */ 227 function getUserData($user) { 228 if(!$this->cando['external']) msg("no valid authorisation system in use", -1); 229 return false; 230 } 231 232 /** 233 * Create a new User [implement only where required/possible] 234 * 235 * Returns false if the user already exists, null when an error 236 * occurred and true if everything went well. 237 * 238 * The new user HAS TO be added to the default group by this 239 * function! 240 * 241 * Set addUser capability when implemented 242 * 243 * @author Andreas Gohr <andi@splitbrain.org> 244 */ 245 function createUser($user,$pass,$name,$mail,$grps=null){ 246 msg("authorisation method does not allow creation of new users", -1); 247 return null; 248 } 249 250 /** 251 * Modify user data [implement only where required/possible] 252 * 253 * Set the mod* capabilities according to the implemented features 254 * 255 * @author Chris Smith <chris@jalakai.co.uk> 256 * @param $user nick of the user to be changed 257 * @param $changes array of field/value pairs to be changed (password will be clear text) 258 * @return bool 259 */ 260 function modifyUser($user, $changes) { 261 msg("authorisation method does not allow modifying of user data", -1); 262 return false; 263 } 264 265 /** 266 * Delete one or more users [implement only where required/possible] 267 * 268 * Set delUser capability when implemented 269 * 270 * @author Chris Smith <chris@jalakai.co.uk> 271 * @param array $users 272 * @return int number of users deleted 273 */ 274 function deleteUsers($users) { 275 msg("authorisation method does not allow deleting of users", -1); 276 return false; 277 } 278 279 /** 280 * Return a count of the number of user which meet $filter criteria 281 * [should be implemented whenever retrieveUsers is implemented] 282 * 283 * Set getUserCount capability when implemented 284 * 285 * @author Chris Smith <chris@jalakai.co.uk> 286 */ 287 function getUserCount($filter=array()) { 288 msg("authorisation method does not provide user counts", -1); 289 return 0; 290 } 291 292 /** 293 * Bulk retrieval of user data [implement only where required/possible] 294 * 295 * Set getUsers capability when implemented 296 * 297 * @author Chris Smith <chris@jalakai.co.uk> 298 * @param start index of first user to be returned 299 * @param limit max number of users to be returned 300 * @param filter array of field/pattern pairs, null for no filter 301 * @return array of userinfo (refer getUserData for internal userinfo details) 302 */ 303 function retrieveUsers($start=0,$limit=-1,$filter=null) { 304 msg("authorisation method does not support mass retrieval of user data", -1); 305 return array(); 306 } 307 308 /** 309 * Define a group [implement only where required/possible] 310 * 311 * Set addGroup capability when implemented 312 * 313 * @author Chris Smith <chris@jalakai.co.uk> 314 * @return bool 315 */ 316 function addGroup($group) { 317 msg("authorisation method does not support independent group creation", -1); 318 return false; 319 } 320 321 /** 322 * Retrieve groups [implement only where required/possible] 323 * 324 * Set getGroups capability when implemented 325 * 326 * @author Chris Smith <chris@jalakai.co.uk> 327 * @return array 328 */ 329 function retrieveGroups($start=0,$limit=0) { 330 msg("authorisation method does not support group list retrieval", -1); 331 return array(); 332 } 333 334 /** 335 * Return case sensitivity of the backend [OPTIONAL] 336 * 337 * When your backend is caseinsensitive (eg. you can login with USER and 338 * user) then you need to overwrite this method and return false 339 */ 340 function isCaseSensitive(){ 341 return true; 342 } 343 344 /** 345 * Sanitize a given username [OPTIONAL] 346 * 347 * This function is applied to any user name that is given to 348 * the backend and should also be applied to any user name within 349 * the backend before returning it somewhere. 350 * 351 * This should be used to enforce username restrictions. 352 * 353 * @author Andreas Gohr <andi@splitbrain.org> 354 * @param string $user - username 355 * @param string - the cleaned username 356 */ 357 function cleanUser($user){ 358 return $user; 359 } 360 361 /** 362 * Sanitize a given groupname [OPTIONAL] 363 * 364 * This function is applied to any groupname that is given to 365 * the backend and should also be applied to any groupname within 366 * the backend before returning it somewhere. 367 * 368 * This should be used to enforce groupname restrictions. 369 * 370 * Groupnames are to be passed without a leading '@' here. 371 * 372 * @author Andreas Gohr <andi@splitbrain.org> 373 * @param string $group - groupname 374 * @param string - the cleaned groupname 375 */ 376 function cleanGroup($group){ 377 return $group; 378 } 379 380 381 /** 382 * Check Session Cache validity [implement only where required/possible] 383 * 384 * DokuWiki caches user info in the user's session for the timespan defined 385 * in $conf['auth_security_timeout']. 386 * 387 * This makes sure slow authentication backends do not slow down DokuWiki. 388 * This also means that changes to the user database will not be reflected 389 * on currently logged in users. 390 * 391 * To accommodate for this, the user manager plugin will touch a reference 392 * file whenever a change is submitted. This function compares the filetime 393 * of this reference file with the time stored in the session. 394 * 395 * This reference file mechanism does not reflect changes done directly in 396 * the backend's database through other means than the user manager plugin. 397 * 398 * Fast backends might want to return always false, to force rechecks on 399 * each page load. Others might want to use their own checking here. If 400 * unsure, do not override. 401 * 402 * @param string $user - The username 403 * @author Andreas Gohr <andi@splitbrain.org> 404 * @return bool 405 */ 406 function useSessionCache($user){ 407 global $conf; 408 return ($_SESSION[DOKU_COOKIE]['auth']['time'] >= @filemtime($conf['cachedir'].'/sessionpurge')); 409 } 410 411 412 /** 413 * loadConfig() 414 * merges the plugin's default settings with any local settings 415 * this function is automatically called through getConf() 416 */ 417 function loadConfig(){ 418 global $conf; 419 420 parent::loadConfig(); 421 422 $this->conf['debug'] = $conf['debug']; 423 $this->conf['useacl'] = $conf['useacl']; 424 $this->conf['disableactions'] = $conf['disableactions']; 425 $this->conf['autopasswd'] = $conf['autopasswd']; 426 $this->conf['passcrypt'] = $conf['ssha']; 427 } 428 429} 430