summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/config/config.php5
-rwxr-xr-xbuild-release.sh3
-rw-r--r--system/core/Input.php37
-rw-r--r--system/libraries/Session/Session.php83
-rw-r--r--system/libraries/Session/Session_driver.php24
-rw-r--r--user_guide_src/source/changelog.rst2
-rw-r--r--user_guide_src/source/libraries/sessions.rst2
7 files changed, 117 insertions, 39 deletions
diff --git a/application/config/config.php b/application/config/config.php
index 596f8fefe..d66d4fce4 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -329,6 +329,10 @@ $config['encryption_key'] = '';
|
| The session cookie name, must contain only [0-9a-z_-] characters
|
+| 'sess_samesite'
+|
+| Session cookie SameSite attribute: Lax (default), Strict or None
+|
| 'sess_expiration'
|
| The number of SECONDS you want the session to last.
@@ -369,6 +373,7 @@ $config['encryption_key'] = '';
*/
$config['sess_driver'] = 'files';
$config['sess_cookie_name'] = 'ci_session';
+$config['sess_samesite'] = 'Lax';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = NULL;
$config['sess_match_ip'] = FALSE;
diff --git a/build-release.sh b/build-release.sh
index 6b3b31d12..30967fc2e 100755
--- a/build-release.sh
+++ b/build-release.sh
@@ -47,7 +47,7 @@ fi
echo "Running tests ..."
-cd tests/
+php -d zend.enable_gc=0 -d date.timezone=UTC -d mbstring.func_overload=7 -d mbstring.internal_encoding=UTF-8 vendor/bin/phpunit --coverage-text --configuration tests/travis/sqlite.phpunit.xml
phpunit
if [ $? -ne 0 ]
@@ -56,7 +56,6 @@ then
exit 1
fi
-cd ..
cd user_guide_src/
echo ""
diff --git a/system/core/Input.php b/system/core/Input.php
index 71f28221f..0beb252ed 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -365,26 +365,31 @@ class CI_Input {
log_message('error', $name.' cookie sent with SameSite=None, but without Secure attribute.');
}
- if (is_php('7.3'))
- {
- $setcookie_options = array(
- 'expires' => $expire,
- 'path' => $path,
- 'domain' => $domain,
- 'secure' => $secure,
- 'httponly' => $httponly,
- 'samesite' => $samesite,
- );
- setcookie($prefix.$name, $value, $setcookie_options);
- }
- else
+ if ( ! is_php('7.3'))
{
+ $maxage = $expire - time();
+ if ($maxage < 1)
+ {
+ $maxage = 0;
+ }
+
$cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value);
- $cookie_header .= ($expire === 0 ? '' : '; expires='.gmdate('D, d-M-Y H:i:s T', $expire));
- $cookie_header .= '; path='.$path.($domain !== '' ? '; domain='.$domain : '');
- $cookie_header .= ($secure ? '; secure' : '').($httponly ? '; HttpOnly' : '').'; SameSite='.$samesite;
+ $cookie_header .= ($expire === 0 ? '' : '; Expires='.gmdate('D, d-M-Y H:i:s T', $expire)).'; Max-Age='.$maxage;
+ $cookie_header .= '; Path='.$path.($domain !== '' ? '; Domain='.$domain : '');
+ $cookie_header .= ($secure ? '; Secure' : '').($httponly ? '; HttpOnly' : '').'; SameSite='.$samesite;
header($cookie_header);
+ return;
}
+
+ $setcookie_options = array(
+ 'expires' => $expire,
+ 'path' => $path,
+ 'domain' => $domain,
+ 'secure' => $secure,
+ 'httponly' => $httponly,
+ 'samesite' => $samesite,
+ );
+ setcookie($prefix.$name, $value, $setcookie_options);
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index 6479d7242..f370f7f19 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -154,15 +154,36 @@ class CI_Session {
// unless it is being currently created or regenerated
elseif (isset($_COOKIE[$this->_config['cookie_name']]) && $_COOKIE[$this->_config['cookie_name']] === session_id())
{
- setcookie(
- $this->_config['cookie_name'],
- session_id(),
- (empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime']),
- $this->_config['cookie_path'],
- $this->_config['cookie_domain'],
- $this->_config['cookie_secure'],
- TRUE
- );
+ $expires = empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime'];
+ if (is_php('7.3'))
+ {
+ setcookie(
+ $this->_config['cookie_name'],
+ session_id(),
+ array(
+ 'expires' => $expires,
+ 'path' => $this->_config['cookie_path'],
+ 'domain' => $this->_config['cookie_domain'],
+ 'secure' => $this->_config['cookie_secure'],
+ 'httponly' => TRUE,
+ 'samesite' => $this->_config['cookie_samesite']
+ )
+ );
+ }
+ else
+ {
+ $header = 'Set-Cookie: '.$this->_config['cookie_name'].'='.session_id();
+ $header .= empty($expires) ? '' : '; Expires='.gmdate('D, d-M-Y H:i:s T', $expires).'; Max-Age='.$this->_config['cookie_lifetime'];
+ $header .= '; Path='.$this->_config['cookie_path'];
+ $header .= ($this->_config['cookie_domain'] !== '' ? '; Domain='.$this->_config['cookie_domain'] : '');
+ $header .= ($this->_config['cookie_secure'] ? '; Secure' : '').'; HttpOnly; SameSite='.$this->_config['cookie_samesite'];
+ header($header);
+ }
+
+ if ( ! $this->_config['cookie_secure'] && $this->_config['cookie_samesite'] === 'None')
+ {
+ log_message('error', 'Session:', $this->_config['cookie_name'].' cookie sent with SameSite=None, but without Secure attribute.');
+ }
}
$this->_ci_init_vars();
@@ -281,13 +302,43 @@ class CI_Session {
isset($params['cookie_domain']) OR $params['cookie_domain'] = config_item('cookie_domain');
isset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');
- session_set_cookie_params(
- $params['cookie_lifetime'],
- $params['cookie_path'],
- $params['cookie_domain'],
- $params['cookie_secure'],
- TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
- );
+ isset($params['cookie_samesite']) OR $params['cookie_samesite'] = config_item('sess_samesite');
+ if ( ! isset($params['cookie_samesite']) && is_php('7.3'))
+ {
+ $params['cookie_samesite'] = ini_get('session.cookie_samesite');
+ }
+
+ if (isset($params['cookie_samesite']))
+ {
+ $params['cookie_samesite'] = ucfirst(strtolower($params['cookie_samesite']));
+ in_array($params['cookie_samesite'], array('Lax', 'Strict', 'None'), TRUE) OR $params['cookie_samesite'] = 'Lax';
+ }
+ else
+ {
+ $params['cookie_samesite'] = 'Lax';
+ }
+
+ if (is_php('7.3'))
+ {
+ session_set_cookie_params(array(
+ 'lifetime' => $params['cookie_lifetime'],
+ 'path' => $params['cookie_path'],
+ 'domain' => $params['cookie_domain'],
+ 'secure' => $params['cookie_secure'],
+ 'httponly' => $params['cookie_httponly'],
+ 'samesite' => $params['cookie_samesite']
+ ));
+ }
+ else
+ {
+ session_set_cookie_params(
+ $params['cookie_lifetime'],
+ $params['cookie_path'],
+ $params['cookie_domain'],
+ $params['cookie_secure'],
+ TRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons
+ );
+ }
if (empty($expiration))
{
diff --git a/system/libraries/Session/Session_driver.php b/system/libraries/Session/Session_driver.php
index d78492b5e..b1b1b073e 100644
--- a/system/libraries/Session/Session_driver.php
+++ b/system/libraries/Session/Session_driver.php
@@ -140,14 +140,28 @@ abstract class CI_Session_driver {
*/
protected function _cookie_destroy()
{
+ if ( ! is_php('7.3'))
+ {
+ $header = 'Set-Cookie: '.$this->_config['cookie_name'].'=';
+ $header .= '; Expires='.gmdate('D, d-M-Y H:i:s T', 1).'; Max-Age=-1';
+ $header .= '; Path='.$this->_config['cookie_path'];
+ $header .= ($this->_config['cookie_domain'] !== '' ? '; Domain='.$this->_config['cookie_domain'] : '');
+ $header .= ($this->_config['cookie_secure'] ? '; Secure' : '').'; HttpOnly; SameSite='.$this->_config['cookie_samesite'];
+ header($header);
+ return;
+ }
+
return setcookie(
$this->_config['cookie_name'],
NULL,
- 1,
- $this->_config['cookie_path'],
- $this->_config['cookie_domain'],
- $this->_config['cookie_secure'],
- TRUE
+ array(
+ 'expires' => 1,
+ 'path' => $this->_config['cookie_path'],
+ 'domain' => $this->_config['cookie_domain'],
+ 'secure' => $this->_config['cookie_secure'],
+ 'httponly' => TRUE,
+ 'samesite' => $this->_config['cookie_samesite']
+ )
);
}
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 7bd51c81e..b4278b1cd 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -145,6 +145,8 @@ Release Date: Not Released
- Added method :doc:`Database Library <database/index>` method ``trans_active()`` to expose transaction state.
- Updated :doc:`Database Library <database/index>` 'pdo' driver to attempt to free resources in order to allow connections to be closed.
- Added ``SameSite=Strict`` attribute to the CSRF cookie sent by the :doc:`Security Class <libraries/security>`.
+ - Added ``$config['cookie_samesite']`` option and ``$samesite`` parameter to :doc:`Input Library <libraries/input>` method ``set_cookie()``.
+ - Added ``SameSite`` support through ``$config['sess_samesite']`` option to the :doc:`Session Library <libraries/sessions>`.
- Added a wrapper class around :doc:`Session <libraries/sessions>` drivers to deal with compatibility between PHP 8.1 and older versions.
- Updated a lot of code for PHP 8.0 and 8.1 compatibility.
diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst
index f2236c633..b87508aba 100644
--- a/user_guide_src/source/libraries/sessions.rst
+++ b/user_guide_src/source/libraries/sessions.rst
@@ -438,6 +438,8 @@ Preference Default Options
============================ =============== ======================================== ============================================================================================
**sess_driver** files files/database/redis/memcached/*custom* The session storage driver to use.
**sess_cookie_name** ci_session [A-Za-z\_-] characters only The name used for the session cookie.
+**sess_samesite** ci_session 'Lax', 'Strict' or 'None' SameSite attribute value for session cookies.
+ Defaults to ``session.cookie_samesite`` on PHP 7.3+ or 'Lax' if not present at all.
**sess_expiration** 7200 (2 hours) Time in seconds (integer) The number of seconds you would like the session to last.
If you would like a non-expiring session (until browser is closed) set the value to zero: 0
**sess_save_path** NULL None Specifies the storage location, depends on the driver being used.