summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--inc/menu.inc.php10
-rw-r--r--inc/message.inc.php29
-rw-r--r--inc/session.inc.php123
-rw-r--r--inc/user.inc.php26
-rw-r--r--inc/util.inc.php10
-rw-r--r--index.php3
-rw-r--r--modules/main.inc.php2
-rw-r--r--modules/session.inc.php17
-rw-r--r--templates/menu-logout.html2
10 files changed, 153 insertions, 70 deletions
diff --git a/.gitignore b/.gitignore
index fbff2634..b351b9d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*~
*.bak
*.tmp
+*.swp
diff --git a/inc/menu.inc.php b/inc/menu.inc.php
index 7b2502b9..90bc4ebd 100644
--- a/inc/menu.inc.php
+++ b/inc/menu.inc.php
@@ -9,12 +9,10 @@ class Menu
public function loginPanel()
{
if (User::getName() === false) return Render::parse('menu-login');
- return Render::parse('menu-logout', array('user' => User::getName()));
- }
-
- public function token()
- {
- return 123;
+ return Render::parse('menu-logout', array(
+ 'user' => User::getName(),
+ 'token' => Session::get('token')
+ ));
}
}
diff --git a/inc/message.inc.php b/inc/message.inc.php
new file mode 100644
index 00000000..9409db95
--- /dev/null
+++ b/inc/message.inc.php
@@ -0,0 +1,29 @@
+<?php
+
+// TODO: Move to extra file
+$error_text = array(
+ 'loginfail' => 'Benutzername oder Kennwort falsch',
+ 'token' => 'Ungültiges Token. CSRF Angriff?',
+);
+
+class Message
+{
+ private static $list = array();
+
+ public static function addError($id)
+ {
+ self::$list[] = array(
+ 'type' => 'error',
+ 'id' => $id
+ );
+ }
+
+ public static function renderList()
+ {
+ foreach (self::$list as $item) {
+ Render::addTemplate('messagebox-' . $item['type'], array('message' => $error_text[$item['id']]));
+ }
+ }
+
+}
+
diff --git a/inc/session.inc.php b/inc/session.inc.php
index a62c5cd3..4b4d4139 100644
--- a/inc/session.inc.php
+++ b/inc/session.inc.php
@@ -4,46 +4,101 @@ require_once('config.php');
@mkdir(CONFIG_SESSION_DIR, 0700);
@chmod(CONFIG_SESSION_DIR, 0700);
+if (!is_writable(CONFIG_SESSION_DIR)) die('Config error: Session Path not writable!');
-session_set_save_handler('sh_open', 'sh_close', 'sh_read', 'sh_write', 'sh_destroy', 'sh_gc');
-
-// Pretty much a reimplementation of the default session handler: Plain files
-// Needs to be switched to db later
-
-function sh_open($path, $name)
+class Session
{
- return true;
-}
+ private static $sid = false;
+ private static $data = false;
+
+ private static function generateSessionId()
+ {
+ if (self::$sid !== false) Util::traceError('Error: Asked to generate session id when already set.');
+ self::$sid = sha1(
+ mt_rand(0, 65535)
+ . $_SERVER['REMOTE_ADDR']
+ . mt_rand(0, 65535)
+ . $_SERVER['REMOTE_PORT']
+ . $_SERVER['HTTP_USER_AGENT']
+ . microtime(true)
+ . mt_rand(0, 65535)
+ );
+ }
-function sh_close()
-{
- return true;
-}
+ public static function createSession()
+ {
+ self::generateSessionId();
+ self::$data = array();
+ }
-function sh_read($id)
-{
- return (string)@file_get_contents(CONFIG_SESSION_DIR . '/slx-session-' . $id);
-}
+ public static function loadSession()
+ {
+ // Try to load session id from cookie
+ if (!self::loadSessionId()) return false;
+ // Succeded, now try to load session data. If successful, job is done
+ if (self::readSessionData()) return true;
+ // Loading session data failed
+ self::delete();
+ }
-function sh_write($id, $data)
-{
- return @file_put_contents(CONFIG_SESSION_DIR . '/slx-session-' . $id, $data);
-}
+ public static function get($key)
+ {
+ if (!isset(self::$data[$key])) return false;
+ return self::$data[$key];
+ }
-function sh_destroy($id)
-{
- return @unlink(CONFIG_SESSION_DIR . '/slx-session-' . $id);
-}
+ public static function set($key, $value)
+ {
+ if (self::$data === false) Util::traceError('Tried to set session data with no active session');
+ self::$data[$key] = $value;
+ }
+
+ private static function loadSessionId()
+ {
+ if (self::$sid !== false) die('Error: Asked to load session id when already set.');
+ if (empty($_COOKIE['sid'])) return false;
+ $id = preg_replace('/[^a-zA-Z0-9]/', '', $_COOKIE['sid']);
+ if (empty($id)) return false;
+ self::$sid = $id;
+ return true;
+ }
+
+ public static function delete()
+ {
+ if (self::$sid === false) return;
+ @unlink(self::getSessionFile());
+ @setcookie('sid', '', time() - 8640000, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
+ self::$sid = false;
+ self::$data = false;
+ }
+
+ private static function getSessionFile()
+ {
+ if (self::$sid === false) Util::traceError('Error: Tried to access session file when no session id was set.');
+ return CONFIG_SESSION_DIR . '/' . self::$sid;
+ }
-function sh_gc($maxAgeSeconds)
-{
- $files = @glob(CONFIG_SESSION_DIR . '/slx-session-*');
- if (!is_array($files)) return false;
- foreach ($files as $file) {
- if (filemtime($file) + $maxAgeSeconds < time()) {
- @unlink($file);
- }
- }
- return true;
+ private static function readSessionData()
+ {
+ if (self::$data !== false) Util::traceError('Tried to call read session data twice');
+ $sessionfile = self::getSessionFile();
+ if (!is_readable($sessionfile) || filemtime($sessionfile) + CONFIG_SESSION_TIMEOUT < time()) {
+ @unlink($sessionfile);
+ return false;
+ }
+ self::$data = @unserialize(@file_get_contents($sessionfile));
+ if (self::$data === false) return false;
+ return true;
+ }
+
+ public static function save()
+ {
+ if (self::$sid === false || self::$data === false) return; //Util::traceError('Called saveSession with no active session');
+ $sessionfile = self::getSessionFile();
+ $ret = @file_put_contents($sessionfile, @serialize(self::$data));
+ if (!$ret) Util::traceError('Storing session data in ' . $sessionfile . ' failed.');
+ $ret = @setcookie('sid', self::$sid, time() + CONFIG_SESSION_TIMEOUT, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
+ if (!$ret) Util::traceError('Error: Could not set Cookie for Client (headers already sent)');
+ }
}
diff --git a/inc/user.inc.php b/inc/user.inc.php
index de615932..f10a4f65 100644
--- a/inc/user.inc.php
+++ b/inc/user.inc.php
@@ -5,7 +5,6 @@ require_once('inc/session.inc.php');
class User
{
private static $user = false;
- private static $session = false;
public static function isLoggedIn()
{
@@ -20,14 +19,8 @@ class User
public static function load()
{
- if (isset($_REQUEST['PHPSESSID']) || isset($_COOKIE['PHPSESSID'])) {
- session_start();
- if (!isset($_SESSION['uid']) || !is_numeric($_SESSION['uid'])) {
- self::logout();
- return false;
- }
- // TODO: Query user db for persistent data
- $user['name'] = 'Hans';
+ if (Session::loadSession()) {
+ self::$user['name'] = 'Hans';
return true;
}
return false;
@@ -36,10 +29,10 @@ class User
public static function login($user, $pass)
{
if ($user == 'test' && $pass == 'test') {
- session_start();
- $_SESSION['uid'] = 1;
- $_SESSION['token'] = md5(rand() . time() . rand() . $_SERVER['REMOTE_ADDR'] . rand() . $_SERVER['REMOTE_PORT'] . rand() . $_SERVER['HTTP_USER_AGENT']);
- session_write_close();
+ Session::createSession();;
+ Session::set('uid', 1);
+ Session::set('token', md5(rand() . time() . rand() . $_SERVER['REMOTE_ADDR'] . rand() . $_SERVER['REMOTE_PORT'] . rand() . $_SERVER['HTTP_USER_AGENT']));
+ Session::save();
return true;
}
return false;
@@ -47,11 +40,8 @@ class User
public static function logout()
{
- session_unset();
- session_destroy();
- if (setcookie('PHPSESSID', '', time() - 86400)) {
- Header('Location: ?do=main&fromlogout');
- }
+ Session::delete();
+ Header('Location: ?do=main&fromlogout');
exit(0);
}
diff --git a/inc/util.inc.php b/inc/util.inc.php
index 793902ec..b4a0036e 100644
--- a/inc/util.inc.php
+++ b/inc/util.inc.php
@@ -20,9 +20,17 @@ class Util
public static function redirect($location)
{
- session_write_close();
+ Session::save();
Header('Location: ' . $location);
exit(0);
}
+
+ public static function verifyToken()
+ {
+ if (Session::get('token') === false) return true;
+ if (isset($_REQUEST['token']) && Session::get('token') === $_REQUEST['token']) return true;
+ Message::addError('token');
+ return false;
+ }
}
diff --git a/index.php b/index.php
index 2bf1b17a..ec1f96fd 100644
--- a/index.php
+++ b/index.php
@@ -6,6 +6,7 @@ require_once('inc/user.inc.php');
require_once('inc/render.inc.php');
require_once('inc/menu.inc.php');
require_once('inc/util.inc.php');
+require_once('inc/message.inc.php');
if (empty($_REQUEST['do'])) {
// No specific module - set default
@@ -26,6 +27,8 @@ unset($module);
$menu = new Menu;
Render::addTemplate('main-menu', $menu);
+Message::renderList();
+
render_module();
Render::output();
diff --git a/modules/main.inc.php b/modules/main.inc.php
index ef83f1c4..fc6a9fac 100644
--- a/modules/main.inc.php
+++ b/modules/main.inc.php
@@ -1,5 +1,7 @@
<?php
+User::load();
+
function render_module()
{
Render::setTitle('Wurstgesicht');
diff --git a/modules/session.inc.php b/modules/session.inc.php
index 5b8c5f4d..456ff6b8 100644
--- a/modules/session.inc.php
+++ b/modules/session.inc.php
@@ -14,26 +14,23 @@ if (isset($_POST['action']) && $_POST['action'] === 'login') {
Util::redirect('?do=main');
}
// Login credentials wrong
- Util::redirect('?do=session&action=fail');
+ Message::addError('loginfail');
}
if ($_REQUEST['action'] === 'logout') {
- // Log user out (or do nothing if not logged in)
- exit(0);
+ if (Util::verifyToken()) {
+ // Log user out (or do nothing if not logged in)
+ User::logout();
+ Util::redirect('?do=main');
+ }
}
function render_module()
{
- if (!isset($_GET['action'])) Util::traceError('No action on render');
- if ($_GET['action'] === 'login') {
+ if ($_REQUEST['action'] === 'login') {
Render::setTitle('Anmelden');
Render::addTemplate('page-login');
return;
}
- if ($_GET['action'] === 'fail') {
- Render::setTitle('Fehler');
- Render::addError('Benutzer oder Passwort falsch');
- return;
- }
}
diff --git a/templates/menu-logout.html b/templates/menu-logout.html
index d99fac58..68cf4671 100644
--- a/templates/menu-logout.html
+++ b/templates/menu-logout.html
@@ -1 +1 @@
-<li><a href="?do=session&amp;action=logout&amp;token={{{token}}}">{{user}} abmelden</a></li>
+<li><a href="?do=session&amp;action=logout&amp;token={{{token}}}"><b>{{user}}</b> (abmelden)</a></li>