Base for the PlSession object.
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Sat, 21 Jun 2008 20:00:48 +0000 (22:00 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Sat, 21 Jun 2008 20:00:48 +0000 (22:00 +0200)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
classes/plsession.php [new file with mode: 0644]
classes/s.php
classes/session.php [deleted file]

diff --git a/classes/plsession.php b/classes/plsession.php
new file mode 100644 (file)
index 0000000..af3e883
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2008 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+
+/** The PlSession is a wrapper around the user session management.
+ */
+abstract class PlSession
+{
+    /** Build a new session object.
+     * If a session is already started, this just wraps the session... if no
+     * session is currently started, this set the base session variables.
+     *  * auth        contains the current authentication level. The level is
+     *                an integer that grows with the security of the authentication
+     *                method.
+     *  * perms       contains the current permission flags of the user. This flags
+     *                depends on the category of the user.
+     *  * challenge   contains a random uniq id for authentication.
+     *  * xsrf_token  contains a random uniq id for xsrf prevention.
+     *  * user        contains a reference to the current user.
+     */
+    public function __construct()
+    {
+        session_start();
+        $this->fillSession();
+    }
+
+    /** Build the session structure with system fields.
+     */
+    private function fillSession()
+    {
+        S::bootstrap('user', null);
+        S::bootstrap('auth', AUTH_PUBLIC);
+        S::bootstrap('challenge', sha1(uniqid(rand(), true)));
+        S::bootstrap('xsrf_token', rand_url_id());
+        S::bootstrap('perms', new PlFlagSet());
+    }
+
+    /** Write current session and close it.
+     */
+    public function close()
+    {
+        session_write_close();
+    }
+
+    /** Kill the current session.
+     */
+    public function destroy()
+    {
+        session_destroy();
+        unset($_SESSION);
+    }
+
+    /** Check if the user has at least the given authentication level.
+     */
+    public function checkAuth($level)
+    {
+        return S::i('auth') >= $level;
+    }
+
+    /** Check if the user has the given permissions.
+     */
+    public function checkPerms($perms)
+    {
+        return S::v('perms')->hasFlagCombination($perms);
+    }
+
+    /** Run authentication procedure to reach at least the given level.
+     */
+    public function start($level)
+    {
+        if ($this->checkAuth($level)) {
+            return true;
+        }
+        $user = $this->doAuth($level);
+        if (is_null($user) || !$this->checkAuth($level)) {
+            return false;
+        }
+        if ($this->startSessionAs($user, $level)) {
+            if (is_null(S::v('user'))) {
+                S::set('user', $user);
+            }
+            return true;
+        } else {
+            $this->destroy();
+        }
+        return false;
+    }
+
+
+    /*** Abstract methods ***/
+
+    /** Run the effectively authentication procedure to reach the given user.
+     * This method must return a user object (that will be used to fill the
+     * $_SESSION['user'] field).
+     *
+     * If auth failed, the function MUST return null. If auth succeed, the
+     * field $_SESSION['auth'] MUST be filled to the current effective level.
+     */
+    abstract protected function doAuth($level);
+
+    /** Set the session environment to the given user and authentication level.
+     * This function MUST return false if a session is already started and the
+     * user mismatch.
+     *
+     * On succes, this function MUST return true.
+     * If $level is set to -1, this means you are building a new SUID session.
+     */
+    abstract protected function startSessionAs($user, $level);
+
+
+    /*** SUID management ***/
+
+    /** Start a new SUID session.
+     */
+    public function startSUID($user)
+    {
+        if (isset($_SESSION['suid'])) {
+            return false;
+        }
+        $newsession = array();
+        $backup   =& $_SESSION;
+        $_SESSION =& $newsession;
+        $this->fillSession();
+        S::set('suid', $backup);
+        if (!$this->startSessionAs($user, -1)) {
+            $this->stopSUID();
+            return false;
+        }
+        return true;
+    }
+
+    /** Stop a SUID session
+     */
+    public function stopSUID()
+    {
+        if (!isset($_SESSION['suid'])) {
+            return false;
+        }
+        $_SESSION =& $_SESSION['suid'];
+        return true;
+    }
+
+
+    /*** Thresholds ***/
+
+    /** Minimum level of authentication that is considered as sure.
+     */
+    abstract public function sureLevel();
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index 338a437..bcb8975 100644 (file)
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
-class S extends Session {
+class S
+{
+    /** Set a constructor because this is called prior to S::s(), so we can
+     * define S::s() for other usages.
+     */
+    private function __construct()
+    {
+        assert(false);
+    }
+
+    public static function has($key)
+    {
+        return isset($_SESSION[$key]);
+    }
+
+    public static function kill($key)
+    {
+        unset($_SESSION[$key]);
+    }
+
+    public static function v($key, $default = null)
+    {
+        return isset($_SESSION[$key]) ? $_SESSION[$key] : $default;
+    }
+
+    public static function s($key, $default = '')
+    {
+        return (string)S::v($key, $default);
+    }
+
+    public static function i($key, $default = 0)
+    {
+        $i = S::v($key, $default);
+        return is_numeric($i) ? intval($i) : $default;
+    }
+
+    public static function l(array $keys)
+    {
+        return array_map(array('S', 'v'), $keys);
+    }
+
+    public static function set($key, &$value)
+    {
+        $_SESSION[$key] =& $value;
+    }
+
+    public static function bootstrap($key, &$value)
+    {
+        if (!S::has($key)) {
+            S::set($key, $value);
+        }
+    }
+
+    public static function has_perms()
+    {
+        global $session;
+        return $session->checkPerms(PERMS_ADMIN);
+    }
+
+    public static function logged()
+    {
+        return S::v('auth', AUTH_PUBLIC) > AUTH_PUBLIC;
+    }
+
+    public static function identified()
+    {
+        global $session;
+        return S::v('auth', AUTH_PUBLIC) >= $session->sureLevel();
+    }
+
+    // Anti-XSRF protections.
+    public static function has_xsrf_token()
+    {
+        return S::has('xsrf_token') && S::v('xsrf_token') == Env::v('token');
+    }
+
+    public static function assert_xsrf_token()
+    {
+        if (!S::has_xsrf_token()) {
+            Platal::page()->kill('L\'opération n\'a pas pu aboutir, merci de réessayer.');
+        }
+    }
+
+    public static function rssActivated()
+    {
+        return S::has('core_rss_hash') && S::v('core_rss_hash');
+    }
 }
 
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
diff --git a/classes/session.php b/classes/session.php
deleted file mode 100644 (file)
index b2874eb..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-/***************************************************************************
- *  Copyright (C) 2003-2008 Polytechnique.org                              *
- *  http://opensource.polytechnique.org/                                   *
- *                                                                         *
- *  This program is free software; you can redistribute it and/or modify   *
- *  it under the terms of the GNU General Public License as published by   *
- *  the Free Software Foundation; either version 2 of the License, or      *
- *  (at your option) any later version.                                    *
- *                                                                         *
- *  This program is distributed in the hope that it will be useful,        *
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- *  GNU General Public License for more details.                           *
- *                                                                         *
- *  You should have received a copy of the GNU General Public License      *
- *  along with this program; if not, write to the Free Software            *
- *  Foundation, Inc.,                                                      *
- *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
- ***************************************************************************/
-
-class Session
-{
-    public static function init()
-    {
-        @session_start();
-        if (empty($_SESSION['challenge'])) {
-            $_SESSION['challenge'] = sha1(uniqid(rand(), true));
-        }
-        if (empty($_SESSION['xsrf_token'])) {
-            require_once 'xorg.misc.inc.php';
-            $_SESSION['xsrf_token'] = rand_url_id();
-        }
-        if (!isset($_SESSION['perms']) || !($_SESSION['perms'] instanceof PlFlagSet)) {
-            $_SESSION['perms'] = new PlFlagSet();
-        }
-    }
-
-    public static function destroy()
-    {
-        @session_destroy();
-        unset($_SESSION);
-    }
-
-    public static function has($key)
-    {
-        return isset($_SESSION[$key]);
-    }
-
-    public static function kill($key)
-    {
-        unset($_SESSION[$key]);
-    }
-
-    public static function v($key, $default = null)
-    {
-        return isset($_SESSION[$key]) ? $_SESSION[$key] : $default;
-    }
-
-    public static function s($key, $default = '')
-    {
-        return (string)Session::v($key, $default);
-    }
-
-    public static function i($key, $default = 0)
-    {
-        $i = Session::v($key, $default);
-        return is_numeric($i) ? intval($i) : $default;
-    }
-
-    public static function l(array $keys)
-    {
-        return array_map(array('Session', 'v'), $keys);
-    }
-
-    public static function has_perms()
-    {
-        return Session::logged() && Session::v('perms')->hasFlag(PERMS_ADMIN);
-    }
-
-    public static function logged()
-    {
-        return Session::v('auth', AUTH_PUBLIC) >= AUTH_COOKIE;
-    }
-
-    public static function identified()
-    {
-        return Session::v('auth', AUTH_PUBLIC) >= AUTH_MDP;
-    }
-
-    // Anti-XSRF protections.
-    public static function has_xsrf_token()
-    {
-        return Session::has('xsrf_token') && Session::v('xsrf_token') == Env::v('token');
-    }
-
-    public static function assert_xsrf_token()
-    {
-        if (!Session::has_xsrf_token()) {
-            global $page;
-            if ($page instanceof PlPage) {
-                $page->kill("L'opération n'a pas pu aboutir, merci de réessayer.");
-            }
-        }
-    }
-
-    public static function rssActivated()
-    {
-        return Session::has('core_rss_hash') && Session::v('core_rss_hash');
-    }
-}
-
-// {{{ function check_perms()
-
-/** verifie si un utilisateur a les droits pour voir une page
- ** si ce n'est pas le cas, on affiche une erreur
- * @return void
- */
-function check_perms()
-{
-    global $page;
-    if (!S::has_perms()) {
-        if ($_SESSION['log']) {
-            $_SESSION['log']->log("noperms",$_SERVER['PHP_SELF']);
-        }
-       $page->kill("Tu n'as pas les permissions nécessaires pour accéder à cette page.");
-    }
-}
-
-// }}}
-
-// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
-?>