diff options
Diffstat (limited to 'system/libraries/Session')
-rw-r--r-- | system/libraries/Session/Session.php | 82 | ||||
-rw-r--r-- | system/libraries/Session/drivers/Session_files_driver.php | 45 |
2 files changed, 119 insertions, 8 deletions
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index 3b391a8ef..01989d2d7 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,82 @@ 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); + + $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) + { + $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); + $bits = 160; + } + elseif (($bits = strlen(hash($hash_function, 'dummy', false)) * 4) < 160) + { + ini_set('session.hash_function', 1); + $bits = 160; + } + + $bits_per_character = (int) ini_get('session.hash_bits_per_character'); + $sid_length = (int) ceil($bits / $bits_per_character); + } + else + { + $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]'; + break; + case 5: + $this->_sid_regexp = '[0-9a-v]'; + break; + case 6: + $this->_sid_regexp = '[0-9a-zA-Z,-]'; + break; + } + + $this->_sid_regexp .= '{'.$sid_length.'}'; } // ------------------------------------------------------------------------ diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php index bf4df8b20..37315d3cd 100644 --- a/system/libraries/Session/drivers/Session_files_driver.php +++ b/system/libraries/Session/drivers/Session_files_driver.php @@ -76,6 +76,20 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle */ protected $_file_new; + /** + * Validate SID regular expression + * + * @var string + */ + protected $_sid_regexp; + + /** + * mbstring.func_override flag + * + * @var bool + */ + protected static $func_override; + // ------------------------------------------------------------------------ /** @@ -98,6 +112,10 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle log_message('debug', 'Session: "sess_save_path" is empty; using "session.save_path" value from php.ini.'); $this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\'); } + + $this->_sid_regexp = $this->_config['_sid_regexp']; + + isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override')); } // ------------------------------------------------------------------------ @@ -187,7 +205,7 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle } $session_data = ''; - for ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += strlen($buffer)) + for ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += self::strlen($buffer)) { if (($buffer = fread($this->_file_handle, $length - $read)) === FALSE) { @@ -343,10 +361,13 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle $ts = time() - $maxlifetime; + $pattern = ($this->_config['match_ip'] === TRUE) + ? '[0-9a-f]{32}' + : ''; + $pattern = sprintf( - '/^%s[0-9a-f]{%d}$/', - preg_quote($this->_config['cookie_name'], '/'), - ($this->_config['match_ip'] === TRUE ? 72 : 40) + '#\A%s'.$pattern.$this->_sid_regexp.'\z#', + preg_quote($this->_config['cookie_name']) ); while (($file = readdir($directory)) !== FALSE) @@ -368,4 +389,18 @@ class CI_Session_files_driver extends CI_Session_driver implements SessionHandle return $this->_success; } -}
\ No newline at end of file + // -------------------------------------------------------------------- + + /** + * Byte-safe strlen() + * + * @param string $str + * @return int + */ + protected static function strlen($str) + { + return (self::$func_override) + ? mb_strlen($str, '8bit') + : strlen($str); + } +} |