From eb770fdc6d809bc7c28d499f897c0ab2c449f669 Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Sun, 28 Feb 2021 20:10:00 +0200 Subject: Initial implementation of samesite for CI_Input::set_cookie --- system/core/Input.php | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index 30d528b89..a7f4edee9 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -300,14 +300,15 @@ class CI_Input { * @param string $prefix Cookie name prefix * @param bool $secure Whether to only transfer cookies via SSL * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) + * @param string $samesite SameSite attribute. NULL will avoid sending the attribute * @return void */ - public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) + public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL) { if (is_array($name)) { // always leave 'name' in last place, as the loop will break otherwise, due to $$item - foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item) + foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name', 'samesite') as $item) { if (isset($name[$item])) { @@ -348,7 +349,25 @@ class CI_Input { $expire = ($expire > 0) ? time() + $expire : 0; } - setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly); + if ($samesite === NULL && config_item('cookie_samesite') !== NULL) + { + $samesite = strtolower(config_item('cookie_samesite')); + } + elseif ($samesite !== NULL) + { + $samesite = strtolower($samesite); + } + + if ( ! in_array($samesite, array('lax', 'strict', 'none', NULL), TRUE)) + { + $samesite = NULL; + } + + $cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value); + $cookie_header .= ($expire === 0 ? '' : '; expires='.gmdate('D, d-M-Y H:i:s T', 0)); + $cookie_header .= '; path='.$path.($domain !== '' ? '; domain='.$domain : ''); + $cookie_header .= ($secure ? '; secure' : '').($httponly ? '; HttpOnly' : '').($samesite !== NULL ? '; SameSite='.$samesite : ''); + header($cookie_header); } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From cd192363f777731e8f382fe7288a44183a448213 Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Mon, 1 Mar 2021 19:45:24 +0200 Subject: Fixes "expires" cookie attribute bug --- system/core/Input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index a7f4edee9..d397850b7 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -364,7 +364,7 @@ class CI_Input { } $cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value); - $cookie_header .= ($expire === 0 ? '' : '; expires='.gmdate('D, d-M-Y H:i:s T', 0)); + $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 !== NULL ? '; SameSite='.$samesite : ''); header($cookie_header); -- cgit v1.2.3-24-g4f1b From 2abda9049a8d006673204f56f4680526232b2360 Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Sun, 14 Mar 2021 01:56:30 +0200 Subject: Dropping the possibility that samesite cookie attribute won't be sent; defaults to Lax; all samesite values are ucfirst'ed; log for SameSite=None non-secure cookies --- system/core/Input.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index d397850b7..9bde8a4f6 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -300,7 +300,7 @@ class CI_Input { * @param string $prefix Cookie name prefix * @param bool $secure Whether to only transfer cookies via SSL * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) - * @param string $samesite SameSite attribute. NULL will avoid sending the attribute + * @param string $samesite SameSite attribute * @return void */ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL) @@ -349,24 +349,26 @@ class CI_Input { $expire = ($expire > 0) ? time() + $expire : 0; } - if ($samesite === NULL && config_item('cookie_samesite') !== NULL) + isset($samesite) OR $samesite = config_item('cookie_samesite'); + if (isset($samesite)) { - $samesite = strtolower(config_item('cookie_samesite')); + $samesite = ucfirst(strtolower($samesite)); + in_array($samesite, array('Lax', 'Strict', 'None'), TRUE) OR $samesite = 'Lax'; } - elseif ($samesite !== NULL) + else { - $samesite = strtolower($samesite); + $samesite = 'Lax'; } - if ( ! in_array($samesite, array('lax', 'strict', 'none', NULL), TRUE)) + if ($samesite === 'None' && !$secure) { - $samesite = NULL; + log_message('error', $name.' is a non-secure cookie sent with SameSite=None. It can be discarded by the browser.'); } $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 !== NULL ? '; SameSite='.$samesite : ''); + $cookie_header .= ($secure ? '; secure' : '').($httponly ? '; HttpOnly' : '').'; SameSite='.$samesite; header($cookie_header); } -- cgit v1.2.3-24-g4f1b From 78084aeac459aa1772db7094480008143fb82e7a Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Fri, 2 Apr 2021 00:55:55 +0300 Subject: Space after ! op --- system/core/Input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index 9bde8a4f6..a2cc23936 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -360,7 +360,7 @@ class CI_Input { $samesite = 'Lax'; } - if ($samesite === 'None' && !$secure) + if ($samesite === 'None' && ! $secure) { log_message('error', $name.' is a non-secure cookie sent with SameSite=None. It can be discarded by the browser.'); } -- cgit v1.2.3-24-g4f1b From 4f6d9ba5b6b690f3b7b30c20926463d41117017a Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Fri, 2 Apr 2021 00:56:51 +0300 Subject: Rewording log_message() message --- system/core/Input.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index a2cc23936..fbe9c59b0 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -362,7 +362,7 @@ class CI_Input { if ($samesite === 'None' && ! $secure) { - log_message('error', $name.' is a non-secure cookie sent with SameSite=None. It can be discarded by the browser.'); + log_message('error', $name.' cookie sent with SameSite=None, but without Secure attribute.'); } $cookie_header = 'Set-Cookie: '.$prefix.$name.'='.rawurlencode($value); -- cgit v1.2.3-24-g4f1b From 0cf5aa1a17bf0fd91797a943b8e696a454f5d326 Mon Sep 17 00:00:00 2001 From: George Petculescu Date: Fri, 2 Apr 2021 02:41:29 +0300 Subject: Switching to setcookie for PHP >= 7.3 --- system/core/Input.php | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'system') diff --git a/system/core/Input.php b/system/core/Input.php index fbe9c59b0..451737167 100644 --- a/system/core/Input.php +++ b/system/core/Input.php @@ -365,11 +365,26 @@ class CI_Input { log_message('error', $name.' cookie sent with SameSite=None, but without Secure attribute.'); } - $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; - header($cookie_header); + 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 + { + $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; + header($cookie_header); + } } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b