|
1 <?php |
|
2 |
|
3 /** |
|
4 * Zend Framework |
|
5 * |
|
6 * LICENSE |
|
7 * |
|
8 * This source file is subject to the new BSD license that is bundled |
|
9 * with this package in the file LICENSE.txt. |
|
10 * It is also available through the world-wide-web at this URL: |
|
11 * http://framework.zend.com/license/new-bsd |
|
12 * If you did not receive a copy of the license and are unable to |
|
13 * obtain it through the world-wide-web, please send an email |
|
14 * to license@zend.com so we can send you a copy immediately. |
|
15 * |
|
16 * @category Zend |
|
17 * @package Zend_OpenId |
|
18 * @subpackage Zend_OpenId_Provider |
|
19 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
20 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
21 * @version $Id: File.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
22 */ |
|
23 |
|
24 /** |
|
25 * @see Zend_OpenId_Provider_Storage |
|
26 */ |
|
27 require_once "Zend/OpenId/Provider/Storage.php"; |
|
28 |
|
29 /** |
|
30 * External storage implemmentation using serialized files |
|
31 * |
|
32 * @category Zend |
|
33 * @package Zend_OpenId |
|
34 * @subpackage Zend_OpenId_Provider |
|
35 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
36 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
37 */ |
|
38 class Zend_OpenId_Provider_Storage_File extends Zend_OpenId_Provider_Storage |
|
39 { |
|
40 |
|
41 /** |
|
42 * Directory name to store data files in |
|
43 * |
|
44 * @var string $_dir |
|
45 */ |
|
46 private $_dir; |
|
47 |
|
48 /** |
|
49 * Constructs storage object and creates storage directory |
|
50 * |
|
51 * @param string $dir directory name to store data files in |
|
52 * @throws Zend_OpenId_Exception |
|
53 */ |
|
54 public function __construct($dir = null) |
|
55 { |
|
56 if ($dir === null) { |
|
57 $tmp = getenv('TMP'); |
|
58 if (empty($tmp)) { |
|
59 $tmp = getenv('TEMP'); |
|
60 if (empty($tmp)) { |
|
61 $tmp = "/tmp"; |
|
62 } |
|
63 } |
|
64 $user = get_current_user(); |
|
65 if (is_string($user) && !empty($user)) { |
|
66 $tmp .= '/' . $user; |
|
67 } |
|
68 $dir = $tmp . '/openid/provider'; |
|
69 } |
|
70 $this->_dir = $dir; |
|
71 if (!is_dir($this->_dir)) { |
|
72 if (!@mkdir($this->_dir, 0700, 1)) { |
|
73 throw new Zend_OpenId_Exception( |
|
74 "Cannot access storage directory $dir", |
|
75 Zend_OpenId_Exception::ERROR_STORAGE); |
|
76 } |
|
77 } |
|
78 if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) { |
|
79 throw new Zend_OpenId_Exception( |
|
80 'Cannot create a lock file in the directory ' . $dir, |
|
81 Zend_OpenId_Exception::ERROR_STORAGE); |
|
82 } |
|
83 fclose($f); |
|
84 if (($f = fopen($this->_dir.'/user.lock', 'w+')) === null) { |
|
85 throw new Zend_OpenId_Exception( |
|
86 'Cannot create a lock file in the directory ' . $dir, |
|
87 Zend_OpenId_Exception::ERROR_STORAGE); |
|
88 } |
|
89 fclose($f); |
|
90 } |
|
91 |
|
92 /** |
|
93 * Stores information about session identified by $handle |
|
94 * |
|
95 * @param string $handle assiciation handle |
|
96 * @param string $macFunc HMAC function (sha1 or sha256) |
|
97 * @param string $secret shared secret |
|
98 * @param string $expires expiration UNIX time |
|
99 * @return bool |
|
100 */ |
|
101 public function addAssociation($handle, $macFunc, $secret, $expires) |
|
102 { |
|
103 $name = $this->_dir . '/assoc_' . md5($handle); |
|
104 $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); |
|
105 if ($lock === false) { |
|
106 return false; |
|
107 } |
|
108 if (!flock($lock, LOCK_EX)) { |
|
109 fclose($lock); |
|
110 return false; |
|
111 } |
|
112 try { |
|
113 $f = @fopen($name, 'w+'); |
|
114 if ($f === false) { |
|
115 fclose($lock); |
|
116 return false; |
|
117 } |
|
118 $data = serialize(array($handle, $macFunc, $secret, $expires)); |
|
119 fwrite($f, $data); |
|
120 fclose($f); |
|
121 fclose($lock); |
|
122 return true; |
|
123 } catch (Exception $e) { |
|
124 fclose($lock); |
|
125 throw $e; |
|
126 } |
|
127 } |
|
128 |
|
129 /** |
|
130 * Gets information about association identified by $handle |
|
131 * Returns true if given association found and not expired and false |
|
132 * otherwise |
|
133 * |
|
134 * @param string $handle assiciation handle |
|
135 * @param string &$macFunc HMAC function (sha1 or sha256) |
|
136 * @param string &$secret shared secret |
|
137 * @param string &$expires expiration UNIX time |
|
138 * @return bool |
|
139 */ |
|
140 public function getAssociation($handle, &$macFunc, &$secret, &$expires) |
|
141 { |
|
142 $name = $this->_dir . '/assoc_' . md5($handle); |
|
143 $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); |
|
144 if ($lock === false) { |
|
145 return false; |
|
146 } |
|
147 if (!flock($lock, LOCK_EX)) { |
|
148 fclose($lock); |
|
149 return false; |
|
150 } |
|
151 try { |
|
152 $f = @fopen($name, 'r'); |
|
153 if ($f === false) { |
|
154 fclose($lock); |
|
155 return false; |
|
156 } |
|
157 $ret = false; |
|
158 $data = stream_get_contents($f); |
|
159 if (!empty($data)) { |
|
160 list($storedHandle, $macFunc, $secret, $expires) = unserialize($data); |
|
161 if ($handle === $storedHandle && $expires > time()) { |
|
162 $ret = true; |
|
163 } else { |
|
164 fclose($f); |
|
165 @unlink($name); |
|
166 fclose($lock); |
|
167 return false; |
|
168 } |
|
169 } |
|
170 fclose($f); |
|
171 fclose($lock); |
|
172 return $ret; |
|
173 } catch (Exception $e) { |
|
174 fclose($lock); |
|
175 throw $e; |
|
176 } |
|
177 } |
|
178 |
|
179 /** |
|
180 * Removes information about association identified by $handle |
|
181 * |
|
182 * @param string $handle assiciation handle |
|
183 * @return bool |
|
184 */ |
|
185 public function delAssociation($handle) |
|
186 { |
|
187 $name = $this->_dir . '/assoc_' . md5($handle); |
|
188 $lock = @fopen($this->_dir . '/assoc.lock', 'w+'); |
|
189 if ($lock === false) { |
|
190 return false; |
|
191 } |
|
192 if (!flock($lock, LOCK_EX)) { |
|
193 fclose($lock); |
|
194 return false; |
|
195 } |
|
196 try { |
|
197 @unlink($name); |
|
198 fclose($lock); |
|
199 return true; |
|
200 } catch (Exception $e) { |
|
201 fclose($lock); |
|
202 throw $e; |
|
203 } |
|
204 } |
|
205 |
|
206 /** |
|
207 * Register new user with given $id and $password |
|
208 * Returns true in case of success and false if user with given $id already |
|
209 * exists |
|
210 * |
|
211 * @param string $id user identity URL |
|
212 * @param string $password encoded user password |
|
213 * @return bool |
|
214 */ |
|
215 public function addUser($id, $password) |
|
216 { |
|
217 $name = $this->_dir . '/user_' . md5($id); |
|
218 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
219 if ($lock === false) { |
|
220 return false; |
|
221 } |
|
222 if (!flock($lock, LOCK_EX)) { |
|
223 fclose($lock); |
|
224 return false; |
|
225 } |
|
226 try { |
|
227 $f = @fopen($name, 'x'); |
|
228 if ($f === false) { |
|
229 fclose($lock); |
|
230 return false; |
|
231 } |
|
232 $data = serialize(array($id, $password, array())); |
|
233 fwrite($f, $data); |
|
234 fclose($f); |
|
235 fclose($lock); |
|
236 return true; |
|
237 } catch (Exception $e) { |
|
238 fclose($lock); |
|
239 throw $e; |
|
240 } |
|
241 } |
|
242 |
|
243 /** |
|
244 * Returns true if user with given $id exists and false otherwise |
|
245 * |
|
246 * @param string $id user identity URL |
|
247 * @return bool |
|
248 */ |
|
249 public function hasUser($id) |
|
250 { |
|
251 $name = $this->_dir . '/user_' . md5($id); |
|
252 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
253 if ($lock === false) { |
|
254 return false; |
|
255 } |
|
256 if (!flock($lock, LOCK_SH)) { |
|
257 fclose($lock); |
|
258 return false; |
|
259 } |
|
260 try { |
|
261 $f = @fopen($name, 'r'); |
|
262 if ($f === false) { |
|
263 fclose($lock); |
|
264 return false; |
|
265 } |
|
266 $ret = false; |
|
267 $data = stream_get_contents($f); |
|
268 if (!empty($data)) { |
|
269 list($storedId, $storedPassword, $trusted) = unserialize($data); |
|
270 if ($id === $storedId) { |
|
271 $ret = true; |
|
272 } |
|
273 } |
|
274 fclose($f); |
|
275 fclose($lock); |
|
276 return $ret; |
|
277 } catch (Exception $e) { |
|
278 fclose($lock); |
|
279 throw $e; |
|
280 } |
|
281 } |
|
282 |
|
283 /** |
|
284 * Verify if user with given $id exists and has specified $password |
|
285 * |
|
286 * @param string $id user identity URL |
|
287 * @param string $password user password |
|
288 * @return bool |
|
289 */ |
|
290 public function checkUser($id, $password) |
|
291 { |
|
292 $name = $this->_dir . '/user_' . md5($id); |
|
293 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
294 if ($lock === false) { |
|
295 return false; |
|
296 } |
|
297 if (!flock($lock, LOCK_SH)) { |
|
298 fclose($lock); |
|
299 return false; |
|
300 } |
|
301 try { |
|
302 $f = @fopen($name, 'r'); |
|
303 if ($f === false) { |
|
304 fclose($lock); |
|
305 return false; |
|
306 } |
|
307 $ret = false; |
|
308 $data = stream_get_contents($f); |
|
309 if (!empty($data)) { |
|
310 list($storedId, $storedPassword, $trusted) = unserialize($data); |
|
311 if ($id === $storedId && $password === $storedPassword) { |
|
312 $ret = true; |
|
313 } |
|
314 } |
|
315 fclose($f); |
|
316 fclose($lock); |
|
317 return $ret; |
|
318 } catch (Exception $e) { |
|
319 fclose($lock); |
|
320 throw $e; |
|
321 } |
|
322 } |
|
323 |
|
324 /** |
|
325 * Removes information abou specified user |
|
326 * |
|
327 * @param string $id user identity URL |
|
328 * @return bool |
|
329 */ |
|
330 public function delUser($id) |
|
331 { |
|
332 $name = $this->_dir . '/user_' . md5($id); |
|
333 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
334 if ($lock === false) { |
|
335 return false; |
|
336 } |
|
337 if (!flock($lock, LOCK_EX)) { |
|
338 fclose($lock); |
|
339 return false; |
|
340 } |
|
341 try { |
|
342 @unlink($name); |
|
343 fclose($lock); |
|
344 return true; |
|
345 } catch (Exception $e) { |
|
346 fclose($lock); |
|
347 throw $e; |
|
348 } |
|
349 } |
|
350 |
|
351 /** |
|
352 * Returns array of all trusted/untrusted sites for given user identified |
|
353 * by $id |
|
354 * |
|
355 * @param string $id user identity URL |
|
356 * @return array |
|
357 */ |
|
358 public function getTrustedSites($id) |
|
359 { |
|
360 $name = $this->_dir . '/user_' . md5($id); |
|
361 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
362 if ($lock === false) { |
|
363 return false; |
|
364 } |
|
365 if (!flock($lock, LOCK_SH)) { |
|
366 fclose($lock); |
|
367 return false; |
|
368 } |
|
369 try { |
|
370 $f = @fopen($name, 'r'); |
|
371 if ($f === false) { |
|
372 fclose($lock); |
|
373 return false; |
|
374 } |
|
375 $ret = false; |
|
376 $data = stream_get_contents($f); |
|
377 if (!empty($data)) { |
|
378 list($storedId, $storedPassword, $trusted) = unserialize($data); |
|
379 if ($id === $storedId) { |
|
380 $ret = $trusted; |
|
381 } |
|
382 } |
|
383 fclose($f); |
|
384 fclose($lock); |
|
385 return $ret; |
|
386 } catch (Exception $e) { |
|
387 fclose($lock); |
|
388 throw $e; |
|
389 } |
|
390 } |
|
391 |
|
392 /** |
|
393 * Stores information about trusted/untrusted site for given user |
|
394 * |
|
395 * @param string $id user identity URL |
|
396 * @param string $site site URL |
|
397 * @param mixed $trusted trust data from extension or just a boolean value |
|
398 * @return bool |
|
399 */ |
|
400 public function addSite($id, $site, $trusted) |
|
401 { |
|
402 $name = $this->_dir . '/user_' . md5($id); |
|
403 $lock = @fopen($this->_dir . '/user.lock', 'w+'); |
|
404 if ($lock === false) { |
|
405 return false; |
|
406 } |
|
407 if (!flock($lock, LOCK_EX)) { |
|
408 fclose($lock); |
|
409 return false; |
|
410 } |
|
411 try { |
|
412 $f = @fopen($name, 'r+'); |
|
413 if ($f === false) { |
|
414 fclose($lock); |
|
415 return false; |
|
416 } |
|
417 $ret = false; |
|
418 $data = stream_get_contents($f); |
|
419 if (!empty($data)) { |
|
420 list($storedId, $storedPassword, $sites) = unserialize($data); |
|
421 if ($id === $storedId) { |
|
422 if ($trusted === null) { |
|
423 unset($sites[$site]); |
|
424 } else { |
|
425 $sites[$site] = $trusted; |
|
426 } |
|
427 rewind($f); |
|
428 ftruncate($f, 0); |
|
429 $data = serialize(array($id, $storedPassword, $sites)); |
|
430 fwrite($f, $data); |
|
431 $ret = true; |
|
432 } |
|
433 } |
|
434 fclose($f); |
|
435 fclose($lock); |
|
436 return $ret; |
|
437 } catch (Exception $e) { |
|
438 fclose($lock); |
|
439 throw $e; |
|
440 } |
|
441 } |
|
442 } |