Commit | Line | Data |
---|---|---|
88a4c51b FB |
1 | <?php |
2 | /*************************************************************************** | |
e92ecb8c | 3 | * Copyright (C) 2003-2011 Polytechnique.org * |
88a4c51b FB |
4 | * http://opensource.polytechnique.org/ * |
5 | * * | |
6 | * This program is free software; you can redistribute it and/or modify * | |
7 | * it under the terms of the GNU General Public License as published by * | |
8 | * the Free Software Foundation; either version 2 of the License, or * | |
9 | * (at your option) any later version. * | |
10 | * * | |
11 | * This program is distributed in the hope that it will be useful, * | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
14 | * GNU General Public License for more details. * | |
15 | * * | |
16 | * You should have received a copy of the GNU General Public License * | |
17 | * along with this program; if not, write to the Free Software * | |
18 | * Foundation, Inc., * | |
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * | |
20 | ***************************************************************************/ | |
21 | ||
47fa97fe FB |
22 | /** Authentication level. |
23 | * Only AUTH_PUBLIC is mandatory. The others are defined as useful values, | |
24 | * but can be overwritten by others auth levels definitions. | |
25 | */ | |
5a074c2f | 26 | define('AUTH_SUID', -1); |
47fa97fe | 27 | define('AUTH_PUBLIC', 0); |
8cd8f58b | 28 | define('AUTH_COOKIE', 5); |
f968d817 | 29 | define('AUTH_PASSWD', 10); |
696f9047 | 30 | // Backwards compatibility: AUTH_MDP must be an alias for AUTH_PASSWD. |
999c36ca | 31 | define('AUTH_MDP', 10); |
47fa97fe | 32 | |
88a4c51b FB |
33 | |
34 | /** The PlSession is a wrapper around the user session management. | |
35 | */ | |
36 | abstract class PlSession | |
37 | { | |
38 | /** Build a new session object. | |
39 | * If a session is already started, this just wraps the session... if no | |
40 | * session is currently started, this set the base session variables. | |
41 | * * auth contains the current authentication level. The level is | |
42 | * an integer that grows with the security of the authentication | |
43 | * method. | |
44 | * * perms contains the current permission flags of the user. This flags | |
45 | * depends on the category of the user. | |
46 | * * challenge contains a random uniq id for authentication. | |
47 | * * xsrf_token contains a random uniq id for xsrf prevention. | |
48 | * * user contains a reference to the current user. | |
49 | */ | |
50 | public function __construct() | |
51 | { | |
c0799142 | 52 | $this->create(); |
88a4c51b FB |
53 | } |
54 | ||
55 | /** Build the session structure with system fields. | |
56 | */ | |
9007d495 | 57 | protected function fillSession() |
88a4c51b FB |
58 | { |
59 | S::bootstrap('user', null); | |
60 | S::bootstrap('auth', AUTH_PUBLIC); | |
61 | S::bootstrap('challenge', sha1(uniqid(rand(), true))); | |
62 | S::bootstrap('xsrf_token', rand_url_id()); | |
63 | S::bootstrap('perms', new PlFlagSet()); | |
64 | } | |
65 | ||
66 | /** Write current session and close it. | |
67 | */ | |
68 | public function close() | |
69 | { | |
70 | session_write_close(); | |
71 | } | |
72 | ||
c0799142 FB |
73 | /** Create a new session |
74 | */ | |
75 | private function create() | |
76 | { | |
77 | session_start(); | |
78 | $this->fillSession(); | |
79 | } | |
80 | ||
88a4c51b FB |
81 | /** Kill the current session. |
82 | */ | |
83 | public function destroy() | |
84 | { | |
85 | session_destroy(); | |
86 | unset($_SESSION); | |
c0799142 | 87 | $this->create(); |
88a4c51b FB |
88 | } |
89 | ||
90 | /** Check if the user has at least the given authentication level. | |
91 | */ | |
92 | public function checkAuth($level) | |
93 | { | |
94 | return S::i('auth') >= $level; | |
95 | } | |
96 | ||
97 | /** Check if the user has the given permissions. | |
98 | */ | |
99 | public function checkPerms($perms) | |
100 | { | |
101 | return S::v('perms')->hasFlagCombination($perms); | |
102 | } | |
103 | ||
104 | /** Run authentication procedure to reach at least the given level. | |
105 | */ | |
106 | public function start($level) | |
107 | { | |
108 | if ($this->checkAuth($level)) { | |
109 | return true; | |
110 | } | |
111 | $user = $this->doAuth($level); | |
c0799142 FB |
112 | if (is_null($user)) { |
113 | return false; | |
114 | } | |
115 | if (!$this->checkAuth($level)) { | |
116 | $this->destroy(); | |
88a4c51b FB |
117 | return false; |
118 | } | |
119 | if ($this->startSessionAs($user, $level)) { | |
120 | if (is_null(S::v('user'))) { | |
121 | S::set('user', $user); | |
122 | } | |
123 | return true; | |
124 | } else { | |
125 | $this->destroy(); | |
126 | } | |
127 | return false; | |
128 | } | |
129 | ||
130 | ||
131 | /*** Abstract methods ***/ | |
132 | ||
c0799142 FB |
133 | /** Function that check authentication at build time of the session object. |
134 | * This is useful to perform authentication from a cookie or when coming | |
135 | * back from a authentication service. | |
136 | * | |
137 | * This function must NOT try to launch a new authenticatioin procedure. It | |
138 | * just tests if the environment contains sufficient information to start | |
139 | * a user session. | |
140 | * | |
141 | * This function return false if informations are available but lead to an | |
142 | * authentication failure (invalid cookie, invalid service return data...) | |
143 | */ | |
144 | abstract public function startAvailableAuth(); | |
145 | ||
88a4c51b FB |
146 | /** Run the effectively authentication procedure to reach the given user. |
147 | * This method must return a user object (that will be used to fill the | |
148 | * $_SESSION['user'] field). | |
149 | * | |
150 | * If auth failed, the function MUST return null. If auth succeed, the | |
151 | * field $_SESSION['auth'] MUST be filled to the current effective level. | |
152 | */ | |
153 | abstract protected function doAuth($level); | |
154 | ||
155 | /** Set the session environment to the given user and authentication level. | |
156 | * This function MUST return false if a session is already started and the | |
157 | * user mismatch. | |
158 | * | |
159 | * On succes, this function MUST return true. | |
160 | * If $level is set to -1, this means you are building a new SUID session. | |
161 | */ | |
162 | abstract protected function startSessionAs($user, $level); | |
163 | ||
504647c5 VZ |
164 | /** Authenticate the request for the given (method, payload) pair. |
165 | * | |
166 | * Implementations are expected to provide strong authentication. It is | |
167 | * suggested to use an HMAC-based scheme, where the signature validates the | |
168 | * method, url, and payload (to avoid replay of the signature against other | |
169 | * methods), and the timestamp (to avoid replay in time). | |
170 | * | |
171 | * @param method method of the request (GET, POST, PUT, DELETE) | |
172 | * @param resource URL path of the resource (eg. "/api/user") | |
173 | * @param payload binary payload sent with the request (before decoding) | |
174 | * @return a valid PlUser object if authentication is successfull, or null. | |
175 | */ | |
176 | public function apiAuth($method, $resource, $payload) | |
177 | { | |
178 | return null; // Default implementation does nothing | |
179 | } | |
180 | ||
8bdb07ee FB |
181 | /** Check authentication with the given token. |
182 | * | |
183 | * Token authentication is a light-weight authentication based on a user-specific token. | |
184 | * This can be used for protocols that requires a 'cookie'-free authentication, such as | |
185 | * RSS, iCal registration... | |
186 | * | |
187 | * This function returns a valid user object if authentication is successful, or null if | |
188 | * token mismatch. | |
189 | */ | |
190 | abstract public function tokenAuth($login, $token); | |
191 | ||
7adcbe0e FB |
192 | /** Set the permissions to the given flagset. |
193 | * | |
194 | * This function sets S::set('perms') with a flagset represeting the combination of | |
195 | * $perms and $is_admin. | |
196 | * | |
197 | * $perms is an abstract object representing the permissions. | |
198 | * $is_admin is a boolean, true if the current user has site-administration rights. | |
199 | */ | |
200 | abstract protected function makePerms($perms, $is_admin); | |
88a4c51b FB |
201 | |
202 | /*** SUID management ***/ | |
203 | ||
204 | /** Start a new SUID session. | |
205 | */ | |
7adcbe0e | 206 | public function startSUID($user, $perms = null) |
88a4c51b | 207 | { |
f1c8bb75 | 208 | if (S::suid()) { |
88a4c51b FB |
209 | return false; |
210 | } | |
663c7f8e | 211 | $backup = S::changeSession(array()); |
88a4c51b FB |
212 | $this->fillSession(); |
213 | S::set('suid', $backup); | |
5a074c2f | 214 | if (!$this->startSessionAs($user, AUTH_SUID)) { |
88a4c51b FB |
215 | $this->stopSUID(); |
216 | return false; | |
217 | } | |
732e5855 | 218 | S::set('user', $user); |
7adcbe0e FB |
219 | if (!is_null($perms)) { |
220 | $this->makePerms($perms, false); | |
221 | } | |
88a4c51b FB |
222 | return true; |
223 | } | |
224 | ||
225 | /** Stop a SUID session | |
226 | */ | |
227 | public function stopSUID() | |
228 | { | |
f1c8bb75 | 229 | if (!S::suid()) { |
88a4c51b FB |
230 | return false; |
231 | } | |
663c7f8e | 232 | S::changeSession(S::v('suid')); |
88a4c51b FB |
233 | return true; |
234 | } | |
235 | ||
236 | ||
237 | /*** Thresholds ***/ | |
238 | ||
8cd8f58b FB |
239 | /** Minimum level of authentication that is considered as logged. |
240 | */ | |
241 | abstract public function loggedLevel(); | |
242 | ||
88a4c51b FB |
243 | /** Minimum level of authentication that is considered as sure. |
244 | */ | |
245 | abstract public function sureLevel(); | |
246 | } | |
247 | ||
248 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: | |
249 | ?> |