diff --git a/bl-kernel/boot/admin.php b/bl-kernel/boot/admin.php index df699720..308ca44e 100644 --- a/bl-kernel/boot/admin.php +++ b/bl-kernel/boot/admin.php @@ -2,8 +2,8 @@ // Start the session // If the session is not started the admin area is not available -Session::start(); -if (Session::started()===false) { +Session::start($site->urlPath(), $site->isHTTPS()); +if (!Session::started()) { exit('Bludit CMS. Session initialization failed.'); } diff --git a/bl-kernel/helpers/session.class.php b/bl-kernel/helpers/session.class.php index 993c340e..a0ee0cd3 100644 --- a/bl-kernel/helpers/session.class.php +++ b/bl-kernel/helpers/session.class.php @@ -2,82 +2,78 @@ class Session { - private static $started = false; - private static $sessionName = 'BLUDIT-KEY'; + private static $started = false; + private static $sessionName = 'BLUDIT-KEY'; - public static function start() - { - // Try to set the session timeout on server side, 1 hour of timeout - ini_set('session.gc_maxlifetime', SESSION_GC_MAXLIFETIME); + public static function start($path, $secure) + { + // Try to set the session timeout on server side, 1 hour of timeout + ini_set('session.gc_maxlifetime', SESSION_GC_MAXLIFETIME); - // If TRUE cookie will only be sent over secure connections. - $secure = false; + // Gets current cookies parameters + $cookieParams = session_get_cookie_params(); - // If set to TRUE then PHP will attempt to send the httponly flag when setting the session cookie. - $httponly = true; + if (empty($path)) { + $path = '/'; + } - // Gets current cookies params. - $cookieParams = session_get_cookie_params(); + session_set_cookie_params([ + 'lifetime' => $cookieParams["lifetime"], + 'path' => $path, + 'domain' => $cookieParams["domain"], + 'secure' => $secure, + 'httponly' => true, + 'samesite' => 'Lax' + ]); - session_set_cookie_params( - SESSION_COOKIE_LIFE_TIME, - $cookieParams["path"], - $cookieParams["domain"], - $secure, - $httponly - ); + // Sets the session name + session_name(self::$sessionName); - // Sets the session name to the one set above. - session_name(self::$sessionName); + // Start session + self::$started = session_start(); - // Start session. - self::$started = session_start(); + if (!self::$started) { + Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to start the session.'); + } + } - // Regenerated the session, delete the old one. There are problems with AJAX. - //session_regenerate_id(true); + public static function started() + { + return self::$started; + } - if (!self::$started) { - Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to start the session.'); - } - } + public static function destroy() + { + session_destroy(); + unset($_SESSION); + unset($_COOKIE[self::$sessionName]); + Cookie::set(self::$sessionName, '', -1); + self::$started = false; + Log::set(__METHOD__.LOG_SEP.'Session destroyed.'); + return !isset($_SESSION); + } - public static function started() - { - return self::$started; - } + public static function set($key, $value) + { + $key = 's_'.$key; - public static function destroy() - { - session_destroy(); - unset($_SESSION); - unset($_COOKIE[self::$sessionName]); - Cookie::set(self::$sessionName, '', -1); - self::$started = false; - Log::set(__METHOD__.LOG_SEP.'Session destroyed.'); - return !isset($_SESSION); - } + $_SESSION[$key] = $value; + } - public static function set($key, $value) - { - $key = 's_'.$key; + public static function get($key) + { + $key = 's_'.$key; - $_SESSION[$key] = $value; - } + if (isset($_SESSION[$key])) { + return $_SESSION[$key]; + } + return false; + } - public static function get($key) - { - $key = 's_'.$key; + public static function remove($key) + { + $key = 's_'.$key; - if (isset($_SESSION[$key])) { - return $_SESSION[$key]; - } - return false; - } - - public static function remove($key) - { - $key = 's_'.$key; - - unset($_SESSION[$key]); - } + unset($_SESSION[$key]); + } } diff --git a/bl-kernel/login.class.php b/bl-kernel/login.class.php index f636f6e1..7d9352ad 100644 --- a/bl-kernel/login.class.php +++ b/bl-kernel/login.class.php @@ -2,180 +2,187 @@ class Login { - protected $users; + protected $users; + protected $site; - function __construct() - { - if (isset($GLOBALS['users'])) { - $this->users = $GLOBALS['users']; - } else { - $this->users = new Users(); - } + function __construct() + { + if (isset($GLOBALS['users'])) { + $this->users = $GLOBALS['users']; + } else { + $this->users = new Users(); + } - // Start the Session - if (!Session::started()) { - Session::start(); - } - } + if (isset($GLOBALS['site'])) { + $this->site = $GLOBALS['site']; + } else { + $this->site = new Site(); + } - // Returns the username - public function username() - { - return Session::get('username'); - } + // Start the Session + if (!Session::started()) { + Session::start($this->site->urlPath(), $this->site->isHTTPS()); + } + } - // Returns the role - public function role() - { - return Session::get('role'); - } + // Returns the username + public function username() + { + return Session::get('username'); + } - // Returns the authentication token - public function tokenAuth() - { - return Session::get('tokenAuth'); - } + // Returns the role + public function role() + { + return Session::get('role'); + } - // Returns TRUE if the user is logged, FALSE otherwise - public function isLogged() - { - if (Session::get('fingerPrint')===$this->fingerPrint()) { - $username = Session::get('username'); - if (!empty($username)) { - return true; - } else { - Log::set(__METHOD__.LOG_SEP.'Session username empty, destroying the session.'); - Session::destroy(); - return false; - } - } + // Returns the authentication token + public function tokenAuth() + { + return Session::get('tokenAuth'); + } - Log::set(__METHOD__.LOG_SEP.'FingerPrints are different. ['.Session::get('fingerPrint').'] != ['.$this->fingerPrint().']'); - return false; - } + // Returns TRUE if the user is logged, FALSE otherwise + public function isLogged() + { + if (Session::get('fingerPrint')===$this->fingerPrint()) { + $username = Session::get('username'); + if (!empty($username)) { + return true; + } else { + Log::set(__METHOD__.LOG_SEP.'Session username empty, destroying the session.'); + Session::destroy(); + return false; + } + } - // Set the session for the user logged - public function setLogin($username, $role, $tokenAuth) - { - Session::set('username', $username); - Session::set('role', $role); - Session::set('tokenAuth', $tokenAuth); - Session::set('fingerPrint', $this->fingerPrint()); - Session::set('sessionTime', time()); + Log::set(__METHOD__.LOG_SEP.'FingerPrints are different. ['.Session::get('fingerPrint').'] != ['.$this->fingerPrint().']'); + return false; + } - Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint ['.$this->fingerPrint().']'); - } + // Set the session for the user logged + public function setLogin($username, $role, $tokenAuth) + { + Session::set('username', $username); + Session::set('role', $role); + Session::set('tokenAuth', $tokenAuth); + Session::set('fingerPrint', $this->fingerPrint()); + Session::set('sessionTime', time()); - public function setRememberMe($username) - { - $username = Sanitize::html($username); + Log::set(__METHOD__.LOG_SEP.'User logged, fingerprint ['.$this->fingerPrint().']'); + } - // Set the token on the users database - $token = $this->users->generateRememberToken(); - $this->users->setRememberToken($username, $token); + public function setRememberMe($username) + { + $username = Sanitize::html($username); - // Set the token on the cookies - Cookie::set(REMEMBER_COOKIE_USERNAME, $username, REMEMBER_COOKIE_EXPIRE_IN_DAYS); - Cookie::set(REMEMBER_COOKIE_TOKEN, $token, REMEMBER_COOKIE_EXPIRE_IN_DAYS); + // Set the token on the users database + $token = $this->users->generateRememberToken(); + $this->users->setRememberToken($username, $token); - Log::set(__METHOD__.LOG_SEP.'Cookies set for Remember Me.'); - } + // Set the token on the cookies + Cookie::set(REMEMBER_COOKIE_USERNAME, $username, REMEMBER_COOKIE_EXPIRE_IN_DAYS); + Cookie::set(REMEMBER_COOKIE_TOKEN, $token, REMEMBER_COOKIE_EXPIRE_IN_DAYS); - public function invalidateRememberMe() - { - // Invalidate all tokens on the user databases - $this->users->invalidateAllRememberTokens(); + Log::set(__METHOD__.LOG_SEP.'Cookies set for Remember Me.'); + } - // Destroy the cookies - Cookie::set(REMEMBER_COOKIE_USERNAME, '', -1); - Cookie::set(REMEMBER_COOKIE_TOKEN, '', -1); - unset($_COOKIE[REMEMBER_COOKIE_USERNAME]); - unset($_COOKIE[REMEMBER_COOKIE_TOKEN]); - } + public function invalidateRememberMe() + { + // Invalidate all tokens on the user databases + $this->users->invalidateAllRememberTokens(); - // Check if the username and the password are valid - // Returns TRUE if valid and set the session - // Returns FALSE for invalid username or password - public function verifyUser($username, $password) - { - $username = Sanitize::html($username); - $username = trim($username); + // Destroy the cookies + Cookie::set(REMEMBER_COOKIE_USERNAME, '', -1); + Cookie::set(REMEMBER_COOKIE_TOKEN, '', -1); + unset($_COOKIE[REMEMBER_COOKIE_USERNAME]); + unset($_COOKIE[REMEMBER_COOKIE_TOKEN]); + } - if (empty($username) || empty($password)) { - Log::set(__METHOD__.LOG_SEP.'Username or password empty. Username: '.$username); - return false; - } + // Check if the username and the password are valid + // Returns TRUE if valid and set the session + // Returns FALSE for invalid username or password + public function verifyUser($username, $password) + { + $username = Sanitize::html($username); + $username = trim($username); - if (Text::length($password)<PASSWORD_LENGTH) { - Log::set(__METHOD__.LOG_SEP.'Password length is shorter than required.'); - return false; - } + if (empty($username) || empty($password)) { + Log::set(__METHOD__.LOG_SEP.'Username or password empty. Username: '.$username); + return false; + } - try { - $user = new User($username); - } catch (Exception $e) { - return false; - } + if (Text::length($password)<PASSWORD_LENGTH) { + Log::set(__METHOD__.LOG_SEP.'Password length is shorter than required.'); + return false; + } - $passwordHash = $this->users->generatePasswordHash($password, $user->salt()); - if ($passwordHash===$user->password()) { - $this->setLogin($username, $user->role(), $user->tokenAuth()); - Log::set(__METHOD__.LOG_SEP.'Successful user login by username and password - Username ['.$username.']'); - return true; - } + try { + $user = new User($username); + } catch (Exception $e) { + return false; + } - Log::set(__METHOD__.LOG_SEP.'Password incorrect.'); - return false; - } + $passwordHash = $this->users->generatePasswordHash($password, $user->salt()); + if ($passwordHash===$user->password()) { + $this->setLogin($username, $user->role(), $user->tokenAuth()); + Log::set(__METHOD__.LOG_SEP.'Successful user login by username and password - Username ['.$username.']'); + return true; + } - // Check if the user has the cookies and the correct token - public function verifyUserByRemember() - { - if (Cookie::isEmpty(REMEMBER_COOKIE_USERNAME) || Cookie::isEmpty(REMEMBER_COOKIE_TOKEN)) { - return false; - } + Log::set(__METHOD__.LOG_SEP.'Password incorrect.'); + return false; + } - $username = Cookie::get(REMEMBER_COOKIE_USERNAME); - $token = Cookie::get(REMEMBER_COOKIE_TOKEN); + // Check if the user has the cookies and the correct token + public function verifyUserByRemember() + { + if (Cookie::isEmpty(REMEMBER_COOKIE_USERNAME) || Cookie::isEmpty(REMEMBER_COOKIE_TOKEN)) { + return false; + } - $username = Sanitize::html($username); - $token = Sanitize::html($token); + $username = Cookie::get(REMEMBER_COOKIE_USERNAME); + $token = Cookie::get(REMEMBER_COOKIE_TOKEN); - $username = trim($username); - $token = trim($token); + $username = Sanitize::html($username); + $token = Sanitize::html($token); - if (empty($username) || empty($token)) { - $this->invalidateRememberMe(); - Log::set(__METHOD__.LOG_SEP.'Username or Token empty. Username: '.$username.' - Token: '.$token); - return false; - } + $username = trim($username); + $token = trim($token); - if ($username !== $this->users->getByRememberToken($token)) { - $this->invalidateRememberMe(); - Log::set(__METHOD__.LOG_SEP.'The user has different token or the token doesn\'t exist.'); - return false; - } + if (empty($username) || empty($token)) { + $this->invalidateRememberMe(); + Log::set(__METHOD__.LOG_SEP.'Username or Token empty. Username: '.$username.' - Token: '.$token); + return false; + } - // Get user from database and login - $user = $this->users->getUserDB($username); - $this->setLogin($username, $user['role'], $user->tokenAuth()); - Log::set(__METHOD__.LOG_SEP.'User authenticated via Remember Me.'); - return true; - } + if ($username !== $this->users->getByRememberToken($token)) { + $this->invalidateRememberMe(); + Log::set(__METHOD__.LOG_SEP.'The user has different token or the token doesn\'t exist.'); + return false; + } - public function fingerPrint() - { - $agent = getenv('HTTP_USER_AGENT'); - if (empty($agent)) { - $agent = 'Bludit/2.0 (Mr Nibbler Protocol)'; - } - return sha1($agent); - } + // Get user from database and login + $user = $this->users->getUserDB($username); + $this->setLogin($username, $user['role'], $user->tokenAuth()); + Log::set(__METHOD__.LOG_SEP.'User authenticated via Remember Me.'); + return true; + } - public function logout() - { - $this->invalidateRememberMe(); - Session::destroy(); - return true; - } + public function fingerPrint() + { + $agent = getenv('HTTP_USER_AGENT'); + if (empty($agent)) { + $agent = 'Bludit/2.0 (Mr Nibbler Protocol)'; + } + return sha1($agent); + } + + public function logout() + { + $this->invalidateRememberMe(); + Session::destroy(); + return true; + } } \ No newline at end of file diff --git a/bl-kernel/site.class.php b/bl-kernel/site.class.php index 0e947363..f0006cb7 100644 --- a/bl-kernel/site.class.php +++ b/bl-kernel/site.class.php @@ -332,6 +332,19 @@ class Site extends dbJSON return $this->getField('url'); } + + public function urlPath() + { + $url = $this->getField('url'); + return parse_url($url, PHP_URL_PATH); + } + + public function isHTTPS() + { + $url = $this->getField('url'); + return parse_url($url, PHP_URL_SCHEME) === 'https'; + } + // Returns the protocol and the domain, without the base url // For example, http://www.domain.com public function domain()