From 6c6ee1a1e73b3f8a93ca031107bec35e56272a0a Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 22 Oct 2016 16:33:06 +0300 Subject: Close #4830, #3649 --- system/libraries/Session/Session.php | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'system/libraries/Session/Session.php') diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index 3b391a8ef..5aac12f36 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -57,6 +57,7 @@ class CI_Session { protected $_driver = 'files'; protected $_config; + protected $_sid_regexp; // ------------------------------------------------------------------------ @@ -99,6 +100,7 @@ class CI_Session { // Configuration ... $this->_configure($params); + $this->_config['_sid_regexp'] = $this->_sid_regexp; $class = new $class($this->_config); if ($class instanceof SessionHandlerInterface) @@ -131,7 +133,7 @@ class CI_Session { if (isset($_COOKIE[$this->_config['cookie_name']]) && ( ! is_string($_COOKIE[$this->_config['cookie_name']]) - OR ! preg_match('/^[0-9a-f]{40}$/', $_COOKIE[$this->_config['cookie_name']]) + OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']]) ) ) { @@ -315,8 +317,36 @@ class CI_Session { ini_set('session.use_strict_mode', 1); ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); - ini_set('session.hash_function', 1); - ini_set('session.hash_bits_per_character', 4); + + if (PHP_VERSION_ID < 70100) + { + if ((int) ini_get('session.hash_function') === 0) + { + ini_set('session.hash_function', 1); + ini_set('session.hash_bits_per_character', $bits_per_character = 4); + } + else + { + $bits_per_character = (int) ini_get('session.hash_bits_per_character'); + } + } + elseif ((int) ini_get('session.sid_length') < 40 && ($bits_per_character = (int) ini_get('session.sid_bits_per_character')) === 4) + { + ini_set('session.sid_length', 40); + } + + switch ($bits_per_character) + { + case 4: + $this->_sid_regexp = '[0-9a-f]{40,}'; + break; + case 5: + $this->_sid_regexp = '[0-9a-v]{40,}'; + break; + case 6: + $this->_sid_regexp = '[0-9a-zA-Z,-]{40,}'; + break; + } } // ------------------------------------------------------------------------ -- cgit v1.2.3-24-g4f1b From 2f760877c313871e5066b93b0b1aa76428c09fb6 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 27 Oct 2016 16:39:12 +0300 Subject: Fix #4874 --- system/libraries/Session/Session.php | 63 ++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 9 deletions(-) (limited to 'system/libraries/Session/Session.php') diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index 5aac12f36..ea7853108 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -318,35 +318,80 @@ class CI_Session { ini_set('session.use_cookies', 1); ini_set('session.use_only_cookies', 1); + $this->_configure_sid_length(); + } + + // ------------------------------------------------------------------------ + + /** + * Configure session ID length + * + * To make life easier, we used to force SHA-1 and 4 bits per + * character on everyone. And of course, someone was unhappy. + * + * Then PHP 7.1 broke backwards-compatibility because ext/session + * is such a mess that nobody wants to touch it with a pole stick, + * and the one guy who does, nobody has the energy to argue with. + * + * So we were forced to make changes, and OF COURSE something was + * going to break and now we have this pile of shit. -- Narf + * + * @return void + */ + protected function _configure_sid_length() + { if (PHP_VERSION_ID < 70100) { - if ((int) ini_get('session.hash_function') === 0) + $hash_function = ini_get('session.hash_function'); + if (ctype_digit($hash_function)) + { + if ($hash_function !== '1') + { + ini_set('session.hash_function', 1); + $bits = 160; + } + } + elseif ( ! in_array($hash_function, hash_algos(), TRUE)) { ini_set('session.hash_function', 1); - ini_set('session.hash_bits_per_character', $bits_per_character = 4); + $bits = 160; } - else + elseif (($bits = strlen(hash($hash_function, 'dummy', false)) * 4) < 160) { - $bits_per_character = (int) ini_get('session.hash_bits_per_character'); + ini_set('session.hash_function', 1); + $bits = 160; } + + $bits_per_character = (int) ini_get('session.hash_bits_per_character'); + $sid_length = $bits * $bits_per_character; } - elseif ((int) ini_get('session.sid_length') < 40 && ($bits_per_character = (int) ini_get('session.sid_bits_per_character')) === 4) + else { - ini_set('session.sid_length', 40); + $bits_per_character = (int) ini_get('session.sid_bits_per_character'); + $sid_length = (int) ini_get('session.sid_length'); + if (($bits = $sid_length * $bits_per_character) < 160) + { + // Add as many more characters as necessary to reach at least 160 bits + $sid_length += (int) ceil((160 % $bits) / $bits_per_character); + ini_set('session.sid_length', $sid_length); + } } + // Yes, 4,5,6 are the only known possible values as of 2016-10-27 switch ($bits_per_character) { case 4: - $this->_sid_regexp = '[0-9a-f]{40,}'; + $this->_sid_regexp = '[0-9a-f]'; break; case 5: - $this->_sid_regexp = '[0-9a-v]{40,}'; + $this->_sid_regexp = '[0-9a-v]'; break; case 6: - $this->_sid_regexp = '[0-9a-zA-Z,-]{40,}'; + $this->_sid_regexp = '[0-9a-zA-Z,-]'; break; } + + $this->_sid_regexp .= '{'.$sid_length.'}'; } // ------------------------------------------------------------------------ -- cgit v1.2.3-24-g4f1b From dbc025b6c2c9b0b085bb79dc126bc58fb2a8c2a8 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 27 Oct 2016 17:37:25 +0300 Subject: [ci skip] Another attempt at #4874 --- system/libraries/Session/Session.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'system/libraries/Session/Session.php') diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index ea7853108..01989d2d7 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -348,8 +348,9 @@ class CI_Session { if ($hash_function !== '1') { ini_set('session.hash_function', 1); - $bits = 160; } + + $bits = 160; } elseif ( ! in_array($hash_function, hash_algos(), TRUE)) { @@ -363,7 +364,7 @@ class CI_Session { } $bits_per_character = (int) ini_get('session.hash_bits_per_character'); - $sid_length = $bits * $bits_per_character; + $sid_length = (int) ceil($bits / $bits_per_character); } else { -- cgit v1.2.3-24-g4f1b