/** * Sets a moodle cookie with a weakly encrypted username * * @param string $username to encrypt and place in a cookie, '' means delete current cookie * @return void */ function set_moodle_cookie($username) { global $CFG; if (NO_MOODLE_COOKIES) { return; } if (empty($CFG->rememberusername)) { // erase current and do not store permanent cookies $username = ''; } if ($username === 'guest') { // keep previous cookie in case of guest account login return; } $cookiename = 'MOODLEID1_' . $CFG->sessioncookie; $cookiesecure = is_moodle_cookie_secure(); // Delete old cookie. setcookie($cookiename, '', time() - HOURSECS, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly); if ($username !== '') { // Set username cookie for 60 days. setcookie($cookiename, rc4encrypt($username), time() + DAYSECS * 60, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly); } }
/** * Verifies if https enabled only secure cookies allowed, * this prevents redirections and sending of cookies to unsecure port. * @param bool $detailed * @return object result */ function report_security_check_cookiesecure($detailed = false) { global $CFG; if (!is_https()) { return null; } $result = new stdClass(); $result->issue = 'report_security_check_cookiesecure'; $result->name = get_string('check_cookiesecure_name', 'report_security'); $result->info = null; $result->details = null; $result->status = null; $result->link = "<a href=\"{$CFG->wwwroot}/{$CFG->admin}/settings.php?section=httpsecurity\">" . get_string('httpsecurity', 'admin') . '</a>'; if (!is_moodle_cookie_secure()) { $result->status = REPORT_SECURITY_SERIOUS; $result->info = get_string('check_cookiesecure_error', 'report_security'); } else { $result->status = REPORT_SECURITY_OK; $result->info = get_string('check_cookiesecure_ok', 'report_security'); } if ($detailed) { $result->details = get_string('check_cookiesecure_details', 'report_security'); } return $result; }
/** * Make sure all cookie and session related stuff is configured properly before session start. */ protected static function prepare_cookies() { global $CFG; $cookiesecure = is_moodle_cookie_secure(); if (!isset($CFG->cookiehttponly)) { $CFG->cookiehttponly = 0; } // Set sessioncookie variable if it isn't already. if (!isset($CFG->sessioncookie)) { $CFG->sessioncookie = ''; } $sessionname = 'MoodleSession' . $CFG->sessioncookie; // Make sure cookie domain makes sense for this wwwroot. if (!isset($CFG->sessioncookiedomain)) { $CFG->sessioncookiedomain = ''; } else { if ($CFG->sessioncookiedomain !== '') { $host = parse_url($CFG->wwwroot, PHP_URL_HOST); if ($CFG->sessioncookiedomain !== $host) { if (substr($CFG->sessioncookiedomain, 0, 1) === '.') { if (!preg_match('|^.*' . preg_quote($CFG->sessioncookiedomain, '|') . '$|', $host)) { // Invalid domain - it must be end part of host. $CFG->sessioncookiedomain = ''; } } else { if (!preg_match('|^.*\\.' . preg_quote($CFG->sessioncookiedomain, '|') . '$|', $host)) { // Invalid domain - it must be end part of host. $CFG->sessioncookiedomain = ''; } } } } } // Make sure the cookiepath is valid for this wwwroot or autodetect if not specified. if (!isset($CFG->sessioncookiepath)) { $CFG->sessioncookiepath = ''; } if ($CFG->sessioncookiepath !== '/') { $path = parse_url($CFG->wwwroot, PHP_URL_PATH) . '/'; if ($CFG->sessioncookiepath === '') { $CFG->sessioncookiepath = $path; } else { if (strpos($path, $CFG->sessioncookiepath) !== 0 or substr($CFG->sessioncookiepath, -1) !== '/') { $CFG->sessioncookiepath = $path; } } } // Discard session ID from POST, GET and globals to tighten security, // this is session fixation prevention. unset($GLOBALS[$sessionname]); unset($_GET[$sessionname]); unset($_POST[$sessionname]); unset($_REQUEST[$sessionname]); // Compatibility hack for non-browser access to our web interface. if (!empty($_COOKIE[$sessionname]) && $_COOKIE[$sessionname] == "deleted") { unset($_COOKIE[$sessionname]); } // Set configuration. session_name($sessionname); session_set_cookie_params(0, $CFG->sessioncookiepath, $CFG->sessioncookiedomain, $cookiesecure, $CFG->cookiehttponly); ini_set('session.use_trans_sid', '0'); ini_set('session.use_only_cookies', '1'); ini_set('session.hash_function', '0'); // For now MD5 - we do not have room for sha-1 in sessions table. ini_set('session.use_strict_mode', '0'); // We have custom protection in session init. ini_set('session.serialize_handler', 'php'); // We can move to 'php_serialize' after we require PHP 5.5.4 form Moodle. // Moodle does normal session timeouts, this is for leftovers only. ini_set('session.gc_probability', 1); ini_set('session.gc_divisor', 1000); ini_set('session.gc_maxlifetime', 60 * 60 * 24 * 4); }
/** * Test for secure cookie * * @dataProvider moodle_cookie_secure_provider * * @param array $config Array of key value config settings * @param bool $secure Wether cookies should be secure or not */ public function test_is_moodle_cookie_secure($config, $secure) { $this->resetAfterTest(); foreach ($config as $key => $value) { set_config($key, $value); } $this->assertEquals($secure, is_moodle_cookie_secure()); }