[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/plugins/ -> auth.php (source)

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