[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/ -> authlib.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * Multiple plugin authentication Support library
  20   *
  21   * 2006-08-28  File created, AUTH return values defined.
  22   *
  23   * @package    core
  24   * @subpackage auth
  25   * @copyright  1999 onwards Martin Dougiamas  http://dougiamas.com
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * Returned when the login was successful.
  33   */
  34  define('AUTH_OK',     0);
  35  
  36  /**
  37   * Returned when the login was unsuccessful.
  38   */
  39  define('AUTH_FAIL',   1);
  40  
  41  /**
  42   * Returned when the login was denied (a reason for AUTH_FAIL).
  43   */
  44  define('AUTH_DENIED', 2);
  45  
  46  /**
  47   * Returned when some error occurred (a reason for AUTH_FAIL).
  48   */
  49  define('AUTH_ERROR',  4);
  50  
  51  /**
  52   * Authentication - error codes for user confirm
  53   */
  54  define('AUTH_CONFIRM_FAIL', 0);
  55  define('AUTH_CONFIRM_OK', 1);
  56  define('AUTH_CONFIRM_ALREADY', 2);
  57  define('AUTH_CONFIRM_ERROR', 3);
  58  
  59  # MDL-14055
  60  define('AUTH_REMOVEUSER_KEEP', 0);
  61  define('AUTH_REMOVEUSER_SUSPEND', 1);
  62  define('AUTH_REMOVEUSER_FULLDELETE', 2);
  63  
  64  /** Login attempt successful. */
  65  define('AUTH_LOGIN_OK', 0);
  66  
  67  /** Can not login because user does not exist. */
  68  define('AUTH_LOGIN_NOUSER', 1);
  69  
  70  /** Can not login because user is suspended. */
  71  define('AUTH_LOGIN_SUSPENDED', 2);
  72  
  73  /** Can not login, most probably password did not match. */
  74  define('AUTH_LOGIN_FAILED', 3);
  75  
  76  /** Can not login because user is locked out. */
  77  define('AUTH_LOGIN_LOCKOUT', 4);
  78  
  79  /** Can not login becauser user is not authorised. */
  80  define('AUTH_LOGIN_UNAUTHORISED', 5);
  81  
  82  /**
  83   * Abstract authentication plugin.
  84   *
  85   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  86   * @package moodlecore
  87   */
  88  class auth_plugin_base {
  89  
  90      /**
  91       * The configuration details for the plugin.
  92       * @var object
  93       */
  94      var $config;
  95  
  96      /**
  97       * Authentication plugin type - the same as db field.
  98       * @var string
  99       */
 100      var $authtype;
 101      /*
 102       * The fields we can lock and update from/to external authentication backends
 103       * @var array
 104       */
 105      var $userfields = array(
 106          'firstname',
 107          'lastname',
 108          'email',
 109          'city',
 110          'country',
 111          'lang',
 112          'description',
 113          'url',
 114          'idnumber',
 115          'institution',
 116          'department',
 117          'phone1',
 118          'phone2',
 119          'address',
 120          'firstnamephonetic',
 121          'lastnamephonetic',
 122          'middlename',
 123          'alternatename'
 124      );
 125  
 126      /**
 127       * Moodle custom fields to sync with.
 128       * @var array()
 129       */
 130      var $customfields = null;
 131  
 132      /**
 133       * This is the primary method that is used by the authenticate_user_login()
 134       * function in moodlelib.php.
 135       *
 136       * This method should return a boolean indicating
 137       * whether or not the username and password authenticate successfully.
 138       *
 139       * Returns true if the username and password work and false if they are
 140       * wrong or don't exist.
 141       *
 142       * @param string $username The username (with system magic quotes)
 143       * @param string $password The password (with system magic quotes)
 144       *
 145       * @return bool Authentication success or failure.
 146       */
 147      function user_login($username, $password) {
 148          print_error('mustbeoveride', 'debug', '', 'user_login()' );
 149      }
 150  
 151      /**
 152       * Returns true if this authentication plugin can change the users'
 153       * password.
 154       *
 155       * @return bool
 156       */
 157      function can_change_password() {
 158          //override if needed
 159          return false;
 160      }
 161  
 162      /**
 163       * Returns the URL for changing the users' passwords, or empty if the default
 164       * URL can be used.
 165       *
 166       * This method is used if can_change_password() returns true.
 167       * This method is called only when user is logged in, it may use global $USER.
 168       * If you are using a plugin config variable in this method, please make sure it is set before using it,
 169       * as this method can be called even if the plugin is disabled, in which case the config values won't be set.
 170       *
 171       * @return moodle_url url of the profile page or null if standard used
 172       */
 173      function change_password_url() {
 174          //override if needed
 175          return null;
 176      }
 177  
 178      /**
 179       * Returns true if this authentication plugin can edit the users'
 180       * profile.
 181       *
 182       * @return bool
 183       */
 184      function can_edit_profile() {
 185          //override if needed
 186          return true;
 187      }
 188  
 189      /**
 190       * Returns the URL for editing the users' profile, or empty if the default
 191       * URL can be used.
 192       *
 193       * This method is used if can_edit_profile() returns true.
 194       * This method is called only when user is logged in, it may use global $USER.
 195       *
 196       * @return moodle_url url of the profile page or null if standard used
 197       */
 198      function edit_profile_url() {
 199          //override if needed
 200          return null;
 201      }
 202  
 203      /**
 204       * Returns true if this authentication plugin is "internal".
 205       *
 206       * Internal plugins use password hashes from Moodle user table for authentication.
 207       *
 208       * @return bool
 209       */
 210      function is_internal() {
 211          //override if needed
 212          return true;
 213      }
 214  
 215      /**
 216       * Returns false if this plugin is enabled but not configured.
 217       *
 218       * @return bool
 219       */
 220      public function is_configured() {
 221          return false;
 222      }
 223  
 224      /**
 225       * Indicates if password hashes should be stored in local moodle database.
 226       * @return bool true means md5 password hash stored in user table, false means flag 'not_cached' stored there instead
 227       */
 228      function prevent_local_passwords() {
 229          return !$this->is_internal();
 230      }
 231  
 232      /**
 233       * Indicates if moodle should automatically update internal user
 234       * records with data from external sources using the information
 235       * from get_userinfo() method.
 236       *
 237       * @return bool true means automatically copy data from ext to user table
 238       */
 239      function is_synchronised_with_external() {
 240          return !$this->is_internal();
 241      }
 242  
 243      /**
 244       * Updates the user's password.
 245       *
 246       * In previous versions of Moodle, the function
 247       * auth_user_update_password accepted a username as the first parameter. The
 248       * revised function expects a user object.
 249       *
 250       * @param  object  $user        User table object
 251       * @param  string  $newpassword Plaintext password
 252       *
 253       * @return bool                  True on success
 254       */
 255      function user_update_password($user, $newpassword) {
 256          //override if needed
 257          return true;
 258      }
 259  
 260      /**
 261       * Called when the user record is updated.
 262       * Modifies user in external database. It takes olduser (before changes) and newuser (after changes)
 263       * compares information saved modified information to external db.
 264       *
 265       * @param mixed $olduser     Userobject before modifications    (without system magic quotes)
 266       * @param mixed $newuser     Userobject new modified userobject (without system magic quotes)
 267       * @return boolean true if updated or update ignored; false if error
 268       *
 269       */
 270      function user_update($olduser, $newuser) {
 271          //override if needed
 272          return true;
 273      }
 274  
 275      /**
 276       * User delete requested - internal user record is mared as deleted already, username not present anymore.
 277       *
 278       * Do any action in external database.
 279       *
 280       * @param object $user       Userobject before delete    (without system magic quotes)
 281       * @return void
 282       */
 283      function user_delete($olduser) {
 284          //override if needed
 285          return;
 286      }
 287  
 288      /**
 289       * Returns true if plugin allows resetting of internal password.
 290       *
 291       * @return bool
 292       */
 293      function can_reset_password() {
 294          //override if needed
 295          return false;
 296      }
 297  
 298      /**
 299       * Returns true if plugin allows resetting of internal password.
 300       *
 301       * @return bool
 302       */
 303      function can_signup() {
 304          //override if needed
 305          return false;
 306      }
 307  
 308      /**
 309       * Sign up a new user ready for confirmation.
 310       * Password is passed in plaintext.
 311       *
 312       * @param object $user new user object
 313       * @param boolean $notify print notice with link and terminate
 314       */
 315      function user_signup($user, $notify=true) {
 316          //override when can signup
 317          print_error('mustbeoveride', 'debug', '', 'user_signup()' );
 318      }
 319  
 320      /**
 321       * Return a form to capture user details for account creation.
 322       * This is used in /login/signup.php.
 323       * @return moodle_form A form which edits a record from the user table.
 324       */
 325      function signup_form() {
 326          global $CFG;
 327  
 328          require_once($CFG->dirroot.'/login/signup_form.php');
 329          return new login_signup_form(null, null, 'post', '', array('autocomplete'=>'on'));
 330      }
 331  
 332      /**
 333       * Returns true if plugin allows confirming of new users.
 334       *
 335       * @return bool
 336       */
 337      function can_confirm() {
 338          //override if needed
 339          return false;
 340      }
 341  
 342      /**
 343       * Confirm the new user as registered.
 344       *
 345       * @param string $username
 346       * @param string $confirmsecret
 347       */
 348      function user_confirm($username, $confirmsecret) {
 349          //override when can confirm
 350          print_error('mustbeoveride', 'debug', '', 'user_confirm()' );
 351      }
 352  
 353      /**
 354       * Checks if user exists in external db
 355       *
 356       * @param string $username (with system magic quotes)
 357       * @return bool
 358       */
 359      function user_exists($username) {
 360          //override if needed
 361          return false;
 362      }
 363  
 364      /**
 365       * return number of days to user password expires
 366       *
 367       * If userpassword does not expire it should return 0. If password is already expired
 368       * it should return negative value.
 369       *
 370       * @param mixed $username username (with system magic quotes)
 371       * @return integer
 372       */
 373      function password_expire($username) {
 374          return 0;
 375      }
 376      /**
 377       * Sync roles for this user - usually creator
 378       *
 379       * @param $user object user object (without system magic quotes)
 380       */
 381      function sync_roles($user) {
 382          //override if needed
 383      }
 384  
 385      /**
 386       * Read user information from external database and returns it as array().
 387       * Function should return all information available. If you are saving
 388       * this information to moodle user-table you should honour synchronisation flags
 389       *
 390       * @param string $username username
 391       *
 392       * @return mixed array with no magic quotes or false on error
 393       */
 394      function get_userinfo($username) {
 395          //override if needed
 396          return array();
 397      }
 398  
 399      /**
 400       * Prints a form for configuring this authentication plugin.
 401       *
 402       * This function is called from admin/auth.php, and outputs a full page with
 403       * a form for configuring this plugin.
 404       *
 405       * @param object $config
 406       * @param object $err
 407       * @param array $user_fields
 408       */
 409      function config_form($config, $err, $user_fields) {
 410          //override if needed
 411      }
 412  
 413      /**
 414       * A chance to validate form data, and last chance to
 415       * do stuff before it is inserted in config_plugin
 416       * @param object object with submitted configuration settings (without system magic quotes)
 417       * @param array $err array of error messages
 418       */
 419       function validate_form($form, &$err) {
 420          //override if needed
 421      }
 422  
 423      /**
 424       * Processes and stores configuration data for this authentication plugin.
 425       *
 426       * @param object object with submitted configuration settings (without system magic quotes)
 427       */
 428      function process_config($config) {
 429          //override if needed
 430          return true;
 431      }
 432  
 433      /**
 434       * Hook for overriding behaviour of login page.
 435       * This method is called from login/index.php page for all enabled auth plugins.
 436       *
 437       * @global object
 438       * @global object
 439       */
 440      function loginpage_hook() {
 441          global $frm;  // can be used to override submitted login form
 442          global $user; // can be used to replace authenticate_user_login()
 443  
 444          //override if needed
 445      }
 446  
 447      /**
 448       * Hook for overriding behaviour before going to the login page.
 449       *
 450       * This method is called from require_login from potentially any page for
 451       * all enabled auth plugins and gives each plugin a chance to redirect
 452       * directly to an external login page, or to instantly login a user where
 453       * possible.
 454       *
 455       * If an auth plugin implements this hook, it must not rely on ONLY this
 456       * hook in order to work, as there are many ways a user can browse directly
 457       * to the standard login page. As a general rule in this case you should
 458       * also implement the loginpage_hook as well.
 459       *
 460       */
 461      function pre_loginpage_hook() {
 462          // override if needed, eg by redirecting to an external login page
 463          // or logging in a user:
 464          // complete_user_login($user);
 465      }
 466  
 467      /**
 468       * Pre user_login hook.
 469       * This method is called from authenticate_user_login() right after the user
 470       * object is generated. This gives the auth plugins an option to make adjustments
 471       * before the verification process starts.
 472       *
 473       * @param object $user user object, later used for $USER
 474       */
 475      public function pre_user_login_hook(&$user) {
 476          // Override if needed.
 477      }
 478  
 479      /**
 480       * Post authentication hook.
 481       * This method is called from authenticate_user_login() for all enabled auth plugins.
 482       *
 483       * @param object $user user object, later used for $USER
 484       * @param string $username (with system magic quotes)
 485       * @param string $password plain text password (with system magic quotes)
 486       */
 487      function user_authenticated_hook(&$user, $username, $password) {
 488          //override if needed
 489      }
 490  
 491      /**
 492       * Pre logout hook.
 493       * This method is called from require_logout() for all enabled auth plugins,
 494       *
 495       * @global object
 496       */
 497      function prelogout_hook() {
 498          global $USER; // use $USER->auth to find the plugin used for login
 499  
 500          //override if needed
 501      }
 502  
 503      /**
 504       * Hook for overriding behaviour of logout page.
 505       * This method is called from login/logout.php page for all enabled auth plugins.
 506       *
 507       * @global object
 508       * @global string
 509       */
 510      function logoutpage_hook() {
 511          global $USER;     // use $USER->auth to find the plugin used for login
 512          global $redirect; // can be used to override redirect after logout
 513  
 514          //override if needed
 515      }
 516  
 517      /**
 518       * Hook called before timing out of database session.
 519       * This is useful for SSO and MNET.
 520       *
 521       * @param object $user
 522       * @param string $sid session id
 523       * @param int $timecreated start of session
 524       * @param int $timemodified user last seen
 525       * @return bool true means do not timeout session yet
 526       */
 527      function ignore_timeout_hook($user, $sid, $timecreated, $timemodified) {
 528          return false;
 529      }
 530  
 531      /**
 532       * Return the properly translated human-friendly title of this auth plugin
 533       *
 534       * @todo Document this function
 535       */
 536      function get_title() {
 537          return get_string('pluginname', "auth_{$this->authtype}");
 538      }
 539  
 540      /**
 541       * Get the auth description (from core or own auth lang files)
 542       *
 543       * @return string The description
 544       */
 545      function get_description() {
 546          $authdescription = get_string("auth_{$this->authtype}description", "auth_{$this->authtype}");
 547          return $authdescription;
 548      }
 549  
 550      /**
 551       * Returns whether or not the captcha element is enabled.
 552       *
 553       * @abstract Implement in child classes
 554       * @return bool
 555       */
 556      function is_captcha_enabled() {
 557          return false;
 558      }
 559  
 560      /**
 561       * Returns whether or not this authentication plugin can be manually set
 562       * for users, for example, when bulk uploading users.
 563       *
 564       * This should be overriden by authentication plugins where setting the
 565       * authentication method manually is allowed.
 566       *
 567       * @return bool
 568       * @since Moodle 2.6
 569       */
 570      function can_be_manually_set() {
 571          // Override if needed.
 572          return false;
 573      }
 574  
 575      /**
 576       * Returns a list of potential IdPs that this authentication plugin supports.
 577       * This is used to provide links on the login page.
 578       *
 579       * @param string $wantsurl the relative url fragment the user wants to get to.  You can use this to compose a returnurl, for example
 580       *
 581       * @return array like:
 582       *              array(
 583       *                  array(
 584       *                      'url' => 'http://someurl',
 585       *                      'icon' => new pix_icon(...),
 586       *                      'name' => get_string('somename', 'auth_yourplugin'),
 587       *                 ),
 588       *             )
 589       */
 590      function loginpage_idp_list($wantsurl) {
 591          return array();
 592      }
 593  
 594      /**
 595       * Return custom user profile fields.
 596       *
 597       * @return array list of custom fields.
 598       */
 599      public function get_custom_user_profile_fields() {
 600          global $DB;
 601          // If already retrieved then return.
 602          if (!is_null($this->customfields)) {
 603              return $this->customfields;
 604          }
 605  
 606          $this->customfields = array();
 607          if ($proffields = $DB->get_records('user_info_field')) {
 608              foreach ($proffields as $proffield) {
 609                  $this->customfields[] = 'profile_field_'.$proffield->shortname;
 610              }
 611          }
 612          unset($proffields);
 613  
 614          return $this->customfields;
 615      }
 616  
 617      /**
 618       * Post logout hook.
 619       *
 620       * This method is used after moodle logout by auth classes to execute server logout.
 621       *
 622       * @param stdClass $user clone of USER object before the user session was terminated
 623       */
 624      public function postlogout_hook($user) {
 625      }
 626  }
 627  
 628  /**
 629   * Verify if user is locked out.
 630   *
 631   * @param stdClass $user
 632   * @return bool true if user locked out
 633   */
 634  function login_is_lockedout($user) {
 635      global $CFG;
 636  
 637      if ($user->mnethostid != $CFG->mnet_localhost_id) {
 638          return false;
 639      }
 640      if (isguestuser($user)) {
 641          return false;
 642      }
 643  
 644      if (empty($CFG->lockoutthreshold)) {
 645          // Lockout not enabled.
 646          return false;
 647      }
 648  
 649      if (get_user_preferences('login_lockout_ignored', 0, $user)) {
 650          // This preference may be used for accounts that must not be locked out.
 651          return false;
 652      }
 653  
 654      $locked = get_user_preferences('login_lockout', 0, $user);
 655      if (!$locked) {
 656          return false;
 657      }
 658  
 659      if (empty($CFG->lockoutduration)) {
 660          // Locked out forever.
 661          return true;
 662      }
 663  
 664      if (time() - $locked < $CFG->lockoutduration) {
 665          return true;
 666      }
 667  
 668      login_unlock_account($user);
 669  
 670      return false;
 671  }
 672  
 673  /**
 674   * To be called after valid user login.
 675   * @param stdClass $user
 676   */
 677  function login_attempt_valid($user) {
 678      global $CFG;
 679  
 680      // Note: user_loggedin event is triggered in complete_user_login().
 681  
 682      if ($user->mnethostid != $CFG->mnet_localhost_id) {
 683          return;
 684      }
 685      if (isguestuser($user)) {
 686          return;
 687      }
 688  
 689      // Always unlock here, there might be some race conditions or leftovers when switching threshold.
 690      login_unlock_account($user);
 691  }
 692  
 693  /**
 694   * To be called after failed user login.
 695   * @param stdClass $user
 696   */
 697  function login_attempt_failed($user) {
 698      global $CFG;
 699  
 700      if ($user->mnethostid != $CFG->mnet_localhost_id) {
 701          return;
 702      }
 703      if (isguestuser($user)) {
 704          return;
 705      }
 706  
 707      $count = get_user_preferences('login_failed_count', 0, $user);
 708      $last = get_user_preferences('login_failed_last', 0, $user);
 709      $sincescuccess = get_user_preferences('login_failed_count_since_success', $count, $user);
 710      $sincescuccess = $sincescuccess + 1;
 711      set_user_preference('login_failed_count_since_success', $sincescuccess, $user);
 712  
 713      if (empty($CFG->lockoutthreshold)) {
 714          // No threshold means no lockout.
 715          // Always unlock here, there might be some race conditions or leftovers when switching threshold.
 716          login_unlock_account($user);
 717          return;
 718      }
 719  
 720      if (!empty($CFG->lockoutwindow) and time() - $last > $CFG->lockoutwindow) {
 721          $count = 0;
 722      }
 723  
 724      $count = $count+1;
 725  
 726      set_user_preference('login_failed_count', $count, $user);
 727      set_user_preference('login_failed_last', time(), $user);
 728  
 729      if ($count >= $CFG->lockoutthreshold) {
 730          login_lock_account($user);
 731      }
 732  }
 733  
 734  /**
 735   * Lockout user and send notification email.
 736   *
 737   * @param stdClass $user
 738   */
 739  function login_lock_account($user) {
 740      global $CFG;
 741  
 742      if ($user->mnethostid != $CFG->mnet_localhost_id) {
 743          return;
 744      }
 745      if (isguestuser($user)) {
 746          return;
 747      }
 748  
 749      if (get_user_preferences('login_lockout_ignored', 0, $user)) {
 750          // This user can not be locked out.
 751          return;
 752      }
 753  
 754      $alreadylockedout = get_user_preferences('login_lockout', 0, $user);
 755  
 756      set_user_preference('login_lockout', time(), $user);
 757  
 758      if ($alreadylockedout == 0) {
 759          $secret = random_string(15);
 760          set_user_preference('login_lockout_secret', $secret, $user);
 761  
 762          $oldforcelang = force_current_language($user->lang);
 763  
 764          $site = get_site();
 765          $supportuser = core_user::get_support_user();
 766  
 767          $data = new stdClass();
 768          $data->firstname = $user->firstname;
 769          $data->lastname  = $user->lastname;
 770          $data->username  = $user->username;
 771          $data->sitename  = format_string($site->fullname);
 772          $data->link      = $CFG->wwwroot.'/login/unlock_account.php?u='.$user->id.'&s='.$secret;
 773          $data->admin     = generate_email_signoff();
 774  
 775          $message = get_string('lockoutemailbody', 'admin', $data);
 776          $subject = get_string('lockoutemailsubject', 'admin', format_string($site->fullname));
 777  
 778          if ($message) {
 779              // Directly email rather than using the messaging system to ensure its not routed to a popup or jabber.
 780              email_to_user($user, $supportuser, $subject, $message);
 781          }
 782  
 783          force_current_language($oldforcelang);
 784      }
 785  }
 786  
 787  /**
 788   * Unlock user account and reset timers.
 789   *
 790   * @param stdClass $user
 791   */
 792  function login_unlock_account($user) {
 793      unset_user_preference('login_lockout', $user);
 794      unset_user_preference('login_failed_count', $user);
 795      unset_user_preference('login_failed_last', $user);
 796  
 797      // Note: do not clear the lockout secret because user might click on the link repeatedly.
 798  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1