Commit 27550c7b authored by Robert Lyon's avatar Robert Lyon
Browse files

Bug 1943525: Setting the non https site cookies 'samesite' option

When we are using non-https site we need to define the samesite option
to be something other than 'none'
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite



So will set this to be 'lax' the new default value

Change-Id: If4011fff680e18ed4ca7600164fb9b64f815b9df
Signed-off-by: default avatarRobert Lyon <robertl@catalyst.net.nz>
(cherry picked from commit 33f2b29b)
parent beae4c55
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2043,13 +2043,14 @@ function get_login_form_js($form) {
    $form = json_encode($form);
    $strcookiesnotenabled    = json_encode(get_string('cookiesnotenabled'));
    $cookiename = get_config('cookieprefix') . 'ctest';
    $samesite = is_https() ? 'None;Secure' : 'Lax';
    $js = <<< EOF
<script>
var loginbox = jQuery('#loginform_container');
document.cookie = "$cookiename=1";
document.cookie = "$cookiename=1;samesite=$samesite";
if (document.cookie) {
    loginbox.html($form);
    document.cookie = '$cookiename=1;expires=1/1/1990 00:00:00';
    document.cookie = '$cookiename=1;samesite=$samesite;expires=1/1/1990 00:00:00';
}
else {
    loginbox.empty().append(jQuery('<p>', { 'text': $strcookiesnotenabled }));
+54 −28
Original line number Diff line number Diff line
@@ -152,6 +152,10 @@ class Session {
        ini_set('session.cookie_httponly', true);
        if (is_https()) {
            ini_set('session.cookie_secure', true);
            ini_set('session.cookie_samesite', 'None');
        }
        else {
            ini_set('session.cookie_samesite', 'Lax');
        }
        if ($domain = get_config('cookiedomain')) {
            ini_set('session.cookie_domain', $domain);
@@ -480,15 +484,7 @@ class Session {
            // will be ignored, and instead the old session cookie will
            // be replaced by the new one.)
            if (isset($_COOKIE[session_name()])) {
                setcookie(
                    session_name(),
                    '',
                    1,
                    ini_get('session.cookie_path'),
                    ini_get('session.cookie_domain'),
                    ini_get('session.cookie_secure'),
                    ini_get('session.cookie_httponly')
                );
                $this->set_session_cookie(session_name(), '', 1);
            }
        }
    }
@@ -597,6 +593,54 @@ class Session {
        $this->set_cookie_secure(true);
    }

    /**
     * Helper function to set session cookie depending on PHP version
     *
     * The way set_cookie works differs from PHP 7.3+
     *
     * @param string  $name    Name of cookie
     * @param string  $value   Value for cookie
     * @param integer $expires Timestamp for expiry of cookie
     */
    public function set_session_cookie($name, $value, $expires) {
        global $SESSION;

        $secure = $SESSION->get_cookie_secure();
        $path = ini_get('session.cookie_path');
        if (empty($path)) {
            $path = '/';
        }

        if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
            setcookie(
                $name,
                $value,
                array('expires' => $expires,
                    'path' => $path,
                    'domain' => ini_get('session.cookie_domain'),
                    'secure' => $secure,
                    'httponly' => ini_get('session.cookie_httponly'),
                    'samesite' => ini_get('session.cookie_samesite')
                )
            );
        }
        else {
            $path_extra = $SESSION->get_cookie_extra_path();
            if (!empty($path_extra)) {
                // We have things to add to path. Prepend it with the separator.
                $path_extra = '; ' . $path_extra;
            }
            setcookie(
                $name,
                $value,
                $expires,
                $path . $path_extra,
                ini_get('session.cookie_domain'),
                $secure,
                ini_get('session.cookie_httponly')
            );
        }
    }
}

/**
@@ -730,25 +774,7 @@ function clear_duplicate_cookies() {

    // Now manually regenerate just ONE session cookie header.
    if ($SESSION->session_id()) {
        $path = ini_get('session.cookie_path');
        if (empty($path)) {
            $path = '/';
        }
        $path_extra = $SESSION->get_cookie_extra_path();
        if (!empty($path_extra)) {
            // We have things to add to path. Prepend it with the separator.
            $path_extra = '; ' . $path_extra;
        }
        $secure = $SESSION->get_cookie_secure();
        setcookie(
            $cookiename,
            $SESSION->session_id(),
            0,
            $path . $path_extra,
            ini_get('session.cookie_domain'),
            $secure,
            ini_get('session.cookie_httponly')
        );
        $SESSION->set_session_cookie($cookiename, $SESSION->session_id(), 0);
    }
}

+31 −1
Original line number Diff line number Diff line
@@ -2142,6 +2142,8 @@ function get_cookies($prefix) {
 * @param int    $expires The unix timestamp of the time the cookie should expire
 */
function set_cookie($name, $value='', $expires=0, $access=false) {
    global $SESSION;

    $name = get_config('cookieprefix') . $name;
    $url = parse_url(get_config('wwwroot'));
    if (!$domain = get_config('cookiedomain')) {
@@ -2149,7 +2151,35 @@ function set_cookie($name, $value='', $expires=0, $access=false) {
    }
    // If no headers are sent - to avoid CLI scripts calling logout() problems
    if (!headers_sent()) {
        setcookie($name, $value, $expires, $url['path'], $domain, is_https(), true);
        if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
            $samesite = is_https() ? 'None' : 'Lax';
            setcookie($name, $value, array('expires' => $expires,
                                           'path' => $url['path'],
                                           'domain' => $domain,
                                           'secure' => $SESSION->get_cookie_secure(),
                                           'httponly' => true,
                                           'samesite' => $samesite));
        }
        else {
            $path = $url['path'];
            if (empty($path)) {
                $path = '/';
            }
            $path_extra = $SESSION->get_cookie_extra_path();
            if (!empty($path_extra)) {
                // We have things to add to path. Prepend it with the separator.
                $path_extra = '; ' . $path_extra;
            }
            setcookie(
                $name,
                $value,
                $expires,
                $path . $path_extra,
                $domain,
                is_https(),
                true
            );
        }
        if ($access) {  // View access cookies may be needed on this request
            $_COOKIE[$name] = $value;
        }