| 
<?php/**
 * Perform security checks on the session requests
 * You may want to fine tune the network validation routines here
 * e.g. being more specific for LAN traffic, less for mobile
 */
 /**
 * note that we need to store data inside the session, and that means we need
 * to use a serialization method accessible from the PHP code
 * and *that* means we need at least v5.5.4
 */
 
 if (version_compare(PHP_VERSION, '5.5.4') >=0) {
 ini_set('session.serialize_handler', 'php_serialize');
 } else {
 trigger_error("Security session handler requires PHP 5.5.4 or later", E_USER_ERROR);
 }
 
 class securitySession extends stackSess {
 function open($save_path, $name)
 {
 if ($this->shStackNext) {
 return $this->shStackNext->open($save_path, $name);
 } else {
 trigger_error("Security session handler has no storage capability", E_USER_ERROR);
 return false;
 }
 }
 function read($session_id)
 {
 // we don't allow an expired session to be read
 if ($this->shStackNext) {
 $session_str=$this->shStackNext->read($session_id);
 // above required to populate lastAccess...
 $lastAccess=$this->shStackNext->lastAccessed();
 $max_ttl=ini_get('session.cookie_lifetime');
 if ($max_ttl && time()-$lastAccess>$lastAccess) {
 $this->logit("Session accessed after expiry", E_USER_NOTICE);
 $this->destroy($session_id);
 return '';
 }
 $session_sr=$this->securityCheck($session_id, $session_str);
 return $session_str;
 }
 return false;
 }
 function create_sid($newlyCreatedSid=false)
 {
 if (is_callable(array($this->shStackNext,'create_sid'))) {
 // we always send down the stack
 $newlyCreatedSid=$this->shStackNext->create_sid($newlyCreatedSid);
 }
 return $newlyCreatedSid;
 }
 function securityCheck($session_id, $session_str)
 {
 $sess=unserialize($session_str);
 if (!isset($sess['securityCheck'])) {
 // data is not yet populated - populate now
 $sess['securityCheck']=array(
 'user_agent'=>$_SERVER['HTTP_USER_AGENT'],
 'c_ip'=>$_SERVER["REMOTE_ADDR"]
 );
 return serialize($sess);
 }
 $stored_ua=get_browser($sess['securityCheck']['user_agent'], true);
 $current_ua=get_browser(null, true);
 if ($stored_ua['platform'] != $current_ua['platform']
 || $stored_ua['parent'] != $current_ua['parent']) {
 $this->logit("Details changed mid session " . var_export($sess['securityCheck'],true), E_USER_NOTICE);
 return false;
 }
 if (!$this->compareIP($sess['securityCheck']['c_ip'], $_SERVER["REMOTE_ADDR"])) {
 $this->logit("Client network changed from $sess[securityCheck][c_ip]", E_USER_NOTICE);
 return false;
 }
 return $session_str;
 }
 // if you don't get an exact match, you might want to
 // compare netmasks, or the Organisation in the whois, or the ASN
 function compareIP($ip1, $ip2)
 {
 if ($ip1==$ip2 || !$ip1 || !$ip2) {
 return true;
 }
 }
 }
 
 |