move ssl client cert handling into separate service class

This commit is contained in:
Christian Weiske 2011-05-09 07:52:44 +02:00
parent c7ec370b47
commit 6447ca7186
2 changed files with 230 additions and 67 deletions

View file

@ -167,15 +167,30 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
return $password; return $password;
} }
function _updateuser($uId, $fieldname, $value) { /**
* Updates a single field in the user's database row
*
* @param integer $uId ID of the user
* @param string $fieldname Name of table column to change
* @param string $value New value
*
* @return boolean True if all was well, false if not
*/
public function _updateuser($uId, $fieldname, $value)
{
$updates = array ($fieldname => $value); $updates = array ($fieldname => $value);
$sql = 'UPDATE '. $this->getTableName() .' SET '. $this->db->sql_build_array('UPDATE', $updates) .' WHERE '. $this->getFieldName('primary') .'='. intval($uId); $sql = 'UPDATE '. $this->getTableName()
. ' SET '. $this->db->sql_build_array('UPDATE', $updates)
. ' WHERE '. $this->getFieldName('primary') . '=' . intval($uId);
// Execute the statement. // Execute the statement.
$this->db->sql_transaction('begin'); $this->db->sql_transaction('begin');
if (!($dbresult = & $this->db->sql_query($sql))) { if (!($dbresult = $this->db->sql_query($sql))) {
$this->db->sql_transaction('rollback'); $this->db->sql_transaction('rollback');
message_die(GENERAL_ERROR, 'Could not update user', '', __LINE__, __FILE__, $sql, $this->db); message_die(
GENERAL_ERROR, 'Could not update user', '',
__LINE__, __FILE__, $sql, $this->db
);
return false; return false;
} }
$this->db->sql_transaction('commit'); $this->db->sql_transaction('commit');
@ -390,10 +405,11 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
$this->db->sql_freeresult($dbresult); $this->db->sql_freeresult($dbresult);
return (int)$_SESSION[$this->getSessionKey()]; return (int)$_SESSION[$this->getSessionKey()];
} }
} else if (isset($_SERVER['SSL_CLIENT_M_SERIAL']) }
&& isset($_SERVER['SSL_CLIENT_V_END'])
) { $ssls = SemanticScuttle_Service_Factory::get('User_SslClientCert');
$id = $this->getUserIdFromSslClientCert(); if ($ssls->hasValidCert()) {
$id = $ssls->getUserIdFromCert();
if ($id !== false) { if ($id !== false) {
$this->setCurrentUserId($id); $this->setCurrentUserId($id);
return (int)$_SESSION[$this->getSessionKey()]; return (int)$_SESSION[$this->getSessionKey()];
@ -428,56 +444,6 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
/**
* Tries to detect the user ID from the SSL client certificate passed
* to the web server.
*
* @return mixed Integer user ID if the certificate is valid and
* assigned to a user, boolean false otherwise
*/
protected function getUserIdFromSslClientCert()
{
if (!isset($_SERVER['SSL_CLIENT_M_SERIAL'])
|| !isset($_SERVER['SSL_CLIENT_V_END'])
|| !isset($_SERVER['SSL_CLIENT_VERIFY'])
|| $_SERVER['SSL_CLIENT_VERIFY'] !== 'SUCCESS'
|| !isset($_SERVER['SSL_CLIENT_I_DN'])
) {
return false;
}
if ($_SERVER['SSL_CLIENT_V_REMAIN'] <= 0) {
return false;
}
$serial = $_SERVER['SSL_CLIENT_M_SERIAL'];
$clientIssuerDn = $_SERVER['SSL_CLIENT_I_DN'];
$query = 'SELECT uId'
. ' FROM ' . $this->getTableName() . '_sslclientcerts'
. ' WHERE sslSerial = \'' . $this->db->sql_escape($serial) . '\''
. ' AND sslClientIssuerDn = \''
. $this->db->sql_escape($clientIssuerDn)
. '\'';
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not load user for client certificate',
'', __LINE__, __FILE__, $query, $this->db
);
return false;
}
$row = $this->db->sql_fetchrow($dbresult);
$this->db->sql_freeresult($dbresult);
if (!$row) {
return false;
}
return (int)$row['uId'];
}
/** /**
* Try to authenticate and login a user with * Try to authenticate and login a user with
* username and password. * username and password.
@ -670,23 +636,57 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
return $uId; return $uId;
} }
function updateUser($uId, $password, $name, $email, $homepage, $uContent) { /**
if (!is_numeric($uId)) * Updates the given user
return false; *
* @param integer $uId ID of user to change
* @param string $password Password to use
* @param string $name Realname to use
* @param string $email Email to use
* @param string $homepage User's homepage
* @param string $uContent User note
*
* @return boolean True when all is well, false if not
*/
public function updateUser(
$uId, $password, $name, $email, $homepage, $uContent
) {
if (!is_numeric($uId)) {
return false;
}
// Set up the SQL UPDATE statement. // Set up the SQL UPDATE statement.
$moddatetime = gmdate('Y-m-d H:i:s', time()); $moddatetime = gmdate('Y-m-d H:i:s', time());
if ($password == '') if ($password == '') {
$updates = array ('uModified' => $moddatetime, 'name' => $name, 'email' => $email, 'homepage' => $homepage, 'uContent' => $uContent); $updates = array(
else 'uModified' => $moddatetime,
$updates = array ('uModified' => $moddatetime, 'password' => $this->sanitisePassword($password), 'name' => $name, 'email' => $email, 'homepage' => $homepage, 'uContent' => $uContent); 'name' => $name,
$sql = 'UPDATE '. $this->getTableName() .' SET '. $this->db->sql_build_array('UPDATE', $updates) .' WHERE '. $this->getFieldName('primary') .'='. intval($uId); 'email' => $email,
'homepage' => $homepage,
'uContent' => $uContent
);
} else {
$updates = array(
'uModified' => $moddatetime,
'password' => $this->sanitisePassword($password),
'name' => $name,
'email' => $email,
'homepage' => $homepage,
'uContent' => $uContent
);
}
$sql = 'UPDATE '. $this->getTableName()
. ' SET '. $this->db->sql_build_array('UPDATE', $updates)
. ' WHERE '. $this->getFieldName('primary') . '=' . intval($uId);
// Execute the statement. // Execute the statement.
$this->db->sql_transaction('begin'); $this->db->sql_transaction('begin');
if (!($dbresult = & $this->db->sql_query($sql))) { if (!($dbresult = & $this->db->sql_query($sql))) {
$this->db->sql_transaction('rollback'); $this->db->sql_transaction('rollback');
message_die(GENERAL_ERROR, 'Could not update user', '', __LINE__, __FILE__, $sql, $this->db); message_die(
GENERAL_ERROR, 'Could not update user', '',
__LINE__, __FILE__, $sql, $this->db
);
return false; return false;
} }
$this->db->sql_transaction('commit'); $this->db->sql_transaction('commit');
@ -695,6 +695,8 @@ class SemanticScuttle_Service_User extends SemanticScuttle_DbService
return true; return true;
} }
function getAllUsers ( ) { function getAllUsers ( ) {
$query = 'SELECT * FROM '. $this->getTableName(); $query = 'SELECT * FROM '. $this->getTableName();

View file

@ -0,0 +1,161 @@
<?php
/**
* SemanticScuttle - your social bookmark manager.
*
* PHP version 5.
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
/**
* SemanticScuttle SSL client certificate management service
*
* @category Bookmarking
* @package SemanticScuttle
* @author Christian Weiske <cweiske@cweiske.de>
* @license AGPL http://www.gnu.org/licenses/agpl.html
* @link http://sourceforge.net/projects/semanticscuttle
*/
class SemanticScuttle_Service_User_SslClientCert extends SemanticScuttle_DbService
{
/**
* Creates a new instance, sets database variable and table name.
*
* @param sql_db $db Database object
*/
protected function __construct($db)
{
$this->db = $db;
$this->tablename = $GLOBALS['tableprefix'] .'users_sslclientcerts';
}
/**
* Returns the single service instance
*
* @param sql_db $db Database object
*
* @return SemanticScuttle_Service_User
*/
public static function getInstance($db)
{
static $instance;
if (!isset($instance)) {
$instance = new self($db);
}
return $instance;
}
/**
* Determines if the browser provided a valid SSL client certificate
*
* @return boolean True if the client cert is there and is valid
*/
public function hasValidCert()
{
if (!isset($_SERVER['SSL_CLIENT_M_SERIAL'])
|| !isset($_SERVER['SSL_CLIENT_V_END'])
|| !isset($_SERVER['SSL_CLIENT_VERIFY'])
|| $_SERVER['SSL_CLIENT_VERIFY'] !== 'SUCCESS'
|| !isset($_SERVER['SSL_CLIENT_I_DN'])
) {
return false;
}
if ($_SERVER['SSL_CLIENT_V_REMAIN'] <= 0) {
return false;
}
return true;
}
/**
* Registers the currently available SSL client certificate
* with the given user. As a result, the user will be able to login
* using the certifiate
*
* @param integer $uId User ID to attach the client cert to.
*
* @return boolean True if registration was well, false if not.
*/
public function registerCurrentCertificate($uId)
{
//FIXME
}
/**
* Takes values from the currently available SSL client certificate
* and adds the available profile data to the user.
*
* @param integer $uId User ID to attach the client cert to.
*
* @return array Array of profile data that were registered.
* Database column name as key, new value as value
*/
public function updateProfileFromCurentCert($uId)
{
$arData = array();
if (isset($_SERVER['SSL_CLIENT_S_DN_CN'])
&& trim($_SERVER['SSL_CLIENT_S_DN_CN']) != ''
) {
$arData['name'] = trim($_SERVER['SSL_CLIENT_S_DN_CN']);
}
if (count($arData)) {
foreach ($arData as $column => $value) {
$userservice->_updateuser($uId, $column, $value);
}
}
return $arData;
}
/**
* Tries to detect the user ID from the SSL client certificate passed
* to the web server.
*
* @return mixed Integer user ID if the certificate is valid and
* assigned to a user, boolean false otherwise
*/
public function getUserIdFromCert()
{
if (!$this->hasValidCert()) {
return false;
}
$serial = $_SERVER['SSL_CLIENT_M_SERIAL'];
$clientIssuerDn = $_SERVER['SSL_CLIENT_I_DN'];
$query = 'SELECT uId'
. ' FROM ' . $this->getTableName()
. ' WHERE sslSerial = \'' . $this->db->sql_escape($serial) . '\''
. ' AND sslClientIssuerDn = \''
. $this->db->sql_escape($clientIssuerDn)
. '\'';
if (!($dbresult = $this->db->sql_query($query))) {
message_die(
GENERAL_ERROR, 'Could not load user for client certificate',
'', __LINE__, __FILE__, $query, $this->db
);
return false;
}
$row = $this->db->sql_fetchrow($dbresult);
$this->db->sql_freeresult($dbresult);
if (!$row) {
return false;
}
return (int)$row['uId'];
}
}
?>