Bug #19530 » 9683.diff
typo3/sysext/openid/ext_tables.sql (working copy) | ||
---|---|---|
# Table structure for table 'be_users'
|
||
#
|
||
CREATE TABLE be_users (
|
||
tx_openid_openid varchar(255) DEFAULT '' NOT NULL
|
||
tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
|
||
);
|
||
#
|
||
# Table structure for table 'fe_users'
|
||
#
|
||
CREATE TABLE fe_users (
|
||
tx_openid_openid varchar(255) DEFAULT '' NOT NULL
|
||
);
|
||
tx_openid_openid varchar(255) DEFAULT '' NOT NULL,
|
||
);
|
||
#
|
||
# Table structure for table 'tx_openid_assoc_store'.
|
||
#
|
||
CREATE TABLE tx_openid_assoc_store (
|
||
uid int(11) unsigned NOT NULL auto_increment,
|
||
pid int(11) unsigned DEFAULT '0' NOT NULL,
|
||
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||
expires int(11) unsigned DEFAULT '0' NOT NULL,
|
||
server_url varchar(2047) DEFAULT '' NOT NULL,
|
||
assoc_handle varchar(255) DEFAULT '' NOT NULL,
|
||
content blob,
|
||
PRIMARY KEY (uid),
|
||
KEY assoc_handle (assoc_handle(8)),
|
||
KEY expires (expires)
|
||
) ENGINE=InnoDB;
|
||
#
|
||
# Table structure for table 'tx_openid_nonce_store'.
|
||
#
|
||
CREATE TABLE tx_openid_nonce_store (
|
||
uid int(11) unsigned NOT NULL auto_increment,
|
||
pid int(11) unsigned DEFAULT '0' NOT NULL,
|
||
crdate int(11) unsigned DEFAULT '0' NOT NULL,
|
||
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
|
||
server_url varchar(2047) DEFAULT '' NOT NULL,
|
||
salt char(40),
|
||
PRIMARY KEY (uid),
|
||
UNIQUE KEY nonce (server_url(255),tstamp,salt),
|
||
KEY crdate (crdate)
|
||
) ENGINE=InnoDB;
|
typo3/sysext/openid/TODO (working copy) | ||
---|---|---|
* use DB (the sessions or the caching framework) instead of the filesystem to store OpenID data (class.tx_openid_sv1.php)
|
||
None
|
typo3/sysext/openid/sv1/class.tx_openid_store.php (revision 0) | ||
---|---|---|
<?php
|
||
/***************************************************************
|
||
* Copyright notice
|
||
*
|
||
* (c) 2009 Dmitry Dulepov (dmitry.dulepov@gmail.com)
|
||
* All rights reserved
|
||
*
|
||
* This script is part of the Typo3 project. The Typo3 project 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.
|
||
*
|
||
* The GNU General Public License can be found at
|
||
* http://www.gnu.org/copyleft/gpl.html.
|
||
*
|
||
* This script 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.
|
||
*
|
||
* This copyright notice MUST APPEAR in all copies of the script!
|
||
***************************************************************/
|
||
/**
|
||
* $Id$
|
||
*/
|
||
require_once(t3lib_extMgm::extPath('openid', 'lib/php-openid/Auth/OpenID/Interface.php'));
|
||
/**
|
||
* This class is a TYPO3-specific OpenID store.
|
||
*
|
||
* @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
|
||
* @package TYPO3
|
||
* @subpackage tx_openid
|
||
*/
|
||
class tx_openid_store extends Auth_OpenID_OpenIDStore {
|
||
const ASSOCIATION_TABLE_NAME = 'tx_openid_assoc_store';
|
||
const ASSOCIATION_EXPIRATION_SAFETY_INTERVAL = 120; /* 2 minutes */
|
||
const NONCE_TABLE_NAME = 'tx_openid_nonce_store';
|
||
const NONCE_STORAGE_TIME = 864000; /* 10 days */
|
||
/**
|
||
* Checks if database tables are created. If not, executes CREATE TABLE
|
||
* for extension's tables.
|
||
*
|
||
* @return void
|
||
*/
|
||
public function __construct() {
|
||
$this->checkAndCreateTables();
|
||
}
|
||
/**
|
||
* Sores the association for future use
|
||
*
|
||
* @param string $serverUrl Server URL
|
||
* @param Auth_OpenID_Association $association OpenID association
|
||
* @return void
|
||
*/
|
||
public function storeAssociation($serverUrl, $association) {
|
||
/* @var $association Auth_OpenID_Association */
|
||
$GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION');
|
||
if ($this->doesAssociationExist($serverUrl, $association->handle)) {
|
||
$this->updateExistingAssociation($serverUrl, $association);
|
||
}
|
||
else {
|
||
$this->storeNewAssociation($serverUrl, $association);
|
||
}
|
||
$GLOBALS['TYPO3_DB']->sql_query('COMMIT');
|
||
}
|
||
/**
|
||
* Removes all expired associations.
|
||
*
|
||
* @return int A number of removed associations
|
||
*/
|
||
public function cleanupAssociations() {
|
||
$where = sprintf('expires<=%d', time());
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
|
||
return $GLOBALS['TYPO3_DB']->sql_affected_rows();
|
||
}
|
||
/**
|
||
* Obtains the association to the server
|
||
*
|
||
* @param string $serverUrl Server URL
|
||
* @param string $handle Association handle (optional)
|
||
* @return Auth_OpenID_Association
|
||
*/
|
||
public function getAssociation($serverUrl, $handle = null) {
|
||
$this->cleanupAssociations();
|
||
$where = sprintf('server_url=%s AND expires>%d',
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
|
||
time());
|
||
if ($handle != null) {
|
||
$where .= sprintf(' AND assoc_handle=%s',
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
|
||
$sort = '';
|
||
}
|
||
else {
|
||
$sort = 'tstamp DESC';
|
||
}
|
||
list($row) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('uid,content',
|
||
self::ASSOCIATION_TABLE_NAME, $where, '', $sort, '1');
|
||
$result = null;
|
||
if (is_array($row)) {
|
||
$result = @unserialize($row['content']);
|
||
$this->updateAssociationTimeStamp($row['tstamp']);
|
||
}
|
||
return $result;
|
||
}
|
||
/**
|
||
* Removes the association
|
||
*
|
||
* @param string $serverUrl Server URL
|
||
* @param string $handle Association handle (optional)
|
||
* @return boolean true if the association existed
|
||
*/
|
||
function removeAssociation($serverUrl, $handle) {
|
||
$where = sprintf('server_url=%s AND assoc_handle=%s',
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
|
||
$deletedCount = $GLOBALS['TYPO3_DB']->sql_affected_rows();
|
||
return ($deletedCount > 0);
|
||
}
|
||
/**
|
||
* Removes old nonces
|
||
*
|
||
* @return void
|
||
*/
|
||
public function cleanupNonces() {
|
||
$where = sprintf('crdate<%d', time() - self::NONCE_STORAGE_TIME);
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, $where);
|
||
}
|
||
/**
|
||
* Checks if this nonce was already used
|
||
* @param $serverUrl Server URL
|
||
* @param $timestamp Time stamp
|
||
* @param $salt Nonce value
|
||
* @return boolean true if nonce was not used before anc can be used now
|
||
*/
|
||
public function useNonce($serverUrl, $timestamp, $salt) {
|
||
$result = false;
|
||
if (abs($timestamp - time()) < $GLOBALS['Auth_OpenID_SKEW']) {
|
||
$values = array(
|
||
'crdate' => time(),
|
||
'salt' => $salt,
|
||
'server_url' => $serverUrl,
|
||
'tstamp' => $timestamp
|
||
);
|
||
$GLOBALS['TYPO3_DB']->exec_INSERTquery(self::NONCE_TABLE_NAME,
|
||
$values);
|
||
$affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
|
||
$result = ($affectedRows > 0);
|
||
}
|
||
return $result;
|
||
}
|
||
/**
|
||
* Resets the store by removing all data in it
|
||
*
|
||
* @return void
|
||
*/
|
||
public function reset() {
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, '1=1');
|
||
$GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, '1=1');
|
||
}
|
||
/**
|
||
* Checks if such association exists.
|
||
*
|
||
* @param string $serverUrl Server URL
|
||
* @param Auth_OpenID_Association $association OpenID association
|
||
* @return boolean
|
||
*/
|
||
protected function doesAssociationExist($serverUrl, $association) {
|
||
$where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
|
||
time());
|
||
list($row) = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
|
||
'COUNT(*) as assocCount', self::ASSOCIATION_TABLE_NAME, $where);
|
||
return ($row['assocCount'] > 0);
|
||
}
|
||
/**
|
||
* Updates existing association.
|
||
*
|
||
* @param string $serverUrl Server URL
|
||
* @param Auth_OpenID_Association $association OpenID association
|
||
* @return void
|
||
*/
|
||
protected function updateExistingAssociation($serverUrl, Auth_OpenID_Association $association) {
|
||
$where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
|
||
$GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
|
||
time());
|
||
$serializedAssociation = serialize($association);
|
||
$values = array(
|
||
'content' => $serializedAssociation,
|
||
'tstamp' => time(),
|
||
);
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
|
||
}
|
||
/**
|
||
* Stores new association to the database.
|
||
*
|
||
* @param $serverUrl Server URL
|
||
* @param $association OpenID association
|
||
* @return void
|
||
*/
|
||
protected function storeNewAssociation($serverUrl, $association) {
|
||
$serializedAssociation = serialize($association);
|
||
$values = array(
|
||
'assoc_handle' => $association->handle,
|
||
'content' => $serializedAssociation,
|
||
'crdate' => $association->issued,
|
||
'tstamp' => time(),
|
||
'expires' => $association->issued + $association->lifetime - self::ASSOCIATION_EXPIRATION_SAFETY_INTERVAL,
|
||
'server_url' => $serverUrl
|
||
);
|
||
// In the next query we can get race conditions. sha1_hash prevents many
|
||
// asociations from being stored for one server
|
||
$GLOBALS['TYPO3_DB']->exec_INSERTquery(self::ASSOCIATION_TABLE_NAME, $values);
|
||
}
|
||
/**
|
||
* Updates association time stamp.
|
||
*
|
||
* @param $recordId Association record id in the database
|
||
* @return void
|
||
*/
|
||
protected function updateAssociationTimeStamp($recordId) {
|
||
$where = sprintf('uid=%d', $recordId);
|
||
$values = array(
|
||
'tstamp' => time()
|
||
);
|
||
$GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
|
||
}
|
||
/**
|
||
* Checks and database tables for this store.
|
||
*
|
||
* @return void
|
||
*/
|
||
protected function checkAndCreateTables() {
|
||
$tableNames = $this->findTableToCreate();
|
||
if (count($tableNames) > 0) {
|
||
$this->doCreateTables($tableNames);
|
||
}
|
||
}
|
||
/**
|
||
* Finds all missing database tables
|
||
*
|
||
* @return array
|
||
*/
|
||
protected function findTableToCreate() {
|
||
$tablesToCreate = array();
|
||
$existingTables = array_keys($GLOBALS['TYPO3_DB']->admin_get_tables());
|
||
// Do that only if could get table list!
|
||
if (count($existingTables) > 0) {
|
||
foreach (array('tx_openid_assoc_store', 'tx_openid_nonce_store') as $tableName) {
|
||
if (!in_array($tableName, $existingTables)) {
|
||
$tablesToCreate[] = $tableName;
|
||
}
|
||
}
|
||
}
|
||
return $tablesToCreate;
|
||
}
|
||
/**
|
||
* Creates tables in the database.
|
||
*
|
||
* @param array $tableNames Table names
|
||
* @return void
|
||
*/
|
||
protected function doCreateTables(array $tableNames) {
|
||
$sqlFile = file_get_contents(t3lib_extMgm::extPath('openid', 'ext_tables.sql'));
|
||
foreach ($tableNames as $tableName) {
|
||
$this->doCreateTable($sqlFile, $tableName);
|
||
}
|
||
}
|
||
/**
|
||
* Creates a single database table
|
||
*
|
||
* @param string $sqlFile ext_tables.sql content
|
||
* @param $tableName Table name
|
||
* @return void
|
||
*/
|
||
protected function doCreateTable($sqlFile, $tableName) {
|
||
$regularExpression = '/.*(CREATE\s*TABLE\s*`?' . $tableName . '`?\s*\([^;]+).*/is';
|
||
$tableDefinition = preg_replace($regularExpression, '\1', $sqlFile);
|
||
if ($tableDefinition != '') {
|
||
$GLOBALS['TYPO3_DB']->sql_query($tableDefinition);
|
||
}
|
||
}
|
||
}
|
||
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php']) {
|
||
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php']);
|
||
}
|
||
?>
|
typo3/sysext/openid/sv1/class.tx_openid_sv1.php (working copy) | ||
---|---|---|
*/
|
||
require_once(PATH_t3lib . 'class.t3lib_svbase.php');
|
||
require_once(t3lib_extMgm::extPath('openid', 'sv1/class.tx_openid_store.php'));
|
||
/**
|
||
* Service "OpenID Authentication" for the "openid" extension.
|
||
... | ... | |
// Include files
|
||
require_once($phpOpenIDLibPath . '/Auth/OpenID/Consumer.php');
|
||
require_once($phpOpenIDLibPath . '/Auth/OpenID/FileStore.php');
|
||
// Restore path
|
||
@set_include_path($oldIncludePath);
|
||
... | ... | |
* @return Auth_OpenID_Consumer Consumer instance
|
||
*/
|
||
protected function getOpenIDConsumer() {
|
||
// TODO Change this to a TYPO3-specific database-based store in future.
|
||
// File-based store is ineffective and insecure. After changing
|
||
// get rid of the FileStore include in includePHPOpenIDLibrary()
|
||
$openIDStorePath = PATH_site . 'typo3temp' . DIRECTORY_SEPARATOR . 'tx_openid';
|
||
$openIDStore = t3lib_div::makeInstance('tx_openid_store');
|
||
/* @var $openIDStore tx_openid_store */
|
||
$openIDStore->cleanup();
|
||
// For now we just prevent any web access to these files
|
||
if (!file_exists($openIDStorePath . '/.htaccess')) {
|
||
file_put_contents($openIDStorePath . '/.htaccess', 'deny from all');
|
||
}
|
||
$openIDStore = new Auth_OpenID_FileStore($openIDStorePath);
|
||
return new Auth_OpenID_Consumer($openIDStore);
|
||
}
|
||