[Phplib-commit] CVS: php-lib/php/session session4.inc,1.14,1.15
Brought to you by:
nhruby,
richardarcher
From: Maxim D. <md...@us...> - 2002-11-26 17:40:01
|
Update of /cvsroot/phplib/php-lib/php/session In directory sc8-pr-cvs1:/tmp/cvs-serv32331 Modified Files: session4.inc Log Message: 1. Merged with -stable 2. some performance tweaks 3. added session forgery check - see in start() (needs testing) Index: session4.inc =================================================================== RCS file: /cvsroot/phplib/php-lib/php/session/session4.inc,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** session4.inc 29 Aug 2001 07:26:44 -0000 1.14 --- session4.inc 26 Nov 2002 17:39:57 -0000 1.15 *************** *** 95,103 **** /** * * @var string * @deprec $Id$ */ ! var $fallback_mode; --- 95,120 ---- /** + * Propagation mode is by default set to cookie + * The other parameter, fallback_mode, decides wether + * we accept ONLY cookies, or cookies and eventually get params + * in php4 parlance, these variables cause a setting of either + * the php.ini directive session.use_cookie or session.use_only_cookie + * The session.use_only_cookie possibility was introdiced in PHP 4.2.2, and + * has no effect on previous versions * * @var string * @deprec $Id$ */ ! var $mode = "cookie"; ## We propagate session IDs with cookies ! ! /** ! * If fallback_mode is set to 'cookie', php4 will impose a cookie-only ! * propagation policy, which is a safer propagation method that get mode ! * ! * @var string ! * @deprec $Id$ ! */ ! var $fallback_mode; ## if fallback_mode is also 'ccokie' ! ## we enforce session.use_only_cookie *************** *** 123,126 **** --- 140,162 ---- var $allowcache = 'nocache'; + + /** + * Do we need session forgery check? + * This check prevents from exploiting SID-in-request vulnerability. + * We check the user's last IP, and start a new session if the user + * has no cookie with the SID, and the IP has changed during the session. + * We also start a new session with the new id, if the session does not exists yet. + * We don't check cookie-enabled clients. + * @var boolean + */ + var $forgery_check_enabled = true; + + /** + * the name of the variable to hold the IP of the session + * @see $forgery_check_enabled + * @var string + */ + var $session_ip = '__session_ip'; + /** *************** *** 133,136 **** --- 169,175 ---- function Session() { $this->name($this->name); + + // find out the register_globals setting + $this->register_globals = (bool) ini_get('register_globals'); } // end constructor *************** *** 143,146 **** --- 182,190 ---- */ function start() { + + if ( $this->mode=="cookie" + && $this->fallback_mode=="cookie") { + ini_set ("session.use_only_cookies","1"); + } $this->set_tokenname(); *************** *** 149,153 **** $ok = session_start(); $this->id = session_id(); ! return $ok; } // end func start --- 193,268 ---- $ok = session_start(); $this->id = session_id(); ! ! if($this->forgery_check_enabled && $this->session_ip) { ! $sess_forged = false; ! $mysid = $this->name.'='.$this->id; ! ! // use old-style request vars. Maybe should be new-style $_* vars already? ! global $HTTP_COOKIE_VARS, $HTTP_SERVER_VARS, $HTTP_POST_VARS, $HTTP_SESSION_VARS; ! ! // check cookies first. ! if(!isset($HTTP_COOKIE_VARS[$this->name]) ! && (strpos($HTTP_SERVER_VARS['REQUEST_URI'],$mysid) || $HTTP_POST_VARS[$this->name])) ! { ! if(isset($HTTP_SESSION_VARS[$this->session_ip]) ! && $HTTP_SESSION_VARS[$this->session_ip] <> $HTTP_SERVER_VARS['REMOTE_ADDR']) ! { ! // we have no session cookie, a SID in the request, ! // the session exists, but the saved IP is ! $sess_forged = true; ! session_write_close(); ! ! } elseif (!isset($HTTP_SESSION_VARS[$this->session_ip])) ! { ! // session does not exist. ! $sess_forged = true; ! session_destroy(); ! } ! } ! if ($sess_forged) { ! /* we redirect only if SID in the path part of the URL, ! to make sure they'll never hit again. ! We don't redirect when SID is in QUERY_STRING only, ! cause it will disappear with the next request ! */ ! if(strpos($_SERVER['PHP_SELF'], $mysid)) { ! // cut session info from PHP_SELF ! $new_qs = 'http://'.$_SERVER['SERVER_NAME'] ! . str_replace($mysid, '', $_SERVER['PHP_SELF']) ! .(($_SERVER['QUERY_STRING']) ! // and QUERY_STRING, for sure ! ? '?'.str_replace($mysid, '', $_SERVER['QUERY_STRING']) ! : ''); ! ! // clear new cookie, if set ! $cprm = session_get_cookie_params(); ! setcookie($sname, '', time() - 3600, $cprm['path'], $cprm['domain'], $cprm['secure']); ! header('Location: '.$new_qs); ! exit(); ! } ! ! // maybe should seed better? ! $this->id(md5(uniqid(rand()))); ! $ok = session_start(); ! } ! } ! ! // If register_globals is off -> restore session variables to global scope ! if(!$this->register_globals) { ! if(is_array($_SESSION)) { ! foreach ($_SESSION as $key => $value) { ! $GLOBALS[$key] = $value; ! } ! } ! } ! ! if($this->forgery_check_enabled && $this->session_ip) { ! // save current IP ! $GLOBALS[$this->session_ip] = $HTTP_SERVER_VARS['REMOTE_ADDR']; ! if(!$this->is_registered($this->session_ip)) { ! $this->register($this->session_ip); ! } ! } ! return $ok; } // end func start *************** *** 222,238 **** * @param mixed String with the name of one or more variables seperated by comma * or a list of variables names: "foo"/"foo,bar,baz"/{"foo","bar","baz"} - * @return boolean false if registration failed, true on success. * @access public */ function register ($var_names) { if (!is_array($var_names)) { - // spaces spoil everything $var_names = trim($var_names); ! return session_register( preg_split('/\s*,\s*/', $var_names) ); ! } ! return session_register($var_names); } // end func register --- 337,360 ---- * @param mixed String with the name of one or more variables seperated by comma * or a list of variables names: "foo"/"foo,bar,baz"/{"foo","bar","baz"} * @access public */ function register ($var_names) { if (!is_array($var_names)) { // spaces spoil everything $var_names = trim($var_names); ! $var_names=explode(",", $var_names); } ! // If register_globals is off -> store session variables values ! if(!$this->register_globals) { ! foreach ($var_names as $key => $value ) { ! if (!isset($_SESSION[$value])){ ! $_SESSION[$value]= $GLOBALS[$value]; ! } ! } ! } ! else { ! return session_register($var_names); ! } } // end func register *************** *** 245,252 **** */ function is_registered ($var_name) { ! $var_name = trim($var_name); // to be sure ! return session_is_registered($var_name); } // end func is_registered /** --- 367,379 ---- */ function is_registered ($var_name) { ! $var_name = trim($var_name); // to be sure ! if(!$this->register_globals) { ! return isset($_SESSION[$var_name]); ! } else { ! return session_is_registered($var_name); ! } } // end func is_registered + /** *************** *** 255,266 **** * @param mixed String with the name of one or more variables seperated by comma * or a list of variables names: "foo"/"foo,bar,baz"/{"foo","bar","baz"} - * @return boolean false if any error, true on success. * @access public */ function unregister ($var_names) { $ok = true; foreach (explode (',', $var_names) as $var_name) { ! $ok = $ok && session_unregister ( trim($var_name) ); } --- 382,399 ---- * @param mixed String with the name of one or more variables seperated by comma * or a list of variables names: "foo"/"foo,bar,baz"/{"foo","bar","baz"} * @access public */ + function unregister ($var_names) { $ok = true; + foreach (explode (',', $var_names) as $var_name) { ! $var_name=trim($var_name); ! if(!$this->register_globals) { ! unset($_SESSION[$var_name]); ## unset is no more a function in php4 ! } else { ! $ok = $ok && session_unregister ($var_name); ! } } *************** *** 331,337 **** // Remove existing session info from url $url = ereg_replace( ! "([&?])".quotemeta(urlencode($this->name))."=".$this->id."(&|$)", ! "\\1", $url); ! // Remove trailing ?/& if needed $url = ereg_replace("[&?]+$", "", $url); --- 464,468 ---- // Remove existing session info from url $url = ereg_replace( ! "([&?])".quotemeta(urlencode($this->name))."=(.)*(&|$)","\\1", $url); # we clean any(also bogus) sess in url // Remove trailing ?/& if needed $url = ereg_replace("[&?]+$", "", $url); *************** *** 369,373 **** */ function self_url() { ! return $this->url(getenv('REQUEST_URI')); } // end func self_url --- 500,509 ---- */ function self_url() { ! global $HTTP_SERVER_VARS; ! ! return $this->url($HTTP_SERVER_VARS["PHP_SELF"] . ! ((isset($HTTP_SERVER_VARS["QUERY_STRING"]) && ("" != $HTTP_SERVER_VARS["QUERY_STRING"])) ! ? "?" . $HTTP_SERVER_VARS["QUERY_STRING"] : "")); ! # return $this->url(getenv('REQUEST_URI')); } // end func self_url *************** *** 478,481 **** --- 614,637 ---- return session_decode($data_string); } // end func deserialize + + /** + * freezes all registered things ( scalar variables, arrays, objects ) + * by saving all registered things to $_SESSION. + * + * @access public + * + * + */ + function freeze() { + // If register_globals is off -> store session variables values + if(!$this->register_globals) { + reset($_SESSION); + + while(list($key,) = each($_SESSION)) { + // foreach ($_SESSION as $key => $value) { + $_SESSION[$key] = $GLOBALS[$key]; + } + } + } /** |