diff --git a/classes/mobile/Mobile.class.php b/classes/mobile/Mobile.class.php index e6bad61ce..ab5135018 100644 --- a/classes/mobile/Mobile.class.php +++ b/classes/mobile/Mobile.class.php @@ -73,7 +73,7 @@ class Mobile $uatype = $uahash . ':' . (self::$_ismobile ? '1' : '0'); if ($cookie !== $uatype) { - setcookie('rx_uatype', $uatype, 0, RX_BASEURL); + setcookie('rx_uatype', $uatype, 0, RX_BASEURL, Rhymix\Framework\Session::getDomain()); $_COOKIE['rx_uatype'] = $uatype; } diff --git a/common/framework/session.php b/common/framework/session.php index 584a87187..2a78f1118 100644 --- a/common/framework/session.php +++ b/common/framework/session.php @@ -10,6 +10,8 @@ class Session /** * Properties for internal use only. */ + protected static $_domain = false; + protected static $_subdomain = false; protected static $_started = false; protected static $_autologin_key = false; protected static $_member_info = false; @@ -758,6 +760,48 @@ class Session $_SESSION['RHYMIX']['timezone'] = $timezone; } + /** + * Get session domain. + * + * @return string + */ + public static function getDomain() + { + if (self::$_domain || (self::$_domain = Config::get('session.domain'))) + { + return self::$_domain; + } + else + { + self::$_domain = ini_get('session.cookie_domain') ?: preg_replace('/:\\d+$/', '', strtolower($_SERVER['HTTP_HOST'])); + if (!strncmp(self::$_domain, 'www.', 4)) + { + self::$_subdomain = self::$_domain; + self::$_domain = substr(self::$_domain, 4); + } + return self::$_domain; + } + } + + /** + * Set session domain. + * + * @return bool + */ + public static function setDomain($domain) + { + if (self::$_started) + { + return false; + } + else + { + self::$_domain = $domain; + self::$_subdomain = false; + return true; + } + } + /** * Mark the current session as trusted for a given duration. * @@ -930,7 +974,7 @@ class Session { $lifetime = Config::get('session.lifetime'); $refresh = Config::get('session.refresh') ?: 300; - $domain = Config::get('session.domain') ?: (ini_get('session.cookie_domain') ?: preg_replace('/:\\d+$/', '', $_SERVER['HTTP_HOST'])); + $domain = self::getDomain(); $path = Config::get('session.path') ?: ini_get('session.cookie_path'); return array($lifetime, $refresh, $domain, $path); } @@ -996,6 +1040,15 @@ class Session $_COOKIE['rx_sesskey2'] = $_SESSION['RHYMIX']['keys'][$domain]['key2']; } + // Delete keys from subdomain. + if (self::$_subdomain && !isset($_SESSION['RHYMIX']['keys'][self::$_subdomain]['deleted'])) + { + setcookie(session_name(), session_id(), $lifetime, $path, $domain, false, false); + setcookie(session_name(), 'deleted', time() - 86400, $path, self::$_subdomain, false, false); + setcookie('rx_sesskey1', 'deleted', time() - 86400, $path, self::$_subdomain, false, false); + setcookie('rx_sesskey2', 'deleted', time() - 86400, $path, self::$_subdomain, false, false); + $_SESSION['RHYMIX']['keys'][self::$_subdomain]['deleted'] = true; + } return true; } diff --git a/tests/unit/framework/SessionTest.php b/tests/unit/framework/SessionTest.php index 0348ecb7a..749fb3246 100644 --- a/tests/unit/framework/SessionTest.php +++ b/tests/unit/framework/SessionTest.php @@ -48,9 +48,11 @@ class SessionTest extends \Codeception\TestCase\Test $this->assertTrue(isset($_COOKIE['rx_sesskey1'])); $this->assertTrue(isset($_COOKIE['rx_sesskey2'])); $this->assertNotEmpty($_SESSION['RHYMIX']['secret']); - $this->assertEquals($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1'], $_COOKIE['rx_sesskey1']); - $this->assertEquals($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2'], $_COOKIE['rx_sesskey2']); - $this->assertEquals(0, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted']); + $this->assertEquals($_SESSION['RHYMIX']['keys']['rhymix.org']['key1'], $_COOKIE['rx_sesskey1']); + $this->assertEquals($_SESSION['RHYMIX']['keys']['rhymix.org']['key2'], $_COOKIE['rx_sesskey2']); + $this->assertEquals(0, $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted']); + $this->assertFalse(isset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['started'])); + $this->assertTrue(isset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['deleted'])); $session_secret = $_SESSION['RHYMIX']['secret']; Rhymix\Framework\Session::close(); @@ -90,7 +92,7 @@ class SessionTest extends \Codeception\TestCase\Test // Test initial transition from HTTP to HTTPS. session_start(); - unset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']); + unset($_SESSION['RHYMIX']['keys']['rhymix.org']['key2']); unset($_COOKIE['rx_sesskey2']); session_write_close(); $this->assertTrue(@Rhymix\Framework\Session::start()); @@ -139,17 +141,17 @@ class SessionTest extends \Codeception\TestCase\Test { @Rhymix\Framework\Session::start(); $session_secret = $_SESSION['RHYMIX']['secret']; - $key1 = $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1']; - $key2 = $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']; - $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1_time'] = time() - 3600; - $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2_time'] = time() - 3600; + $key1 = $_SESSION['RHYMIX']['keys']['rhymix.org']['key1']; + $key2 = $_SESSION['RHYMIX']['keys']['rhymix.org']['key2']; + $_SESSION['RHYMIX']['keys']['rhymix.org']['key1_time'] = time() - 3600; + $_SESSION['RHYMIX']['keys']['rhymix.org']['key2_time'] = time() - 3600; Rhymix\Framework\Session::close(); @Rhymix\Framework\Session::start(); - $this->assertNotEquals($key1, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1']); - $this->assertNotEquals($key2, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']); - $this->assertEquals($key1, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1_prev']); - $this->assertEquals($key2, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2_prev']); + $this->assertNotEquals($key1, $_SESSION['RHYMIX']['keys']['rhymix.org']['key1']); + $this->assertNotEquals($key2, $_SESSION['RHYMIX']['keys']['rhymix.org']['key2']); + $this->assertEquals($key1, $_SESSION['RHYMIX']['keys']['rhymix.org']['key1_prev']); + $this->assertEquals($key2, $_SESSION['RHYMIX']['keys']['rhymix.org']['key2_prev']); $this->assertEquals($session_secret, $_SESSION['RHYMIX']['secret']); Rhymix\Framework\Session::close(); } @@ -231,9 +233,9 @@ class SessionTest extends \Codeception\TestCase\Test { @Rhymix\Framework\Session::start(); - $_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted'] = 0; + $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted'] = 0; $this->assertFalse(Rhymix\Framework\Session::isTrusted()); - $_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted'] = time() + 300; + $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted'] = time() + 300; $this->assertTrue(Rhymix\Framework\Session::isTrusted()); Rhymix\Framework\Session::close();