9683.diff

Administrator Admin, 2009-11-24 17:02

Download (13.6 KB)

View differences:

typo3/sysext/openid/ext_tables.sql (working copy)
2 2
# Table structure for table 'be_users'
3 3
#
4 4
CREATE TABLE be_users (
5
	tx_openid_openid varchar(255) DEFAULT '' NOT NULL
5
	tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
6 6
);
7 7

  
8 8
#
9 9
# Table structure for table 'fe_users'
10 10
#
11 11
CREATE TABLE fe_users (
12
	tx_openid_openid varchar(255) DEFAULT '' NOT NULL
13
);
12
	tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
13
);
14

  
15
#
16
# Table structure for table 'tx_openid_assoc_store'.
17
#
18
CREATE TABLE tx_openid_assoc_store (
19
	uid int(11) unsigned NOT NULL auto_increment,
20
	pid int(11) unsigned DEFAULT '0' NOT NULL,
21
	crdate int(11) unsigned DEFAULT '0' NOT NULL,
22
	tstamp int(11) unsigned DEFAULT '0' NOT NULL,
23
	expires int(11) unsigned DEFAULT '0' NOT NULL,
24
	server_url varchar(2047) DEFAULT '' NOT NULL,
25
	assoc_handle varchar(255) DEFAULT '' NOT NULL,
26
	content blob,
27

  
28
	PRIMARY KEY (uid),
29
	KEY assoc_handle (assoc_handle(8)),
30
	KEY expires (expires)
31
) ENGINE=InnoDB;
32

  
33
#
34
# Table structure for table 'tx_openid_nonce_store'.
35
#
36
CREATE TABLE tx_openid_nonce_store (
37
	uid int(11) unsigned NOT NULL auto_increment,
38
	pid int(11) unsigned DEFAULT '0' NOT NULL,
39
	crdate int(11) unsigned DEFAULT '0' NOT NULL,
40
	tstamp int(11) unsigned DEFAULT '0' NOT NULL,
41
	server_url varchar(2047) DEFAULT '' NOT NULL,
42
	salt char(40),
43

  
44
	PRIMARY KEY (uid),
45
	UNIQUE KEY nonce (server_url(255),tstamp,salt),
46
	KEY crdate (crdate)
47
) ENGINE=InnoDB;
typo3/sysext/openid/TODO (working copy)
1

  
2
* use DB (the sessions or the caching framework) instead of the filesystem to store OpenID data (class.tx_openid_sv1.php)
1
None
typo3/sysext/openid/sv1/class.tx_openid_store.php (revision 0)
1
<?php
2
/***************************************************************
3
*  Copyright notice
4
*
5
*  (c) 2009 Dmitry Dulepov (dmitry.dulepov@gmail.com)
6
*  All rights reserved
7
*
8
*  This script is part of the Typo3 project. The Typo3 project is
9
*  free software; you can redistribute it and/or modify
10
*  it under the terms of the GNU General Public License as published by
11
*  the Free Software Foundation; either version 2 of the License, or
12
*  (at your option) any later version.
13
*
14
*  The GNU General Public License can be found at
15
*  http://www.gnu.org/copyleft/gpl.html.
16
*
17
*  This script is distributed in the hope that it will be useful,
18
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
19
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
*  GNU General Public License for more details.
21
*
22
*  This copyright notice MUST APPEAR in all copies of the script!
23
***************************************************************/
24
/**
25
 * $Id$
26
 */
27

  
28
require_once(t3lib_extMgm::extPath('openid', 'lib/php-openid/Auth/OpenID/Interface.php'));
29

  
30
/**
31
  * This class is a TYPO3-specific OpenID store.
32
  *
33
  * @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
34
  * @package TYPO3
35
  * @subpackage tx_openid
36
  */
37
class tx_openid_store extends Auth_OpenID_OpenIDStore {
38

  
39
	const ASSOCIATION_TABLE_NAME = 'tx_openid_assoc_store';
40

  
41
	const ASSOCIATION_EXPIRATION_SAFETY_INTERVAL = 120; /* 2 minutes */
42

  
43
	const NONCE_TABLE_NAME = 'tx_openid_nonce_store';
44

  
45
	const NONCE_STORAGE_TIME = 864000; /* 10 days */
46

  
47
	/**
48
	 * Checks if database tables are created. If not, executes CREATE TABLE
49
	 * for extension's tables.
50
	 *
51
	 * @return void
52
	 */
53
	public function __construct() {
54
		$this->checkAndCreateTables();
55
	}
56

  
57
	/**
58
	 * Sores the association for future use
59
	 *
60
	 * @param string $serverUrl Server URL
61
	 * @param Auth_OpenID_Association $association OpenID association
62
	 * @return void
63
	 */
64
	public function storeAssociation($serverUrl, $association) {
65
		/* @var $association Auth_OpenID_Association */
66
		$GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION');
67

  
68
		if ($this->doesAssociationExist($serverUrl, $association->handle)) {
69
			$this->updateExistingAssociation($serverUrl, $association);
70
		}
71
		else {
72
			$this->storeNewAssociation($serverUrl, $association);
73
		}
74

  
75
		$GLOBALS['TYPO3_DB']->sql_query('COMMIT');
76
	}
77

  
78
	/**
79
	 * Removes all expired associations.
80
	 *
81
	 * @return int A number of removed associations
82
	 */
83
	public function cleanupAssociations() {
84
		$where = sprintf('expires<=%d', time());
85
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
86
		return $GLOBALS['TYPO3_DB']->sql_affected_rows();
87
	}
88

  
89
	/**
90
	 * Obtains the association to the server
91
	 *
92
	 * @param string $serverUrl Server URL
93
	 * @param string $handle Association handle (optional)
94
	 * @return Auth_OpenID_Association
95
	 */
96
	public function getAssociation($serverUrl, $handle = null) {
97
		$this->cleanupAssociations();
98

  
99
		$where = sprintf('server_url=%s AND expires>%d',
100
			$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
101
			time());
102
		if ($handle != null) {
103
			$where .= sprintf(' AND assoc_handle=%s',
104
				$GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
105
			$sort = '';
106
		}
107
		else {
108
			$sort = 'tstamp DESC';
109
		}
110
		list($row) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,content',
111
			self::ASSOCIATION_TABLE_NAME, $where, '', $sort, '1');
112

  
113
		$result = null;
114
		if (is_array($row)) {
115
			$result = @unserialize($row['content']);
116
			$this->updateAssociationTimeStamp($row['tstamp']);
117
		}
118
		return $result;
119
	}
120

  
121
	/**
122
	 * Removes the association
123
	 *
124
	 * @param string $serverUrl Server URL
125
	 * @param string $handle Association handle (optional)
126
	 * @return boolean true if the association existed
127
	 */
128
	function removeAssociation($serverUrl, $handle) {
129
		$where = sprintf('server_url=%s AND assoc_handle=%s',
130
			$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
131
			$GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
132
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
133
		$deletedCount = $GLOBALS['TYPO3_DB']->sql_affected_rows();
134
		return ($deletedCount > 0);
135
	}
136

  
137
	/**
138
	 * Removes old nonces
139
	 *
140
	 * @return void
141
	 */
142
	public function cleanupNonces() {
143
		$where = sprintf('crdate<%d', time() - self::NONCE_STORAGE_TIME);
144
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, $where);
145
	}
146

  
147
	/**
148
	 * Checks if this nonce was already used
149
	 * @param $serverUrl Server URL
150
	 * @param $timestamp Time stamp
151
	 * @param $salt Nonce value
152
	 * @return boolean true if nonce was not used before anc can be used now
153
	 */
154
	public function useNonce($serverUrl, $timestamp, $salt) {
155
		$result = false;
156

  
157
		if (abs($timestamp - time()) < $GLOBALS['Auth_OpenID_SKEW']) {
158
			$values = array(
159
				'crdate' => time(),
160
				'salt' => $salt,
161
				'server_url' => $serverUrl,
162
				'tstamp' => $timestamp
163
			);
164
			$GLOBALS['TYPO3_DB']->exec_INSERTquery(self::NONCE_TABLE_NAME,
165
				$values);
166
			$affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
167
			$result = ($affectedRows > 0);
168
		}
169

  
170
		return $result;
171
	}
172

  
173
	/**
174
	 * Resets the store by removing all data in it
175
	 *
176
	 * @return void
177
	 */
178
	public function reset() {
179
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, '1=1');
180
		$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, '1=1');
181
	}
182

  
183
	/**
184
	 * Checks if such association exists.
185
	 *
186
	 * @param string $serverUrl Server URL
187
	 * @param Auth_OpenID_Association $association OpenID association
188
	 * @return boolean
189
	 */
190
	protected function doesAssociationExist($serverUrl, $association) {
191
		$where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
192
			$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
193
			$GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
194
			time());
195
		list($row) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
196
			'COUNT(*) as assocCount', self::ASSOCIATION_TABLE_NAME, $where);
197
		return ($row['assocCount'] > 0);
198
	}
199

  
200
	/**
201
	 * Updates existing association.
202
	 *
203
	 * @param string $serverUrl Server URL
204
	 * @param Auth_OpenID_Association $association OpenID association
205
	 * @return void
206
	 */
207
	protected function updateExistingAssociation($serverUrl, Auth_OpenID_Association $association) {
208
		$where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
209
			$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
210
			$GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
211
			time());
212
		$serializedAssociation = serialize($association);
213
		$values = array(
214
			'content' => $serializedAssociation,
215
			'tstamp' => time(),
216
		);
217
		$GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
218
	}
219

  
220
	/**
221
	 * Stores new association to the database.
222
	 *
223
	 * @param $serverUrl Server URL
224
	 * @param $association OpenID association
225
	 * @return void
226
	 */
227
	protected function storeNewAssociation($serverUrl, $association) {
228
		$serializedAssociation = serialize($association);
229
		$values = array(
230
			'assoc_handle' => $association->handle,
231
			'content' => $serializedAssociation,
232
			'crdate' => $association->issued,
233
			'tstamp' => time(),
234
			'expires' => $association->issued + $association->lifetime - self::ASSOCIATION_EXPIRATION_SAFETY_INTERVAL,
235
			'server_url' => $serverUrl
236
		);
237
		// In the next query we can get race conditions. sha1_hash prevents many
238
		// asociations from being stored for one server
239
		$GLOBALS['TYPO3_DB']->exec_INSERTquery(self::ASSOCIATION_TABLE_NAME, $values);
240
	}
241

  
242
	/**
243
	 * Updates association time stamp.
244
	 *
245
	 * @param $recordId Association record id in the database
246
	 * @return void
247
	 */
248
	protected function updateAssociationTimeStamp($recordId) {
249
		$where = sprintf('uid=%d', $recordId);
250
		$values = array(
251
			'tstamp' => time()
252
		);
253
		$GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
254
	}
255

  
256
	/**
257
	 * Checks and database tables for this store.
258
	 *
259
	 * @return void
260
	 */
261
	protected function checkAndCreateTables() {
262
		$tableNames = $this->findTableToCreate();
263
		if (count($tableNames) > 0) {
264
			$this->doCreateTables($tableNames);
265
		}
266
	}
267

  
268
	/**
269
	 * Finds all missing database tables
270
	 *
271
	 * @return array
272
	 */
273
	protected function findTableToCreate() {
274
		$tablesToCreate = array();
275
		$existingTables = array_keys($GLOBALS['TYPO3_DB']->admin_get_tables());
276
		// Do that only if could get table list!
277
		if (count($existingTables) > 0) {
278
			foreach (array('tx_openid_assoc_store', 'tx_openid_nonce_store') as $tableName) {
279
				if (!in_array($tableName, $existingTables)) {
280
					$tablesToCreate[] = $tableName;
281
				}
282
			}
283
		}
284
		return $tablesToCreate;
285
	}
286

  
287
	/**
288
	 * Creates tables in the database.
289
	 *
290
	 * @param array $tableNames Table names
291
	 * @return void
292
	 */
293
	protected function doCreateTables(array $tableNames) {
294
		$sqlFile = file_get_contents(t3lib_extMgm::extPath('openid', 'ext_tables.sql'));
295
		foreach ($tableNames as $tableName) {
296
			$this->doCreateTable($sqlFile, $tableName);
297
		}
298
	}
299

  
300
	/**
301
	 * Creates a single database table
302
	 *
303
	 * @param string $sqlFile ext_tables.sql content
304
	 * @param $tableName Table name
305
	 * @return void
306
	 */
307
	protected function doCreateTable($sqlFile, $tableName) {
308
		$regularExpression = '/.*(CREATE\s*TABLE\s*`?' . $tableName . '`?\s*\([^;]+).*/is';
309
		$tableDefinition = preg_replace($regularExpression, '\1', $sqlFile);
310
		if ($tableDefinition != '') {
311
			$GLOBALS['TYPO3_DB']->sql_query($tableDefinition);
312
		}
313
	}
314
}
315

  
316
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php'])	{
317
	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php']);
318
}
319

  
320
?>
typo3/sysext/openid/sv1/class.tx_openid_sv1.php (working copy)
44 44
 */
45 45

  
46 46
require_once(PATH_t3lib . 'class.t3lib_svbase.php');
47
require_once(t3lib_extMgm::extPath('openid', 'sv1/class.tx_openid_store.php'));
47 48

  
48 49
/**
49 50
 * Service "OpenID Authentication" for the "openid" extension.
......
276 277

  
277 278
			// Include files
278 279
			require_once($phpOpenIDLibPath . '/Auth/OpenID/Consumer.php');
279
			require_once($phpOpenIDLibPath . '/Auth/OpenID/FileStore.php');
280 280

  
281 281
			// Restore path
282 282
			@set_include_path($oldIncludePath);
......
319 319
	 * @return	Auth_OpenID_Consumer		Consumer instance
320 320
	 */
321 321
	protected function getOpenIDConsumer() {
322
		// TODO Change this to a TYPO3-specific database-based store in future.
323
		// File-based store is ineffective and insecure. After changing
324
		// get rid of the FileStore include in includePHPOpenIDLibrary()
325
		$openIDStorePath = PATH_site . 'typo3temp' . DIRECTORY_SEPARATOR . 'tx_openid';
322
		$openIDStore = t3lib_div::makeInstance('tx_openid_store');
323
		/* @var $openIDStore tx_openid_store */
324
		$openIDStore->cleanup();
326 325

  
327
		// For now we just prevent any web access to these files
328
		if (!file_exists($openIDStorePath . '/.htaccess')) {
329
			file_put_contents($openIDStorePath . '/.htaccess', 'deny from all');
330
		}
331
		$openIDStore = new Auth_OpenID_FileStore($openIDStorePath);
332 326
		return new Auth_OpenID_Consumer($openIDStore);
333 327
	}
334 328