Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
/lib/ -> sessionlib.php (source)

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * @package    core
  19   * @subpackage session
  20   * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
  21   * @copyright  2008, 2009 Petr Skoda  {@link http://skodak.org}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  
  28  /**
  29   * Makes sure that $USER->sesskey exists, if $USER itself exists. It sets a new sesskey
  30   * if one does not already exist, but does not overwrite existing sesskeys. Returns the
  31   * sesskey string if $USER exists, or boolean false if not.
  32   *
  33   * @uses $USER
  34   * @return string
  35   */
  36  function sesskey() {
  37      // note: do not use $USER because it may not be initialised yet
  38      if (empty($_SESSION['USER']->sesskey)) {
  39          if (!isset($_SESSION['USER'])) {
  40              // This should never happen,
  41              // do not mess with session and globals here,
  42              // let any checks fail instead!
  43              return false;
  44          }
  45          $_SESSION['USER']->sesskey = random_string(10);
  46      }
  47  
  48      return $_SESSION['USER']->sesskey;
  49  }
  50  
  51  
  52  /**
  53   * Check the sesskey and return true of false for whether it is valid.
  54   * (You might like to imagine this function is called sesskey_is_valid().)
  55   *
  56   * Every script that lets the user perform a significant action (that is,
  57   * changes data in the database) should check the sesskey before doing the action.
  58   * Depending on your code flow, you may want to use the {@link require_sesskey()}
  59   * helper function.
  60   *
  61   * @param string $sesskey The sesskey value to check (optional). Normally leave this blank
  62   *      and this function will do required_param('sesskey', ...).
  63   * @return bool whether the sesskey sent in the request matches the one stored in the session.
  64   */
  65  function confirm_sesskey($sesskey=NULL) {
  66      global $USER;
  67  
  68      if (!empty($USER->ignoresesskey)) {
  69          return true;
  70      }
  71  
  72      if (empty($sesskey)) {
  73          $sesskey = required_param('sesskey', PARAM_RAW);  // Check script parameters
  74      }
  75  
  76      return (sesskey() === $sesskey);
  77  }
  78  
  79  /**
  80   * Check the session key using {@link confirm_sesskey()},
  81   * and cause a fatal error if it does not match.
  82   */
  83  function require_sesskey() {
  84      if (!confirm_sesskey()) {
  85          throw new \moodle_exception('invalidsesskey');
  86      }
  87  }
  88  
  89  /**
  90   * Determine wether the secure flag should be set on cookies
  91   * @return bool
  92   */
  93  function is_moodle_cookie_secure() {
  94      global $CFG;
  95  
  96      if (!isset($CFG->cookiesecure)) {
  97          return false;
  98      }
  99      if (!is_https() and empty($CFG->sslproxy)) {
 100          return false;
 101      }
 102      return !empty($CFG->cookiesecure);
 103  }
 104  
 105  /**
 106   * Sets a moodle cookie with a weakly encrypted username
 107   *
 108   * @param string $username to encrypt and place in a cookie, '' means delete current cookie
 109   * @return void
 110   */
 111  function set_moodle_cookie($username) {
 112      global $CFG;
 113  
 114      if (NO_MOODLE_COOKIES) {
 115          return;
 116      }
 117  
 118      if (empty($CFG->rememberusername)) {
 119          // erase current and do not store permanent cookies
 120          $username = '';
 121      }
 122  
 123      if ($username === 'guest') {
 124          // keep previous cookie in case of guest account login
 125          return;
 126      }
 127  
 128      $cookiename = 'MOODLEID1_'.$CFG->sessioncookie;
 129  
 130      $cookiesecure = is_moodle_cookie_secure();
 131  
 132      // Delete old cookie.
 133      setcookie($cookiename, '', time() - HOURSECS, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
 134  
 135      if ($username !== '') {
 136          // Set username cookie for 60 days.
 137          setcookie($cookiename, rc4encrypt($username), time() + (DAYSECS * 60), $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly);
 138      }
 139  }
 140  
 141  /**
 142   * Gets a moodle cookie with a weakly encrypted username
 143   *
 144   * @return string username
 145   */
 146  function get_moodle_cookie() {
 147      global $CFG;
 148  
 149      if (NO_MOODLE_COOKIES) {
 150          return '';
 151      }
 152  
 153      if (empty($CFG->rememberusername)) {
 154          return '';
 155      }
 156  
 157      $cookiename = 'MOODLEID1_'.$CFG->sessioncookie;
 158  
 159      if (empty($_COOKIE[$cookiename])) {
 160          return '';
 161      } else {
 162          $username = rc4decrypt($_COOKIE[$cookiename]);
 163          if ($username === 'guest' or $username === 'nobody') {
 164              // backwards compatibility - we do not set these cookies any more
 165              $username = '';
 166          }
 167          return $username;
 168      }
 169  }
 170  
 171  /**
 172   * Sets up current user and course environment (lang, etc.) in cron.
 173   * Note: This function is intended only for use in:
 174   * - the cron runner scripts
 175   * - individual tasks which extend the adhoc_task and scheduled_task classes
 176   * - unit tests related to tasks
 177   * - other parts of the cron/task system
 178   *
 179   * @param stdClass $user full user object, null means default cron user (admin),
 180   *                 value 'reset' means reset internal static caches.
 181   * @param stdClass $course full course record, null means $SITE
 182   * @param bool $leavepagealone If specified, stops it messing with global page object
 183   * @return void
 184   */
 185  function cron_setup_user($user = null, $course = null, $leavepagealone = false) {
 186      global $CFG, $SITE, $PAGE;
 187  
 188      if (!CLI_SCRIPT && !$leavepagealone) {
 189          throw new coding_exception('Function cron_setup_user() cannot be used in normal requests!');
 190      }
 191  
 192      static $cronuser    = NULL;
 193      static $cronsession = NULL;
 194  
 195      if ($user === 'reset') {
 196          $cronuser = null;
 197          $cronsession = null;
 198          \core\session\manager::init_empty_session();
 199          return;
 200      }
 201  
 202      if (empty($cronuser)) {
 203          /// ignore admins timezone, language and locale - use site default instead!
 204          $cronuser = get_admin();
 205          $cronuser->timezone = $CFG->timezone;
 206          $cronuser->lang     = '';
 207          $cronuser->theme    = '';
 208          unset($cronuser->description);
 209  
 210          $cronsession = new stdClass();
 211      }
 212  
 213      if (!$user) {
 214          // Cached default cron user (==modified admin for now).
 215          \core\session\manager::init_empty_session();
 216          \core\session\manager::set_user($cronuser);
 217          $GLOBALS['SESSION'] = $cronsession;
 218  
 219      } else {
 220          // Emulate real user session - needed for caps in cron.
 221          if ($GLOBALS['USER']->id != $user->id) {
 222              \core\session\manager::init_empty_session();
 223              \core\session\manager::set_user($user);
 224          }
 225      }
 226  
 227      // TODO MDL-19774 relying on global $PAGE in cron is a bad idea.
 228      // Temporary hack so that cron does not give fatal errors.
 229      if (!$leavepagealone) {
 230          $PAGE = new moodle_page();
 231          if ($course) {
 232              $PAGE->set_course($course);
 233          } else {
 234              $PAGE->set_course($SITE);
 235          }
 236      }
 237  
 238      // TODO: it should be possible to improve perf by caching some limited number of users here ;-)
 239  
 240  }